const SESSION_PREFIX = "masters_toolkit_tab_session_v2:"; const MAX_SESSION_CHARS = 850_000; const SAVE_DEBOUNCE_MS = 220; const saveTimers = new Map(); const pendingSerialized = new Map(); export function loadTabSession(tabKey: string): T | null { if (typeof window === "undefined") return null; try { const raw = window.localStorage.getItem(`${SESSION_PREFIX}${tabKey}`); if (!raw) return null; return JSON.parse(raw) as T; } catch { return null; } } export function saveTabSession(tabKey: string, value: T): boolean { if (typeof window === "undefined") return false; try { const serialized = JSON.stringify(value); if (serialized.length > MAX_SESSION_CHARS) return false; window.localStorage.setItem(`${SESSION_PREFIX}${tabKey}`, serialized); return true; } catch { return false; } } export function saveTabSessionDebounced(tabKey: string, value: T, debounceMs = SAVE_DEBOUNCE_MS): void { if (typeof window === "undefined") return; try { const serialized = JSON.stringify(value); if (serialized.length > MAX_SESSION_CHARS) return; pendingSerialized.set(tabKey, serialized); const prev = saveTimers.get(tabKey); if (typeof prev === "number") window.clearTimeout(prev); const t = window.setTimeout(() => { const payload = pendingSerialized.get(tabKey); if (!payload) return; try { window.localStorage.setItem(`${SESSION_PREFIX}${tabKey}`, payload); } catch { // ignore } finally { pendingSerialized.delete(tabKey); saveTimers.delete(tabKey); } }, Math.max(80, debounceMs)); saveTimers.set(tabKey, t); } catch { // ignore } } export function clearTabSession(tabKey: string): void { if (typeof window === "undefined") return; try { const pending = saveTimers.get(tabKey); if (typeof pending === "number") { window.clearTimeout(pending); saveTimers.delete(tabKey); } pendingSerialized.delete(tabKey); window.localStorage.removeItem(`${SESSION_PREFIX}${tabKey}`); } catch { // ignore } }