SHA256
Доработать финал регистрации для мобильного UI
This commit is contained in:
+2
-2
@@ -1,2 +1,2 @@
|
||||
client.version=1.2.326
|
||||
server.version=1.2.297
|
||||
client.version=1.2.327
|
||||
server.version=1.2.298
|
||||
|
||||
@@ -24,10 +24,29 @@ import { defaultServerLogin } from '../deploy-config.js';
|
||||
|
||||
export const pageMeta = { id: 'registration-payment-view', title: 'Оплата регистрации', showAppChrome: false };
|
||||
const MIN_REQUIRED_SOL = 0.01;
|
||||
const AUTO_LOGIN_INITIAL_DELAY_MS = 5000;
|
||||
const AUTO_LOGIN_RETRY_MS = 1000;
|
||||
const AUTO_LOGIN_INITIAL_DELAY_MS = 10000;
|
||||
const AUTO_LOGIN_RETRY_MS = 2000;
|
||||
const EMPTY_PASSWORD_WORDS = Array.from({ length: 12 }, () => '');
|
||||
|
||||
function getExplorerClusterName(endpoint) {
|
||||
const source = String(endpoint || '').trim().toLowerCase();
|
||||
if (!source) return 'mainnet-beta';
|
||||
if (source.includes('devnet')) return 'devnet';
|
||||
if (source.includes('testnet')) return 'testnet';
|
||||
return 'mainnet-beta';
|
||||
}
|
||||
|
||||
function makeSolanaExplorerTxUrl(signature, endpoint) {
|
||||
const cleanSignature = String(signature || '').trim();
|
||||
if (!cleanSignature) return '';
|
||||
const cluster = getExplorerClusterName(endpoint);
|
||||
const url = new URL(`https://explorer.solana.com/tx/${encodeURIComponent(cleanSignature)}`);
|
||||
if (cluster !== 'mainnet-beta') {
|
||||
url.searchParams.set('cluster', cluster);
|
||||
}
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
function parseBalanceSol(value) {
|
||||
const parsed = Number.parseFloat(String(value || '').replace(',', '.'));
|
||||
return Number.isFinite(parsed) ? parsed : 0;
|
||||
@@ -262,14 +281,16 @@ export function render({ navigate }) {
|
||||
|
||||
// Регистрация на Solana (смарт контракт)
|
||||
submitButton.textContent = 'Регистрация в Solana...';
|
||||
let registrationTxId = '';
|
||||
try {
|
||||
await registerUserOnSolana({
|
||||
const registrationResult = await registerUserOnSolana({
|
||||
login: state.registrationDraft.login,
|
||||
keyBundle,
|
||||
solanaEndpoint: state.entrySettings.solanaServer,
|
||||
accessServers: [state.entrySettings.shineServerLogin || defaultServerLogin],
|
||||
promoCode: '',
|
||||
});
|
||||
registrationTxId = String(registrationResult?.signature || '').trim();
|
||||
} catch (solanaError) {
|
||||
const solanaMsg = formatSolanaErrorDetails(solanaError);
|
||||
// Пользователь уже зарегистрирован в Solana — продолжаем
|
||||
@@ -278,7 +299,7 @@ export function render({ navigate }) {
|
||||
}
|
||||
}
|
||||
|
||||
renderSolanaDoneStage({ navigate, status, keyBundle });
|
||||
renderSolanaDoneStage({ navigate, status, keyBundle, registrationTxId });
|
||||
} catch (error) {
|
||||
const message = toUserMessage(error, 'Не удалось завершить регистрацию.');
|
||||
setAuthError(message);
|
||||
@@ -324,37 +345,47 @@ export function render({ navigate }) {
|
||||
return screen;
|
||||
}
|
||||
|
||||
function renderSolanaDoneStage({ navigate, status, keyBundle }) {
|
||||
function renderSolanaDoneStage({ navigate, status, keyBundle, registrationTxId = '' }) {
|
||||
const screen = document.querySelector('section.stack');
|
||||
if (!screen) return;
|
||||
const headerBackButton = screen.querySelector('.page-header .header-left .icon-btn');
|
||||
const card = screen.querySelector('.card.stack');
|
||||
if (!card) return;
|
||||
card.classList.add('registration-finish-card');
|
||||
|
||||
let initialDelayId = null;
|
||||
let retryTimerId = null;
|
||||
let loginInFlight = false;
|
||||
let loginCompleted = false;
|
||||
const txExplorerUrl = makeSolanaExplorerTxUrl(registrationTxId, state.entrySettings.solanaServer);
|
||||
|
||||
const title = document.createElement('h2');
|
||||
title.className = 'registration-finish-title';
|
||||
title.textContent = 'Поздравляем, регистрация завершена';
|
||||
title.style.margin = '0';
|
||||
|
||||
const hint = document.createElement('p');
|
||||
hint.className = 'auth-copy';
|
||||
hint.textContent = 'Осталось подождать несколько секунд, пока обновится запись в блокчейне. После этого приложение автоматически войдёт в ваш аккаунт.';
|
||||
hint.className = 'auth-copy registration-finish-text';
|
||||
hint.textContent = 'Подождите 10 секунд, пока обновится транзакция вашей регистрации в блокчейне Solana. После этого вход в аккаунт произойдёт автоматически.';
|
||||
|
||||
const txIdLine = document.createElement('p');
|
||||
txIdLine.className = 'meta-muted registration-finish-tx';
|
||||
if (registrationTxId && txExplorerUrl) {
|
||||
const txLabel = document.createElement('span');
|
||||
txLabel.textContent = 'Tx ID регистрации: ';
|
||||
const txLink = document.createElement('a');
|
||||
txLink.className = 'registration-finish-tx-link';
|
||||
txLink.href = txExplorerUrl;
|
||||
txLink.target = '_blank';
|
||||
txLink.rel = 'noopener noreferrer';
|
||||
txLink.textContent = registrationTxId;
|
||||
txIdLine.append(txLabel, txLink);
|
||||
} else {
|
||||
txIdLine.textContent = 'Tx ID регистрации: ожидаем подтверждённую подпись';
|
||||
}
|
||||
|
||||
const progress = document.createElement('p');
|
||||
progress.className = 'meta-muted';
|
||||
progress.textContent = 'Подготавливаем автоматический вход...';
|
||||
|
||||
const altHint = document.createElement('p');
|
||||
altHint.className = 'meta-muted';
|
||||
altHint.textContent = 'Или вы можете';
|
||||
|
||||
const backBtn = document.createElement('button');
|
||||
backBtn.className = 'ghost-btn';
|
||||
backBtn.type = 'button';
|
||||
backBtn.textContent = 'Вернуться в главное меню';
|
||||
progress.className = 'meta-muted registration-finish-progress';
|
||||
progress.textContent = 'Подготавливаем проверку регистрации...';
|
||||
|
||||
const stopAutoLogin = () => {
|
||||
if (initialDelayId) {
|
||||
@@ -370,7 +401,7 @@ function renderSolanaDoneStage({ navigate, status, keyBundle }) {
|
||||
const tryAutoLogin = async () => {
|
||||
if (loginCompleted || loginInFlight) return;
|
||||
loginInFlight = true;
|
||||
progress.textContent = 'Пробуем автоматически войти в аккаунт...';
|
||||
progress.textContent = 'Проверяем, прошла ли регистрация...';
|
||||
status.style.display = 'none';
|
||||
try {
|
||||
await completeRegistrationLogin({ navigate, keyBundle });
|
||||
@@ -378,7 +409,7 @@ function renderSolanaDoneStage({ navigate, status, keyBundle }) {
|
||||
stopAutoLogin();
|
||||
} catch (error) {
|
||||
if (!loginCompleted) {
|
||||
progress.textContent = 'Ждём обновления записи и скоро попробуем снова...';
|
||||
progress.textContent = 'Пока ещё не прошла, подождите ещё секундочку...';
|
||||
console.warn('Auto login after registration is not ready yet', toUserMessage(error, 'auto-login-wait'));
|
||||
}
|
||||
} finally {
|
||||
@@ -386,14 +417,18 @@ function renderSolanaDoneStage({ navigate, status, keyBundle }) {
|
||||
}
|
||||
};
|
||||
|
||||
backBtn.addEventListener('click', () => {
|
||||
loginCompleted = true;
|
||||
stopAutoLogin();
|
||||
navigate('start-view');
|
||||
});
|
||||
if (headerBackButton) {
|
||||
const replacement = headerBackButton.cloneNode(true);
|
||||
replacement.addEventListener('click', () => {
|
||||
loginCompleted = true;
|
||||
stopAutoLogin();
|
||||
navigate('start-view');
|
||||
});
|
||||
headerBackButton.replaceWith(replacement);
|
||||
}
|
||||
|
||||
card.innerHTML = '';
|
||||
card.append(title, hint, progress, altHint, backBtn, status);
|
||||
card.append(title, hint, txIdLine, progress, status);
|
||||
|
||||
initialDelayId = window.setTimeout(() => {
|
||||
if (loginCompleted) return;
|
||||
|
||||
@@ -1324,6 +1324,39 @@
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.registration-finish-card {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.registration-finish-title {
|
||||
margin: 0;
|
||||
font-size: clamp(1.7rem, 6vw, 2.15rem);
|
||||
line-height: 1.18;
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
.registration-finish-text,
|
||||
.registration-finish-tx,
|
||||
.registration-finish-progress {
|
||||
max-width: 100%;
|
||||
overflow-wrap: anywhere;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.registration-finish-tx-link {
|
||||
color: #9fd8ff;
|
||||
text-decoration: underline;
|
||||
overflow-wrap: anywhere;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.registration-finish-tx-link:hover,
|
||||
.registration-finish-tx-link:focus-visible {
|
||||
color: #c9ebff;
|
||||
}
|
||||
|
||||
.session-status {
|
||||
color: var(--text-muted);
|
||||
font-size: 13px;
|
||||
|
||||
Reference in New Issue
Block a user