Обновить UI сети и профиль

This commit is contained in:
AidarKC
2026-09-01 18:45:32 +04:00
parent 3dec5e3225
commit 52a9f1ac1d
12 changed files with 208 additions and 326 deletions
+20 -64
View File
@@ -11,9 +11,9 @@ import { renderUserAvatar } from '../components/avatar-image.js';
import { createOverflowDots } from '../components/overflow-dots.js';
import { createDropdownMenu } from '../components/dropdown-menu.js';
import { createShineConnectionsLogo } from '../components/shine-logo.js';
import { loadProfileSnapshot } from '../services/user-profile-params.js';
import { parseDmTechBlocks } from '../services/dm-tech-blocks.js';
import { formatRelativeTime } from '../services/channels-ux.js';
import { userDisplayName } from '../services/user-display.js';
export const pageMeta = { id: 'messages-list', title: 'Личные сообщения' };
const PREVIEW_MAX_LEN = 200;
@@ -24,69 +24,9 @@ const SVG_CHEVRON = `
`;
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;
const key = cleanLogin.toLowerCase();
if (dmAvatarSnapshotCache.has(key)) return dmAvatarSnapshotCache.get(key);
if (dmAvatarPendingByLogin.has(key)) return dmAvatarPendingByLogin.get(key);
const pending = loadProfileSnapshot(cleanLogin)
.then((snapshot) => {
dmAvatarSnapshotCache.set(key, snapshot || null);
dmAvatarPendingByLogin.delete(key);
return snapshot || null;
})
.catch(() => {
dmAvatarSnapshotCache.set(key, null);
dmAvatarPendingByLogin.delete(key);
return null;
});
dmAvatarPendingByLogin.set(key, pending);
return pending;
}
function createDmAvatar(login, { className = '' } = {}) {
const cleanLogin = String(login || '').trim();
const title = cleanLogin ? `Профиль ${cleanLogin}` : '';
const avatarEl = renderUserAvatar({
login: cleanLogin || 'unknown',
size: 'lg',
title,
className,
});
if (!cleanLogin) return avatarEl;
void loadDmAvatarSnapshot(cleanLogin).then((snapshot) => {
if (!avatarEl.isConnected) return;
const upgraded = renderUserAvatar({
login: cleanLogin,
avatar: snapshot?.avatar?.txId
? {
ar: String(snapshot.avatar.txId || '').trim(),
sha256Hex: String(snapshot?.avatar?.sha256Hex || '').trim().toLowerCase(),
}
: null,
size: 'lg',
title,
className,
});
upgraded.classList.add('avatar');
avatarEl.replaceWith(upgraded);
});
return avatarEl;
}
function normalizeRelationFlag(value) {
const clean = String(value || '').trim().toLowerCase();
if (clean === 'close_friend' || clean === 'contact') return clean;
if (clean === 'close_friend' || clean === 'friend' || clean === 'contact') return clean;
return 'none';
}
@@ -98,6 +38,8 @@ function relationLabel(flag) {
switch (normalizeRelationFlag(flag)) {
case 'close_friend':
return 'близкий друг';
case 'friend':
return 'друг';
case 'contact':
return 'контакт';
default:
@@ -225,6 +167,7 @@ export function render({ navigate, chrome }) {
const filterLabels = {
all: 'Чаты',
close_friend: 'Близкие друзья',
friend: 'Друзья',
contact: 'Контакты',
none: 'Новые',
};
@@ -237,6 +180,7 @@ export function render({ navigate, chrome }) {
items: [
{ label: 'Все чаты', action: () => { currentChatFilter = 'all'; filterTitle.textContent = filterLabels.all; reloadForFilter(); } },
{ label: 'Близкие друзья', action: () => { currentChatFilter = 'close_friend'; filterTitle.textContent = filterLabels.close_friend; reloadForFilter(); } },
{ label: 'Друзья', action: () => { currentChatFilter = 'friend'; filterTitle.textContent = filterLabels.friend; reloadForFilter(); } },
{ label: 'Контакты', action: () => { currentChatFilter = 'contact'; filterTitle.textContent = filterLabels.contact; reloadForFilter(); } },
{ label: 'Новые', action: () => { currentChatFilter = 'none'; filterTitle.textContent = filterLabels.none; reloadForFilter(); } },
],
@@ -338,7 +282,14 @@ function renderRow(item) {
const relationBadge = relationFlag === 'none'
? 'не в контактах'
: relationLabel(relationFlag);
const avatarEl = createDmAvatar(item.peerLogin);
const avatarEl = renderUserAvatar({
login: item.peerLogin,
firstName: item.firstName,
lastName: item.lastName,
avatar: item.avatarAr ? { ar: String(item.avatarAr).trim() } : null,
size: 'lg',
title: `Профиль ${item.peerLogin}`,
});
avatarEl.classList.add('avatar');
const avatarWrap = document.createElement('div');
avatarWrap.className = 'dm-av dm-av--default';
@@ -362,7 +313,7 @@ function renderRow(item) {
const titleEl = row.querySelector('.dm-row-title');
const previewEl = row.querySelector('.dm-row-last-message');
const timeEl = row.querySelector('.dm-row-time');
if (titleEl) titleEl.textContent = String(item.peerLogin || '');
if (titleEl) titleEl.textContent = userDisplayName(item);
if (previewEl) previewEl.textContent = 'Загрузка…';
if (timeEl) timeEl.textContent = formatChatRowTime(item.lastMessageTimeMs);
row.prepend(avatarWrap);
@@ -399,6 +350,11 @@ function renderRow(item) {
const next = {
id: peerLogin,
peerLogin,
firstName: String(dialog?.firstName || '').trim(),
lastName: String(dialog?.lastName || '').trim(),
avatarAr: String(dialog?.avatarAr || '').trim(),
accountRole: String(dialog?.accountRole || '').trim(),
shineStatus: String(dialog?.shineStatus || '').trim(),
relationFlag,
lastMessageBlobB64: String(dialog?.lastMessageBlobB64 || ''),
lastMessageTimeMs: Number(dialog?.lastMessageTimeMs || 0),