diff --git a/shine-UI/js/pages/messages-list.js b/shine-UI/js/pages/messages-list.js index aaadb086..9bb8b217 100644 --- a/shine-UI/js/pages/messages-list.js +++ b/shine-UI/js/pages/messages-list.js @@ -1,21 +1,28 @@ -import { directMessages } from '../mock-data.js'; import { - getChatMessages, + authService, isSessionInvalidError, normalizeDmChatId, setContacts, state, terminateCurrentSession, } from '../state.js'; -import { loadCurrentRelations } from '../services/user-connections.js'; import { renderUserAvatar } from '../components/avatar-image.js'; import { loadProfileSnapshot } from '../services/user-profile-params.js'; import { parseDmTechBlocks } from '../services/dm-tech-blocks.js'; export const pageMeta = { id: 'messages-list', title: 'Личные сообщения' }; +const PREVIEW_MAX_LEN = 200; +const DM_BLOB_PREVIEW_CACHE = new Map(); +const DM_BLOB_PREVIEW_PENDING = new Map(); const dmAvatarSnapshotCache = new Map(); const dmAvatarPendingByLogin = new Map(); +const RELATION_ORDER = new Map([ + ['close_friend', 0], + ['contact', 1], + ['none', 2], +]); + async function loadDmAvatarSnapshot(login) { const cleanLogin = String(login || '').trim(); if (!cleanLogin) return null; @@ -65,10 +72,72 @@ function createDmAvatar(login) { return avatarEl; } -function resolveLastMessagePreview(text = '') { - const parsed = parseDmTechBlocks(String(text || '')); - const display = String(parsed.displayText || '').trim(); - return display || ''; +function normalizeRelationFlag(value) { + const clean = String(value || '').trim().toLowerCase(); + if (clean === 'close_friend' || clean === 'contact') return clean; + return 'none'; +} + +function relationOrder(flag) { + return RELATION_ORDER.get(normalizeRelationFlag(flag)) ?? 99; +} + +function relationLabel(flag) { + switch (normalizeRelationFlag(flag)) { + case 'close_friend': + return 'близкий друг'; + case 'contact': + return 'контакт'; + default: + return 'не в контактах'; + } +} + +function clipPreviewText(text, maxLen = PREVIEW_MAX_LEN) { + const normalized = String(text || '').replace(/\s+/g, ' ').trim(); + if (!normalized) return ''; + if (normalized.length <= maxLen) return normalized; + return `${normalized.slice(0, maxLen - 1)}…`; +} + +async function resolveDialogPreview(dialog) { + const blobB64 = String(dialog?.lastMessageBlobB64 || '').trim(); + if (!blobB64) return 'Диалог пока пуст.'; + + const cacheKey = [ + blobB64, + String(state.session.login || '').trim().toLowerCase(), + String(state.session.storagePwdInMemory || '').trim(), + ].join('|'); + + if (DM_BLOB_PREVIEW_CACHE.has(cacheKey)) return DM_BLOB_PREVIEW_CACHE.get(cacheKey); + if (DM_BLOB_PREVIEW_PENDING.has(cacheKey)) return DM_BLOB_PREVIEW_PENDING.get(cacheKey); + + const pending = (async () => { + try { + const parsed = authService.parseSignedMessageBlob(blobB64); + const decrypted = await authService.decryptSignedMessageContent({ + parsed, + blobB64, + login: state.session.login, + storagePwd: state.session.storagePwdInMemory, + }); + const parsedText = parseDmTechBlocks(String(decrypted?.text || '')); + const display = clipPreviewText(String(parsedText.displayText || '').trim()); + const result = display || 'Сообщение'; + DM_BLOB_PREVIEW_CACHE.set(cacheKey, result); + return result; + } catch { + const fallback = 'Сообщение недоступно'; + DM_BLOB_PREVIEW_CACHE.set(cacheKey, fallback); + return fallback; + } finally { + DM_BLOB_PREVIEW_PENDING.delete(cacheKey); + } + })(); + + DM_BLOB_PREVIEW_PENDING.set(cacheKey, pending); + return pending; } function formatChatRowTime(ts) { @@ -83,11 +152,11 @@ function formatChatRowTime(ts) { } function compareChatRows(a, b) { - const timeA = Number(a?.lastTimeMs || 0); - const timeB = Number(b?.lastTimeMs || 0); + const timeA = Number(a?.lastMessageTimeMs || 0); + const timeB = Number(b?.lastMessageTimeMs || 0); if (timeA !== timeB) return timeB - timeA; - const nameA = String(a?.name || '').toLowerCase(); - const nameB = String(b?.name || '').toLowerCase(); + const nameA = String(a?.peerLogin || '').toLowerCase(); + const nameB = String(b?.peerLogin || '').toLowerCase(); return nameA.localeCompare(nameB, 'ru'); } @@ -107,9 +176,9 @@ export function render({ navigate, chrome }) { -