Исправить восстановление DM после перелогина

This commit is contained in:
AidarKC
2026-07-10 11:47:39 +04:00
parent 0730837ad7
commit bb92cb6b2b
6 changed files with 130 additions and 20 deletions
+73 -16
View File
@@ -135,6 +135,8 @@ const toolbarEl = document.getElementById('toolbar-slot');
const appShellEl = document.querySelector('.app-shell');
const CONNECTION_CHECK_INTERVAL_MS = 20 * 1000;
const SIGNED_DM_DECRYPT_CONTEXT_WAIT_MS = 2000;
const SIGNED_DM_DECRYPT_CONTEXT_POLL_MS = 50;
const UI_VERSION_PERIODIC_CHECK_MS = 5 * 60 * 1000;
const CURRENT_BUILD_HASH = String(window.__SHINE_BUILD_HASH__ || '').trim();
const UI_BUILD_HASH_PATTERN = /window\.__SHINE_BUILD_HASH__\s*=\s*'([^']+)'/;
@@ -641,6 +643,44 @@ function wsIsOpen() {
return !!(ws && ws.readyState === WebSocket.OPEN);
}
function sleep(ms) {
return new Promise((resolve) => {
window.setTimeout(resolve, ms);
});
}
async function waitForSignedDmDecryptContext(timeoutMs = SIGNED_DM_DECRYPT_CONTEXT_WAIT_MS) {
const startedAtMs = Date.now();
while ((Date.now() - startedAtMs) < timeoutMs) {
const login = String(state.session?.login || '').trim();
const storagePwd = String(state.session?.storagePwdInMemory || '').trim();
if (login && storagePwd) {
return { login, storagePwd };
}
await sleep(SIGNED_DM_DECRYPT_CONTEXT_POLL_MS);
}
return {
login: String(state.session?.login || '').trim(),
storagePwd: String(state.session?.storagePwdInMemory || '').trim(),
};
}
function resolveSignedDmChatId({ parsed, login }) {
const parsedBlock = parsed || {};
const messageType = Number(parsedBlock.messageType || 0);
const fromLogin = String(parsedBlock.fromLogin || '').trim();
const toLogin = String(parsedBlock.toLogin || '').trim();
const currentLogin = String(login || '').trim().toLowerCase();
if (messageType === 1) return normalizeDmChatId(fromLogin);
if (messageType === 2) return normalizeDmChatId(toLogin);
if (currentLogin && currentLogin === fromLogin.toLowerCase()) {
return normalizeDmChatId(toLogin);
}
return normalizeDmChatId(fromLogin);
}
async function ensureSessionAfterWsReconnect() {
if (!state.session.isAuthorized) return true;
if (wsSessionRestoreInFlight) return wsSessionRestoreInFlight;
@@ -1020,29 +1060,44 @@ async function init() {
const fromLogin = parsed.fromLogin || '';
const toLogin = parsed.toLogin || '';
const messageType = Number(parsed.messageType || 0);
const currentLogin = String(state.session?.login || '').trim().toLowerCase();
const chatPeerLogin = currentLogin && currentLogin === String(fromLogin || '').trim().toLowerCase()
? toLogin
: fromLogin;
const chatId = normalizeDmChatId(chatPeerLogin);
let shouldAckSessionDelivery = true;
let text = '';
let sessionLoginForRouting = String(state.session?.login || '').trim();
if (messageType === 1 || messageType === 2) {
const decryptContext = await waitForSignedDmDecryptContext();
if (!decryptContext.login || !decryptContext.storagePwd) {
shouldAckSessionDelivery = false;
addAppLogEntry({
level: 'warn',
source: 'signed-dm',
message: 'Отложена обработка DM: decrypt-контекст сессии ещё не готов',
details: { messageKey, baseKey: parsed.baseKey, messageType },
});
return;
}
sessionLoginForRouting = decryptContext.login;
try {
const decrypted = await authService.decryptSignedMessageContent({
parsed,
login: state.session?.login || '',
storagePwd: state.session?.storagePwdInMemory || '',
login: decryptContext.login,
storagePwd: decryptContext.storagePwd,
});
text = String(decrypted?.text || '');
} catch (error) {
shouldAckSessionDelivery = false;
addAppLogEntry({
level: 'warn',
source: 'signed-dm',
message: 'Не удалось расшифровать DM',
details: { messageKey, baseKey: parsed.baseKey, error: error?.message || 'unknown' },
});
return;
}
}
const chatId = resolveSignedDmChatId({
parsed,
login: sessionLoginForRouting,
});
let shouldRefreshToolbarUnread = false;
@@ -1125,15 +1180,17 @@ async function init() {
});
}
try {
await authService.ackSessionDelivery(messageKey);
} catch (error) {
addAppLogEntry({
level: 'warn',
source: 'signed-dm',
message: 'Не удалось отправить ACK доставки по сессии',
details: { messageKey, error: error?.message || 'unknown' },
});
if (shouldAckSessionDelivery) {
try {
await authService.ackSessionDelivery(messageKey);
} catch (error) {
addAppLogEntry({
level: 'warn',
source: 'signed-dm',
message: 'Не удалось отправить ACK доставки по сессии',
details: { messageKey, error: error?.message || 'unknown' },
});
}
}
const pageId = getRoute().pageId || '';