fix(branding): preserve customCss through preset switches + theme changes (#645)
Reporter @aemisrogers nailed the root cause: same #317 class of bug as logoUrl. None of `GALLERY_THEME_PRESETS` (`theme.types.ts:125`) include `customCss` in their `config` object, so any path that REPLACES `currentTheme` with `preset.config` (or with a sparse `newTheme` that came from `preset.config` upstream) silently dropped `customCss` from React state. The persisted value in `theme_config` stayed correct (the public gallery still rendered it), but the admin textarea showed empty on reload — admin-UI display drift, not data loss. Three surgical fixes, mirroring the #317 logoUrl pattern: 1. `BrandingPage.tsx` `handleThemeChange` — `customCss: newTheme.customCss ?? currentTheme.customCss` alongside the existing `logoUrl` fallback. Closes the propagation hole where the customizer's `handlePresetSelect` fires `onChange(preset.config)` (no customCss) and the parent wipes it from currentTheme. 2. `BrandingPage.tsx` `handlePresetChange` — preserve `customCss` from prev/currentTheme on preset switch, same shape as the existing `logoUrl: prev.logoUrl` preservation. Touches both the `setCurrentTheme` and the preview-mode `setTheme` paths. 3. `ThemeCustomizerEnhanced.tsx` `handlePresetSelect` — remove the `setCustomCss('')` that wiped the local textarea state on preset pick. The previous comment ("Clear custom CSS when selecting a preset") described the original intent but produced data drift across the preset round-trip. The sibling `ThemeCustomizer.tsx` already never cleared it; this aligns the two. Verified against `v3.44.0` and `origin/beta`: identical code on both branches, so the bug exists on stable + beta. Lint + tsc clean on the two changed files. Closes #645.
This commit is contained in:
@@ -259,7 +259,13 @@ export const ThemeCustomizerEnhanced: React.FC<ThemeCustomizerEnhancedProps> = (
|
||||
if (preset) {
|
||||
setSelectedPreset(presetKey);
|
||||
setLocalTheme(preset.config);
|
||||
setCustomCss(''); // Clear custom CSS when selecting a preset
|
||||
// Don't wipe customCss on preset pick — preset configs carry no
|
||||
// customCss, and the admin's persisted styling extras should
|
||||
// survive a layout switch (#645). Matches ThemeCustomizer.tsx
|
||||
// which never cleared it. The parent's handleThemeChange merges
|
||||
// via `customCss: newTheme.customCss ?? currentTheme.customCss`,
|
||||
// so propagating preset.config (no customCss) keeps the saved
|
||||
// value intact end-to-end.
|
||||
if (onPresetChange) {
|
||||
onPresetChange(presetKey);
|
||||
}
|
||||
|
||||
@@ -186,12 +186,14 @@ export const BrandingPage: React.FC = () => {
|
||||
};
|
||||
|
||||
const handleThemeChange = (newTheme: ThemeConfig) => {
|
||||
// Preset configs don't carry a logoUrl, so a preset change inside the
|
||||
// customizer arrives here with newTheme.logoUrl=undefined. Keep the
|
||||
// existing logo instead of wiping branding_logo_url on save (#317).
|
||||
// Preset configs don't carry a logoUrl or customCss, so a preset change
|
||||
// inside the customizer arrives here with those fields undefined. Keep
|
||||
// the existing values instead of wiping the persisted ones on save
|
||||
// (#317 for logoUrl, #645 for customCss).
|
||||
const mergedTheme: ThemeConfig = {
|
||||
...newTheme,
|
||||
logoUrl: newTheme.logoUrl ?? currentTheme.logoUrl
|
||||
logoUrl: newTheme.logoUrl ?? currentTheme.logoUrl,
|
||||
customCss: newTheme.customCss ?? currentTheme.customCss
|
||||
};
|
||||
setCurrentTheme(mergedTheme);
|
||||
if (newTheme.logoUrl !== undefined && newTheme.logoUrl !== currentTheme.logoUrl) {
|
||||
@@ -207,10 +209,20 @@ export const BrandingPage: React.FC = () => {
|
||||
// Get the preset theme config
|
||||
const preset = GALLERY_THEME_PRESETS[presetName];
|
||||
if (preset) {
|
||||
// Preserve the existing logo when switching presets (#317).
|
||||
setCurrentTheme(prev => ({ ...preset.config, logoUrl: prev.logoUrl }));
|
||||
// Preserve the existing logo + custom CSS when switching presets
|
||||
// (#317 for logo, #645 for customCss). Presets define a look; they
|
||||
// shouldn't silently drop the admin's persisted styling extras.
|
||||
setCurrentTheme(prev => ({
|
||||
...preset.config,
|
||||
logoUrl: prev.logoUrl,
|
||||
customCss: prev.customCss
|
||||
}));
|
||||
if (isPreviewMode) {
|
||||
setTheme({ ...preset.config, logoUrl: currentTheme.logoUrl });
|
||||
setTheme({
|
||||
...preset.config,
|
||||
logoUrl: currentTheme.logoUrl,
|
||||
customCss: currentTheme.customCss
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user