78 lines
2.9 KiB
TypeScript
78 lines
2.9 KiB
TypeScript
/**
|
|
* Workspace draft — keep an anonymous user's in-progress circuit + code across
|
|
* a full-page navigation to /login and back.
|
|
*
|
|
* The Sign-in links mount in a separate React root without Router context, so
|
|
* they navigate with `window.location.assign` (full page load), which wipes
|
|
* the in-memory Zustand stores. Before that navigation we stash the whole
|
|
* workspace (reusing the lossless `.vlx` serialisation) into sessionStorage;
|
|
* when the editor remounts after login it restores the stash. sessionStorage
|
|
* is same-tab and survives the reload, and is discarded when the tab closes.
|
|
*
|
|
* Scoped strictly to the login round-trip via a one-shot restore flag — it is
|
|
* NOT a general autosave, so a normal reload never resurrects an old draft.
|
|
*/
|
|
|
|
import type { BoardInstance } from '../types/board';
|
|
import { useProjectStore } from '../store/useProjectStore';
|
|
import { useSimulatorStore } from '../store/useSimulatorStore';
|
|
import { buildVlxPayload } from './vlxFile';
|
|
|
|
const DRAFT_KEY = 'velxio_ws_draft';
|
|
const RESTORE_FLAG = 'velxio_ws_restore';
|
|
|
|
/** True when the canvas holds something worth preserving (a real build, not
|
|
* just the empty starter board). */
|
|
export function workspaceHasWork(): boolean {
|
|
const sim = useSimulatorStore.getState();
|
|
return sim.components.length > 0 || sim.wires.length > 0;
|
|
}
|
|
|
|
/**
|
|
* Snapshot the current workspace and mark it for restore on the next editor
|
|
* mount. Call right before a full-page navigation to /login. No-op when there
|
|
* is nothing worth keeping or storage is unavailable.
|
|
*/
|
|
export function stashWorkspaceForAuth(): void {
|
|
try {
|
|
if (!workspaceHasWork()) return;
|
|
sessionStorage.setItem(DRAFT_KEY, JSON.stringify(buildVlxPayload()));
|
|
sessionStorage.setItem(RESTORE_FLAG, '1');
|
|
} catch {
|
|
// storage full / disabled — degrade to losing the draft, never throw.
|
|
}
|
|
}
|
|
|
|
/**
|
|
* If a stash is pending (set before the login redirect), load it into the
|
|
* stores and clear it. Runs once on editor mount. Skips when a named project
|
|
* is already loaded so it never clobbers one. Returns whether it restored.
|
|
*/
|
|
export function restoreStashedWorkspace(): boolean {
|
|
let raw: string | null = null;
|
|
try {
|
|
if (sessionStorage.getItem(RESTORE_FLAG) !== '1') return false;
|
|
sessionStorage.removeItem(RESTORE_FLAG);
|
|
raw = sessionStorage.getItem(DRAFT_KEY);
|
|
sessionStorage.removeItem(DRAFT_KEY);
|
|
} catch {
|
|
return false;
|
|
}
|
|
if (!raw) return false;
|
|
if (useProjectStore.getState().currentProject) return false;
|
|
try {
|
|
const payload = JSON.parse(raw);
|
|
useSimulatorStore.getState().loadProjectState({
|
|
boards: payload.boards as unknown as BoardInstance[],
|
|
fileGroups: payload.fileGroups,
|
|
folderGroups: payload.folderGroups,
|
|
components: payload.components,
|
|
wires: payload.wires,
|
|
activeBoardId: payload.activeBoardId,
|
|
});
|
|
return true;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|