fix(rdocs): persist demo notebook state in localStorage
Demo mode edits were lost on page reload — now debounce-saved to localStorage and restored on next visit. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
432a3597de
commit
4d5c394e9e
|
|
@ -319,7 +319,46 @@ class FolkDocsApp extends HTMLElement {
|
||||||
|
|
||||||
// ── Demo data ──
|
// ── Demo data ──
|
||||||
|
|
||||||
|
private static readonly DEMO_STORAGE_KEY = 'rdocs_demo_data';
|
||||||
|
private _demoSaveTimer: ReturnType<typeof setTimeout> | null = null;
|
||||||
|
|
||||||
|
/** Debounce-save demo notebooks to localStorage (500ms). */
|
||||||
|
private saveDemoState() {
|
||||||
|
if (this._demoSaveTimer) clearTimeout(this._demoSaveTimer);
|
||||||
|
this._demoSaveTimer = setTimeout(() => {
|
||||||
|
try {
|
||||||
|
const serializable = this.demoNotebooks.map(nb => ({
|
||||||
|
id: nb.id, title: nb.title, description: nb.description,
|
||||||
|
cover_color: nb.cover_color, note_count: nb.note_count,
|
||||||
|
updated_at: nb.updated_at, notes: nb.notes,
|
||||||
|
}));
|
||||||
|
localStorage.setItem(FolkDocsApp.DEMO_STORAGE_KEY, JSON.stringify(serializable));
|
||||||
|
} catch { /* localStorage full or unavailable */ }
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
|
||||||
private loadDemoData() {
|
private loadDemoData() {
|
||||||
|
// Try restoring from localStorage first
|
||||||
|
try {
|
||||||
|
const saved = localStorage.getItem(FolkDocsApp.DEMO_STORAGE_KEY);
|
||||||
|
if (saved) {
|
||||||
|
const parsed = JSON.parse(saved);
|
||||||
|
if (Array.isArray(parsed) && parsed.length > 0) {
|
||||||
|
this.demoNotebooks = parsed;
|
||||||
|
this.notebooks = this.demoNotebooks.map(({ notes, ...nb }: any) => nb as Notebook);
|
||||||
|
for (const nb of this.demoNotebooks) {
|
||||||
|
this.notebookNotes.set(nb.id, nb.notes);
|
||||||
|
}
|
||||||
|
if (this.demoNotebooks.length > 0) {
|
||||||
|
this.expandedNotebooks.add(this.demoNotebooks[0].id);
|
||||||
|
}
|
||||||
|
this.loading = false;
|
||||||
|
this.render();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch { /* corrupt data — fall through to defaults */ }
|
||||||
|
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const hour = 3600000;
|
const hour = 3600000;
|
||||||
const day = 86400000;
|
const day = 86400000;
|
||||||
|
|
@ -483,6 +522,7 @@ Gear: EUR 400 (10%)</code></pre><p><em>Maya is tracking expenses in rF
|
||||||
}
|
}
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.render();
|
this.render();
|
||||||
|
this.saveDemoState(); // persist initial state
|
||||||
}
|
}
|
||||||
|
|
||||||
private demoSearchNotes(query: string) {
|
private demoSearchNotes(query: string) {
|
||||||
|
|
@ -549,6 +589,7 @@ Gear: EUR 400 (10%)</code></pre><p><em>Maya is tracking expenses in rF
|
||||||
this.renderNav();
|
this.renderNav();
|
||||||
this.renderMeta();
|
this.renderMeta();
|
||||||
this.mountEditor(newNote);
|
this.mountEditor(newNote);
|
||||||
|
this.saveDemoState();
|
||||||
}
|
}
|
||||||
|
|
||||||
private demoCreateNote(opts: CreateNoteOpts = {}) {
|
private demoCreateNote(opts: CreateNoteOpts = {}) {
|
||||||
|
|
@ -584,6 +625,7 @@ Gear: EUR 400 (10%)</code></pre><p><em>Maya is tracking expenses in rF
|
||||||
this.renderNav();
|
this.renderNav();
|
||||||
this.renderMeta();
|
this.renderMeta();
|
||||||
this.mountEditor(newNote);
|
this.mountEditor(newNote);
|
||||||
|
this.saveDemoState();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Mobile stack navigation ──
|
// ── Mobile stack navigation ──
|
||||||
|
|
@ -3520,6 +3562,7 @@ Gear: EUR 400 (10%)</code></pre><p><em>Maya is tracking expenses in rF
|
||||||
note.updated_at = new Date().toISOString();
|
note.updated_at = new Date().toISOString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.saveDemoState();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Import/Export Dialog ──
|
// ── Import/Export Dialog ──
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue