42 lines
1.1 KiB
TypeScript
42 lines
1.1 KiB
TypeScript
import type { Theme } from '../types';
|
|
|
|
const STORAGE_KEY = 'gc_local_theme';
|
|
|
|
const VALID: readonly Theme[] = ['dark', 'light', 'blue'];
|
|
|
|
function isTheme(v: unknown): v is Theme {
|
|
return typeof v === 'string' && (VALID as readonly string[]).includes(v);
|
|
}
|
|
|
|
/** 이 브라우저(기기)에 저장된 UI 테마. 계정·DB와 무관 */
|
|
export function loadLocalTheme(): Theme {
|
|
try {
|
|
const raw = localStorage.getItem(STORAGE_KEY);
|
|
if (isTheme(raw)) return raw;
|
|
} catch {
|
|
/* private mode 등 */
|
|
}
|
|
return 'dark';
|
|
}
|
|
|
|
export function saveLocalTheme(theme: Theme): void {
|
|
try {
|
|
localStorage.setItem(STORAGE_KEY, theme);
|
|
} catch {
|
|
/* quota / private mode */
|
|
}
|
|
}
|
|
|
|
/** localStorage에 없을 때만 DB defaultTheme을 이 기기에 1회 복사 */
|
|
export function migrateDbThemeToLocalIfNeeded(dbTheme: string | undefined): Theme {
|
|
try {
|
|
const existing = localStorage.getItem(STORAGE_KEY);
|
|
if (isTheme(existing)) return existing;
|
|
} catch {
|
|
/* ignore */
|
|
}
|
|
const theme: Theme = isTheme(dbTheme) ? dbTheme : 'dark';
|
|
saveLocalTheme(theme);
|
|
return theme;
|
|
}
|