Compare commits

...
Author SHA1 Message Date
Cursor Agentand陈大猫 78db63a20e perf(vault): skip connection-log side-store parse in non-log windows
Settings, tray, and the terminal popup mount useVaultState but never
show connection-log replay. Skip the bulky side-store load and storage
handlers there so a main-window persist does not JSON.parse it in those
renderers. Main-window behaviour and the write path stay unchanged.

Co-authored-by: 陈大猫 <binaricat@users.noreply.github.com>
2026-10-22 06:42:55 +00:00
4 changed files with 26 additions and 7 deletions

No files matched your search

+23 -4
View File
@@ -304,7 +304,18 @@ const writeConnectionLogTerminalDataMap = (
return localStorageAdapter.write(STORAGE_KEY_CONNECTION_LOG_TERMINAL_DATA, pruned);
};
export const useVaultState = () => {
export type UseVaultStateOptions = {
/**
* When false, skip loading and cross-window sync of the bulky
* connection-log terminal-data side store (~30–50 MB in localStorage).
* Pass false from windows that never show connection-log replay
* (Settings, tray panel, terminal popup). Default true.
*/
syncConnectionLogTerminalData?: boolean;
};
export const useVaultState = (options?: UseVaultStateOptions) => {
const syncConnectionLogTerminalData = options?.syncConnectionLogTerminalData !== false;
const [isInitialized, setIsInitialized] = useState(false);
const [hosts, setHosts] = useState<Host[]>([]);
const [keys, setKeys] = useState<SSHKey[]>([]);
@@ -1636,7 +1647,11 @@ export const useVaultState = () => {
const savedConnectionLogs = localStorageAdapter.read<ConnectionLog[]>(
STORAGE_KEY_CONNECTION_LOGS,
);
const terminalDataMap = readConnectionLogTerminalDataMap();
// Windows that never render connection-log replay skip the ~30–50 MB
// side-store parse on boot (Settings / tray / popup).
const terminalDataMap = syncConnectionLogTerminalData
? readConnectionLogTerminalDataMap()
: {};
connectionLogTerminalDataRef.current = terminalDataMap;
if (savedConnectionLogs) {
setConnectionLogs(mergeTerminalDataIntoLogs(savedConnectionLogs, terminalDataMap));
@@ -1681,7 +1696,7 @@ export const useVaultState = () => {
return () => {
cancelled = true;
};
}, [commitEncryptedHostsUnderVaultLock, updateHosts, updateSnippets]);
}, [commitEncryptedHostsUnderVaultLock, syncConnectionLogTerminalData, updateHosts, updateSnippets]);
useEffect(() => {
if (!isInitialized) return;
@@ -1890,6 +1905,9 @@ export const useVaultState = () => {
}
if (key === STORAGE_KEY_CONNECTION_LOG_TERMINAL_DATA) {
// Other windows still receive the storage event; skip the multi-MB
// JSON.parse when this mount does not show connection-log replay.
if (!syncConnectionLogTerminalData) return;
const next = safeParse<ConnectionLogTerminalDataMap>(event.newValue) ?? {};
connectionLogTerminalDataRef.current = next;
setConnectionLogs((prev) => mergeConnectionLogsFromStorage(prev, prev, next));
@@ -1930,6 +1948,7 @@ export const useVaultState = () => {
return;
}
if (key === STORAGE_KEY_CONNECTION_LOG_TERMINAL_DATA) {
if (!syncConnectionLogTerminalData) return;
const next = readConnectionLogTerminalDataMap();
connectionLogTerminalDataRef.current = next;
setConnectionLogs((prev) => mergeConnectionLogsFromStorage(prev, prev, next));
@@ -1942,7 +1961,7 @@ export const useVaultState = () => {
window.removeEventListener("storage", handleStorage);
window.removeEventListener(LOCAL_STORAGE_ADAPTER_CHANGED_EVENT, handleLocalStorageAdapterChanged);
};
}, [applyConnectionLogsFromStorage]);
}, [applyConnectionLogsFromStorage, syncConnectionLogTerminalData]);
const updateHostLastConnected = useCallback((hostId: string) => {
setHosts((prev) => {
+1 -1
View File
@@ -270,7 +270,7 @@ const SettingsSyncTabWithVault: React.FC<{ onSettingsApplied?: () => void }> = (
groupConfigs,
importDataFromString,
clearVaultData,
} = useVaultState();
} = useVaultState({ syncConnectionLogTerminalData: false });
const { rules: portForwardingRules, importRules: importPortForwardingRules } = usePortForwardingState();
+1 -1
View File
@@ -286,7 +286,7 @@ function TerminalPopupPageInner({
groupConfigs,
updateKnownHosts,
deleteSelectedSnippets,
} = useVaultState();
} = useVaultState({ syncConnectionLogTerminalData: false });
const [config, setConfig] = useState<TerminalPopupPayload | null>(null);
const [terminalReady, setTerminalReady] = useState(false);
const [startupError, setStartupError] = useState<string | null>(null);
+1 -1
View File
@@ -148,7 +148,7 @@ const TrayPanelContent: React.FC = () => {
onTrayPanelMenuData,
} = useTrayPanelBackend();
const { hosts, knownHosts, updateKnownHosts } = useVaultState();
const { hosts, knownHosts, updateKnownHosts } = useVaultState({ syncConnectionLogTerminalData: false });
// TrayPanel runs in its own BrowserWindow, so this hook's session state is
// independent from (and typically empty compared to) the main App's — it's
// used here only for its storage-sync side effects, never for closeSession.