/** * Per-viewer memory of the live wall's map view (server-26#234): the last * overlays, basemap and viewport this browser used. A convenience only — * every access is wrapped, and a blocked/empty store (private window, cleared * site data) simply yields {} so the wall falls back to its defaults. * * Precedence when the wall opens: URL hash > this store > defaults * (resolveWallView below). Nothing here is shared with other viewers. */ import { DEFAULT_BASE, DEFAULT_LAYERS, isBaseKey, normaliseLayers, parseViewport, type WallView, } from "@/lib/liveWall"; const KEY = "drb.wall.view.v1"; export function loadWallPrefs(): WallView { try { const raw = window.localStorage.getItem(KEY); if (!raw) return {}; const v: unknown = JSON.parse(raw); if (!v || typeof v !== "object") return {}; const o = v as Record; const out: WallView = {}; if (Array.isArray(o.layers)) out.layers = normaliseLayers(o.layers.filter((x): x is string => typeof x === "string")); if (typeof o.base === "string" && isBaseKey(o.base)) out.base = o.base; const view = o.view && typeof o.view === "object" ? (o.view as Record) : null; const vp = view ? parseViewport(view.z, view.lat, view.lon) : undefined; if (vp) out.view = vp; return out; } catch { return {}; } } export function saveWallPrefs(v: WallView): void { try { window.localStorage.setItem(KEY, JSON.stringify({ layers: v.layers, base: v.base, view: v.view })); } catch { /* storage blocked or full — the URL hash still carries the view */ } } /** Field-by-field: hash wins, then what this browser remembers, then defaults. */ export function resolveWallView(hash: WallView, stored: WallView): Required> & Pick { return { layers: hash.layers ?? stored.layers ?? DEFAULT_LAYERS, base: hash.base ?? stored.base ?? DEFAULT_BASE, view: hash.view ?? stored.view, }; }