From 8320a3619590e9f34a1986007cffeb7f177cd49c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=91=98=E9=98=BF=E6=B1=9F=28Relakkes?= =?UTF-8?q?=29?= Date: Sat, 11 Jul 2026 00:44:20 +0800 Subject: [PATCH] fix(desktop): isolate app theme from Claude CLI #987 Keep the desktop appearance in cc-haha local storage instead of reading or writing the user-owned Claude settings theme. Tested: bun run test -- src/stores/settingsStore.test.ts Tested: bun run check:desktop Tested: bun run check:coverage Tested: agent-browser theme isolation smoke with temporary CLAUDE_CONFIG_DIR Confidence: high Scope-risk: narrow --- desktop/src/stores/settingsStore.test.ts | 21 ++++++++++++++------- desktop/src/stores/settingsStore.ts | 10 +--------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/desktop/src/stores/settingsStore.test.ts b/desktop/src/stores/settingsStore.test.ts index c0fbdaa2..679082f9 100644 --- a/desktop/src/stores/settingsStore.test.ts +++ b/desktop/src/stores/settingsStore.test.ts @@ -1112,11 +1112,13 @@ describe('settingsStore theme persistence', () => { expect(document.documentElement.style.colorScheme).toBe('light') }) - it('hydrates the pure white theme from user settings', async () => { + it('keeps the desktop theme independent from the Claude user theme', async () => { + window.localStorage.setItem('cc-haha-theme', 'dark') + const updateUser = vi.fn() vi.doMock('../api/settings', () => ({ settingsApi: { - getUser: vi.fn().mockResolvedValue({ theme: 'white' }), - updateUser: vi.fn(), + getUser: vi.fn().mockResolvedValue({ theme: 'light', unknownField: 'keep-me' }), + updateUser, getPermissionMode: vi.fn().mockResolvedValue({ mode: 'default' }), setPermissionMode: vi.fn(), getCliLauncherStatus: vi.fn(), @@ -1153,10 +1155,15 @@ describe('settingsStore theme persistence', () => { await useSettingsStore.getState().fetchAll() - expect(useSettingsStore.getState().theme).toBe('white') - expect(useUIStore.getState().theme).toBe('white') - expect(document.documentElement.getAttribute('data-theme')).toBe('white') - expect(document.documentElement.style.colorScheme).toBe('light') + expect(useSettingsStore.getState().theme).toBe('dark') + expect(useUIStore.getState().theme).toBe('dark') + expect(document.documentElement.getAttribute('data-theme')).toBe('dark') + expect(document.documentElement.style.colorScheme).toBe('dark') + + await useSettingsStore.getState().setTheme('light') + + expect(window.localStorage.getItem('cc-haha-theme')).toBe('light') + expect(updateUser).not.toHaveBeenCalled() }) }) diff --git a/desktop/src/stores/settingsStore.ts b/desktop/src/stores/settingsStore.ts index 634f20f0..efe2f356 100644 --- a/desktop/src/stores/settingsStore.ts +++ b/desktop/src/stores/settingsStore.ts @@ -5,7 +5,6 @@ import { modelsApi } from '../api/models' import { h5AccessApi } from '../api/h5Access' import { tracesApi } from '../api/traces' import { - isThemeMode, type AppMode, type AppModeConfig, type ChatSendBehavior, @@ -230,7 +229,7 @@ export const useSettingsStore = create((set, get) => ({ loadH5AccessSettings(previousH5Access), loadTraceCaptureSettings(), ]) - const theme = isThemeMode(userSettings.theme) ? userSettings.theme : 'white' + const theme = useUIStore.getState().theme useUIStore.getState().setTheme(theme) set({ permissionMode: mode, @@ -327,15 +326,8 @@ export const useSettingsStore = create((set, get) => ({ }, setTheme: async (theme) => { - const prev = get().theme set({ theme }) useUIStore.getState().setTheme(theme) - try { - await settingsApi.updateUser({ theme }) - } catch { - set({ theme: prev }) - useUIStore.getState().setTheme(prev) - } }, setChatSendBehavior: async (behavior) => {