From ef818f8d8cdb500a4d4cdf0e7f4b7e0b3c46c1d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=91=98=E9=98=BF=E6=B1=9F=28Relakkes?= =?UTF-8?q?=29?= Date: Sun, 31 May 2026 13:52:54 +0800 Subject: [PATCH] fix(desktop): keep dismissed task progress hidden Dismissed completed task lists are a user visibility choice for that completed cycle, so polling the same persisted tasks during the next chat turn should not resurrect the bar. The store now keeps the dismissed completion key while the remote reset is in flight, and the markdown renderer gives default lists enough inset so bullets stay inside message cards. Constraint: Preserve future task cycles when new TodoWrite or task updates arrive. Rejected: Clear only the visible task array | polling can rehydrate the same completed list before remote reset finishes Confidence: high Scope-risk: narrow Tested: cd desktop && bun run test -- run src/stores/cliTaskStore.test.ts src/components/markdown/MarkdownRenderer.test.tsx Tested: bun run check:desktop Tested: git diff --check Not-tested: Live Tauri chat session task creation and dismissal --- .../markdown/MarkdownRenderer.test.tsx | 13 ++++++++ .../components/markdown/MarkdownRenderer.tsx | 2 +- desktop/src/stores/cliTaskStore.test.ts | 32 +++++++++++++++++-- desktop/src/stores/cliTaskStore.ts | 4 +-- 4 files changed, 46 insertions(+), 5 deletions(-) diff --git a/desktop/src/components/markdown/MarkdownRenderer.test.tsx b/desktop/src/components/markdown/MarkdownRenderer.test.tsx index 3bb7ffc8..164897b4 100644 --- a/desktop/src/components/markdown/MarkdownRenderer.test.tsx +++ b/desktop/src/components/markdown/MarkdownRenderer.test.tsx @@ -57,6 +57,19 @@ describe('MarkdownRenderer', () => { expect(screen.getByText('Body copy.')).toBeInTheDocument() }) + it('gives default markdown lists enough inset to keep bullets inside message cards', () => { + const { container } = render( + , + ) + + const root = container.firstChild as HTMLDivElement + expect(root.className).toContain('prose-ul:pl-5') + expect(root.className).toContain('prose-ol:pl-5') + expect(root.className).toContain('prose-ul:list-outside') + expect(root.className).toContain('prose-ol:list-outside') + expect(screen.getByText('First item')).toBeInTheDocument() + }) + it('applies compact prose classes for dense surfaces', () => { const { container } = render( { expect(useCLITaskStore.getState()).toMatchObject({ tasks: [], resetting: true, - completedAndDismissed: false, - dismissedCompletionKey: null, + completedAndDismissed: true, + dismissedCompletionKey: 'session-1::1::Keep current session isolated::completed::::|session-1::2::Second completed task::completed::::', expanded: false, }) @@ -107,6 +107,34 @@ describe('cliTaskStore', () => { expect(useCLITaskStore.getState().resetting).toBe(false) }) + it('keeps a dismissed completed list hidden if polling returns it again', async () => { + const completedTasks = [ + makeTask('session-1', 'completed'), + { ...makeTask('session-1', 'completed'), id: '2', subject: 'Second completed task' }, + ] + + vi.mocked(cliTasksApi.resetTaskList).mockResolvedValue({ ok: true }) + vi.mocked(cliTasksApi.getTasksForList).mockResolvedValue({ tasks: completedTasks }) + + useCLITaskStore.setState({ + sessionId: 'session-1', + tasks: completedTasks, + expanded: true, + completedAndDismissed: false, + dismissedCompletionKey: null, + }) + + await useCLITaskStore.getState().resetCompletedTasks() + await useCLITaskStore.getState().fetchSessionTasks('session-1') + + expect(useCLITaskStore.getState()).toMatchObject({ + tasks: completedTasks, + completedAndDismissed: true, + dismissedCompletionKey: 'session-1::1::Keep current session isolated::completed::::|session-1::2::Second completed task::completed::::', + expanded: false, + }) + }) + it('refreshes tasks for the currently tracked session by default', async () => { vi.mocked(cliTasksApi.getTasksForList).mockResolvedValue({ tasks: [makeTask('session-1', 'in_progress')], diff --git a/desktop/src/stores/cliTaskStore.ts b/desktop/src/stores/cliTaskStore.ts index 192f9892..8f7007ca 100644 --- a/desktop/src/stores/cliTaskStore.ts +++ b/desktop/src/stores/cliTaskStore.ts @@ -165,8 +165,8 @@ export const useCLITaskStore = create((set, get) => ({ set({ tasks: [], resetting: true, - completedAndDismissed: false, - dismissedCompletionKey: null, + completedAndDismissed: true, + dismissedCompletionKey: completionKey, expanded: false, })