// Экран «Личные сообщения» — единый слой «семантика отношения → визуальное состояние». // messages-list.js только рендерит готовый результат; здесь вся логика выбора тона/статуса/бейджа. // Источник полей — мок directMessages (оффлайн-демо). На проде сюда же подставятся реальные // relationFlagsForTarget / shineConfirmed / shine — UI карточек переписывать не придётся. // Тон обода аватара. ВАЖНО: «Подтверждён» НЕ красит обод золотым (золото = семья/близкий круг). // isShining → 'shining' (небесный) ; relationType==='family' → 'family' (золотой) ; иначе 'default' (violet). // toneOverride — только для тестового мока (в проде не задавать). export function resolveAvatarTone(msg) { const o = String(msg?.toneOverride || '').trim(); if (o === 'default' || o === 'family' || o === 'shining') return o; if (msg?.isShining) return 'shining'; if (msg?.relationType === 'family') return 'family'; return 'default'; } // Непрочитанные: показываем только при >0; 1–99, далее «99+». Отдельная violet-сфера (НЕ изумруд). export function resolveUnreadStyle(msg) { const n = Math.max(0, Math.trunc(Number(msg?.unreadCount ?? msg?.unread ?? 0)) || 0); if (n <= 0) return null; return { count: n, label: n > 99 ? '99+' : String(n) }; } // Итоговое визуальное состояние карточки. export function resolveDmVisualState(msg) { const via = Array.isArray(msg?.connectedVia) && msg.connectedVia.length ? msg.connectedVia : null; return { tone: resolveAvatarTone(msg), // 'default' | 'family' | 'shining' shining: Boolean(msg?.isShining), confirmed: Boolean(msg?.isConfirmed), // галочка ✓ у имени (без слова «Подтверждён») via, // путь «через кого»: [{name, photo}, …] | null unread: resolveUnreadStyle(msg), // { count, label } | null }; }