From ddcaaebe570c7cc4e3dc19ed0eeec95e9fd3a8b4 Mon Sep 17 00:00:00 2001 From: scotttong Date: Fri, 7 Aug 2026 17:09:00 -0700 Subject: [PATCH] fix(ui): flush pending composer drafts on teardown --- .../task-chat/TaskChatComposer.test.tsx | 15 +++++++++++++++ ui/src/components/task-chat/TaskChatComposer.tsx | 3 ++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/ui/src/components/task-chat/TaskChatComposer.test.tsx b/ui/src/components/task-chat/TaskChatComposer.test.tsx index d2123595419..84780d4bc97 100644 --- a/ui/src/components/task-chat/TaskChatComposer.test.tsx +++ b/ui/src/components/task-chat/TaskChatComposer.test.tsx @@ -563,6 +563,21 @@ describe("TaskChatComposer", () => { } }); + it("flushes a pending draft when the composer unmounts", () => { + vi.useFakeTimers(); + try { + render(); + + typeText("save before leaving"); + flushSync(() => root?.unmount()); + root = null; + + expect(localStorage.getItem(KEY)).toBe("save before leaving"); + } finally { + vi.useRealTimers(); + } + }); + it("clears the draft key on a successful send (not via the empty-body debounce)", async () => { localStorage.setItem(KEY, "queued message"); const onAdd = vi.fn().mockResolvedValue(undefined); diff --git a/ui/src/components/task-chat/TaskChatComposer.tsx b/ui/src/components/task-chat/TaskChatComposer.tsx index 0b3c52b70de..1bd94209881 100644 --- a/ui/src/components/task-chat/TaskChatComposer.tsx +++ b/ui/src/components/task-chat/TaskChatComposer.tsx @@ -188,8 +188,9 @@ export function TaskChatComposer({ useEffect(() => { return () => { if (draftTimer.current) clearTimeout(draftTimer.current); + if (draftKey) saveDraft(draftKey, bodyRef.current); }; - }, []); + }, [draftKey]); const modeMeta = workModeMetaFor(pendingMode); const canAcceptFiles = Boolean(onAttachImage || onImageUpload);