/** * Avatar — круглая заглушка с инициалом, опционально online-пип. * Нет зависимостей от асинхронных источников (картинок) — для messenger-тайла * важнее мгновенный рендер, чем фотография. Если в будущем будут фото, * расширяем здесь. */ import React from 'react'; import { View, Text } from 'react-native'; import { Ionicons } from '@expo/vector-icons'; export interface AvatarProps { /** Имя / @username — берём первый символ для placeholder. */ name?: string; /** Адрес (hex pubkey) — fallback для тех у кого нет имени. */ address?: string; /** Общий размер в px. По умолчанию 48 (tile size). */ size?: number; /** Цвет пипа справа-снизу. undefined = без пипа. */ dotColor?: string; /** Класс для обёртки (position: relative кадр). */ className?: string; /** * Saved Messages variant — blue circle with a bookmark glyph, Telegram-style. * When set, `name`/`address` are ignored for the visual. */ saved?: boolean; } /** Простое хэширование имени → один из 6 оттенков серого для разнообразия. */ function pickBg(seed: string): string { const shades = ['#1a1a1a', '#222222', '#2a2a2a', '#151515', '#1c1c1c', '#1f1f1f']; let h = 0; for (let i = 0; i < seed.length; i++) h = (h * 31 + seed.charCodeAt(i)) & 0xffff; return shades[h % shades.length]; } export function Avatar({ name, address, size = 48, dotColor, className, saved }: AvatarProps) { const seed = (name ?? address ?? '?').replace(/^@/, ''); const initial = seed.charAt(0).toUpperCase() || '?'; const bg = saved ? '#1d9bf0' : pickBg(seed); return ( {saved ? ( ) : ( {initial} )} {dotColor && ( )} ); }