mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-10-06 11:48:24 +00:00
Six items, all of which the room either lacked outright or showed as a truncated label. **Quoted replies.** A reply used to carry "Replying to: <first 60 characters>", which said a reply existed without ever saying who it answered — in a group, most of what you need. `CordnQuotedMessage` names the author in their own pubkey-derived colour behind an accent bar, and is used in two places so what you are answering looks the same while you write it as it does once it is sent. **Jump to the quoted message.** Tapping that quote scrolls to what it answers and flashes it, through ChatBubbleLayout's shouldHighlight — which the bubble already supported and nothing drove. A quote whose target is older than what is loaded flashes nothing rather than scrolling somewhere arbitrary. **Who reacted.** Long-pressing a chip opens the senders per emoji. The fold keys reactions to a set of pubkeys, so the sheet is the whole truth the room holds — there is no separate receipt and no count that could disagree with the list under it. **Unread divider.** From a cursor snapshotted when the room opens: markRead() runs on open, so a divider read from the live cursor would erase itself at the moment it became useful. Own traffic is excluded, to match what unreadCount already counts — a message of yours echoing back is not news. It draws below the day separator, since in a reversed list the later-emitted row draws higher. **Faces and a member count in the top bar**, with the whole title as the way in to group info, as in every other group chat. **A confirm step before sending a file.** Attaching was irreversible the instant the picker closed: no preview, no caption, no way back from the wrong file — and a cordn attachment is encrypted, uploaded and announced to the room in one action that cannot be recalled. The dialog previews images (bounds-first subsampled decode, on IO), takes a caption that rides as the message's own content so an attachment with something written about it is one message rather than two, and holds itself open on failure so retrying is one tap rather than the picker again. Its progress bar is indeterminate on purpose: the upload is a single suspend call that encrypts and posts and reports nothing in between, so a percentage would be invented. A stage string written for a two-phase label was dropped rather than wired to a phase that isn't observable. It also fixes the filename. `uri.lastPathSegment` is a document id on a content:// URI, not a name — it is what every cordn attachment has been named. The dialog resolves the real one through OpenableColumns, off the main thread, and hands it to the upload. Left alone deliberately: zaps and the shared note-action inventory need a Note, which a cordn room may not have. Un-reacting still needs the reaction's own envelope id, which the annotation index does not keep — protocol work, not UI. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012BfD4txdnsaPRXmNXbup9n