SHA256
Улучшен вход пользователя в аккаунт
This commit is contained in:
+143
-17
@@ -1,31 +1,156 @@
|
||||
import { renderHeader } from '../components/header.js';
|
||||
import {
|
||||
authService,
|
||||
clearAuthMessages,
|
||||
setAuthBusy,
|
||||
setAuthError,
|
||||
state,
|
||||
} from '../state.js';
|
||||
import { buildShineHttpUrlFromAddress } from '../services/shine-server-resolver.js';
|
||||
import { toUserMessage } from '../services/ui-error-texts.js';
|
||||
|
||||
export const pageMeta = { id: 'login-view', title: 'Войти', showAppChrome: false };
|
||||
|
||||
function setStatus(statusEl, message, kind = 'error') {
|
||||
statusEl.classList.toggle('is-unavailable', kind === 'error');
|
||||
statusEl.classList.toggle('is-available', kind !== 'error');
|
||||
statusEl.textContent = message;
|
||||
statusEl.style.display = message ? '' : 'none';
|
||||
}
|
||||
|
||||
function setRemoteServer(remoteWrap, serverLoginEl, serverLinkEl, payload) {
|
||||
const serverLogin = String(payload?.accessServerLogin || '').trim();
|
||||
const serverUrl = String(payload?.accessServerUrl || '').trim();
|
||||
serverLoginEl.textContent = serverLogin ? `@${serverLogin}` : 'другой сервер доступа';
|
||||
serverLinkEl.textContent = serverUrl || 'Открыть сервер';
|
||||
serverLinkEl.href = buildShineHttpUrlFromAddress(serverUrl);
|
||||
remoteWrap.style.display = '';
|
||||
}
|
||||
|
||||
export function render({ navigate }) {
|
||||
const screen = document.createElement('section');
|
||||
screen.className = 'stack auth-screen auth-screen--lower login-choice-screen';
|
||||
|
||||
const loginButton = document.createElement('button');
|
||||
loginButton.className = 'ghost-btn';
|
||||
loginButton.type = 'button';
|
||||
loginButton.textContent = 'Войти по паролю';
|
||||
loginButton.addEventListener('click', () => navigate('login-password-view'));
|
||||
|
||||
const otherDeviceButton = document.createElement('button');
|
||||
otherDeviceButton.className = 'ghost-btn';
|
||||
otherDeviceButton.type = 'button';
|
||||
otherDeviceButton.textContent = 'Войти через другое устройство';
|
||||
otherDeviceButton.addEventListener('click', () => navigate('login-other-device-view'));
|
||||
|
||||
const actions = document.createElement('div');
|
||||
actions.className = 'auth-actions login-actions-wide';
|
||||
actions.append(loginButton, otherDeviceButton);
|
||||
clearAuthMessages();
|
||||
|
||||
const panel = document.createElement('section');
|
||||
panel.className = 'login-panel stack';
|
||||
panel.innerHTML = '<h1 class="login-panel-title">Войти</h1>';
|
||||
panel.append(actions);
|
||||
|
||||
const title = document.createElement('h1');
|
||||
title.className = 'login-panel-title';
|
||||
title.textContent = 'Введите логин';
|
||||
|
||||
const loginField = document.createElement('label');
|
||||
loginField.className = 'stack';
|
||||
|
||||
const loginInput = document.createElement('input');
|
||||
loginInput.className = 'input';
|
||||
loginInput.type = 'text';
|
||||
loginInput.autocomplete = 'username';
|
||||
loginInput.autocapitalize = 'off';
|
||||
loginInput.spellcheck = false;
|
||||
loginInput.placeholder = 'Логин';
|
||||
loginInput.value = String(state.loginDraft.login || '');
|
||||
|
||||
loginField.append(loginInput);
|
||||
|
||||
const status = document.createElement('p');
|
||||
status.className = 'status-line is-unavailable';
|
||||
status.style.display = 'none';
|
||||
|
||||
const remoteWrap = document.createElement('div');
|
||||
remoteWrap.className = 'login-remote-server stack';
|
||||
remoteWrap.style.display = 'none';
|
||||
|
||||
const remoteText = document.createElement('p');
|
||||
remoteText.className = 'auth-copy';
|
||||
const serverLoginEl = document.createElement('strong');
|
||||
const textBefore = document.createTextNode('Этот пользователь SHiNE зарегистрирован на другом сервере доступа: ');
|
||||
remoteText.append(textBefore, serverLoginEl, document.createTextNode('. Для входа перейдите на его сервер.'));
|
||||
|
||||
const serverLinkEl = document.createElement('a');
|
||||
serverLinkEl.className = 'primary-btn login-server-link';
|
||||
serverLinkEl.target = '_self';
|
||||
serverLinkEl.rel = 'noopener';
|
||||
|
||||
remoteWrap.append(remoteText, serverLinkEl);
|
||||
|
||||
const passwordButton = document.createElement('button');
|
||||
passwordButton.className = 'primary-btn';
|
||||
passwordButton.type = 'button';
|
||||
passwordButton.textContent = 'Войти по паролю';
|
||||
|
||||
const deviceButton = document.createElement('button');
|
||||
deviceButton.className = 'ghost-btn';
|
||||
deviceButton.type = 'button';
|
||||
deviceButton.textContent = 'Войти через другое устройство';
|
||||
|
||||
const actions = document.createElement('div');
|
||||
actions.className = 'auth-actions login-actions-wide';
|
||||
actions.append(passwordButton, deviceButton);
|
||||
|
||||
const resolveAndContinue = async (targetPage) => {
|
||||
const login = String(loginInput.value || '').trim();
|
||||
setStatus(status, '');
|
||||
remoteWrap.style.display = 'none';
|
||||
if (!login) {
|
||||
setStatus(status, 'Введите логин.');
|
||||
loginInput.focus();
|
||||
return;
|
||||
}
|
||||
|
||||
passwordButton.disabled = true;
|
||||
deviceButton.disabled = true;
|
||||
setAuthBusy(true);
|
||||
setAuthError('');
|
||||
|
||||
try {
|
||||
await authService.reconnect(state.entrySettings.shineServer);
|
||||
const resolved = await authService.resolveLoginForAuth(login);
|
||||
const resolution = String(resolved?.resolution || '').trim().toUpperCase();
|
||||
|
||||
if (resolution === 'NOT_FOUND') {
|
||||
setStatus(status, 'Пользователь с таким логином не зарегистрирован в SHiNE.');
|
||||
return;
|
||||
}
|
||||
if (resolution === 'NO_ACCESS_SERVER') {
|
||||
setStatus(status, 'Пользователь зарегистрирован в SHiNE, но для него не найден действующий сервер доступа.');
|
||||
return;
|
||||
}
|
||||
if (resolution === 'REMOTE') {
|
||||
state.loginDraft.login = String(resolved?.login || login).trim();
|
||||
setRemoteServer(remoteWrap, serverLoginEl, serverLinkEl, resolved);
|
||||
return;
|
||||
}
|
||||
if (resolution !== 'LOCAL') {
|
||||
setStatus(status, 'Сервер вернул неизвестный статус проверки логина.');
|
||||
return;
|
||||
}
|
||||
|
||||
state.loginDraft.login = String(resolved?.login || login).trim();
|
||||
state.loginDraft.password = '';
|
||||
navigate(targetPage);
|
||||
} catch (error) {
|
||||
const message = toUserMessage(error, 'Не удалось проверить логин.');
|
||||
setAuthError(message);
|
||||
setStatus(status, message);
|
||||
} finally {
|
||||
setAuthBusy(false);
|
||||
passwordButton.disabled = false;
|
||||
deviceButton.disabled = false;
|
||||
}
|
||||
};
|
||||
|
||||
passwordButton.addEventListener('click', () => resolveAndContinue('login-password-view'));
|
||||
deviceButton.addEventListener('click', () => resolveAndContinue('login-other-device-view'));
|
||||
loginInput.addEventListener('keydown', (event) => {
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
void resolveAndContinue('login-password-view');
|
||||
}
|
||||
});
|
||||
|
||||
panel.append(title, loginField, status, remoteWrap, actions);
|
||||
|
||||
screen.append(
|
||||
renderHeader({
|
||||
@@ -35,5 +160,6 @@ export function render({ navigate }) {
|
||||
panel,
|
||||
);
|
||||
|
||||
window.setTimeout(() => loginInput.focus(), 0);
|
||||
return screen;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user