56 lines
1.3 KiB
JavaScript
56 lines
1.3 KiB
JavaScript
// Persisted settings with a tiny subscribe API. Storage can throw
|
|
// (private mode, blocked site data), so every access is guarded.
|
|
|
|
const KEY = 'picker.settings.v1';
|
|
|
|
export const DEFAULTS = Object.freeze({
|
|
mode: 'one', // one | pickN | teams | order | elimination
|
|
pickN: 2,
|
|
teams: 2,
|
|
theme: 'neon', // neon | pastel | contrast
|
|
lang: null, // null = follow the browser
|
|
muted: false,
|
|
haptics: true,
|
|
stakeId: null, // preset key, translated at display time
|
|
stakeText: '', // custom text, used when stakeId is null
|
|
});
|
|
|
|
function load() {
|
|
try {
|
|
const raw = localStorage.getItem(KEY);
|
|
if (!raw) return { ...DEFAULTS };
|
|
const parsed = JSON.parse(raw);
|
|
const out = { ...DEFAULTS };
|
|
for (const k of Object.keys(DEFAULTS)) {
|
|
if (k in parsed) out[k] = parsed[k];
|
|
}
|
|
return out;
|
|
} catch {
|
|
return { ...DEFAULTS };
|
|
}
|
|
}
|
|
|
|
function save(s) {
|
|
try {
|
|
localStorage.setItem(KEY, JSON.stringify(s));
|
|
} catch {
|
|
/* storage unavailable: settings just won't persist */
|
|
}
|
|
}
|
|
|
|
export function createSettings() {
|
|
let state = load();
|
|
const listeners = new Set();
|
|
return {
|
|
get: () => state,
|
|
set(patch) {
|
|
state = { ...state, ...patch };
|
|
save(state);
|
|
for (const fn of listeners) fn(state, patch);
|
|
},
|
|
subscribe(fn) {
|
|
listeners.add(fn);
|
|
return () => listeners.delete(fn);
|
|
},
|
|
};
|
|
}
|