- zoneView: an eventId always shows the timeline; the back-to-albums button is hidden then.
- buildAlbums: null/non-object inputs and replies are skipped, non-numeric timestamps
count as 0, an empty-body root is titled "Untitled album", m.replace events are never
files or albums.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- A zone sends the read receipt the timeline would; the unread badge clears.
- Timeline stays one tap away (and back); an event deep link opens the timeline.
- Kinds come from a Map, so "constructor"/"__proto__" are not files.
- Album titles follow m.replace edits.
- Fetch: retry once, at most 6 relation reads in flight, refresh every 30 s, a failed
refetch keeps the loaded albums.
- Encrypted zone says so instead of "No albums yet".
- Audio renders without the chat Attachment frame and type badge.
- useIsFileZone follows alias changes.
- Tests kill the surviving mutants: event type, event_id, create-type prefix.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The pretend server answers /threads, m.thread relations and media downloads
(generated WAV and PNG bytes, no binaries in the repo).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
useAlbums reads one page of /threads and each root's m.thread relations; AlbumView
lists albums and their files through RenderMessageContent. RoomView shows it in
place of the timeline and composer when isFileZone holds.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>