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>
33 lines
846 B
TypeScript
33 lines
846 B
TypeScript
// SSR-safe localStorage wrapper. Returns null / no-ops when window
|
|
// is undefined or access throws (private mode, quota, security).
|
|
//
|
|
// Caller handles parse / serialize. For object payloads, JSON.stringify
|
|
// before write and JSON.parse(read(key) ?? '...') after.
|
|
|
|
export function read(key: string): string | null {
|
|
if (typeof localStorage === 'undefined') return null;
|
|
try {
|
|
return localStorage.getItem(key);
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export function write(key: string, value: string): void {
|
|
if (typeof localStorage === 'undefined') return;
|
|
try {
|
|
localStorage.setItem(key, value);
|
|
} catch {
|
|
// quota / security — drop silently
|
|
}
|
|
}
|
|
|
|
export function remove(key: string): void {
|
|
if (typeof localStorage === 'undefined') return;
|
|
try {
|
|
localStorage.removeItem(key);
|
|
} catch {
|
|
/* ignore */
|
|
}
|
|
}
|