From e436a698394c474b060e98301396c7e0053bf181 Mon Sep 17 00:00:00 2001 From: Jake Date: Sat, 18 Apr 2026 10:18:29 +0100 Subject: [PATCH] fix(preferences): use Object.assign mutation to prevent infinite effect loops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replacing the preferences object (spread reassignment) caused all consumers' prefs references to go stale — the loop guard read the old value forever. Svelte 5 shared state pattern requires a stable const object with property mutations, not reassignment. Also removes duplicate theme sync $effect from SettingsPage (already handled in +layout.svelte). --- src/lib/pages/SettingsPage.svelte | 8 -------- src/lib/stores/preferences.svelte.js | 12 ++++++------ 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/src/lib/pages/SettingsPage.svelte b/src/lib/pages/SettingsPage.svelte index 5207c03..100c160 100644 --- a/src/lib/pages/SettingsPage.svelte +++ b/src/lib/pages/SettingsPage.svelte @@ -281,14 +281,6 @@ saveSettings(); }); - // Sync theme setting to preferences store - $effect(() => { - const map = { Dark: 'dark', Light: 'light', System: 'system' }; - const mapped = map[settings.theme] || 'dark'; - if (prefs.theme !== mapped) { - updatePreferences({ theme: mapped }); - } - }); $effect(() => { settings.engine; diff --git a/src/lib/stores/preferences.svelte.js b/src/lib/stores/preferences.svelte.js index f3f80df..354cd40 100644 --- a/src/lib/stores/preferences.svelte.js +++ b/src/lib/stores/preferences.svelte.js @@ -98,7 +98,9 @@ function persistToSQLite(prefs) { }, 500); } -let preferences = $state(readFromDOM()); +// Export as const so it is never reassigned — consumers hold a stable reference +// and mutations are tracked by Svelte 5's deep reactivity. +export const preferences = $state(readFromDOM()); // Ensure data-theme and zone attributes are always present on the DOM, even // when there is no Tauri webview injection script (e.g. browser dev mode). @@ -106,21 +108,19 @@ if (typeof window !== 'undefined') { applyToDOM(preferences); } +/** @deprecated Use `preferences` directly — kept for backwards compatibility */ export function getPreferences() { return preferences; } export function updatePreferences(updates) { - preferences = { ...preferences, ...updates }; + Object.assign(preferences, updates); applyToDOM(preferences); persistToSQLite(preferences); } export function updateAccessibility(updates) { - preferences = { - ...preferences, - accessibility: { ...preferences.accessibility, ...updates } - }; + Object.assign(preferences.accessibility, updates); applyToDOM(preferences); persistToSQLite(preferences); }