refactor(web): safeLocalStorage helper for store persistence (#375)

Three nearly-identical try/catch wrappers across theme + player stores
collapse to read()/write()/remove() in lib/util/safeLocalStorage.ts.
Sets the pattern for future stores. Caller still does parse/serialize
since the existing call sites store strings (theme preference, volume
number) — no JSON wrapper needed yet.

persisted.ts left alone — its JSON-payload + per-key-suffix shape is
distinct enough to keep self-contained.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-10 15:36:45 -04:00
co-authored by Claude Opus 4.7
parent 2357df83be
commit 633406c05b
3 changed files with 44 additions and 20 deletions
+5 -10
View File
@@ -1,16 +1,13 @@
import * as storage from '$lib/util/safeLocalStorage';
const STORAGE_KEY = 'minstrel:theme';
export type ThemePreference = 'dark' | 'light' | 'system';
export type ResolvedTheme = 'dark' | 'light';
function readPref(): ThemePreference {
if (typeof localStorage === 'undefined') return 'system';
try {
const v = localStorage.getItem(STORAGE_KEY);
return v === 'dark' || v === 'light' || v === 'system' ? v : 'system';
} catch {
return 'system';
}
const v = storage.read(STORAGE_KEY);
return v === 'dark' || v === 'light' || v === 'system' ? v : 'system';
}
function systemResolved(): ResolvedTheme {
@@ -51,9 +48,7 @@ export const resolvedTheme = {
export function setTheme(pref: ThemePreference): void {
_theme = pref;
_resolved = resolve(pref);
if (typeof localStorage !== 'undefined') {
try { localStorage.setItem(STORAGE_KEY, pref); } catch { /* ignore quota / unavailable */ }
}
storage.write(STORAGE_KEY, pref);
applyToDOM(_resolved);
}