From 94addf2bd13b00277ceb1078f9cf7b86e9b8f0ce Mon Sep 17 00:00:00 2001 From: kenny lopez Date: Thu, 13 Aug 2026 18:35:29 +0100 Subject: [PATCH] fix(theme): preserve legacy appearance migration Signed-off-by: kenny lopez --- .../features/settings/ui/SettingsPanels.tsx | 25 ++---- .../shared/theme/CommunityThemeController.tsx | 68 ++++++++++----- .../theme/communityThemePreference.test.mjs | 85 ++++++++++++++++++- .../shared/theme/communityThemePreference.ts | 38 +++++++++ .../theme/community_theme_preference.dart | 36 ++++++-- .../community_theme_preference_test.dart | 54 +++++++++++- .../theme/community_theme_provider_test.dart | 59 +++++++++++++ schema/community-theme-v1.json | 44 ++++++++++ 8 files changed, 360 insertions(+), 49 deletions(-) create mode 100644 schema/community-theme-v1.json diff --git a/desktop/src/features/settings/ui/SettingsPanels.tsx b/desktop/src/features/settings/ui/SettingsPanels.tsx index ab423c833..14632697a 100644 --- a/desktop/src/features/settings/ui/SettingsPanels.tsx +++ b/desktop/src/features/settings/ui/SettingsPanels.tsx @@ -1,4 +1,4 @@ -import { useEffect, useMemo, useState } from "react"; +import { useMemo, useState } from "react"; import { AnimatePresence, motion, useReducedMotion } from "motion/react"; import { Archive, @@ -438,14 +438,8 @@ function ThemeSettingsCard() { ? "light" : "dark"; - const [selectedMode, setSelectedMode] = useState(activeMode); const [themeStyleExpanded, setThemeStyleExpanded] = useState(false); - // Community sync can replace the appearance while this panel remains open. - // Mirror that external value so the segmented control never describes the - // previous community's color mode. - useEffect(() => setSelectedMode(activeMode), [activeMode]); - const getVars = (name: SyntaxThemeName) => withAccentPreviewVars( previewVarsByTheme[name] ?? getThemeFallbackPreviewVars(name), @@ -467,7 +461,6 @@ function ThemeSettingsCard() { }, [pairedLight, darkOnly]); const handleModeSelect = (mode: AppearanceMode) => { - setSelectedMode(mode); if (mode === "system") { setFollowSystem(true); // If the current theme is unpaired, resolveSystemTheme can't switch it @@ -505,7 +498,7 @@ function ThemeSettingsCard() { const handleSelectTheme = (name: SyntaxThemeName) => { setTheme(name); - if (selectedMode === "system") { + if (activeMode === "system") { setFollowSystem(true); } else { setFollowSystem(false); @@ -518,7 +511,7 @@ function ThemeSettingsCard() { return selectedThemeName === lightName || selectedThemeName === darkName; }; const selectedPairedTheme = - selectedMode === "system" ? pairedLight.find(isPairActive) : undefined; + activeMode === "system" ? pairedLight.find(isPairActive) : undefined; const selectedTheme = selectedThemeName as SyntaxThemeName; const selectedPairedDarkTheme = selectedPairedTheme ? getThemePair(selectedPairedTheme) @@ -579,7 +572,7 @@ function ThemeSettingsCard() { ) : null}
- {selectedMode === "system" && + {activeMode === "system" && pairedLight.map((lightName) => { const darkName = getThemePair(lightName); if (!darkName) return null; @@ -594,7 +587,7 @@ function ThemeSettingsCard() { /> ); })} - {selectedMode === "light" && + {activeMode === "light" && allLightThemes.map((name) => ( ))} - {selectedMode === "dark" && + {activeMode === "dark" && allDarkThemes.map((name) => ( option.mode === selectedMode) * 100}%)`, + transform: `translateX(${APPEARANCE_MODE_OPTIONS.findIndex((option) => option.mode === activeMode) * 100}%)`, width: "calc((100% - 4px) / 3)", }} /> {APPEARANCE_MODE_OPTIONS.map(({ mode, label, Icon }) => (