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:
@@ -27,7 +27,10 @@ export function useHydrateMsgDrafts(): void {
|
||||
keys.forEach((key) => {
|
||||
if (!key.startsWith(DRAFT_MSG_KEY_PREFIX)) return;
|
||||
const draftKey = key.slice(DRAFT_MSG_KEY_PREFIX.length);
|
||||
if (!draftKey || draftKey.includes('::')) return; // room-level drafts only
|
||||
// Skip thread drafts (`<roomId>::<$threadRootEventId>`) — room-level only.
|
||||
// Match `::$` specifically so an IPv6-literal server name (e.g. `[::1]`)
|
||||
// in a roomId isn't mistaken for a thread key.
|
||||
if (!draftKey || draftKey.includes('::$')) return;
|
||||
try {
|
||||
const stored = localStorage.getItem(key);
|
||||
if (!stored) return;
|
||||
|
||||
Reference in New Issue
Block a user