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);