2024-07-13 14:25:27 +02:00
|
|
|
import { derived, readable, type Updater } from 'svelte/store';
|
2024-06-19 17:12:51 +02:00
|
|
|
import { merge } from 'ts-deepmerge';
|
|
|
|
|
|
|
|
import type { RecursivePartial } from './types/generic';
|
|
|
|
import type { CobaltSettings } from './types/settings';
|
|
|
|
|
2024-07-10 19:47:46 +02:00
|
|
|
import defaultSettings from './settings/defaults';
|
2024-06-19 17:12:51 +02:00
|
|
|
|
2024-07-10 19:47:46 +02:00
|
|
|
type PartialSettings = RecursivePartial<CobaltSettings>;
|
2024-07-13 14:05:52 +02:00
|
|
|
type PartialSettingsWithSchema = RecursivePartial<CobaltSettings> & { schemaVersion: number };
|
2024-07-10 19:47:46 +02:00
|
|
|
|
|
|
|
const writeToStorage = (settings: PartialSettings) => {
|
2024-06-19 17:12:51 +02:00
|
|
|
localStorage.setItem(
|
|
|
|
"settings",
|
2024-07-13 14:32:08 +02:00
|
|
|
JSON.stringify(settings)
|
2024-06-19 17:12:51 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
return settings;
|
|
|
|
}
|
|
|
|
|
2024-07-13 14:05:52 +02:00
|
|
|
type Migrator = (s: PartialSettings) => PartialSettings;
|
|
|
|
const migrations: Record<number, Migrator> = {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const migrate = (settings: PartialSettingsWithSchema) => {
|
|
|
|
return Object.keys(migrations)
|
|
|
|
.map(Number)
|
|
|
|
.filter(version => version > settings.schemaVersion)
|
|
|
|
.reduce((settings, migrationVersion) => {
|
|
|
|
return migrations[migrationVersion](settings);
|
|
|
|
}, settings as PartialSettings);
|
|
|
|
}
|
|
|
|
|
2024-06-19 17:12:51 +02:00
|
|
|
const loadFromStorage = () => {
|
|
|
|
const settings = localStorage.getItem('settings');
|
|
|
|
if (!settings) {
|
2024-07-10 19:47:46 +02:00
|
|
|
return {};
|
2024-06-19 17:12:51 +02:00
|
|
|
}
|
|
|
|
|
2024-07-13 14:05:52 +02:00
|
|
|
const parsed = JSON.parse(settings) as PartialSettingsWithSchema;
|
|
|
|
if (parsed.schemaVersion < defaultSettings.schemaVersion) {
|
|
|
|
return migrate(parsed);
|
|
|
|
}
|
|
|
|
|
|
|
|
return parsed;
|
2024-06-19 17:12:51 +02:00
|
|
|
}
|
|
|
|
|
2024-07-13 14:25:27 +02:00
|
|
|
let update: (_: Updater<PartialSettings>) => void;
|
2024-06-19 17:12:51 +02:00
|
|
|
|
2024-07-10 19:47:46 +02:00
|
|
|
// deep merge partial type into full CobaltSettings type
|
|
|
|
const mergeWithDefaults = (partial: PartialSettings) => {
|
|
|
|
return merge(defaultSettings, partial) as CobaltSettings;
|
|
|
|
}
|
|
|
|
|
2024-07-13 14:25:27 +02:00
|
|
|
export const storedSettings = readable<PartialSettings>(
|
|
|
|
loadFromStorage(),
|
2024-06-19 17:12:51 +02:00
|
|
|
(_, _update) => { update = _update }
|
|
|
|
);
|
|
|
|
|
|
|
|
// update settings from outside
|
2024-07-10 19:47:46 +02:00
|
|
|
export function updateSetting(partial: PartialSettings) {
|
2024-07-13 14:25:27 +02:00
|
|
|
update((current) => {
|
2024-07-10 19:47:46 +02:00
|
|
|
const updated = writeToStorage(
|
2024-07-13 14:32:08 +02:00
|
|
|
merge(
|
|
|
|
current,
|
|
|
|
partial,
|
|
|
|
{ schemaVersion: defaultSettings.schemaVersion }
|
|
|
|
)
|
2024-07-10 19:47:46 +02:00
|
|
|
);
|
2024-06-19 17:12:51 +02:00
|
|
|
|
2024-07-13 14:25:27 +02:00
|
|
|
return updated;
|
2024-06-19 17:12:51 +02:00
|
|
|
});
|
|
|
|
}
|
2024-07-13 14:25:27 +02:00
|
|
|
|
|
|
|
export default derived(
|
|
|
|
storedSettings,
|
|
|
|
$settings => mergeWithDefaults($settings)
|
|
|
|
);
|