perf: move file explorer reveal cleanup to shell ref (#4204)

This commit is contained in:
Neil
2026-05-31 08:10:45 -07:00
committed by GitHub
parent 21aa0bc047
commit b7277e20f1
2 changed files with 25 additions and 16 deletions
@@ -120,7 +120,7 @@ function FileExplorerInner(): React.JSX.Element {
const [bgMenuPoint, setBgMenuPoint] = useState({ x: 0, y: 0 })
const scrollRef = useRef<HTMLDivElement>(null)
/** Includes Radix scroll viewport + scrollbar (scrollbar is not a child of the viewport). */
const explorerShellRef = useRef<HTMLDivElement>(null)
const explorerShellRef = useRef<HTMLDivElement | null>(null)
const flashTimeoutRef = useRef<number | null>(null)
const isMac = useMemo(() => navigator.userAgent.includes('Mac'), [])
const isWindows = useMemo(() => navigator.userAgent.includes('Windows'), [])
@@ -280,7 +280,7 @@ function FileExplorerInner(): React.JSX.Element {
}
})
useFileExplorerReveal({
const cancelRevealTimers = useFileExplorerReveal({
activeWorktreeId,
worktreePath,
pendingExplorerReveal,
@@ -296,6 +296,18 @@ function FileExplorerInner(): React.JSX.Element {
flashTimeoutRef,
virtualizer
})
const setExplorerShellRef = useCallback(
(node: HTMLDivElement | null): void => {
explorerShellRef.current = node
if (node !== null) {
return
}
// Why: reveal flash/scroll timers target the explorer shell; clear them
// when that owner detaches instead of keeping a passive unmount Effect.
cancelRevealTimers()
},
[cancelRevealTimers]
)
useFileExplorerAutoReveal({
activeFileId,
@@ -424,7 +436,7 @@ function FileExplorerInner(): React.JSX.Element {
return (
<>
<div
ref={explorerShellRef}
ref={setExplorerShellRef}
data-orca-explorer-shell
data-selected-folder-relative-path={
selectedNode?.isDirectory ? selectedNode.relativePath : undefined
@@ -42,7 +42,7 @@ export function useFileExplorerReveal({
setFlashingPath,
flashTimeoutRef,
virtualizer
}: UseFileExplorerRevealParams): void {
}: UseFileExplorerRevealParams): () => void {
const revealScrollFrameRef = useRef<number | null>(null)
const revealScrollTimeoutRef = useRef<number | null>(null)
@@ -57,18 +57,13 @@ export function useFileExplorerReveal({
}
}, [])
// Why: reveal owns the flash and scroll timers it schedules; keep cleanup on
// hook unmount so no-worktree renders preserve the existing timeout behavior.
useEffect(
() => () => {
cancelRevealScroll()
if (flashTimeoutRef.current !== null) {
window.clearTimeout(flashTimeoutRef.current)
flashTimeoutRef.current = null
}
},
[cancelRevealScroll, flashTimeoutRef]
)
const cancelRevealTimers = useCallback((): void => {
cancelRevealScroll()
if (flashTimeoutRef.current !== null) {
window.clearTimeout(flashTimeoutRef.current)
flashTimeoutRef.current = null
}
}, [cancelRevealScroll, flashTimeoutRef])
const pendingRevealAncestorDirs = useMemo(() => {
if (
@@ -225,4 +220,6 @@ export function useFileExplorerReveal({
virtualizer,
worktreePath
])
return cancelRevealTimers
}