diff --git a/apps/web/src/composerDraftStore.test.ts b/apps/web/src/composerDraftStore.test.ts index e1d9d462a661..068bb1ff41f0 100644 --- a/apps/web/src/composerDraftStore.test.ts +++ b/apps/web/src/composerDraftStore.test.ts @@ -1458,17 +1458,18 @@ describe("composerDraftStore project draft thread mapping", () => { expect(draftFor(threadId, TEST_ENVIRONMENT_ID)?.prompt).toBe("keep me"); }); - it("finalizes a promoted draft after the canonical thread route is active", () => { + it("moves composer edits made during promotion to the canonical thread", () => { const store = useComposerDraftStore.getState(); store.setProjectDraftThreadId(projectRef, draftId, { threadId }); - store.setPrompt(draftId, "promote me"); markPromotedDraftThread(threadId); + store.setPrompt(draftId, "typed during setup"); finalizePromotedDraftThreadByRef(scopeThreadRef(TEST_ENVIRONMENT_ID, threadId)); expect(useComposerDraftStore.getState().getDraftThreadByProjectRef(projectRef)).toBeNull(); expect(useComposerDraftStore.getState().getDraftThread(draftId)).toBeNull(); expect(draftByKey(draftId)).toBeUndefined(); + expect(draftFor(threadId, TEST_ENVIRONMENT_ID)?.prompt).toBe("typed during setup"); }); it("finalizes a matching materialized draft even when promotion was not pre-marked", () => { @@ -1481,6 +1482,7 @@ describe("composerDraftStore project draft thread mapping", () => { expect(useComposerDraftStore.getState().getDraftThreadByProjectRef(projectRef)).toBeNull(); expect(useComposerDraftStore.getState().getDraftThread(draftId)).toBeNull(); expect(draftByKey(draftId)).toBeUndefined(); + expect(draftFor(threadId, TEST_ENVIRONMENT_ID)?.prompt).toBe("promote me"); }); it("updates branch context on an existing draft thread", () => { diff --git a/apps/web/src/composerDraftStore.ts b/apps/web/src/composerDraftStore.ts index 6ef8c6518858..0032ababbae4 100644 --- a/apps/web/src/composerDraftStore.ts +++ b/apps/web/src/composerDraftStore.ts @@ -1583,6 +1583,7 @@ function removeDraftThreadReferences( | "logicalProjectDraftThreadKeyByLogicalProjectKey" >, threadKey: string, + composerDestination?: ScopedThreadRef, ): Pick< ComposerDraftStoreState, | "draftThreadsByThreadKey" @@ -1597,7 +1598,11 @@ function removeDraftThreadReferences( const { [threadKey]: _removedDraftThread, ...restDraftThreadsByThreadKey } = state.draftThreadsByThreadKey; const { [threadKey]: removedComposerDraft, ...restDraftsByThreadKey } = state.draftsByThreadKey; - revokeDraftThreadPreviewUrls(removedComposerDraft); + if (composerDestination && removedComposerDraft) { + restDraftsByThreadKey[composerTargetKey(composerDestination)] = removedComposerDraft; + } else { + revokeDraftThreadPreviewUrls(removedComposerDraft); + } return { draftsByThreadKey: restDraftsByThreadKey, draftThreadsByThreadKey: restDraftThreadsByThreadKey, @@ -2785,10 +2790,10 @@ const composerDraftStore = create()( } set((state) => { const existing = state.draftThreadsByThreadKey[threadKey]; - if (!isDraftThreadPromoting(existing)) { + if (!existing || !isDraftThreadPromoting(existing)) { return state; } - return removeDraftThreadReferences(state, threadKey); + return removeDraftThreadReferences(state, threadKey, existing.promotedTo ?? undefined); }); }, clearDraftThread: (threadRef) => {