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
This commit is contained in:
@@ -28,6 +28,7 @@ export default function ChatsScreen() {
|
||||
const insets = useSafeAreaInsets();
|
||||
const contacts = useStore(s => s.contacts);
|
||||
const messages = useStore(s => s.messages);
|
||||
const keyFile = useStore(s => s.keyFile);
|
||||
|
||||
// Статус подключения: online / connecting / offline.
|
||||
// Название шапки и цвет pip'а на аватаре зависят от него.
|
||||
@@ -48,9 +49,14 @@ export default function ChatsScreen() {
|
||||
return msgs && msgs.length ? msgs[msgs.length - 1] : null;
|
||||
};
|
||||
|
||||
// Сортировка по последней активности.
|
||||
// Сортировка по последней активности. Saved Messages (self-chat) всегда
|
||||
// закреплён сверху — это "Избранное", бессмысленно конкурировать с ним
|
||||
// по recency'и обычным чатам.
|
||||
const selfAddr = keyFile?.pub_key;
|
||||
const sorted = useMemo(() => {
|
||||
return [...contacts]
|
||||
const saved = selfAddr ? contacts.find(c => c.address === selfAddr) : undefined;
|
||||
const rest = contacts
|
||||
.filter(c => c.address !== selfAddr)
|
||||
.map(c => ({ c, last: lastOf(c) }))
|
||||
.sort((a, b) => {
|
||||
const ka = a.last ? a.last.timestamp : a.c.addedAt / 1000;
|
||||
@@ -58,7 +64,8 @@ export default function ChatsScreen() {
|
||||
return kb - ka;
|
||||
})
|
||||
.map(x => x.c);
|
||||
}, [contacts, messages]);
|
||||
return saved ? [saved, ...rest] : rest;
|
||||
}, [contacts, messages, selfAddr]);
|
||||
|
||||
return (
|
||||
<View style={{ flex: 1, backgroundColor: '#000000', paddingTop: insets.top }}>
|
||||
@@ -72,6 +79,7 @@ export default function ChatsScreen() {
|
||||
<ChatTile
|
||||
contact={item}
|
||||
lastMessage={lastOf(item)}
|
||||
saved={item.address === selfAddr}
|
||||
onPress={() => router.push(`/(app)/chats/${item.address}` as never)}
|
||||
/>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user