feat(ui): persist theme preference
Persist system/light/dark theme mode in app config and default new installs to system so the UI follows OS theme unless overridden.
This commit is contained in:
@@ -78,12 +78,12 @@ const resolvePaletteColors = (dark: boolean): ResolvedPaletteColors => {
|
|||||||
|
|
||||||
export function ThemeProvider(props: { children: JSX.Element }) {
|
export function ThemeProvider(props: { children: JSX.Element }) {
|
||||||
const mediaQuery = typeof window !== "undefined" ? window.matchMedia("(prefers-color-scheme: dark)") : null
|
const mediaQuery = typeof window !== "undefined" ? window.matchMedia("(prefers-color-scheme: dark)") : null
|
||||||
const { themePreference } = useConfig()
|
const { themePreference, setThemePreference } = useConfig()
|
||||||
const [isDark, setIsDarkSignal] = createSignal(true)
|
const [isDark, setIsDarkSignal] = createSignal(true)
|
||||||
const [themeMode, setThemeModeSignal] = createSignal<ThemeMode>(themePreference())
|
|
||||||
const [hasUserOverride, setHasUserOverride] = createSignal(false)
|
|
||||||
const [themeRevision, setThemeRevision] = createSignal(0)
|
const [themeRevision, setThemeRevision] = createSignal(0)
|
||||||
|
|
||||||
|
const themeMode = () => themePreference() as ThemeMode
|
||||||
|
|
||||||
const resolveDarkTheme = () => {
|
const resolveDarkTheme = () => {
|
||||||
const mode = themeMode()
|
const mode = themeMode()
|
||||||
if (mode === "dark") return true
|
if (mode === "dark") return true
|
||||||
@@ -111,12 +111,6 @@ export function ThemeProvider(props: { children: JSX.Element }) {
|
|||||||
applyResolvedTheme()
|
applyResolvedTheme()
|
||||||
})
|
})
|
||||||
|
|
||||||
createEffect(() => {
|
|
||||||
const preference = themePreference()
|
|
||||||
if (hasUserOverride()) return
|
|
||||||
setThemeModeSignal(preference)
|
|
||||||
})
|
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
if (!mediaQuery) return
|
if (!mediaQuery) return
|
||||||
const handleSystemThemeChange = () => {
|
const handleSystemThemeChange = () => {
|
||||||
@@ -131,10 +125,7 @@ export function ThemeProvider(props: { children: JSX.Element }) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const setThemeMode = (mode: ThemeMode) => {
|
const setThemeMode = (mode: ThemeMode) => {
|
||||||
setHasUserOverride(true)
|
setThemePreference(mode)
|
||||||
setThemeModeSignal(mode)
|
|
||||||
// Persistence is intentionally implemented later.
|
|
||||||
// When we wire it up, this should call `setThemePreference(mode)`.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const cycleThemeMode = () => {
|
const cycleThemeMode = () => {
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ const [isConfigLoaded, setIsConfigLoaded] = createSignal(false)
|
|||||||
const preferences = createMemo<Preferences>(() => internalConfig().preferences)
|
const preferences = createMemo<Preferences>(() => internalConfig().preferences)
|
||||||
const recentFolders = createMemo<RecentFolder[]>(() => internalConfig().recentFolders ?? [])
|
const recentFolders = createMemo<RecentFolder[]>(() => internalConfig().recentFolders ?? [])
|
||||||
const opencodeBinaries = createMemo<OpenCodeBinary[]>(() => internalConfig().opencodeBinaries ?? [])
|
const opencodeBinaries = createMemo<OpenCodeBinary[]>(() => internalConfig().opencodeBinaries ?? [])
|
||||||
const themePreference = createMemo<ThemePreference>(() => internalConfig().theme ?? "dark")
|
const themePreference = createMemo<ThemePreference>(() => internalConfig().theme ?? "system")
|
||||||
let loadPromise: Promise<void> | null = null
|
let loadPromise: Promise<void> | null = null
|
||||||
|
|
||||||
function normalizeConfig(config?: ConfigData | null): ConfigData {
|
function normalizeConfig(config?: ConfigData | null): ConfigData {
|
||||||
@@ -202,7 +202,7 @@ function normalizeConfig(config?: ConfigData | null): ConfigData {
|
|||||||
preferences: normalizePreferences(config?.preferences),
|
preferences: normalizePreferences(config?.preferences),
|
||||||
recentFolders: (config?.recentFolders ?? []).map((folder) => ({ ...folder })),
|
recentFolders: (config?.recentFolders ?? []).map((folder) => ({ ...folder })),
|
||||||
opencodeBinaries: (config?.opencodeBinaries ?? []).map((binary) => ({ ...binary })),
|
opencodeBinaries: (config?.opencodeBinaries ?? []).map((binary) => ({ ...binary })),
|
||||||
theme: config?.theme ?? "dark",
|
theme: config?.theme ?? "system",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user