-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuseWorkspaceLocalStorage.ts
More file actions
104 lines (100 loc) · 3.67 KB
/
useWorkspaceLocalStorage.ts
File metadata and controls
104 lines (100 loc) · 3.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import { useEffect, type Dispatch, type MutableRefObject, type SetStateAction } from "react";
import { WORKSPACES_STORAGE_KEY } from "../features/app-preferences";
import { cloneSplitTree, type SplitTreeNode } from "../features/split-tree";
import { clonePaneLayouts, normalizePersistedWorkspacesPayload, type WorkspaceSnapshot } from "../features/workspace-snapshot";
import type { PaneLayoutItem } from "../types";
export type WorkspaceBootstrapDeps = {
isApplyingWorkspaceSnapshotRef: MutableRefObject<boolean>;
setWorkspaceOrder: Dispatch<SetStateAction<string[]>>;
setWorkspaceSnapshots: Dispatch<SetStateAction<Record<string, WorkspaceSnapshot>>>;
setActiveWorkspaceId: Dispatch<SetStateAction<string>>;
setSplitSlots: Dispatch<SetStateAction<Array<string | null>>>;
setPaneLayouts: Dispatch<SetStateAction<PaneLayoutItem[]>>;
setSplitTree: Dispatch<SetStateAction<SplitTreeNode>>;
setActivePaneIndex: Dispatch<SetStateAction<number>>;
setActiveSession: Dispatch<SetStateAction<string>>;
setSessionFileViews: Dispatch<SetStateAction<Record<string, "terminal" | "remote" | "local">>>;
};
/** One-shot restore of workspace tabs from localStorage on mount. */
export function useWorkspaceBootstrapFromStorage(deps: WorkspaceBootstrapDeps): void {
const {
isApplyingWorkspaceSnapshotRef,
setWorkspaceOrder,
setWorkspaceSnapshots,
setActiveWorkspaceId,
setSplitSlots,
setPaneLayouts,
setSplitTree,
setActivePaneIndex,
setActiveSession,
setSessionFileViews,
} = deps;
useEffect(() => {
if (typeof window === "undefined") {
return;
}
const raw = window.localStorage.getItem(WORKSPACES_STORAGE_KEY);
if (!raw) {
return;
}
try {
const parsed: unknown = JSON.parse(raw);
const normalized = normalizePersistedWorkspacesPayload(parsed);
if (!normalized) {
return;
}
const { normalizedOrder, normalizedSnapshots, nextActiveWorkspaceId, nextActiveSnapshot } = normalized;
isApplyingWorkspaceSnapshotRef.current = true;
setWorkspaceOrder(normalizedOrder);
setWorkspaceSnapshots(normalizedSnapshots);
setActiveWorkspaceId(nextActiveWorkspaceId);
setSplitSlots([...nextActiveSnapshot.splitSlots]);
setPaneLayouts(clonePaneLayouts(nextActiveSnapshot.paneLayouts));
setSplitTree(cloneSplitTree(nextActiveSnapshot.splitTree));
setActivePaneIndex(nextActiveSnapshot.activePaneIndex);
setActiveSession(nextActiveSnapshot.activeSessionId);
if (nextActiveSnapshot.kind === "nss-commander") {
const fileViews: Record<string, "terminal" | "remote" | "local"> = {};
for (const sid of nextActiveSnapshot.splitSlots) {
if (sid) fileViews[sid] = "local";
}
setSessionFileViews(fileViews);
}
window.setTimeout(() => {
isApplyingWorkspaceSnapshotRef.current = false;
}, 0);
} catch {
// ignore broken persisted workspace data
}
}, [
isApplyingWorkspaceSnapshotRef,
setWorkspaceOrder,
setWorkspaceSnapshots,
setActiveWorkspaceId,
setSplitSlots,
setPaneLayouts,
setSplitTree,
setActivePaneIndex,
setActiveSession,
setSessionFileViews,
]);
}
export function useWorkspacePersistToStorage(
workspaceOrder: string[],
activeWorkspaceId: string,
workspaceSnapshots: Record<string, WorkspaceSnapshot>,
): void {
useEffect(() => {
if (typeof window === "undefined") {
return;
}
window.localStorage.setItem(
WORKSPACES_STORAGE_KEY,
JSON.stringify({
order: workspaceOrder,
activeWorkspaceId,
snapshots: workspaceSnapshots,
}),
);
}, [activeWorkspaceId, workspaceOrder, workspaceSnapshots]);
}