From c542f39779607350a0f98c8afd6088e54febb8f0 Mon Sep 17 00:00:00 2001 From: Ho Lim Date: Sun, 12 Jul 2026 22:51:38 -0700 Subject: [PATCH 1/3] fix(desktop): scope messaging sidebar by profile Signed-off-by: Ho Lim --- apps/desktop/src/app/chat/sidebar/index.tsx | 21 ++++- .../app/chat/sidebar/section-states.test.ts | 25 ++++++ .../src/app/chat/sidebar/section-states.tsx | 18 ++++ .../hooks/use-session-list-actions.test.ts | 82 +++++++++++++++++++ .../session/hooks/use-session-list-actions.ts | 53 ++++++------ 5 files changed, 173 insertions(+), 26 deletions(-) create mode 100644 apps/desktop/src/app/chat/sidebar/section-states.test.ts create mode 100644 apps/desktop/src/app/session/hooks/use-session-list-actions.test.ts diff --git a/apps/desktop/src/app/chat/sidebar/index.tsx b/apps/desktop/src/app/chat/sidebar/index.tsx index 9a3fbe3a2748..e4ed1d20c01c 100644 --- a/apps/desktop/src/app/chat/sidebar/index.tsx +++ b/apps/desktop/src/app/chat/sidebar/index.tsx @@ -128,7 +128,12 @@ import { StartWorkButton, useRepoWorktreeMap } from './projects' -import { SidebarBlankState, SidebarPinnedEmptyState, SidebarSessionSkeletons } from './section-states' +import { + shouldShowSessionSections, + SidebarBlankState, + SidebarPinnedEmptyState, + SidebarSessionSkeletons +} from './section-states' import { SidebarSessionsSection, VIRTUALIZE_THRESHOLD } from './sessions-section' import { CONTEXT_SPLIT_KIT, SplitSubmenu } from './split-submenu' @@ -855,6 +860,10 @@ export function ChatSidebar({ const bySource = new Map() for (const session of messagingSessions) { + if (!showAllProfiles && normalizeProfileKey(session.profile) !== profileScope) { + continue + } + const sourceId = normalizeSessionSource(session.source) if (!sourceId) { @@ -884,7 +893,7 @@ export function ChatSidebar({ } }) .sort((a, b) => sessionTime(b.sessions[0]) - sessionTime(a.sessions[0])) - }, [messagingSessions, messagingPlatformTotals, messagingTruncated]) + }, [messagingSessions, messagingPlatformTotals, messagingTruncated, profileScope, showAllProfiles]) // ALL-profiles view: one collapsible group per profile, color on the header // (not on every row). Default profile floats to the top, the rest alpha. @@ -1043,7 +1052,13 @@ export function ChatSidebar({ const showSessionSkeletons = sessionsLoading && sortedSessions.length === 0 - const showSessionSections = showSessionSkeletons || sortedSessions.length > 0 || projectModel.length > 0 + const showSessionSections = shouldShowSessionSections({ + hasCronJobs: cronJobs.length > 0, + hasMessaging: messagingGroups.length > 0, + hasProjects: projectModel.length > 0, + hasSessions: sortedSessions.length > 0, + loadingSessions: showSessionSkeletons + }) // Each reorderable list reports its OWN new id order; persisting is a direct, // typed write — no id-prefix sniffing to figure out which level moved. diff --git a/apps/desktop/src/app/chat/sidebar/section-states.test.ts b/apps/desktop/src/app/chat/sidebar/section-states.test.ts new file mode 100644 index 000000000000..d100a5598490 --- /dev/null +++ b/apps/desktop/src/app/chat/sidebar/section-states.test.ts @@ -0,0 +1,25 @@ +import { describe, expect, it } from 'vitest' + +import { shouldShowSessionSections } from './section-states' + +const emptySidebar = { + hasCronJobs: false, + hasMessaging: false, + hasProjects: false, + hasSessions: false, + loadingSessions: false +} + +describe('shouldShowSessionSections', () => { + it('keeps messaging visible without normal sessions', () => { + expect(shouldShowSessionSections({ ...emptySidebar, hasMessaging: true })).toBe(true) + }) + + it('keeps cron jobs visible without normal sessions', () => { + expect(shouldShowSessionSections({ ...emptySidebar, hasCronJobs: true })).toBe(true) + }) + + it('uses the blank state only when every section is empty', () => { + expect(shouldShowSessionSections(emptySidebar)).toBe(false) + }) +}) diff --git a/apps/desktop/src/app/chat/sidebar/section-states.tsx b/apps/desktop/src/app/chat/sidebar/section-states.tsx index d65eda981326..fe3009e715f7 100644 --- a/apps/desktop/src/app/chat/sidebar/section-states.tsx +++ b/apps/desktop/src/app/chat/sidebar/section-states.tsx @@ -4,6 +4,24 @@ import { Skeleton } from '@/components/ui/skeleton' import { useI18n } from '@/i18n' import { cn } from '@/lib/utils' +interface SidebarSectionVisibility { + hasCronJobs: boolean + hasMessaging: boolean + hasProjects: boolean + hasSessions: boolean + loadingSessions: boolean +} + +export function shouldShowSessionSections({ + hasCronJobs, + hasMessaging, + hasProjects, + hasSessions, + loadingSessions +}: SidebarSectionVisibility): boolean { + return loadingSessions || hasSessions || hasProjects || hasMessaging || hasCronJobs +} + export function SidebarSessionSkeletons() { return (