SHA256
Обновить UI кошелька и регистрацию
This commit is contained in:
@@ -1,10 +1,13 @@
|
||||
import { renderHeader } from '../components/header.js';
|
||||
import {
|
||||
authService,
|
||||
authorizeSession,
|
||||
refreshSessions,
|
||||
setAuthError,
|
||||
setAuthInfo,
|
||||
state,
|
||||
} from '../state.js';
|
||||
import { clearStoredMessages } from '../services/message-store.js';
|
||||
import { toUserMessage } from '../services/ui-error-texts.js';
|
||||
import {
|
||||
formatSol,
|
||||
@@ -20,7 +23,8 @@ import { defaultServerLogin } from '../deploy-config.js';
|
||||
|
||||
export const pageMeta = { id: 'registration-payment-view', title: 'Оплата регистрации', showAppChrome: false };
|
||||
const MIN_REQUIRED_SOL = 0.01;
|
||||
const SOLANA_SYNC_WAIT_SEC = 15;
|
||||
const SOLANA_SYNC_WAIT_SEC = 12;
|
||||
const EMPTY_PASSWORD_WORDS = Array.from({ length: 12 }, () => '');
|
||||
|
||||
function parseBalanceSol(value) {
|
||||
const parsed = Number.parseFloat(String(value || '').replace(',', '.'));
|
||||
@@ -35,6 +39,69 @@ function getCryptoRuntimeState() {
|
||||
return { hasCrypto, hasGetRandomValues, hasSubtle, secureContext };
|
||||
}
|
||||
|
||||
async function completeRegistrationLogin({ navigate, keyBundle }) {
|
||||
await authService.reconnect(state.entrySettings.shineServer);
|
||||
const result = await authService.createSessionForExistingUser(
|
||||
state.registrationDraft.login,
|
||||
state.registrationDraft.password,
|
||||
);
|
||||
|
||||
state.keyStorage.saveRoot = Boolean(state.keyStorage.saveRoot);
|
||||
state.keyStorage.saveBlockchain = Boolean(state.keyStorage.saveBlockchain);
|
||||
|
||||
await authService.persistSelectedKeys(
|
||||
result.login,
|
||||
result.storagePwd,
|
||||
keyBundle,
|
||||
{
|
||||
saveRoot: state.keyStorage.saveRoot,
|
||||
saveBlockchain: state.keyStorage.saveBlockchain,
|
||||
},
|
||||
);
|
||||
await authService.persistSessionMaterial(result.login, result.sessionMaterial);
|
||||
await clearStoredMessages().catch(() => {});
|
||||
|
||||
const resumed = await authService.resumeSession(result.login, result.sessionId);
|
||||
const resumedLogin = resumed.login || result.login;
|
||||
const resumedSessionId = resumed.sessionId || result.sessionId;
|
||||
const resumedStoragePwd = resumed.storagePwd || result.storagePwd;
|
||||
|
||||
authorizeSession({
|
||||
login: resumedLogin,
|
||||
sessionId: resumedSessionId,
|
||||
storagePwd: resumedStoragePwd,
|
||||
});
|
||||
|
||||
state.loginDraft.login = resumedLogin;
|
||||
state.loginDraft.password = '';
|
||||
state.loginDraft.passwordMode = 'single';
|
||||
state.loginDraft.passwordWords = EMPTY_PASSWORD_WORDS.slice();
|
||||
|
||||
state.registrationDraft.flowType = '';
|
||||
state.registrationDraft.password = '';
|
||||
state.registrationDraft.passwordMode = 'single';
|
||||
state.registrationDraft.passwordWords = EMPTY_PASSWORD_WORDS.slice();
|
||||
state.registrationDraft.storagePwd = '';
|
||||
state.registrationDraft.sessionId = '';
|
||||
state.registrationDraft.pendingKeyBundle = null;
|
||||
state.registrationDraft.pendingSessionMaterial = null;
|
||||
state.registrationDraft.preGeneratedKeyBundle = null;
|
||||
|
||||
state.registrationPayment.walletAddress = '';
|
||||
state.registrationPayment.balanceSOL = '0.0000';
|
||||
|
||||
await refreshSessions();
|
||||
setAuthInfo(`Регистрация завершена. Вы автоматически вошли как @${resumedLogin}.`);
|
||||
|
||||
const nextHash = String(state.authReturnHash || '').trim();
|
||||
state.authReturnHash = '';
|
||||
if (nextHash.startsWith('/')) {
|
||||
navigate(nextHash.slice(1));
|
||||
} else {
|
||||
navigate('profile-view');
|
||||
}
|
||||
}
|
||||
|
||||
export function render({ navigate }) {
|
||||
const screen = document.createElement('section');
|
||||
screen.className = 'stack';
|
||||
@@ -258,32 +325,30 @@ function renderSolanaDoneStage({ navigate, status, keyBundle }) {
|
||||
if (!card) return;
|
||||
|
||||
let remainingSec = SOLANA_SYNC_WAIT_SEC;
|
||||
let canTryLogin = false;
|
||||
let timerId = null;
|
||||
let loginStarted = false;
|
||||
|
||||
const info = document.createElement('p');
|
||||
info.className = 'auth-copy';
|
||||
info.textContent = 'Регистрация в Solana прошла успешно.';
|
||||
info.textContent = 'Регистрация завершена успешно.';
|
||||
|
||||
const hint = document.createElement('p');
|
||||
hint.className = 'meta-muted';
|
||||
hint.textContent = 'Подождите 10–15 секунд, пока запись обновится в блокчейне. После этого можно входить на сервер.';
|
||||
hint.textContent = 'Нужно подождать 10–15 секунд, пока в блокчейне SHiNE обновится ваша запись о регистрации. После этого мы автоматически войдём в ваш аккаунт.';
|
||||
|
||||
const timer = document.createElement('p');
|
||||
timer.className = 'meta-muted';
|
||||
timer.textContent = `До попытки входа: ${remainingSec} сек`;
|
||||
timer.textContent = `Готовим автоматический вход: ${remainingSec} сек`;
|
||||
|
||||
const tryLoginBtn = document.createElement('button');
|
||||
tryLoginBtn.className = 'primary-btn';
|
||||
tryLoginBtn.type = 'button';
|
||||
tryLoginBtn.textContent = `Попробовать войти (${remainingSec})`;
|
||||
tryLoginBtn.textContent = 'Входим автоматически...';
|
||||
tryLoginBtn.disabled = true;
|
||||
|
||||
const backBtn = document.createElement('button');
|
||||
backBtn.className = 'ghost-btn';
|
||||
backBtn.type = 'button';
|
||||
backBtn.textContent = 'Назад';
|
||||
backBtn.addEventListener('click', () => navigate('register-view'));
|
||||
const statusHint = document.createElement('p');
|
||||
statusHint.className = 'meta-muted';
|
||||
statusHint.textContent = 'Ничего нажимать не нужно. Если сервер ответит раньше, войдём сразу.';
|
||||
|
||||
const stopTimer = () => {
|
||||
if (timerId) {
|
||||
@@ -292,54 +357,46 @@ function renderSolanaDoneStage({ navigate, status, keyBundle }) {
|
||||
}
|
||||
};
|
||||
|
||||
const startAutoLogin = async () => {
|
||||
if (loginStarted) return;
|
||||
loginStarted = true;
|
||||
stopTimer();
|
||||
status.style.display = 'none';
|
||||
timer.textContent = 'Пробуем автоматически войти...';
|
||||
tryLoginBtn.textContent = 'Входим...';
|
||||
try {
|
||||
await completeRegistrationLogin({ navigate, keyBundle });
|
||||
} catch (error) {
|
||||
loginStarted = false;
|
||||
status.className = 'status-line is-unavailable';
|
||||
status.textContent = toUserMessage(error, 'Пока не удалось автоматически войти. Попробуйте ещё раз через несколько секунд.');
|
||||
status.style.display = '';
|
||||
timer.textContent = 'Автовход пока не удался.';
|
||||
tryLoginBtn.disabled = false;
|
||||
tryLoginBtn.textContent = 'Попробовать войти сейчас';
|
||||
}
|
||||
};
|
||||
|
||||
const updateTimerUi = () => {
|
||||
if (remainingSec > 0) {
|
||||
timer.textContent = `До попытки входа: ${remainingSec} сек`;
|
||||
tryLoginBtn.textContent = `Попробовать войти (${remainingSec})`;
|
||||
timer.textContent = `Готовим автоматический вход: ${remainingSec} сек`;
|
||||
tryLoginBtn.textContent = `Автовход через ${remainingSec} сек`;
|
||||
tryLoginBtn.disabled = true;
|
||||
} else {
|
||||
canTryLogin = true;
|
||||
timer.textContent = 'Можно входить на сервер.';
|
||||
tryLoginBtn.textContent = 'Попробовать войти на сервер';
|
||||
tryLoginBtn.disabled = false;
|
||||
stopTimer();
|
||||
timer.textContent = 'Запускаем автоматический вход...';
|
||||
tryLoginBtn.textContent = 'Входим...';
|
||||
tryLoginBtn.disabled = true;
|
||||
void startAutoLogin();
|
||||
}
|
||||
};
|
||||
|
||||
tryLoginBtn.addEventListener('click', async () => {
|
||||
if (!canTryLogin) return;
|
||||
status.style.display = 'none';
|
||||
tryLoginBtn.disabled = true;
|
||||
tryLoginBtn.textContent = 'Вход...';
|
||||
try {
|
||||
await authService.reconnect(state.entrySettings.shineServer);
|
||||
const result = await authService.createSessionForExistingUser(
|
||||
state.registrationDraft.login,
|
||||
state.registrationDraft.password,
|
||||
);
|
||||
await authService.persistSessionMaterial(
|
||||
result.login,
|
||||
result.sessionMaterial,
|
||||
);
|
||||
const resumed = await authService.resumeSession(result.login, result.sessionId);
|
||||
state.registrationDraft.flowType = 'registration';
|
||||
state.registrationDraft.sessionId = resumed.sessionId || result.sessionId;
|
||||
state.registrationDraft.storagePwd = resumed.storagePwd || result.storagePwd;
|
||||
state.registrationDraft.pendingKeyBundle = keyBundle;
|
||||
state.registrationDraft.pendingSessionMaterial = result.sessionMaterial;
|
||||
setAuthInfo(`Регистрация завершена. Вы вошли как @${result.login}. Далее откройте вкладку «Каналы».`);
|
||||
navigate('registration-keys-view');
|
||||
} catch (error) {
|
||||
status.className = 'status-line is-unavailable';
|
||||
status.textContent = toUserMessage(error, 'Пока не удалось войти. Попробуйте ещё раз через несколько секунд.');
|
||||
status.style.display = '';
|
||||
tryLoginBtn.disabled = false;
|
||||
tryLoginBtn.textContent = 'Попробовать войти на сервер';
|
||||
}
|
||||
if (loginStarted) return;
|
||||
await startAutoLogin();
|
||||
});
|
||||
|
||||
card.innerHTML = '';
|
||||
card.append(info, hint, timer, tryLoginBtn, backBtn, status);
|
||||
card.append(info, hint, statusHint, timer, tryLoginBtn, status);
|
||||
updateTimerUi();
|
||||
timerId = window.setInterval(() => {
|
||||
remainingSec -= 1;
|
||||
|
||||
Reference in New Issue
Block a user