From 98426bf86104edb151a6767010a988c2d8e06faf Mon Sep 17 00:00:00 2001 From: dadaloop82 Date: Thu, 21 May 2026 18:41:12 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20dark=5Fmode=20persisted=20in=20server=20?= =?UTF-8?q?.env=20(not=20localStorage)=20=E2=80=94=20add=20to=20saveSettin?= =?UTF-8?q?gs,=20getServerSettings,=20applySyncedSettings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/index.php | 2 ++ assets/js/app.js | 11 +++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/api/index.php b/api/index.php index 6958928..867fae2 100644 --- a/api/index.php +++ b/api/index.php @@ -3081,6 +3081,7 @@ function getServerSettings(): void { 'shopping_smart_suggestions' => env('SHOPPING_SMART_SUGGESTIONS', 'true') === 'true', 'shopping_forecast' => env('SHOPPING_FORECAST', 'true') === 'true', 'shopping_auto_add_threshold' => (int)env('SHOPPING_AUTO_ADD_THRESHOLD', '0'), + 'dark_mode' => env('DARK_MODE', 'auto'), ]); } @@ -3146,6 +3147,7 @@ function saveSettings(): void { 'gdrive_client_id' => 'GDRIVE_CLIENT_ID', 'gdrive_client_secret' => 'GDRIVE_CLIENT_SECRET', 'shopping_mode' => 'SHOPPING_MODE', + 'dark_mode' => 'DARK_MODE', ]; // Boolean keys $boolMap = [ diff --git a/assets/js/app.js b/assets/js/app.js index 0c0f009..d7b4494 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -2073,9 +2073,7 @@ function getSettings() { if (!_settingsCache) { // Settings come from server — do NOT read from localStorage (per-device storage). // _settingsCache is populated by _applySyncedSettings() on app init. - // Exception: dark_mode is intentionally device-local (stored in localStorage). _settingsCache = {}; - try { const dm = localStorage.getItem('evershelf_dark_mode'); if (dm) _settingsCache.dark_mode = dm; } catch(_) {} } const s = _settingsCache; // Build recipe_prefs array from individual booleans @@ -2092,8 +2090,8 @@ function getSettings() { function saveSettingsToStorage(settings) { _settingsCache = settings; - // Store ONLY dark_mode locally for the pre-render early-theme IIFE. - // All other settings are server-side only (centralised, shared across clients). + // Cache dark_mode in localStorage ONLY as a hint for the pre-render _earlyTheme() IIFE + // (prevents flash before server fetch). Authoritative value is in server .env. try { localStorage.setItem('evershelf_dark_mode', settings.dark_mode || 'auto'); } catch(_) {} // Persist user-prefs subset to DB _settingsDirty = true; @@ -2213,7 +2211,8 @@ function _applySyncedSettings(serverSettings) { 'price_enabled','price_country','price_currency','price_update_months', 'zerowaste_tips_enabled', 'shopping_enabled','shopping_mode','shopping_smart_suggestions', - 'shopping_forecast','shopping_auto_add_threshold']; + 'shopping_forecast','shopping_auto_add_threshold', + 'dark_mode']; let changed = false; for (const key of serverKeys) { if (serverSettings[key] !== undefined && serverSettings[key] !== null && serverSettings[key] !== '') { @@ -2223,7 +2222,7 @@ function _applySyncedSettings(serverSettings) { } if (changed) { _settingsCache = s; - // Persist dark_mode locally for early-theme only + // Update localStorage hint for _earlyTheme() IIFE on next load try { localStorage.setItem('evershelf_dark_mode', s.dark_mode || 'auto'); } catch(_) {} } }