SHA256
ЛС: редизайн списка (фото-аватары, галочка/значок связи у имени, попап-цепочка→профиль) + demo-чат и lab-маршрут
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
// Demo-состояние ЛС для оффлайн-флоу /messages-list/lab (только demo, на проде НЕ используется).
|
||||
// Хранится в localStorage, поэтому переживает навигацию список ↔ чат и перезагрузку.
|
||||
// Источник стартовых тредов — мок directMessages: последнее сообщение = preview карточки.
|
||||
import { directMessages } from '../../mock-data.js';
|
||||
|
||||
const KEY = 'dm-lab-demo-v1';
|
||||
|
||||
function nowLabel() {
|
||||
try {
|
||||
const d = new Date();
|
||||
return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
// Стартовый набор тредов: пара входящих, последнее = preview карточки (чтобы список совпал с моком).
|
||||
function seed() {
|
||||
const store = {};
|
||||
(Array.isArray(directMessages) ? directMessages : []).forEach((m) => {
|
||||
const last = m.preview || m.lastMessage || 'Сообщение';
|
||||
store[m.id] = {
|
||||
unread: Math.max(0, Math.trunc(Number(m.unreadCount) || 0)),
|
||||
messages: [
|
||||
{ from: 'in', text: 'Привет! Это тестовый диалог demo-режима.', time: m.time || '' },
|
||||
{ from: 'in', text: last, time: m.time || '' },
|
||||
],
|
||||
};
|
||||
});
|
||||
return store;
|
||||
}
|
||||
|
||||
function readAll() {
|
||||
try {
|
||||
const raw = localStorage.getItem(KEY);
|
||||
if (raw) {
|
||||
const parsed = JSON.parse(raw);
|
||||
if (parsed && typeof parsed === 'object') return parsed;
|
||||
}
|
||||
} catch {}
|
||||
const fresh = seed();
|
||||
writeAll(fresh);
|
||||
return fresh;
|
||||
}
|
||||
|
||||
function writeAll(store) {
|
||||
try { localStorage.setItem(KEY, JSON.stringify(store)); } catch {}
|
||||
}
|
||||
|
||||
export function getThread(id) {
|
||||
const all = readAll();
|
||||
const t = all[id];
|
||||
return t && Array.isArray(t.messages) ? t.messages : [];
|
||||
}
|
||||
|
||||
export function getUnread(id) {
|
||||
const all = readAll();
|
||||
return all[id] ? Math.max(0, Math.trunc(Number(all[id].unread) || 0)) : 0;
|
||||
}
|
||||
|
||||
// Превью для списка = текст последнего сообщения треда (или fallback из мока).
|
||||
export function getPreview(id, fallback = '') {
|
||||
const msgs = getThread(id);
|
||||
const last = msgs[msgs.length - 1];
|
||||
return last && last.text ? last.text : fallback;
|
||||
}
|
||||
|
||||
// Добавить исходящее сообщение; вернуть его (или null, если текст пуст).
|
||||
export function appendOut(id, text) {
|
||||
const clean = String(text || '').trim();
|
||||
if (!id || !clean) return null;
|
||||
const all = readAll();
|
||||
if (!all[id]) all[id] = { unread: 0, messages: [] };
|
||||
const msg = { from: 'out', text: clean, time: nowLabel() };
|
||||
all[id].messages.push(msg);
|
||||
writeAll(all);
|
||||
return msg;
|
||||
}
|
||||
|
||||
// Открытие диалога сбрасывает непрочитанные у него.
|
||||
export function markRead(id) {
|
||||
const all = readAll();
|
||||
if (all[id]) { all[id].unread = 0; writeAll(all); }
|
||||
}
|
||||
|
||||
// На случай отладки: сбросить demo-состояние к стартовому.
|
||||
export function resetDemo() {
|
||||
writeAll(seed());
|
||||
}
|
||||
Reference in New Issue
Block a user