Merge UI redesign v4 в смену ключей

Стартовый экран взят из origin/ui-redesign-v4. Конфликты разрешены с сохранением новой логики blockchain key.
This commit is contained in:
AidarKC
2026-10-01 12:52:32 +03:00
84 changed files with 2506 additions and 1567 deletions
+5 -5
View File
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Регистрация сервера — SHiNE Server Admin</title>
<title>Регистрация сервера – SHiNE Server Admin</title>
<link rel="stylesheet" href="styles.css" />
<style>
.pwd-wrap { display: flex; }
@@ -79,7 +79,7 @@
<input type="password" id="password" name="server-ui-password-create" placeholder="Пароль аккаунта сервера" autocomplete="new-password" autocapitalize="off" spellcheck="false" />
<button class="btn-eye" id="btnEye" type="button">Показать</button>
</div>
<div class="hint">Нажмите «Сгенерировать» — поля ниже заполнятся из логина + пароля (Argon2id).<br/>Или введите ключи вручную.</div>
<div class="hint">Нажмите «Сгенерировать» – поля ниже заполнятся из логина + пароля (Argon2id).<br/>Или введите ключи вручную.</div>
</div>
<div class="btn-row">
@@ -95,17 +95,17 @@
<div class="sec-lbl">Ключевые пары (base58)</div>
<div class="kp-block">
<div class="kp-title">Root Key — холодное восстановление / полный контроль PDA</div>
<div class="kp-title">Root Key – холодное восстановление / полный контроль PDA</div>
<div class="kp-row"><span class="kp-lbl">Публичный</span><input class="kp-inp" type="text" id="rootPub" placeholder="base58, ~44 символа" /></div>
<div class="kp-row"><span class="kp-lbl">Приватный</span><input class="kp-inp" type="text" id="rootPriv" placeholder="seed base58, ~44 символа" /></div>
</div>
<div class="kp-block">
<div class="kp-title">Blockchain Key — активный ключ блокчейна и обычный authority PDA</div>
<div class="kp-title">Blockchain Key – активный ключ блокчейна и обычный authority PDA</div>
<div class="kp-row"><span class="kp-lbl">Публичный</span><input class="kp-inp" type="text" id="bchPub" placeholder="base58, ~44 символа" /></div>
<div class="kp-row"><span class="kp-lbl">Приватный</span><input class="kp-inp" type="text" id="bchPriv" placeholder="seed base58, ~44 символа" /></div>
</div>
<div class="kp-block">
<div class="kp-title">Device Key — оплата транзакции Solana</div>
<div class="kp-title">Device Key – оплата транзакции Solana</div>
<div class="kp-row"><span class="kp-lbl">Публичный</span><input class="kp-inp" type="text" id="devPub" placeholder="base58, ~44 символа (= Solana-адрес)" /></div>
<div class="kp-row"><span class="kp-lbl">Приватный</span><input class="kp-inp" type="text" id="devPriv" placeholder="seed base58, ~44 символа" /></div>
<div class="sol-box" id="solBox">
+4 -4
View File
@@ -69,7 +69,7 @@ function renderBlock(title, subtitle, items) {
return card;
}
function renderArrayLine(values, emptyLabel = '—') {
function renderArrayLine(values, emptyLabel = '–') {
const arr = Array.isArray(values) ? values : [];
return arr.length ? arr.join(', ') : emptyLabel;
}
@@ -93,7 +93,7 @@ function renderSessionList(sessions) {
`Session #${idx + 1}`,
`type=${session.sessionType}, version=${session.sessionVersion}`,
[
{ label: 'Имя', value: session.sessionName || '—' },
{ label: 'Имя', value: session.sessionName || '–' },
{ label: 'PubKey', value: base58(session.sessionPubKey32) },
],
));
@@ -153,7 +153,7 @@ function renderParsed(parsed) {
);
blocks.appendChild(renderBlock('BlockchainRegistryBlock', 'block_type=3, version=0', [
{ label: 'forkCount', value: String(parsed.forks?.length || 0) },
{ label: 'forks', value: forkLines.length ? forkLines.join('\n') : '—' },
{ label: 'forks', value: forkLines.length ? forkLines.join('\n') : '–' },
]));
if (parsed.isServer) {
@@ -162,7 +162,7 @@ function renderParsed(parsed) {
);
blocks.appendChild(renderBlock('ServerProfileBlock', 'block_type=30, version=0', [
{ label: 'addressCount', value: String(parsed.serverAddresses?.length || 0) },
{ label: 'address', value: addressLines.length ? addressLines.join('\n') : '—' },
{ label: 'address', value: addressLines.length ? addressLines.join('\n') : '–' },
]));
}
if (Array.isArray(parsed.accessServers) && parsed.accessServers.length) {
+1 -1
View File
@@ -43,7 +43,7 @@ export function formatBigInt(value) {
export function formatTimestamp(value) {
const ts = Number(BigInt(value || 0n));
if (!Number.isFinite(ts) || ts <= 0) return '—';
if (!Number.isFinite(ts) || ts <= 0) return '–';
return new Date(ts).toLocaleString('ru-RU');
}
@@ -171,7 +171,7 @@ $('btnLoad').addEventListener('click', async () => {
$('iVer').textContent = `#${parsed.recordNumber}`;
$('iCreated').textContent = formatTimestamp(parsed.createdAtMs);
$('iUpdated').textContent = formatTimestamp(parsed.updatedAtMs);
$('iSrvAddr').textContent = parsed.serverAddress || '—';
$('iSrvAddr').textContent = parsed.serverAddress || '–';
$('iBch').textContent = parsed.blockchain.blockchainName;
$('iLimit').textContent = formatBigInt(parsed.blockchain.paidLimitBytes);
+1 -1
View File
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Просмотр PDA — SHiNE Server Admin</title>
<title>Просмотр PDA – SHiNE Server Admin</title>
<link rel="stylesheet" href="styles.css" />
<style>
.field-row { display: grid; grid-template-columns: 180px 1fr; gap: 12px; padding: 6px 0; border-bottom: 1px solid var(--border); }
+6 -6
View File
@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Обновление PDA сервера — SHiNE Server Admin</title>
<title>Обновление PDA сервера – SHiNE Server Admin</title>
<link rel="stylesheet" href="styles.css" />
<style>
.pwd-wrap { display: flex; }
@@ -92,7 +92,7 @@
<div class="card">
<h2>Ключи для подписи и оплаты</h2>
<p class="muted">Root-ключ подписывает новую PDA-запись. Device-ключ оплачивает транзакцию.<br/>Blockchain-ключ не нужен — подпись LastBlockState из PDA переиспользуется автоматически.</p>
<p class="muted">Root-ключ подписывает новую PDA-запись. Device-ключ оплачивает транзакцию.<br/>Blockchain-ключ не нужен – подпись LastBlockState из PDA переиспользуется автоматически.</p>
<div class="field">
<label>Пароль</label>
@@ -100,7 +100,7 @@
<input type="password" id="password" name="server-ui-password-update" placeholder="Пароль аккаунта сервера" autocomplete="new-password" autocapitalize="off" spellcheck="false" />
<button class="btn-eye" id="btnEye" type="button">Показать</button>
</div>
<div class="hint">Нажмите «Сгенерировать» — поля ниже заполнятся из логина + пароля.<br/>Или введите ключи вручную.</div>
<div class="hint">Нажмите «Сгенерировать» – поля ниже заполнятся из логина + пароля.<br/>Или введите ключи вручную.</div>
</div>
<div class="btn-row">
<button class="btn-secondary" id="btnGen" type="button">Сгенерировать ключи</button>
@@ -115,17 +115,17 @@
<div class="sec-lbl">Ключевые пары (base58)</div>
<div class="kp-block">
<div class="kp-title">Root Key — холодное восстановление / полный контроль PDA</div>
<div class="kp-title">Root Key – холодное восстановление / полный контроль PDA</div>
<div class="kp-row"><span class="kp-lbl">Публичный</span><input class="kp-inp" type="text" id="rootPub" placeholder="base58, ~44 символа" /></div>
<div class="kp-row"><span class="kp-lbl">Приватный</span><input class="kp-inp" type="text" id="rootPriv" placeholder="seed base58, ~44 символа" /></div>
</div>
<div class="kp-block">
<div class="kp-title">Blockchain Key — справочно, при обновлении не используется</div>
<div class="kp-title">Blockchain Key – справочно, при обновлении не используется</div>
<div class="kp-row"><span class="kp-lbl">Публичный</span><input class="kp-inp" type="text" id="bchPub" placeholder="base58, ~44 символа" /></div>
<div class="kp-row"><span class="kp-lbl">Приватный</span><input class="kp-inp" type="text" id="bchPriv" placeholder="seed base58, ~44 символа" /></div>
</div>
<div class="kp-block">
<div class="kp-title">Device Key — оплата транзакции Solana</div>
<div class="kp-title">Device Key – оплата транзакции Solana</div>
<div class="kp-row"><span class="kp-lbl">Публичный</span><input class="kp-inp" type="text" id="devPub" placeholder="base58, ~44 символа (= Solana-адрес)" /></div>
<div class="kp-row"><span class="kp-lbl">Приватный</span><input class="kp-inp" type="text" id="devPriv" placeholder="seed base58, ~44 символа" /></div>
<div class="sol-box" id="solBox">