export const composerDraftStorageKey = "jyotisha.composer-draft"; const composerDraftLimit = 500; const composerDraftMaxAgeMs = 24 * 60 * 60 * 1000; const listeners = new Set<() => void>(); let draft = ""; let restored = false; function draftStorage(): Storage | null { if (typeof window === "undefined") return null; try { return window.sessionStorage; } catch { // Private-mode browsers without session storage keep the draft in memory only. return null; } } function clearStoredDraft() { const storage = draftStorage(); if (!storage) return; try { storage.removeItem(composerDraftStorageKey); } catch { // A rejected write never blocks the composer. } } export function readStoredComposerDraft(): string { const storage = draftStorage(); if (!storage) return ""; let stored: string | null = null; try { stored = storage.getItem(composerDraftStorageKey); } catch { return ""; } if (!stored) return ""; try { const parsed = JSON.parse(stored) as Record; const text = parsed.text; const savedAt = parsed.savedAt; if (typeof text !== "string" || typeof savedAt !== "number" || !Number.isFinite(savedAt) || savedAt > Date.now() || Date.now() - savedAt > composerDraftMaxAgeMs) { clearStoredDraft(); return ""; } return text.slice(0, composerDraftLimit); } catch { clearStoredDraft(); return ""; } } function writeStoredComposerDraft(value: string) { if (!value) { clearStoredDraft(); return; } const storage = draftStorage(); if (!storage) return; try { storage.setItem(composerDraftStorageKey, JSON.stringify({ text: value.slice(0, composerDraftLimit), savedAt: Date.now(), })); } catch { // A full or blocked storage never blocks typing. } } function restoreComposerDraft() { if (restored) return; restored = true; draft = readStoredComposerDraft(); } export function composerDraftSnapshot(): string { restoreComposerDraft(); return draft; } export function serverComposerDraftSnapshot(): string { return ""; } export function setComposerDraft(value: string) { restoreComposerDraft(); if (draft === value) return; draft = value; writeStoredComposerDraft(value); for (const listener of [...listeners]) listener(); } export function subscribeComposerDraft(listener: () => void): () => void { listeners.add(listener); return () => { listeners.delete(listener); }; }