Убрали старый sync и обновили bundle

Что сделано: вычистили неиспользуемый user-settings sync/DM sync хвост, сохранили сборку, обновили bundle.sh так, чтобы gradle-wrapper.jar всегда попадал в архив.

Проверено: compileJava и deploy на t2 (server + UI).
Не проверяли: полные интеграционные сценарии, ручные UI-флоу и продовый деплой.
This commit is contained in:
AidarKC
2026-08-28 14:51:47 +04:00
parent ef1fd9f579
commit 8a0275d962
56 changed files with 747 additions and 2428 deletions
+28 -91
View File
@@ -6,8 +6,8 @@ import { resolveShineServerByServerLogin } from '../services/shine-server-resolv
import { readShineUserPda, updateShineUserPdaOnSolana } from '../services/shine-user-pda-service.js';
import { getTopupSiteUrl } from '../services/solana-wallet-service.js';
export const pageMeta = { id: 'access-servers-view', title: 'Серверы доступа' };
const MAX_ACCESS_SERVERS = 2;
export const pageMeta = { id: 'access-servers-view', title: 'Сервер доступа' };
const MAX_ACCESS_SERVERS = 1;
function escapeHtml(value) {
return String(value || '')
@@ -281,9 +281,10 @@ export function render({ navigate }) {
introCard.innerHTML = `
<p class="field-label">Где хранятся личные данные</p>
<p class="meta-muted">
Серверы доступа хранят зашифрованную личную переписку пользователя и участвуют в звонках.
Единственный сервер доступа хранит зашифрованную личную переписку пользователя и участвует в звонках.
Всё, что публикуется в блокчейне SHiNE, доступно через любой сервер Сияния,
а доступ пользователя и приватная переписка хранятся только на этих серверах.
а настройки и приватная переписка хранятся только на выбранном сервере.
При смене сервера прежняя переписка и настройки автоматически не переносятся.
</p>
`;
@@ -291,7 +292,7 @@ export function render({ navigate }) {
listCard.className = 'card stack';
const listTitle = document.createElement('p');
listTitle.className = 'field-label';
listTitle.textContent = 'Текущий список серверов доступа';
listTitle.textContent = 'Текущий сервер доступа';
const listHint = document.createElement('p');
listHint.className = 'meta-muted';
listHint.textContent = sessionLogin
@@ -308,10 +309,10 @@ export function render({ navigate }) {
addCard.className = 'card stack';
const addTitle = document.createElement('p');
addTitle.className = 'field-label';
addTitle.textContent = 'Добавить сервер доступа';
addTitle.textContent = 'Сменить сервер доступа';
const addHint = document.createElement('p');
addHint.className = 'meta-muted';
addHint.textContent = 'Можно использовать максимум два сервера доступа. Введите логин сервера или несколько первых букв, затем выберите сервер из подсказок.';
addHint.textContent = 'Введите логин нового сервера или несколько первых букв, затем выберите сервер из подсказок. Новый сервер заменит текущий.';
const addInput = document.createElement('input');
addInput.className = 'input';
addInput.type = 'text';
@@ -326,13 +327,12 @@ export function render({ navigate }) {
const addButton = document.createElement('button');
addButton.className = 'primary-btn';
addButton.type = 'button';
addButton.textContent = 'Добавить сервер';
addButton.textContent = 'Сменить сервер';
addButton.disabled = true;
addCard.append(addTitle, addHint, addInput, suggestEl, addStatus, addButton);
const refreshAddButton = () => {
addButton.disabled = operationBusy
|| currentAccessServers.length >= MAX_ACCESS_SERVERS
|| (!selectedCandidate && !normalizeLogin(addInput.value));
};
@@ -352,9 +352,7 @@ export function render({ navigate }) {
addInput.value = candidate.login;
addStatus.textContent = `Выбран сервер @${candidate.login}${candidate.url ? ` (${candidate.url})` : ''}`;
} else {
addStatus.textContent = currentAccessServers.length >= MAX_ACCESS_SERVERS
? 'У пользователя уже выбраны два сервера доступа. Сначала отключите один из них.'
: 'Для изменения списка понадобится подпись root key.';
addStatus.textContent = 'Для смены сервера понадобится подпись root key.';
}
};
@@ -368,69 +366,15 @@ export function render({ navigate }) {
return;
}
currentAccessServers.forEach((server, index) => {
const button = document.createElement('button');
button.className = 'text-btn';
button.type = 'button';
button.disabled = operationBusy;
button.innerHTML = `
currentAccessServers.forEach((server) => {
const row = document.createElement('div');
row.innerHTML = `
<span style="display:block; text-align:left;">
<strong>@${escapeHtml(server.login)}</strong>
<span class="meta-muted" style="display:block; margin-top:0.2rem;">${escapeHtml(server.url || 'URL не указан')}</span>
</span>
`;
button.addEventListener('click', () => {
if (operationBusy) return;
const isLast = currentAccessServers.length <= 1;
const performDisable = async () => {
const nextList = currentAccessServers
.map((item) => item.login)
.filter((login) => login !== server.login);
try {
await updateAccessServers(nextList, {
statusTarget: listStatus,
successText: `Сервер доступа @${server.login} отключён.`,
inFlightText: `Обновляем PDA и отключаем сервер @${server.login}...`,
});
} catch {
// Сообщение уже показано в статусе.
}
};
const askFinal = (noteText = '') => {
confirmModal?.open({
title: isLast ? 'Последний сервер доступа' : 'Отключить сервер доступа?',
text: isLast
? 'Это последний сервер доступа пользователя. Если его отключить, личная переписка пользователя на серверах доступа будет удалена.'
: `Хотите изменить запись в блокчейне Solana и отключить сервер доступа @${server.login}?`,
note: noteText,
confirmLabel: isLast ? 'Понимаю' : 'Да',
cancelLabel: isLast ? 'Отмена' : 'Нет',
onConfirm: performDisable,
});
};
if (isLast) {
confirmModal?.open({
title: 'Отключить последний сервер?',
text: `У пользователя остался только один сервер доступа: @${server.login}.`,
note: 'После отключения последнего сервера доступа личная переписка пользователя на серверах доступа будет удалена.',
confirmLabel: 'Продолжить',
cancelLabel: 'Отмена',
onConfirm: () => askFinal('Это повторное предупреждение перед записью нового списка серверов в Solana PDA.'),
});
return;
}
askFinal();
});
listBody.append(button);
if (index < currentAccessServers.length - 1) {
const divider = document.createElement('div');
divider.style.height = '1px';
divider.style.background = 'rgba(255,255,255,0.08)';
listBody.append(divider);
}
listBody.append(row);
});
};
@@ -465,16 +409,13 @@ export function render({ navigate }) {
renderServerList();
refreshAddButton();
listStatus.textContent = rows.length
? `Найдено серверов доступа: ${rows.length}`
? 'Сервер доступа загружен из PDA.'
: 'В PDA пользователя пока нет серверов доступа.';
if (rows.length >= MAX_ACCESS_SERVERS) {
addStatus.textContent = 'У пользователя уже выбраны два сервера доступа. Сначала отключите один из них.';
}
} catch (error) {
currentAccessServers = [];
renderServerList();
refreshAddButton();
listStatus.textContent = error?.message || 'Не удалось прочитать список серверов доступа.';
listStatus.textContent = error?.message || 'Не удалось прочитать сервер доступа.';
}
};
@@ -559,7 +500,7 @@ export function render({ navigate }) {
const passwordResult = await passwordModal?.open({
title: 'Нужен пароль для обновления серверов доступа',
text: 'Чтобы изменить список серверов доступа, нужно подписать обновление user PDA через root key. Этот ключ не найден в локальном зашифрованном контейнере устройства.',
text: 'Чтобы изменить сервер доступа, нужно подписать обновление user PDA через root key. Этот ключ не найден в локальном зашифрованном контейнере устройства.',
note: savedClient
? 'client key уже сохранён на устройстве. Из пароля будет восстановлен только root key.'
: 'На устройстве не хватает root key и/или client key. Они будут восстановлены из пароля аккаунта.',
@@ -604,7 +545,7 @@ export function render({ navigate }) {
const normalizedList = uniqueLogins(nextLogins);
setOperationBusy(true);
target.textContent = String(inFlightText || 'Обновляем список серверов доступа...');
target.textContent = String(inFlightText || 'Обновляем сервер доступа...');
let signingMaterial = null;
try {
const currentPda = await readShineUserPda({ login: sessionLogin, solanaEndpoint });
@@ -626,7 +567,7 @@ export function render({ navigate }) {
if (isInsufficientFundsForRentError(error)) {
showTopupRequiredStatus(target, signingMaterial?.clientAddress);
} else {
target.textContent = error?.message || 'Не удалось обновить список серверов доступа.';
target.textContent = error?.message || 'Не удалось обновить сервер доступа.';
}
throw error;
} finally {
@@ -662,29 +603,25 @@ export function render({ navigate }) {
return;
}
if (currentAccessServers.some((item) => item.login === login)) {
addStatus.textContent = `Сервер @${login} уже есть в списке.`;
return;
}
if (currentAccessServers.length >= MAX_ACCESS_SERVERS) {
addStatus.textContent = 'Нельзя добавить больше двух серверов доступа. Сначала отключите один из текущих.';
addStatus.textContent = `Сервер @${login} уже выбран.`;
return;
}
try {
const resolved = await resolveShineServerByServerLogin({ serverLogin: login, solanaEndpoint });
confirmModal?.open({
title: 'Добавить сервер доступа?',
text: `Вы хотите добавить сервер доступа @${resolved.serverLogin}?`,
title: 'Сменить сервер доступа?',
text: `Заменить текущий сервер доступа на @${resolved.serverLogin}?`,
note: resolved.httpBase
? `Адрес сервера: ${resolved.httpBase}\nИзменение будет записано в Solana user PDA.`
: 'Изменение будет записано в Solana user PDA.',
? `Адрес сервера: ${resolved.httpBase}\nПрежняя переписка и настройки автоматически не перенесутся. Изменение будет записано в Solana user PDA.`
: 'Прежняя переписка и настройки автоматически не перенесутся. Изменение будет записано в Solana user PDA.',
onConfirm: async () => {
const nextList = uniqueLogins([...currentAccessServers.map((item) => item.login), resolved.serverLogin]);
const nextList = [resolved.serverLogin];
try {
await updateAccessServers(nextList, {
statusTarget: addStatus,
successText: `Сервер доступа @${resolved.serverLogin} добавлен.`,
inFlightText: `Обновляем PDA и добавляем сервер @${resolved.serverLogin}...`,
successText: `Сервер доступа заменён на @${resolved.serverLogin}.`,
inFlightText: `Обновляем PDA и меняем сервер на @${resolved.serverLogin}...`,
});
} catch {
// Сообщение уже показано в статусе.
@@ -698,7 +635,7 @@ export function render({ navigate }) {
screen.append(
renderHeader({
title: 'Серверы доступа',
title: 'Сервер доступа',
leftAction: { label: '←', onClick: () => navigate('settings-view') },
}),
introCard,
+1 -1
View File
@@ -44,7 +44,7 @@ export function render({ navigate }) {
<button class="text-btn" type="button" id="settings-remote-addblock">Remote AddBlock через homeserver</button>
<button class="text-btn" type="button" id="settings-access-servers">
<span style="display:block; text-align:left;">
<strong>Серверы доступа</strong>
<strong>Сервер доступа</strong>
<span class="meta-muted" style="display:block; margin-top:0.2rem;">Личная переписка, звонки и зашифрованные данные</span>
</span>
</button>
+2 -10
View File
@@ -2611,14 +2611,8 @@ export class AuthService {
async sendMessagePair({ incomingBlobB64, outgoingBlobB64 }) {
const body = { incomingBlobB64, outgoingBlobB64 };
const primaryOp = 'ReceiveOutcomingMessage';
let response = await this.ws.request(primaryOp, body);
if (response.status === 404) {
response = await this.ws.request('SendMessagePair', body);
if (response.status !== 200) throw opError('SendMessagePair', response);
return response.payload || {};
}
if (response.status !== 200) throw opError(primaryOp, response);
const response = await this.ws.request('SendMessagePair', body);
if (response.status !== 200) throw opError('SendMessagePair', response);
return response.payload || {};
}
@@ -2938,7 +2932,6 @@ export class AuthService {
valueText = '',
valueNum = 0,
storagePwd,
syncDelivery = false,
}) {
const cleanLogin = String(login || '').trim();
const cleanSettingKey = String(settingKey || '').trim();
@@ -2977,7 +2970,6 @@ export class AuthService {
value_num: Math.trunc(cleanValueNum),
client_key: clientKey,
signature,
sync_delivery: !!syncDelivery,
});
if (response.status !== 200) throw opError('UpsertUserSetting', response);
return response.payload || {};
@@ -69,7 +69,7 @@ export async function resolveShineServerForUserLogin({ login, solanaEndpoint, fa
solanaEndpoint,
});
const accessServers = Array.isArray(parsedUser?.accessServers)
? parsedUser.accessServers.map((value) => normalizeShineServerLogin(value)).filter(Boolean).slice(0, 2)
? parsedUser.accessServers.map((value) => normalizeShineServerLogin(value)).filter(Boolean).slice(0, 1)
: [];
const pickedServerLogin = accessServers[0] || normalizeShineServerLogin(fallbackServerLogin);
if (!pickedServerLogin) {
@@ -30,7 +30,7 @@ const BLOCK_TYPE_TRUSTED_STATE = 70;
const SESSIONS_MODE_MIXED = 1;
const SESSION_TYPE_USER = 1;
const SESSION_TYPE_HOMESERVER = 100;
const MAX_EFFECTIVE_ACCESS_SERVERS = 2;
const MAX_EFFECTIVE_ACCESS_SERVERS = 1;
let solanaLibPromise = null;
function loadSolanaLib() {