feat: persist circuit and components to localStorage

Auto-saves every 3 seconds and on page unload. Restores the full
state (circuit, camera, custom components) on page load.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jose Luis
2026-03-20 04:25:28 +01:00
parent 5bd157c059
commit 2fd22cc79d
2 changed files with 57 additions and 0 deletions

View File

@@ -2,9 +2,21 @@
import { initRenderer } from './renderer.js'; import { initRenderer } from './renderer.js';
import { initEvents } from './events.js'; import { initEvents } from './events.js';
import { initPuzzleUI } from './puzzleUI.js'; import { initPuzzleUI } from './puzzleUI.js';
import { loadFromStorage, startAutoSave } from './saveLoad.js';
import { updateComponentButtons } from './components.js';
import { evaluateAll } from './gates.js';
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
initRenderer(); initRenderer();
initEvents(); initEvents();
initPuzzleUI(); initPuzzleUI();
// Restore previous session from localStorage
if (loadFromStorage()) {
updateComponentButtons();
evaluateAll();
}
// Auto-save every 3 seconds + on page unload
startAutoSave(3000);
}); });

View File

@@ -2,6 +2,8 @@
import { state } from './state.js'; import { state } from './state.js';
import { progress } from './levels.js'; import { progress } from './levels.js';
const STORAGE_KEY = 'logiclab_state';
/** /**
* Save complete application state to JSON * Save complete application state to JSON
*/ */
@@ -147,3 +149,46 @@ export async function pasteFromClipboard() {
return { success: false, error: e.message }; return { success: false, error: e.message };
} }
} }
/**
* Save state to localStorage
*/
export function saveToStorage() {
try {
const data = saveState();
localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
} catch (e) {
console.warn('[storage] failed to save:', e.message);
}
}
/**
* Load state from localStorage (returns true if state was restored)
*/
export function loadFromStorage() {
try {
const json = localStorage.getItem(STORAGE_KEY);
if (!json) return false;
const data = JSON.parse(json);
const result = loadState(data);
if (result.success) {
console.log('[storage] restored state from localStorage');
}
return result.success;
} catch (e) {
console.warn('[storage] failed to load:', e.message);
return false;
}
}
/**
* Start auto-saving to localStorage on an interval
*/
let autoSaveInterval = null;
export function startAutoSave(intervalMs = 3000) {
if (autoSaveInterval) clearInterval(autoSaveInterval);
autoSaveInterval = setInterval(saveToStorage, intervalMs);
// Also save on page unload
window.addEventListener('beforeunload', saveToStorage);
console.log(`[storage] auto-save enabled (every ${intervalMs}ms)`);
}