From b88399ac148e0ad8d09a140a3579138eacab127f Mon Sep 17 00:00:00 2001 From: ginnoir Date: Thu, 11 Jun 2026 18:52:39 -0500 Subject: [PATCH] feat(state): localStorage player prefs for story and action display --- src/state/__tests__/prefs.test.ts | 25 +++++++++++++++++++++++ src/state/prefs.ts | 33 +++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 src/state/__tests__/prefs.test.ts create mode 100644 src/state/prefs.ts diff --git a/src/state/__tests__/prefs.test.ts b/src/state/__tests__/prefs.test.ts new file mode 100644 index 0000000..d08e668 --- /dev/null +++ b/src/state/__tests__/prefs.test.ts @@ -0,0 +1,25 @@ +import { beforeEach, describe, expect, it, vi } from 'vitest'; +import { getPrefs, setPrefs } from '../prefs'; + +describe('prefs', () => { + beforeEach(() => { + vi.stubGlobal('localStorage', { + store: {} as Record, + getItem(key: string) { + return this.store[key] ?? null; + }, + setItem(key: string, value: string) { + this.store[key] = value; + }, + }); + }); + + it('returns defaults when localStorage empty', () => { + expect(getPrefs()).toEqual({ storyOpenMode: 'auto', actionDetailMode: 'inline' }); + }); + + it('round-trips updated prefs', () => { + setPrefs({ storyOpenMode: 'manual', actionDetailMode: 'hover' }); + expect(getPrefs().storyOpenMode).toBe('manual'); + }); +}); diff --git a/src/state/prefs.ts b/src/state/prefs.ts new file mode 100644 index 0000000..1055b71 --- /dev/null +++ b/src/state/prefs.ts @@ -0,0 +1,33 @@ +const PREFS_KEY = 'idlegame:prefs:v1'; + +export type StoryOpenMode = 'auto' | 'choices-only' | 'manual'; +export type ActionDetailMode = 'inline' | 'hover' | 'info-button'; + +export interface GamePrefs { + storyOpenMode: StoryOpenMode; + actionDetailMode: ActionDetailMode; +} + +const DEFAULTS: GamePrefs = { + storyOpenMode: 'auto', + actionDetailMode: 'inline', +}; + +export function getPrefs(): GamePrefs { + if (typeof localStorage === 'undefined') return { ...DEFAULTS }; + try { + const raw = localStorage.getItem(PREFS_KEY); + if (!raw) return { ...DEFAULTS }; + return { ...DEFAULTS, ...JSON.parse(raw) }; + } catch { + return { ...DEFAULTS }; + } +} + +export function setPrefs(partial: Partial): GamePrefs { + const next = { ...getPrefs(), ...partial }; + if (typeof localStorage !== 'undefined') { + localStorage.setItem(PREFS_KEY, JSON.stringify(next)); + } + return next; +}