Introduced Refresh-Resistant Session Persistence

This commit is contained in:
Nicole Rappe 2025-05-06 05:27:42 -06:00
parent 1c9873dedd
commit ca1348fcb8

View File

@ -57,12 +57,10 @@ if (!window.BorealisSocket) {
});
}
// Global Node Update Timer Variable
if (!window.BorealisUpdateRate) {
window.BorealisUpdateRate = 200;
}
// Dynamically load all node components via Vite
const modules = import.meta.glob('./nodes/**/*.jsx', { eager: true });
const nodeTypes = {};
const categorizedNodes = {};
@ -72,11 +70,8 @@ Object.entries(modules).forEach(([path, mod]) => {
if (!comp) return;
const { type, component } = comp;
if (!type || !component) return;
// derive category folder name from path: "./nodes/<Category>/File.jsx"
const parts = path.replace('./nodes/', '').split('/');
const category = parts[0];
if (!categorizedNodes[category]) {
categorizedNodes[category] = [];
}
@ -112,6 +107,7 @@ const darkTheme = createTheme({
}
});
const LOCAL_STORAGE_KEY = "borealis_persistent_state";
export default function App() {
const [tabs, setTabs] = useState([
@ -134,6 +130,29 @@ export default function App() {
const [tabMenuTabId, setTabMenuTabId] = useState(null);
const fileInputRef = useRef(null);
useEffect(() => {
const saved = localStorage.getItem(LOCAL_STORAGE_KEY);
if (saved) {
try {
const parsed = JSON.parse(saved);
if (Array.isArray(parsed.tabs) && parsed.activeTabId) {
setTabs(parsed.tabs);
setActiveTabId(parsed.activeTabId);
}
} catch (err) {
console.warn("Failed to parse saved state:", err);
}
}
}, []);
useEffect(() => {
const timeout = setTimeout(() => {
const data = JSON.stringify({ tabs, activeTabId });
localStorage.setItem(LOCAL_STORAGE_KEY, data);
}, 1000);
return () => clearTimeout(timeout);
}, [tabs, activeTabId]);
const handleSetNodes = useCallback(
(callbackOrArray, tId) => {
const targetId = tId || activeTabId;
@ -232,10 +251,8 @@ export default function App() {
setTabs((old) => {
const idx = old.findIndex((t) => t.id === tabMenuTabId);
if (idx === -1) return old;
const newList = [...old];
newList.splice(idx, 1);
if (tabMenuTabId === activeTabId && newList.length > 0) {
setActiveTabId(newList[0].id);
} else if (newList.length === 0) {
@ -270,7 +287,6 @@ export default function App() {
const handleExportFlow = async () => {
const activeTab = tabs.find((x) => x.id === activeTabId);
if (!activeTab) return;
const data = JSON.stringify(
{
nodes: activeTab.nodes,
@ -283,7 +299,6 @@ export default function App() {
const blob = new Blob([data], { type: "application/json" });
const sanitizedTabName = activeTab.tab_name.replace(/\s+/g, "_").toLowerCase();
const suggestedFilename = sanitizedTabName + "_workflow.json";
if (window.showSaveFilePicker) {
try {
const fileHandle = await window.showSaveFilePicker({
@ -295,7 +310,6 @@ export default function App() {
}
]
});
const writable = await fileHandle.createWritable();
await writable.write(blob);
await writable.close();
@ -328,7 +342,6 @@ export default function App() {
const file = await fileHandle.getFile();
const text = await file.text();
const json = JSON.parse(text);
const newId = "flow_" + (tabs.length + 1);
setTabs((prev) => [
...prev,
@ -354,7 +367,6 @@ export default function App() {
try {
const text = await file.text();
const json = JSON.parse(text);
const newId = "flow_" + (tabs.length + 1);
setTabs((prev) => [
...prev,
@ -374,7 +386,6 @@ export default function App() {
return (
<ThemeProvider theme={darkTheme}>
<CssBaseline />
<Box sx={{ width: "100vw", height: "100vh", display: "flex", flexDirection: "column", overflow: "hidden" }}>
<AppBar position="static" sx={{ bgcolor: "#16191d" }}>
<Toolbar sx={{ minHeight: "36px" }}>
@ -399,7 +410,6 @@ export default function App() {
</Menu>
</Toolbar>
</AppBar>
<Box sx={{ display: "flex", flexGrow: 1, overflow: "hidden" }}>
<NodeSidebar
categorizedNodes={categorizedNodes}
@ -409,7 +419,6 @@ export default function App() {
fileInputRef={fileInputRef}
onFileInputChange={handleFileInputChange}
/>
<Box sx={{ display: "flex", flexDirection: "column", flexGrow: 1, overflow: "hidden" }}>
<FlowTabs
tabs={tabs}
@ -418,7 +427,6 @@ export default function App() {
onAddTab={createNewTab}
onTabRightClick={handleTabRightClick}
/>
<Box sx={{ flexGrow: 1, position: "relative" }}>
{tabs.map((tab) => (
<Box
@ -434,7 +442,7 @@ export default function App() {
>
<ReactFlowProvider id={tab.id}>
<FlowEditor
flowId={tab.id} //Used to Fix Grid Issues Across Multiple Flow Tabs
flowId={tab.id}
nodes={tab.nodes}
edges={tab.edges}
setNodes={(val) => handleSetNodes(val, tab.id)}
@ -448,10 +456,8 @@ export default function App() {
</Box>
</Box>
</Box>
<StatusBar />
</Box>
<CloseAllDialog
open={confirmCloseOpen}
onClose={handleCloseDialog}