Skip to content

fix(ui): keep unsent composer drafts per conversation - #34

Open
CatJuly wants to merge 1 commit into
HKUDS:mainfrom
CatJuly:fix/per-channel-composer-draft
Open

fix(ui): keep unsent composer drafts per conversation#34
CatJuly wants to merge 1 commit into
HKUDS:mainfrom
CatJuly:fix/per-channel-composer-draft

Conversation

@CatJuly

@CatJuly CatJuly commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Summary

With multiple task sessions open, typing into one session's composer and then switching to another task discards the draft — in both sessions. Whatever the user had typed is simply gone.

Repro: open two task sessions → type into session A's composer without sending → click session B in the sidebar → switch back to A. The composer is empty in both A and B.

Root cause

Two independent paths throw the text away on a session switch:

  1. ContextPanel mounts the composer with key={channelId}, so switching sessions unmounts and recreates the component — and text lives in plain useState('').
  2. MessageComposer additionally has a channelId effect that explicitly resets the text to '' on every change, so even a non-remounting switch wipes it.

Neither path saves the draft anywhere first.

Fix

Follow the convention chat products use: a draft belongs to its conversation.

  • Keep unsent drafts in a module-level Map<channelId, string> (survives the key-driven remounts).
  • Every keystroke writes through to the map.
  • Mounting or switching restores the current channel's draft instead of wiping it.
  • A successful send clears that channel's entry.

Attachments intentionally still reset on switch: their object URLs and upload state are tied to the current mount, and preserving them would leak resources.

Testing

  • npm run typecheck — clean
  • npm run build — clean; rebuilt frontend_dist bundle included
  • Manual: typed in session A → switched to B (composer empty, no cross-talk) → typed in B → switched back and forth: both drafts restored to their own sessions; sending in A cleared only A's draft; drafts survive repeated switches

Scope

Frontend only (MessageComposer.tsx + rebuilt dist). Independent of my other open PRs — no shared files.

Typing in one session's composer and switching to another task threw
the text away in both directions: parents remount the composer with
`key={channelId}` on session switches, and a channelId effect
additionally reset the text to '' on every change. Users lost whatever
they had typed the moment they glanced at another task.

Keep unsent drafts in a module-level map keyed by channel id — the
convention chat products follow, where a draft belongs to its
conversation. Every keystroke writes through to the map, mounting or
switching restores the current channel's draft instead of wiping it,
and a successful send clears the entry. Attachments intentionally
still reset on switch: their object URLs and upload state are tied to
the current mount.

Verified with `npm run typecheck` and `npm run build`; manually typed
in session A, switched to B (empty composer, no cross-talk), typed in
B, switched back and forth — both drafts restored; sending cleared the
draft for that session only.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant