From 9c91cf2998646cd240566d928bf702d23d54a49f Mon Sep 17 00:00:00 2001 From: Alex Southwell <4596216+saphid@users.noreply.github.com> Date: Tue, 3 Nov 2026 08:45:53 +1100 Subject: [PATCH] fix(mobile): a failed archive or delete keeps the earlier Undo Co-Authored-By: Claude Opus 5.5 --- .../src/features/home/useThreadListActions.test.ts | 13 +++++++++++++ .../src/features/home/useThreadListActions.ts | 6 +++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/apps/mobile/src/features/home/useThreadListActions.test.ts b/apps/mobile/src/features/home/useThreadListActions.test.ts index 9313aef299881..52a552ed978d8 100644 --- a/apps/mobile/src/features/home/useThreadListActions.test.ts +++ b/apps/mobile/src/features/home/useThreadListActions.test.ts @@ -539,6 +539,19 @@ describe("thread action undo", () => { expect(state.requests.map(({ action }) => action)).toEqual(["archive"]); expect(state.archivedRefreshes).toEqual([primaryEnvironmentId]); }); + + it("keeps the earlier Undo until archiving succeeds", async () => { + const actions = useThreadListActions(); + const thread = makeThread(); + await actions.settleThread(thread); + state.failedAction = "archive"; + expect(await actions.archiveThread(thread)).toBe(false); + expect(readThreadUndoNotice()?.action).toBe("Settled"); + + state.failedAction = null; + expect(await actions.archiveThread(thread)).toBe(true); + expect(readThreadUndoNotice()).toBeNull(); + }); }); describe("thread archive guard", () => { diff --git a/apps/mobile/src/features/home/useThreadListActions.ts b/apps/mobile/src/features/home/useThreadListActions.ts index 248c436905311..ee74dec44664b 100644 --- a/apps/mobile/src/features/home/useThreadListActions.ts +++ b/apps/mobile/src/features/home/useThreadListActions.ts @@ -125,9 +125,6 @@ function useThreadActionExecutor( return false; } if (action === "unsettle") ThreadUndo.invalidate("settle", key); - if (action === "archive" || action === "delete") { - for (const kind of ["settle", "snooze", "pin"]) ThreadUndo.invalidate(kind, key); - } onStarted?.(); const result = await withThreadDismissal( key, @@ -157,6 +154,9 @@ function useThreadActionExecutor( Dialog.alert(actionFailureTitle(action), actionFailureMessage(action, result.cause)); return false; } + if (action === "archive" || action === "delete") { + for (const kind of ["settle", "snooze", "pin"]) ThreadUndo.invalidate(kind, key); + } if (action === "archive" || action === "unarchive" || action === "delete") { refreshArchivedThreadsForEnvironment(thread.environmentId); }