diff --git a/packages/ui/src/components/session/SessionSidebar.tsx b/packages/ui/src/components/session/SessionSidebar.tsx index 5a3c716c..4c875e8b 100644 --- a/packages/ui/src/components/session/SessionSidebar.tsx +++ b/packages/ui/src/components/session/SessionSidebar.tsx @@ -381,6 +381,11 @@ export const SessionSidebar: React.FC = ({ })); }, [globalActiveSessions, isVSCode, knownSessionDirectories, liveSessions]); + const persistenceSessions = React.useMemo( + () => [...globalActiveSessions, ...archivedSessions], + [archivedSessions, globalActiveSessions], + ); + const syncSessionStructureSignature = React.useMemo( () => liveSessions .map((session) => { @@ -541,7 +546,7 @@ export const SessionSidebar: React.FC = ({ projectActiveSession: PROJECT_ACTIVE_SESSION_STORAGE_KEY, groupCollapse: GROUP_COLLAPSE_STORAGE_KEY, }, - sessions, + sessions: persistenceSessions, pinnedSessionIds, setPinnedSessionIds, groupOrderByProject, diff --git a/packages/ui/src/components/session/sidebar/hooks/pinnedSessionCleanup.ts b/packages/ui/src/components/session/sidebar/hooks/pinnedSessionCleanup.ts new file mode 100644 index 00000000..f2381896 --- /dev/null +++ b/packages/ui/src/components/session/sidebar/hooks/pinnedSessionCleanup.ts @@ -0,0 +1,20 @@ +import type { Session } from '@opencode-ai/sdk/v2'; + +export const prunePinnedSessionIds = ( + sessions: Array>, + pinnedSessionIds: Set, +): Set => { + const existingSessionIds = new Set(sessions.map((session) => session.id)); + let changed = false; + const next = new Set(); + + pinnedSessionIds.forEach((id) => { + if (existingSessionIds.has(id)) { + next.add(id); + return; + } + changed = true; + }); + + return changed ? next : pinnedSessionIds; +}; diff --git a/packages/ui/src/components/session/sidebar/hooks/useSidebarPersistence.test.ts b/packages/ui/src/components/session/sidebar/hooks/useSidebarPersistence.test.ts new file mode 100644 index 00000000..2d0b8a29 --- /dev/null +++ b/packages/ui/src/components/session/sidebar/hooks/useSidebarPersistence.test.ts @@ -0,0 +1,26 @@ +import { describe, expect, test } from 'bun:test'; +import type { Session } from '@opencode-ai/sdk/v2'; +import { prunePinnedSessionIds } from './pinnedSessionCleanup'; + +const makeSession = (id: string): Pick => ({ id }); + +describe('prunePinnedSessionIds', () => { + test('keeps pinned ids that still exist in the authoritative session list', () => { + const sessions = [makeSession('visible-session'), makeSession('hidden-session')]; + const pinnedSessionIds = new Set(['hidden-session', 'missing-session']); + + const next = prunePinnedSessionIds(sessions, pinnedSessionIds); + + expect([...next]).toEqual(['hidden-session']); + expect(next).not.toBe(pinnedSessionIds); + }); + + test('returns the original set when nothing needs pruning', () => { + const sessions = [makeSession('visible-session'), makeSession('hidden-session')]; + const pinnedSessionIds = new Set(['visible-session', 'hidden-session']); + + const next = prunePinnedSessionIds(sessions, pinnedSessionIds); + + expect(next).toBe(pinnedSessionIds); + }); +}); diff --git a/packages/ui/src/components/session/sidebar/hooks/useSidebarPersistence.ts b/packages/ui/src/components/session/sidebar/hooks/useSidebarPersistence.ts index a6652533..13519d9a 100644 --- a/packages/ui/src/components/session/sidebar/hooks/useSidebarPersistence.ts +++ b/packages/ui/src/components/session/sidebar/hooks/useSidebarPersistence.ts @@ -2,6 +2,7 @@ import React from 'react'; import type { Session } from '@opencode-ai/sdk/v2'; import { updateDesktopSettings } from '@/lib/persistence'; import { useProjectsStore } from '@/stores/useProjectsStore'; +import { prunePinnedSessionIds } from './pinnedSessionCleanup'; type SafeStorageLike = { getItem: (key: string) => string | null; @@ -154,22 +155,8 @@ export const useSidebarPersistence = (args: Args) => { return; } - if (sessions.length === 0) { - return; - } - - const existingSessionIds = new Set(sessions.map((session) => session.id)); setPinnedSessionIds((prev) => { - let changed = false; - const next = new Set(); - prev.forEach((id) => { - if (existingSessionIds.has(id)) { - next.add(id); - } else { - changed = true; - } - }); - return changed ? next : prev; + return prunePinnedSessionIds(sessions, prev); }); }, [hasLoadedGlobalSessions, sessions, setPinnedSessionIds]);