mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-27 15:13:37 +08:00
feat(desktop): default new installs to dark theme (#53)
Coding workbench, eyes-friendly default. The theme picker still has
white/light/dark/system; this only flips the fallback that applies when:
- localStorage has no `cc-haha-theme` (fresh install)
- the server has no persisted user theme (`getUser` returns no
`theme` field)
Existing users who already set any preference (including 'white') keep
theirs — both the localStorage hydration in uiStore and the fetchAll
merge in settingsStore preserve a stored value over the new default.
Files:
- desktop/index.html: prepaint <html data-theme> "white" -> "dark"
(this is the value the page shows for the few ms before
initializeTheme() runs, so flipping it kills the white flash)
- desktop/src/stores/uiStore.ts: getStoredTheme() fallback
- desktop/src/stores/settingsStore.ts: fetchAll serverTheme fallback
- tests for both stores updated; cycle test pinned to an explicit
starting point so it does not depend on the default
Tested:
- bunx vitest src/stores/uiStore.test.ts (3/3)
- bunx vitest src/stores/settingsStore.test.ts (31/31)
- bunx vitest src/__tests__/generalSettings.test.tsx (54/54)
- bunx vitest src/__tests__/diagnosticsSettings.test.tsx + Mermaid +
DiffViewer (10/10)
- bun run lint (tsc --noEmit) clean
Confidence: high
Scope-risk: narrow
Co-authored-by: 你的姓名 <you@example.com>
This commit is contained in:
parent
f31b3c39f5
commit
de88dd792e
@ -1,5 +1,5 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN" data-theme="white">
|
||||
<html lang="zh-CN" data-theme="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<!--
|
||||
|
||||
@ -1008,7 +1008,7 @@ describe('settingsStore theme persistence', () => {
|
||||
document.documentElement.style.colorScheme = ''
|
||||
})
|
||||
|
||||
it('falls back to the pure white theme when user settings have no theme', async () => {
|
||||
it('falls back to dark when user settings have no theme', async () => {
|
||||
vi.doMock('../api/settings', () => ({
|
||||
settingsApi: {
|
||||
getUser: vi.fn().mockResolvedValue({}),
|
||||
@ -1049,10 +1049,10 @@ 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')
|
||||
})
|
||||
|
||||
it('hydrates the pure white theme from user settings', async () => {
|
||||
|
||||
@ -229,7 +229,7 @@ export const useSettingsStore = create<SettingsStore>((set, get) => ({
|
||||
loadH5AccessSettings(previousH5Access),
|
||||
loadTraceCaptureSettings(),
|
||||
])
|
||||
const serverTheme = isThemeMode(userSettings.theme) ? userSettings.theme : 'white'
|
||||
const serverTheme = isThemeMode(userSettings.theme) ? userSettings.theme : 'dark'
|
||||
// 'system' is a desktop-only logical mode that never gets persisted to the
|
||||
// server (the server rejects it). If the user previously chose 'system' and
|
||||
// it was stored locally, honour the local value instead of overwriting it
|
||||
|
||||
@ -8,16 +8,16 @@ describe('uiStore theme handling', () => {
|
||||
document.documentElement.style.colorScheme = ''
|
||||
})
|
||||
|
||||
it('defaults new installs to the pure white theme', async () => {
|
||||
it('defaults new installs to dark', async () => {
|
||||
const { initializeTheme, useUIStore } = await import('./uiStore')
|
||||
|
||||
expect(useUIStore.getState().theme).toBe('white')
|
||||
expect(useUIStore.getState().theme).toBe('dark')
|
||||
initializeTheme()
|
||||
expect(document.documentElement.getAttribute('data-theme')).toBe('white')
|
||||
expect(document.documentElement.style.colorScheme).toBe('light')
|
||||
expect(document.documentElement.getAttribute('data-theme')).toBe('dark')
|
||||
expect(document.documentElement.style.colorScheme).toBe('dark')
|
||||
})
|
||||
|
||||
it('hydrates and applies the pure white theme as a light color scheme', async () => {
|
||||
it('honours an existing stored preference over the new default (no upgrade clobber)', async () => {
|
||||
window.localStorage.setItem('cc-haha-theme', 'white')
|
||||
|
||||
const { initializeTheme, useUIStore } = await import('./uiStore')
|
||||
@ -31,7 +31,10 @@ describe('uiStore theme handling', () => {
|
||||
it('cycles through all theme modes in order', async () => {
|
||||
const { useUIStore } = await import('./uiStore')
|
||||
|
||||
// white (default) → light
|
||||
// Pin the starting point so this test does not depend on the default.
|
||||
useUIStore.getState().setTheme('white')
|
||||
|
||||
// white → light
|
||||
useUIStore.getState().toggleTheme()
|
||||
expect(useUIStore.getState().theme).toBe('light')
|
||||
expect(document.documentElement.style.colorScheme).toBe('light')
|
||||
|
||||
@ -8,7 +8,9 @@ function getStoredTheme(): ThemeMode {
|
||||
const stored = localStorage.getItem(THEME_STORAGE_KEY)
|
||||
if (isThemeMode(stored)) return stored
|
||||
} catch { /* localStorage unavailable */ }
|
||||
return 'white'
|
||||
// New installs default to dark — easier on the eyes for a coding workbench.
|
||||
// Existing users with a stored preference (including 'white') keep theirs.
|
||||
return 'dark'
|
||||
}
|
||||
|
||||
function getSystemPrefersDark(): boolean {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user