fix(session): keep pinned sessions on refresh (#2057)

* fix(session): keep pinned sessions on refresh

* fix(session): type sidebar persistence test

* fix(session): remove invalid sidebar persistence harness

---------

Co-authored-by: bashrusakh <bashrusakh@users.noreply.github.com>
This commit is contained in:
Leonid
2026-07-11 14:50:39 +03:00
committed by GitHub
co-authored by bashrusakh
parent 17af1f3369
commit 0242765bc8
4 changed files with 54 additions and 16 deletions
@@ -381,6 +381,11 @@ export const SessionSidebar: React.FC<SessionSidebarProps> = ({
}));
}, [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<SessionSidebarProps> = ({
projectActiveSession: PROJECT_ACTIVE_SESSION_STORAGE_KEY,
groupCollapse: GROUP_COLLAPSE_STORAGE_KEY,
},
sessions,
sessions: persistenceSessions,
pinnedSessionIds,
setPinnedSessionIds,
groupOrderByProject,
@@ -0,0 +1,20 @@
import type { Session } from '@opencode-ai/sdk/v2';
export const prunePinnedSessionIds = (
sessions: Array<Pick<Session, 'id'>>,
pinnedSessionIds: Set<string>,
): Set<string> => {
const existingSessionIds = new Set(sessions.map((session) => session.id));
let changed = false;
const next = new Set<string>();
pinnedSessionIds.forEach((id) => {
if (existingSessionIds.has(id)) {
next.add(id);
return;
}
changed = true;
});
return changed ? next : pinnedSessionIds;
};
@@ -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<Session, 'id'> => ({ 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);
});
});
@@ -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<string>();
prev.forEach((id) => {
if (existingSessionIds.has(id)) {
next.add(id);
} else {
changed = true;
}
});
return changed ? next : prev;
return prunePinnedSessionIds(sessions, prev);
});
}, [hasLoadedGlobalSessions, sessions, setPinnedSessionIds]);