perf(ui): isolate sidebar session selection

This commit is contained in:
c_w_xiaohei
2026-08-26 00:42:36 +08:00
parent 77da97953f
commit ed37d8e249
8 changed files with 351 additions and 159 deletions
@@ -1,6 +1,6 @@
import React from 'react';
import { useSessionUIStore } from '@/sync/session-ui-store';
import { useSync } from '@/sync/use-sync';
import { usePrefetchSessionMessages } from '@/sync/use-sync';
import { useGitHubAuthStore } from '@/stores/useGitHubAuthStore';
import { getGitHubPrStatusKey, useGitHubPrStatusStore } from '@/stores/useGitHubPrStatusStore';
import { useRuntimeAPIs } from '@/hooks/useRuntimeAPIs';
@@ -148,7 +148,7 @@ const VisibleSessionProjects: React.FC<SessionProjectCollectionProps> = ({ topol
if (sessionId === useSessionUIStore.getState().currentSessionId) return;
setCurrentSession(sessionId, sessionDirectory);
}, [setCurrentSession]);
const sync = useSync();
const prefetchSession = usePrefetchSessionMessages();
const { buildGroupedSessions, filterSessionNodesForSearch, buildGroupSearchText } = useSessionGrouping({
homeDirectory: view.homeDirectory,
worktreeMetadata: topology.worktreeMetadata,
@@ -487,7 +487,7 @@ const VisibleSessionProjects: React.FC<SessionProjectCollectionProps> = ({ topol
<SessionPrefetchEffect
sortedSessions={collection.orderedSessions}
recentSessions={recentSessions}
prefetchSession={sync.prefetchSession}
prefetchSession={prefetchSession}
/>
<SessionProjectScroller model={scrollerModel} view={scrollerView} actions={scrollerActionSet} />
<SessionBulkActions
@@ -28,7 +28,7 @@ describe('session prefetch demand', () => {
currentSessionId: current.id,
sortedSessions: [current, nearby],
recentSessions: [current, nearby],
prefetchSession: async (sessionId) => { calls.push(sessionId); },
prefetchSession: async ({ sessionID }) => { calls.push(sessionID); },
});
return null;
};
@@ -14,7 +14,7 @@ type Args = {
currentSessionId: string | null;
sortedSessions: Session[];
recentSessions?: Session[];
prefetchSession: (sessionId: string, directory: string) => Promise<void>;
prefetchSession: (target: { directory: string; sessionID: string }) => Promise<void>;
};
type PrefetchRequest = {
@@ -23,6 +23,10 @@ type PrefetchRequest = {
generation: number;
};
const getPrefetchRequestKey = (request: Pick<PrefetchRequest, 'directory' | 'sessionId'>): string => (
`${request.directory}\n${request.sessionId}`
);
const sessionDirectory = (session: Session | null | undefined): string | null => {
const directory = session?.directory?.trim();
return directory || null;
@@ -35,10 +39,6 @@ export const useSessionPrefetch = ({ enabled = true, currentSessionId, sortedSes
const generationRef = React.useRef(0);
const prefetchDisabled = React.useMemo(() => isVSCodeRuntime(), []);
const requestKey = React.useCallback((request: Pick<PrefetchRequest, 'directory' | 'sessionId'>) => (
`${request.directory}\n${request.sessionId}`
), []);
const clearPendingPrefetches = React.useCallback(() => {
generationRef.current += 1;
sessionPrefetchQueueRef.current = [];
@@ -68,16 +68,16 @@ export const useSessionPrefetch = ({ enabled = true, currentSessionId, sortedSes
continue;
}
const key = requestKey(request);
const key = getPrefetchRequestKey(request);
sessionPrefetchInFlightRef.current.add(key);
void prefetchSession(request.sessionId, request.directory)
void prefetchSession({ directory: request.directory, sessionID: request.sessionId })
.catch(() => undefined)
.finally(() => {
sessionPrefetchInFlightRef.current.delete(key);
pumpSessionPrefetchQueue();
});
}
}, [enabled, prefetchDisabled, prefetchSession, requestKey]);
}, [enabled, prefetchDisabled, prefetchSession]);
const scheduleSessionPrefetch = React.useCallback((session: Session | null | undefined) => {
const sessionId = session?.id;
@@ -86,7 +86,7 @@ export const useSessionPrefetch = ({ enabled = true, currentSessionId, sortedSes
return;
}
const request = { sessionId, directory, generation: generationRef.current };
const key = requestKey(request);
const key = getPrefetchRequestKey(request);
// Already renderable in sync
if (getSyncSessionMaterializationStatus(sessionId, directory).renderable) {
@@ -97,7 +97,7 @@ export const useSessionPrefetch = ({ enabled = true, currentSessionId, sortedSes
return;
}
if (sessionPrefetchQueueRef.current.some((candidate) => requestKey(candidate) === key)) {
if (sessionPrefetchQueueRef.current.some((candidate) => getPrefetchRequestKey(candidate) === key)) {
return;
}
@@ -117,7 +117,7 @@ export const useSessionPrefetch = ({ enabled = true, currentSessionId, sortedSes
pumpSessionPrefetchQueue();
}, SESSION_PREFETCH_HOVER_DELAY_MS);
sessionPrefetchTimersRef.current.set(key, timer);
}, [currentSessionId, enabled, prefetchDisabled, pumpSessionPrefetchQueue, requestKey]);
}, [currentSessionId, enabled, prefetchDisabled, pumpSessionPrefetchQueue]);
React.useEffect(() => {
clearPendingPrefetches();