From 13ac19d54630e4b8fdc43930566359c576bc07fe Mon Sep 17 00:00:00 2001 From: Bnaya Zilberfarb Date: Mon, 8 Jun 2026 14:50:15 +0300 Subject: [PATCH 1/3] feat: add attention mode to Active Tasks sidebar Bell icon button next to the scope toggle shows tasks in user-questions/review-by-user across all projects, sorted oldest-first. Pulsing badge shows count when tasks are waiting. Co-Authored-By: Claude Sonnet 4.6 --- .../06/08/feature-sidebar-attention-mode.md | 1 + .../components/ActiveTasksSidebar.tsx | 67 ++++++++++++++++--- src/mainview/i18n/translations/en/common.ts | 2 + src/mainview/i18n/translations/en/tips.ts | 2 + src/mainview/i18n/translations/es/common.ts | 2 + src/mainview/i18n/translations/es/tips.ts | 2 + src/mainview/i18n/translations/ru/common.ts | 2 + src/mainview/i18n/translations/ru/tips.ts | 2 + src/mainview/tips.ts | 7 ++ 9 files changed, 78 insertions(+), 9 deletions(-) create mode 100644 change-logs/2026/06/08/feature-sidebar-attention-mode.md diff --git a/change-logs/2026/06/08/feature-sidebar-attention-mode.md b/change-logs/2026/06/08/feature-sidebar-attention-mode.md new file mode 100644 index 00000000..f7669c89 --- /dev/null +++ b/change-logs/2026/06/08/feature-sidebar-attention-mode.md @@ -0,0 +1 @@ +Added an "attention" mode to the Active Tasks sidebar. A bell icon button appears next to the existing project/global scope toggle; clicking it filters the list cross-project to only tasks in `user-questions` or `review-by-user` status, sorted oldest-first. The bell shows a pulsing count badge when tasks are waiting and the mode is not already active. diff --git a/src/mainview/components/ActiveTasksSidebar.tsx b/src/mainview/components/ActiveTasksSidebar.tsx index 2d67858d..d08f2bda 100644 --- a/src/mainview/components/ActiveTasksSidebar.tsx +++ b/src/mainview/components/ActiveTasksSidebar.tsx @@ -14,13 +14,16 @@ import AgentLauncherBadge from "./AgentLauncherBadge"; import VariantDots from "./VariantDots"; import { getTaskAgentMeta } from "../utils/taskAgentMeta"; -type SidebarScope = "project" | "global"; +type SidebarScope = "project" | "global" | "attention"; const LS_SIDEBAR_SCOPE = "dev3-sidebar-scope"; +/** Statuses that require the user's attention — the "attention" scope shows only these. */ +const ATTENTION_STATUSES: TaskStatus[] = ["user-questions", "review-by-user"]; + function readScope(): SidebarScope { try { const v = localStorage.getItem(LS_SIDEBAR_SCOPE); - if (v === "global" || v === "project") return v; + if (v === "global" || v === "project" || v === "attention") return v; } catch { /* ignore */ } return "project"; } @@ -96,9 +99,9 @@ function ActiveTasksSidebar({ return () => window.removeEventListener("keydown", handleKeyDown); }, [disableGlobalFindShortcut]); - // Fetch active tasks from all projects when in global scope. + // Fetch active tasks from all projects when in global or attention scope. useEffect(() => { - if (scope !== "global") return; + if (scope !== "global" && scope !== "attention") return; let cancelled = false; setGlobalLoading(true); (async () => { @@ -125,7 +128,7 @@ function ActiveTasksSidebar({ // Keep global tasks live across all projects. useEffect(() => { - if (scope !== "global") return; + if (scope !== "global" && scope !== "attention") return; function onTaskUpdated(e: Event) { const { task } = (e as CustomEvent).detail as { task: Task }; setGlobalTasks((prev) => { @@ -151,9 +154,24 @@ function ActiveTasksSidebar({ return () => window.removeEventListener("rpc:taskUpdated", onTaskUpdated); }, [scope]); - const sourceTasks = scope === "global" ? globalTasks : tasks; + const sourceTasks = (scope === "global" || scope === "attention") ? globalTasks : tasks; + + // Count of attention tasks across all available data (global when loaded, else project). + const attentionCount = useMemo(() => { + const pool = globalTasks.length > 0 ? globalTasks : tasks; + return pool.filter((t) => ATTENTION_STATUSES.includes(t.status)).length; + }, [globalTasks, tasks]); let activeTasks = sourceTasks.filter((task) => ACTIVE_STATUSES.includes(task.status)); + if (scope === "attention") { + activeTasks = activeTasks.filter((task) => ATTENTION_STATUSES.includes(task.status)); + // Sort oldest-first so the longest-waiting task is always at the top. + activeTasks = activeTasks.slice().sort((a, b) => { + const aTime = a.updatedAt ? new Date(a.updatedAt).getTime() : 0; + const bTime = b.updatedAt ? new Date(b.updatedAt).getTime() : 0; + return aTime - bTime; + }); + } if (searchQuery.trim()) { activeTasks = activeTasks.filter((task) => matchesSearchQuery(task, searchQuery)); } @@ -269,6 +287,33 @@ function ActiveTasksSidebar({ + {/* Attention mode \u2014 cross-project view filtered to tasks needing the user's input */} + - + {/* Globe \u2014 all projects */} - - {/* Attention mode \u2014 cross-project view filtered to tasks needing the user's input */} - + {attentionCount > 0 && scope !== "attention" && ( + + {attentionCount > 9 ? "9+" : attentionCount} + + )} + +