From c904c1b5436647cd059b371cadf2c3d46e715290 Mon Sep 17 00:00:00 2001 From: JonathanLab Date: Tue, 28 Apr 2026 16:47:19 +0200 Subject: [PATCH] fix(sidebar): show created task immediately The sidebar filter required workspaces[task.id] to be set, but in worktree mode onTaskReady fires early with workspace=null so the task detail pane navigates while the sidebar hides the task until workspace creation completes. Include actively provisioning task ids in the filter so the sidebar matches the detail pane. Also fix invalidateTasks: setQueryData(taskKeys.list()) wrote to a key with no filters that the sidebar query never reads from. Switch to setQueriesData over taskKeys.lists() with a duplicate guard so the optimistic insert lands in every active list query. Closes #1820 Generated-By: PostHog Code Task-Id: 053dcd37-ddc9-4c17-869f-d67c405d0c1f --- .../renderer/features/sidebar/hooks/useSidebarData.ts | 8 ++++++-- .../src/renderer/features/tasks/hooks/useTasks.ts | 11 +++++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/apps/code/src/renderer/features/sidebar/hooks/useSidebarData.ts b/apps/code/src/renderer/features/sidebar/hooks/useSidebarData.ts index c436ac864..3fca36207 100644 --- a/apps/code/src/renderer/features/sidebar/hooks/useSidebarData.ts +++ b/apps/code/src/renderer/features/sidebar/hooks/useSidebarData.ts @@ -1,4 +1,5 @@ import { useArchivedTaskIds } from "@features/archive/hooks/useArchivedTaskIds"; +import { useProvisioningStore } from "@features/provisioning/stores/provisioningStore"; import { useSessions } from "@features/sessions/stores/sessionStore"; import { useSuspendedTaskIds } from "@features/suspension/hooks/useSuspendedTaskIds"; import { useTasks } from "@features/tasks/hooks/useTasks"; @@ -85,15 +86,18 @@ export function useSidebarData({ const { data: workspaces, isFetched: isWorkspacesFetched } = useWorkspaces(); const archivedTaskIds = useArchivedTaskIds(); const suspendedTaskIds = useSuspendedTaskIds(); + const provisioningTaskIds = useProvisioningStore((s) => s.activeTasks); const isLoading = !isTasksFetched || !isWorkspacesFetched; const allTasks = useMemo( () => rawTasks.filter( (task) => !archivedTaskIds.has(task.id) && - (showAllUsers || !!workspaces?.[task.id]), + (showAllUsers || + !!workspaces?.[task.id] || + provisioningTaskIds.has(task.id)), ), - [rawTasks, archivedTaskIds, workspaces, showAllUsers], + [rawTasks, archivedTaskIds, workspaces, showAllUsers, provisioningTaskIds], ); const sessions = useSessions(); const { timestamps } = useTaskViewed(); diff --git a/apps/code/src/renderer/features/tasks/hooks/useTasks.ts b/apps/code/src/renderer/features/tasks/hooks/useTasks.ts index 4097200c8..51c6f3819 100644 --- a/apps/code/src/renderer/features/tasks/hooks/useTasks.ts +++ b/apps/code/src/renderer/features/tasks/hooks/useTasks.ts @@ -51,13 +51,16 @@ export function useCreateTask() { const queryClient = useQueryClient(); const invalidateTasks = (newTask?: Task) => { - // If a new task is provided, add it to cache immediately for instant UI update if (newTask) { - queryClient.setQueryData(taskKeys.list(), (old) => - old ? [newTask, ...old] : [newTask], + queryClient.setQueriesData( + { queryKey: taskKeys.lists() }, + (old) => { + if (!old) return old; + if (old.some((task) => task.id === newTask.id)) return old; + return [newTask, ...old]; + }, ); } - // Also invalidate to ensure we're in sync with server queryClient.invalidateQueries({ queryKey: taskKeys.lists() }); };