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:
committed by
GitHub
co-authored by
bashrusakh
parent
17af1f3369
commit
0242765bc8
@@ -381,6 +381,11 @@ export const SessionSidebar: React.FC<SessionSidebarProps> = ({
|
|||||||
}));
|
}));
|
||||||
}, [globalActiveSessions, isVSCode, knownSessionDirectories, liveSessions]);
|
}, [globalActiveSessions, isVSCode, knownSessionDirectories, liveSessions]);
|
||||||
|
|
||||||
|
const persistenceSessions = React.useMemo(
|
||||||
|
() => [...globalActiveSessions, ...archivedSessions],
|
||||||
|
[archivedSessions, globalActiveSessions],
|
||||||
|
);
|
||||||
|
|
||||||
const syncSessionStructureSignature = React.useMemo(
|
const syncSessionStructureSignature = React.useMemo(
|
||||||
() => liveSessions
|
() => liveSessions
|
||||||
.map((session) => {
|
.map((session) => {
|
||||||
@@ -541,7 +546,7 @@ export const SessionSidebar: React.FC<SessionSidebarProps> = ({
|
|||||||
projectActiveSession: PROJECT_ACTIVE_SESSION_STORAGE_KEY,
|
projectActiveSession: PROJECT_ACTIVE_SESSION_STORAGE_KEY,
|
||||||
groupCollapse: GROUP_COLLAPSE_STORAGE_KEY,
|
groupCollapse: GROUP_COLLAPSE_STORAGE_KEY,
|
||||||
},
|
},
|
||||||
sessions,
|
sessions: persistenceSessions,
|
||||||
pinnedSessionIds,
|
pinnedSessionIds,
|
||||||
setPinnedSessionIds,
|
setPinnedSessionIds,
|
||||||
groupOrderByProject,
|
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 type { Session } from '@opencode-ai/sdk/v2';
|
||||||
import { updateDesktopSettings } from '@/lib/persistence';
|
import { updateDesktopSettings } from '@/lib/persistence';
|
||||||
import { useProjectsStore } from '@/stores/useProjectsStore';
|
import { useProjectsStore } from '@/stores/useProjectsStore';
|
||||||
|
import { prunePinnedSessionIds } from './pinnedSessionCleanup';
|
||||||
|
|
||||||
type SafeStorageLike = {
|
type SafeStorageLike = {
|
||||||
getItem: (key: string) => string | null;
|
getItem: (key: string) => string | null;
|
||||||
@@ -154,22 +155,8 @@ export const useSidebarPersistence = (args: Args) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sessions.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const existingSessionIds = new Set(sessions.map((session) => session.id));
|
|
||||||
setPinnedSessionIds((prev) => {
|
setPinnedSessionIds((prev) => {
|
||||||
let changed = false;
|
return prunePinnedSessionIds(sessions, prev);
|
||||||
const next = new Set<string>();
|
|
||||||
prev.forEach((id) => {
|
|
||||||
if (existingSessionIds.has(id)) {
|
|
||||||
next.add(id);
|
|
||||||
} else {
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return changed ? next : prev;
|
|
||||||
});
|
});
|
||||||
}, [hasLoadedGlobalSessions, sessions, setPinnedSessionIds]);
|
}, [hasLoadedGlobalSessions, sessions, setPinnedSessionIds]);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user