93 lines
2.3 KiB
TypeScript
93 lines
2.3 KiB
TypeScript
// User settings, persisted in localStorage (including the GitHub token —
|
|
// by design there is no backend holding it).
|
|
|
|
import { DEFAULT_PALM, type PalmOptions } from '$lib/ink/palm';
|
|
|
|
export type ThemePref = 'system' | 'light' | 'dark';
|
|
export type PageStylePref = 'paper' | 'match';
|
|
|
|
export interface GitHubSettings {
|
|
token: string;
|
|
owner: string;
|
|
repo: string;
|
|
branch: string;
|
|
/** Folder inside the repo that holds the vault ('' = repo root). */
|
|
dir: string;
|
|
}
|
|
|
|
interface SettingsData {
|
|
theme: ThemePref;
|
|
pageStyle: PageStylePref;
|
|
fingerDraw: boolean;
|
|
palm: PalmOptions;
|
|
github: GitHubSettings;
|
|
/** Minutes between automatic pushes (0 = manual only). */
|
|
pushInterval: number;
|
|
penColors: string[];
|
|
highlighterColors: string[];
|
|
}
|
|
|
|
const DEFAULTS: SettingsData = {
|
|
theme: 'system',
|
|
pageStyle: 'match',
|
|
fingerDraw: true,
|
|
palm: DEFAULT_PALM,
|
|
github: { token: '', owner: '', repo: '', branch: 'main', dir: '' },
|
|
pushInterval: 5,
|
|
penColors: ['#1f1f1f', '#2563eb', '#dc2626', '#16a34a', '#9333ea'],
|
|
highlighterColors: ['#ffd400', '#7ee081', '#6ec5ff', '#ff8ad8']
|
|
};
|
|
|
|
const KEY = 'papure:settings';
|
|
|
|
function load(): SettingsData {
|
|
try {
|
|
const raw = localStorage.getItem(KEY);
|
|
if (!raw) return structuredClone(DEFAULTS);
|
|
const saved = JSON.parse(raw);
|
|
return {
|
|
...DEFAULTS,
|
|
...saved,
|
|
palm: { ...DEFAULTS.palm, ...saved.palm },
|
|
github: { ...DEFAULTS.github, ...saved.github }
|
|
};
|
|
} catch {
|
|
return structuredClone(DEFAULTS);
|
|
}
|
|
}
|
|
|
|
class Settings {
|
|
data = $state<SettingsData>(load());
|
|
private systemDark = $state(false);
|
|
|
|
constructor() {
|
|
if (typeof window === 'undefined') return;
|
|
const mq = window.matchMedia('(prefers-color-scheme: dark)');
|
|
this.systemDark = mq.matches;
|
|
mq.addEventListener('change', (e) => (this.systemDark = e.matches));
|
|
}
|
|
|
|
get dark() {
|
|
return this.data.theme === 'dark' || (this.data.theme === 'system' && this.systemDark);
|
|
}
|
|
|
|
get githubReady() {
|
|
const g = this.data.github;
|
|
return !!(g.token && g.owner && g.repo && g.branch);
|
|
}
|
|
|
|
save() {
|
|
try {
|
|
localStorage.setItem(KEY, JSON.stringify($state.snapshot(this.data)));
|
|
} catch {
|
|
// Storage unavailable (private mode) — settings last for this session only.
|
|
}
|
|
}
|
|
|
|
toggleTheme() {
|
|
this.data.theme = this.dark ? 'light' : 'dark';
|
|
this.save();
|
|
}
|
|
}
|
|
|
|
export const settings = new Settings();
|