Files
Netcatty/application/state/useTreeExpandedState.ts
陈大猫 36e5779d94 perf(terminal): reduce terminal tab-switch and layout jank (#1321)
* perf(terminal): smooth layout drags and faster tab switching

Defer xterm refit during split, sidebar, and host-tree drags while keeping pane containers in sync with live layout measurements. Refactor TerminalLayer into focused sections with TabBridge/memo optimizations and add the terminal host tree sidebar.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(terminal): keep side panels alive and guard session attach races

Prevent terminal boot unmount from leaking backend sessions, keep SFTP/scripts/theme/AI state when switching side tabs, and defer heavy SFTP UI mount so first entry stays responsive.

Co-authored-by: Cursor <cursoragent@cursor.com>

* perf(terminal): reduce tab switch jank

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-09 03:35:03 +08:00

59 lines
1.5 KiB
TypeScript

import { useCallback, useEffect, useState } from "react";
import { localStorageAdapter } from "../../infrastructure/persistence/localStorageAdapter";
export const useTreeExpandedState = (storageKey: string) => {
const [expandedPaths, setExpandedPaths] = useState<Set<string>>(() => {
const stored = localStorageAdapter.readString(storageKey);
if (stored) {
try {
const paths = JSON.parse(stored) as string[];
return new Set(paths);
} catch {
return new Set();
}
}
return new Set();
});
useEffect(() => {
const pathsArray = Array.from(expandedPaths);
localStorageAdapter.writeString(storageKey, JSON.stringify(pathsArray));
}, [storageKey, expandedPaths]);
const togglePath = useCallback((path: string) => {
setExpandedPaths((current) => {
const next = new Set(current);
if (next.has(path)) {
next.delete(path);
} else {
next.add(path);
}
return next;
});
}, []);
const expandAll = useCallback((allPaths: string[]) => {
setExpandedPaths(new Set(allPaths));
}, []);
const collapseAll = useCallback(() => {
setExpandedPaths(new Set());
}, []);
const ensurePathExpanded = useCallback((path: string) => {
setExpandedPaths((current) => {
if (current.has(path)) return current;
const next = new Set(current);
next.add(path);
return next;
});
}, []);
return {
expandedPaths,
togglePath,
expandAll,
collapseAll,
ensurePathExpanded,
};
};