From 2de4174ecaea9bacb3ababcae085c2d131190ab7 Mon Sep 17 00:00:00 2001 From: Fred Boniface Date: Sun, 12 Oct 2025 20:51:56 +0100 Subject: [PATCH] Add new preferences store and migrations --- .../migrations/preferencesMigrations.ts | 91 +++++++++++++++++++ src/lib/stores/preferences.ts | 51 +++++++++++ 2 files changed, 142 insertions(+) create mode 100644 src/lib/scripts/migrations/preferencesMigrations.ts create mode 100644 src/lib/stores/preferences.ts diff --git a/src/lib/scripts/migrations/preferencesMigrations.ts b/src/lib/scripts/migrations/preferencesMigrations.ts new file mode 100644 index 0000000..0b6b7a8 --- /dev/null +++ b/src/lib/scripts/migrations/preferencesMigrations.ts @@ -0,0 +1,91 @@ +import { preferences, PREFERENCE_FORMAT_VERSION } from "$lib/stores/preferences"; +import type { Preferences } from "$lib/stores/preferences"; +import { get } from "svelte/store"; + +export function CheckMigrationStatus() { + let currentStore = get(preferences); + if ( currentStore.format == 1 ) { + const hasOldKeys = + localStorage.getItem('ql') !== null || + localStorage.getItem('location') !== null || + localStorage.getItem('telemetry') !== null; + + if (hasOldKeys) { + migrateToV1() + } + } + + // Handle higher current version than supported or unparsable number + if ( + !currentStore || + typeof currentStore.format !== 'number' || + currentStore.format > PREFERENCE_FORMAT_VERSION + ) { + preferences.reset(); + console.warn('[Migration] Preferences reset due to invalid format version') + // Re-read store after reset + currentStore = get(preferences); + } + + // Loop through required migrations + while (currentStore.format < PREFERENCE_FORMAT_VERSION) { + // Future Migration Logic + /* + switch (currentStore.format) { + case 0: + migrateToV1(); + break; + + default: + console.warn(`[Migration] Unknown format ${currentStore.format}, resetting to default`); + preferences.reset(); + break; + } + + // Re-read store after migration + currentStore = get(preferences); + */ + break; // Don't forget to remove this! + } + + +} + +// Migrations + +function migrateToV1() { + const oldQlRaw = localStorage.getItem('ql'); + const oldLocationRaw = localStorage.getItem('location'); + const oldTelemetryRaw = localStorage.getItem('telemetry'); + + const ql: string[] = safeParseJSON(oldQlRaw, []); + const location: boolean = parseBool(oldLocationRaw, false); + const telemetry: boolean = parseBool(oldTelemetryRaw, false); + + const migrated: Preferences = { ql, location, telemetry, format: 1 }; + + preferences.set(migrated); + + localStorage.removeItem('ql'); + localStorage.removeItem('location'); + localStorage.removeItem('telemetry'); + + console.info('[Migration] Preferences migrated to version 1'); +} + +// Helpers + +function safeParseJSON(raw: string | null, fallback: T): T { + if (!raw) return fallback; + try { + return JSON.parse(raw) as T; + } catch { + return fallback; + } +} + +function parseBool(raw: string | null, fallback: boolean): boolean { + if (raw == 'true') return true; + if (raw == 'false') return false; + return fallback; +} diff --git a/src/lib/stores/preferences.ts b/src/lib/stores/preferences.ts new file mode 100644 index 0000000..cf16b31 --- /dev/null +++ b/src/lib/stores/preferences.ts @@ -0,0 +1,51 @@ +import { CheckMigrationStatus } from "$lib/scripts/migrations/preferencesMigrations"; +import { writable } from "svelte/store"; + +export const PREFERENCE_FORMAT_VERSION = 1; + +export interface Preferences { + ql: string[]; + location: boolean; + telemetry: boolean; + format: number; +} + +const STORAGE_KEY = 'preferences'; + +const DEFAULT_PREFERENCES: Preferences = { + ql: [], + location: false, + telemetry: false, + format: PREFERENCE_FORMAT_VERSION, +}; + +function createPreferencesStore() { + let stored: Preferences; + try { + const json = localStorage.getItem(STORAGE_KEY); + stored = json ? JSON.parse(json) : DEFAULT_PREFERENCES; + } catch { + stored = DEFAULT_PREFERENCES; + } + + const { subscribe, set, update } = writable(stored); + + subscribe((value) => { + localStorage.setItem(STORAGE_KEY, JSON.stringify(value)); + }); + + return { + subscribe, + set, + update, + reset: () => set(DEFAULT_PREFERENCES) + } +} + +export const preferences = createPreferencesStore(); +try { + CheckMigrationStatus(); +} catch (e) { + console.error("Preferences migration failed, resetting store", e); + preferences.reset(); +}