perf(ui): narrow session switch fanout

Keep sidebar rows independent from the active sync directory by moving export history loading behind an explicit-directory command.

Make active-project selection preserve project topology and remove activeProjectId from mounted group render props. Reuse a per-session-array ID index so subscription snapshots do not repeatedly scan session lists.
This commit is contained in:
c_w_xiaohei
2026-08-26 00:44:14 +08:00
parent 701173e399
commit fa1503a038
9 changed files with 74 additions and 39 deletions
@@ -20,6 +20,26 @@ describe("useProjectsStore settings synchronization", () => {
})
})
describe("useProjectsStore selection identity", () => {
test("changes only the active project id", () => {
const first = { id: "project-a", path: "/repo-a", lastOpenedAt: 10 } as ProjectEntry
const second = { id: "project-b", path: "/repo-b", lastOpenedAt: 20 } as ProjectEntry
const projects = [first, second]
useProjectsStore.setState({
projects,
activeProjectId: first.id,
manualProjectOrder: projects.map((project) => project.id),
})
useProjectsStore.getState().setActiveProjectIdOnly(second.id)
const state = useProjectsStore.getState()
expect(state.activeProjectId).toBe(second.id)
expect(state.projects).toBe(projects)
expect(state.projects.map((project) => project.lastOpenedAt)).toEqual([10, 20])
})
})
describe("useProjectsStore default model and thinking level", () => {
const seed = (project: ProjectEntry) => {
useProjectsStore.setState({
+14 -16
View File
@@ -357,13 +357,7 @@ const readPersistedActiveProjectId = (): string | null => {
return null;
};
const cacheProjects = (projects: ProjectEntry[], activeProjectId: string | null) => {
try {
safeStorage.setItem(getProjectsStorageKey(), JSON.stringify(projects));
} catch {
// ignored
}
const cacheActiveProjectId = (activeProjectId: string | null) => {
try {
const activeProjectStorageKey = getActiveProjectStorageKey();
if (activeProjectId) {
@@ -376,6 +370,15 @@ const cacheProjects = (projects: ProjectEntry[], activeProjectId: string | null)
}
};
const cacheProjects = (projects: ProjectEntry[], activeProjectId: string | null) => {
try {
safeStorage.setItem(getProjectsStorageKey(), JSON.stringify(projects));
} catch {
// ignored
}
cacheActiveProjectId(activeProjectId);
};
const persistProjects = (projects: ProjectEntry[], activeProjectId: string | null, manualOrder?: string[]) => {
cacheProjects(projects, activeProjectId);
if (manualOrder) {
@@ -693,18 +696,13 @@ export const useProjectsStore = create<ProjectsStore>()(
if (activeProjectId === id) {
return;
}
const target = projects.find((project) => project.id === id);
if (!target) {
if (!projects.some((project) => project.id === id)) {
return;
}
const now = Date.now();
const nextProjects = projects.map((project) =>
project.id === id ? { ...project, lastOpenedAt: now } : project
);
set({ projects: nextProjects, activeProjectId: id });
persistProjects(nextProjects, id, get().manualProjectOrder);
set({ activeProjectId: id });
cacheActiveProjectId(id);
void updateDesktopSettings({ activeProjectId: id });
},
renameProject: (id: string, label: string) => {