// Copyright: Ankitects Pty Ltd and contributors // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html import { Writable, writable, get } from "svelte/store"; export interface CustomStore extends Writable { subscribe: (getter: (value: T) => void) => () => void; set: (value: T) => void; } export type PreferenceStore = { [K in keyof Omit]: CustomStore; }; export type PreferencePayload = { [K in keyof Omit]: T[K]; }; export type PreferenceRaw = { [K in keyof T]: T[K]; }; function createPreference( initialValue: T, savePreferences: () => void, ): CustomStore { const { subscribe, set, update } = writable(initialValue); return { subscribe, set: (value: T): void => { set(value); savePreferences(); }, update: (updater: (value: T) => T): void => { update(updater); savePreferences(); }, }; } function preparePreferences( Preferences: T, setter: (payload: PreferencePayload) => Promise, toObject: (preferences: T, options: { defaults: boolean }) => PreferenceRaw, ): PreferenceStore { const preferences: Partial> = {}; function constructPreferences(): PreferencePayload { const payload: Partial> = {}; for (const key in preferences as PreferenceStore) { payload[key] = get(preferences[key]); } return payload as PreferencePayload; } function savePreferences(): void { setter(constructPreferences()); } for (const [key, value] of Object.entries( toObject(Preferences, { defaults: true }), )) { preferences[key] = createPreference(value, savePreferences); } return preferences as PreferenceStore; } export async function getPreferences( getter: () => Promise, setter: (payload: PreferencePayload) => Promise, toObject: (preferences: T, options: { defaults: boolean }) => PreferenceRaw, ): Promise> { const initialPreferences = await getter(); return preparePreferences(initialPreferences, setter, toObject); }