diff --git a/apps/desktop/src/themes/backend-sync.test.ts b/apps/desktop/src/themes/backend-sync.test.ts index 63b28712e86..504e4e45c88 100644 --- a/apps/desktop/src/themes/backend-sync.test.ts +++ b/apps/desktop/src/themes/backend-sync.test.ts @@ -45,13 +45,25 @@ describe('ingestBackendSkin', () => { expect($pendingSkinApply.get()).toBe('forest') }) - it('treats default as no-opinion: never registers or applies it', () => { + it('never registers default in the backend store (desktop keeps its own palette)', () => { ingestBackendSkin(skin('default'), { apply: true }) - expect($pendingSkinApply.get()).toBeNull() expect($backendThemes.get().default).toBeUndefined() }) + it('does not apply default on the connect-time seed', () => { + ingestBackendSkin(skin('default'), { apply: false }) + + expect($pendingSkinApply.get()).toBeNull() + }) + + it('applies a runtime switch back to default (repaints the desktop to its own default)', () => { + ingestBackendSkin(skin('neon'), { apply: false }) // gateway.ready seed on some skin + ingestBackendSkin(skin('default'), { apply: true }) // Hermes switched back to default + + expect($pendingSkinApply.get()).toBe('default') + }) + it('does not shadow a built-in name but can still apply it', () => { ingestBackendSkin(skin('mono'), { apply: true }) diff --git a/apps/desktop/src/themes/backend-sync.ts b/apps/desktop/src/themes/backend-sync.ts index f6146829066..d0e4ddc2031 100644 --- a/apps/desktop/src/themes/backend-sync.ts +++ b/apps/desktop/src/themes/backend-sync.ts @@ -53,17 +53,14 @@ export function ingestBackendSkin(skin: HermesSkin | undefined | null, { apply } return } - // `default` is "no opinion" — the desktop keeps its own default (nous). Record - // it as the baseline so a real skin authored later reads as a change. - if (name === 'default') { - lastSynced = 'default' - - return - } - + // `default` is "no opinion" on the PALETTE — the desktop keeps its own default + // (nous), so we never register a converted theme under `default`. It is still a + // valid apply TARGET though: a runtime switch back to `default` must repaint the + // desktop to its own default (setTheme normalizes `default` → nous). So we only + // skip the registry step here and let it flow through the apply logic below. // Built-in names (mono/slate/…) already have a hand-tuned desktop palette — we // never shadow it, but the name is still a valid apply target. - if (!BUILTIN_THEMES[name]) { + if (name !== 'default' && !BUILTIN_THEMES[name]) { const theme = skinToDesktopTheme(skin as HermesSkin) if (!theme) {