Files
dchain/client-app/components/Avatar.tsx
vsecoder a75cbcd224 feat: resource caps, Saved Messages, author walls, docs for node bring-up
Node flags (cmd/node/main.go):
  --max-cpu / --max-ram-mb — Go runtime caps (GOMAXPROCS / GOMEMLIMIT)
  --feed-disk-limit-mb — hard 507 refusal for new post bodies over quota
  --chain-disk-limit-mb — advisory watcher (can't reject blocks without
  breaking consensus; logs WARN every minute)

Client — Saved Messages (self-chat):
  - Auto-created on sign-in, pinned top of chat list, blue bookmark avatar
  - Send short-circuits the relay (no encrypt, no fee, no mailbox hop)
  - Empty state rendered outside inverted FlatList — fixes the mirrored
    "say hi…" on Android RTL-aware layout builds
  - PostCard shows "You" for own posts instead of the self-contact alias

Client — user walls:
  - New route /(app)/feed/author/[pub] with infinite-scroll via
    `created_at` cursor and pull-to-refresh
  - Profile screen gains "View posts" button (universal) next to
    "Open chat" (contact-only)

Feed pipeline:
  - Bump client JPEG quality 0.5 → 0.75 to match server scrubber (Q=75),
    so a 60 KiB compose doesn't balloon past 256 KiB after server re-encode
  - ErrPostTooLarge now wraps with the actual size vs cap, errors.Is
    preserved in the HTTP layer
  - FeedMailbox quota + DiskUsage surface — supports new CLI flag

README:
  - Step-by-step "first node / joiner" section on the landing page,
    full flag tables incl. the new resource-cap group, minimal
    checklists for open/private/low-end deployments
2026-04-19 13:14:47 +03:00

87 lines
2.9 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 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 (
<View className={className} style={{ width: size, height: size, position: 'relative' }}>
<View
style={{
width: size,
height: size,
borderRadius: size / 2,
backgroundColor: bg,
alignItems: 'center',
justifyContent: 'center',
}}
>
{saved ? (
<Ionicons name="bookmark" size={size * 0.5} color="#ffffff" />
) : (
<Text
style={{
color: '#d0d0d0',
fontSize: size * 0.4,
fontWeight: '600',
includeFontPadding: false,
}}
>
{initial}
</Text>
)}
</View>
{dotColor && (
<View
style={{
position: 'absolute',
right: 0,
bottom: 0,
width: size * 0.28,
height: size * 0.28,
borderRadius: size * 0.14,
backgroundColor: dotColor,
borderWidth: 2,
borderColor: '#000',
}}
/>
)}
</View>
);
}