/** localStorage keys for panel UI preferences — single source of truth. * * The VALUES are a compatibility contract: they are what users' browsers * already have stored, so they must never change (the mixed msp-/full-name * prefixes are historical and stay). Centralizing the names just makes a typo * in one call site impossible — a DRY audit (2026-07-10) found every key * duplicated inline at its get/set pair. */ export const LS_KEYS = { /** #179: object-page sections the user folded away (JSON list of section * ids: tasks | documents | parts | history) — one setting for every object. */ objectSections: "msp-object-sections", /** #170: service-booklet print options (layout + include switches). */ printOptions: "msp-print-options", /** D#162: the battery roster starts open; a deliberate collapse is remembered. */ batteryRosterOpen: "msp-bf-roster-open", /** #164: how the object's document list is ordered (newest | oldest | title | category). */ docSort: "msp-doc-sort", /** #161: the camera (deviceId) the in-app viewfinder should open with. */ cameraDevice: "msp-camera-device", overviewTab: "msp-overview-tab", collapsedSections: "msp-collapsed-sections", chartRange: "msp-chart-range", chartHideOutliers: "msp-chart-hide-outliers", taskSort: "maintenance_supporter_sort", objectSort: "maintenance_supporter_object_sort", groupBy: "maintenance_supporter_groupby", objectView: "maintenance_supporter_object_view", objectsCache: "msp-objects-cache", gettingStartedDismissed: "msp-gs-dismissed", batteryRosterSort: "ms_bf_roster_sort", } as const; /** * Guarded storage access — localStorage can THROW (Safari private mode / * locked-down policies raise instead of returning null), and an unguarded * call aborts the surrounding handler. The 2026-08 DRY audit found two * hand-written call sites that had missed the guard; every access now goes * through these two (a source tripwire forbids direct localStorage use * outside this module). */ export function lsGet(key: string): string | null { try { return localStorage.getItem(key); } catch { return null; } } export function lsSet(key: string, value: string): void { try { localStorage.setItem(key, value); } catch { /* private mode / storage blocked */ } }