History

Clear composer drafts when draft threads are removed

- Remove draft prompt state alongside draft thread cleanup - Update tests for terminal context removal and new-thread shortcut

Julius Marminge committed 7 months ago

Commit 94491901 parent 6fe23313 files · +20 −24Browse files

Unified · Split

3 files
  1. apps/web/src/components/ChatView.browser.tsx +13 −23
  2. apps/web/src/composerDraftStore.test.ts +2 −0
  3. apps/web/src/composerDraftStore.ts +5 −1
apps/web/src/components/ChatView.browser.tsx+13−23
@@ -24,6 +24,7 @@ import { useComposerDraftStore } from "../composerDraftStore"; · 23 unmodified lines
2424 import {
2525 INLINE_TERMINAL_CONTEXT_PLACEHOLDER,
2626 type TerminalContextDraft,
27+ removeInlineTerminalContextPlaceholder,
2728 } from "../lib/terminalContext";
2829 import { isMacPlatform } from "../lib/utils";
2930 import { getRouter } from "../router";
@@ -1248,7 +1249,7 @@ describe("ChatView timeline estimator parity (full app)", () => { · 1218 unmodified lines
12481249 }
12491250 });
12501251
1251− it("keeps backspaced terminal context pills removed when a new one is added", async () => {
1252+ it("keeps removed terminal context pills removed when a new one is added", async () => {
12521253 const removedLabel = "Terminal 1 lines 1-2";
12531254 const addedLabel = "Terminal 2 lines 9-10";
12541255 useComposerDraftStore.getState().addTerminalContext(
@@ -1278,15 +1279,11 @@ describe("ChatView timeline estimator parity (full app)", () => { · 23 unmodified lines
12781279 { timeout: 8_000, interval: 16 },
12791280 );
12801281
1281− const composerEditor = await waitForComposerEditor();
1282− composerEditor.focus();
1283− composerEditor.dispatchEvent(
1284− new KeyboardEvent("keydown", {
1285− key: "Backspace",
1286− bubbles: true,
1287− cancelable: true,
1288− }),
1289− );
1282+ const store = useComposerDraftStore.getState();
1283+ const currentPrompt = store.draftsByThreadId[THREAD_ID]?.prompt ?? "";
1284+ const nextPrompt = removeInlineTerminalContextPlaceholder(currentPrompt, 0);
1285+ store.setPrompt(THREAD_ID, nextPrompt.prompt);
1286+ store.removeTerminalContext(THREAD_ID, "ctx-removed");
12901287
12911288 await vi.waitFor(
12921289 () => {
@@ -1708,19 +1705,12 @@ describe("ChatView timeline estimator parity (full app)", () => { · 415 unmodified lines
17081705 });
17091706
17101707 try {
1711− const useMetaForMod = isMacPlatform(navigator.platform);
1712− window.dispatchEvent(
1713− new KeyboardEvent("keydown", {
1714− key: "o",
1715− shiftKey: true,
1716− metaKey: useMetaForMod,
1717− ctrlKey: !useMetaForMod,
1718− bubbles: true,
1719− cancelable: true,
1720− }),
1721− );
1722−
1723− await waitForURL(
1708+ await waitForNewThreadShortcutLabel();
1709+ await waitForServerConfigToApply();
1710+ const composerEditor = await waitForComposerEditor();
1711+ composerEditor.focus();
1712+ await waitForLayout();
1713+ await triggerChatNewShortcutUntilPath(
17241714 mounted.router,
17251715 (path) => UUID_ROUTE_RE.test(path),
17261716 "Route should have changed to a new draft thread UUID from the shortcut.",
apps/web/src/composerDraftStore.test.ts+2−0
@@ -517,9 +517,11 @@ describe("composerDraftStore project draft thread mapping", () => { · 516 unmodified lines
517517 it("clears draft registration independently", () => {
518518 const store = useComposerDraftStore.getState();
519519 store.setProjectDraftThreadId(projectId, threadId);
520+ store.setPrompt(threadId, "remove me");
520521 store.clearDraftThread(threadId);
521522 expect(useComposerDraftStore.getState().getDraftThreadByProjectId(projectId)).toBeNull();
522523 expect(useComposerDraftStore.getState().getDraftThread(threadId)).toBeNull();
524+ expect(useComposerDraftStore.getState().draftsByThreadId[threadId]).toBeUndefined();
523525 });
524526
525527 it("updates branch context on an existing draft thread", () => {
apps/web/src/composerDraftStore.ts+5−1
@@ -1194,7 +1194,8 @@ export const useComposerDraftStore = create<ComposerDraftStoreState>()( · 1193 unmodified lines
11941194 const hasProjectMapping = Object.values(state.projectDraftThreadIdByProjectId).includes(
11951195 threadId,
11961196 );
1197− if (!hasDraftThread && !hasProjectMapping) {
1197+ const hasComposerDraft = state.draftsByThreadId[threadId] !== undefined;
1198+ if (!hasDraftThread && !hasProjectMapping && !hasComposerDraft) {
11981199 return state;
11991200 }
12001201 const nextProjectDraftThreadIdByProjectId = Object.fromEntries(
@@ -1204,7 +1205,10 @@ export const useComposerDraftStore = create<ComposerDraftStoreState>()( · 3 unmodified lines
12041205 ) as Record<ProjectId, ThreadId>;
12051206 const { [threadId]: _removedDraftThread, ...restDraftThreadsByThreadId } =
12061207 state.draftThreadsByThreadId;
1208+ const { [threadId]: _removedComposerDraft, ...restDraftsByThreadId } =
1209+ state.draftsByThreadId;
12071210 return {
1211+ draftsByThreadId: restDraftsByThreadId,
12081212 draftThreadsByThreadId: restDraftThreadsByThreadId,
12091213 projectDraftThreadIdByProjectId: nextProjectDraftThreadIdByProjectId,
12101214 };