fix(nav): harden draft indicator after review
Address findings from 2 review agents on the room-nav draft indicator: - Icon semantics (a11y): Icons.Message read as message activity and collided with two existing bubble uses in the same row (call-chat toggle, mark-unread), especially next to the unread badge. Replace it with the composer's shared DraftDot (a small color.Success.Main dot), so both draft surfaces share one visual language. Rendered as a role="img" span with aria-label "Unsent draft" (reliably announced, unlike a bare aria-labelled svg). - Precise thread-key filter: hydration skipped any draftKey containing '::', which would also skip an IPv6-literal server name in a roomId. Match '::$' (thread root is an event id) so only real thread drafts are skipped. - Defensive hasMsgDraft: guard toPlainText so a corrupted/foreign draft value can't throw during a nav render. - Clear the draft atom on send: the send / scheduled-send handlers reset the editor and localStorage but left the jotai draft atom set, so the composer DraftIndicator could show a stale dot after sending a restored draft. Add setMsgDraft([]) to both. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -686,7 +686,7 @@ Context menu → **Forward** allows forwarding a message to any room the user is
|
||||
- Composer drafts are stored in `localStorage` keyed by `roomId`
|
||||
- Draft is cleared on successful send
|
||||
- The Jotai atom is the primary source of truth; `localStorage` is only read on room mount
|
||||
- **Room-nav draft indicator**: a subtle chat-bubble icon (`Icons.Message`) appears on a room's nav item when it has an unsent message draft (and isn't the open room), so you can see at a glance where you left half-written messages. It reacts to the shared draft atom via a memoized `selectAtom(…, hasMsgDraft)` (re-renders only when the flag flips; the atom is written on room-leave, not per keystroke). `useHydrateMsgDrafts` (mounted in `ClientNonUIFeatures`) pre-fills the draft atoms from `draft-msg-*` localStorage on startup so indicators are correct after a reload. Emptiness check shared via the pure, unit-tested `hasMsgDraft` (`src/app/utils/draft.ts`), also used by the composer's `DraftIndicator`.
|
||||
- **Room-nav draft indicator**: a subtle green dot (the composer's shared `DraftDot`, `color.Success.Main`) appears on a room's nav item when it has an unsent message draft (and isn't the open room), so you can see at a glance where you left half-written messages. The dot reuses the composer draft affordance's vocabulary (`role="img"`, aria-label "Unsent draft"). It reacts to the shared draft atom via a memoized `selectAtom(…, hasMsgDraft)` (re-renders only when the flag flips; the atom is written on room-leave, not per keystroke). `useHydrateMsgDrafts` (mounted in `ClientNonUIFeatures`) pre-fills the draft atoms from `draft-msg-*` localStorage on startup so indicators are correct after a reload. Emptiness check shared via the pure, unit-tested `hasMsgDraft` (`src/app/utils/draft.ts`), also used by the composer's `DraftIndicator`.
|
||||
|
||||
### Message Search Date Range
|
||||
|
||||
|
||||
Reference in New Issue
Block a user