manually lock/unlock theme mode (#18905)

This commit is contained in:
Sebastian
2026-03-24 10:00:19 +01:00
committed by GitHub
parent 34f43fff89
commit d3debc191f
2 changed files with 46 additions and 7 deletions

View File

@@ -212,7 +212,7 @@ function App() {
const command = useCommandDialog() const command = useCommandDialog()
const sdk = useSDK() const sdk = useSDK()
const toast = useToast() const toast = useToast()
const { theme, mode, setMode } = useTheme() const { theme, mode, setMode, locked, lock, unlock } = useTheme()
const sync = useSync() const sync = useSync()
const exit = useExit() const exit = useExit()
const promptRef = usePromptRef() const promptRef = usePromptRef()
@@ -557,7 +557,7 @@ function App() {
category: "System", category: "System",
}, },
{ {
title: "Toggle appearance", title: "Toggle Theme Mode",
value: "theme.switch_mode", value: "theme.switch_mode",
onSelect: (dialog) => { onSelect: (dialog) => {
setMode(mode() === "dark" ? "light" : "dark") setMode(mode() === "dark" ? "light" : "dark")
@@ -565,6 +565,16 @@ function App() {
}, },
category: "System", category: "System",
}, },
{
title: locked() ? "Unlock Theme Mode" : "Lock Theme Mode",
value: "theme.mode.lock",
onSelect: (dialog) => {
if (locked()) unlock()
else lock()
dialog.clear()
},
category: "System",
},
{ {
title: "Help", title: "Help",
value: "help.show", value: "help.show",

View File

@@ -283,9 +283,15 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({
const renderer = useRenderer() const renderer = useRenderer()
const config = useTuiConfig() const config = useTuiConfig()
const kv = useKV() const kv = useKV()
const pick = (value: unknown) => {
if (value === "dark" || value === "light") return value
return
}
const lock = pick(kv.get("theme_mode_lock"))
const [store, setStore] = createStore({ const [store, setStore] = createStore({
themes: DEFAULT_THEMES, themes: DEFAULT_THEMES,
mode: kv.get("theme_mode", props.mode), mode: lock ?? pick(kv.get("theme_mode", props.mode)) ?? props.mode,
lock,
active: (config.theme ?? kv.get("theme", "opencode")) as string, active: (config.theme ?? kv.get("theme", "opencode")) as string,
ready: false, ready: false,
}) })
@@ -345,16 +351,30 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({
}) })
} }
function update(mode: "dark" | "light") { function apply(mode: "dark" | "light") {
kv.set("theme_mode", mode)
if (store.mode === mode) return if (store.mode === mode) return
setStore("mode", mode) setStore("mode", mode)
kv.set("theme_mode", mode)
renderer.clearPaletteCache() renderer.clearPaletteCache()
resolveSystemTheme(mode) resolveSystemTheme(mode)
} }
function pin(mode: "dark" | "light" = store.mode) {
setStore("lock", mode)
kv.set("theme_mode_lock", mode)
apply(mode)
}
function free() {
setStore("lock", undefined)
kv.set("theme_mode_lock", undefined)
const mode = renderer.themeMode
if (mode) apply(mode)
}
const handle = (mode: "dark" | "light") => { const handle = (mode: "dark" | "light") => {
update(mode) if (store.lock) return
apply(mode)
} }
renderer.on(CliRenderEvents.THEME_MODE, handle) renderer.on(CliRenderEvents.THEME_MODE, handle)
onCleanup(() => { onCleanup(() => {
@@ -390,8 +410,17 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({
mode() { mode() {
return store.mode return store.mode
}, },
locked() {
return store.lock !== undefined
},
lock() {
pin(store.mode)
},
unlock() {
free()
},
setMode(mode: "dark" | "light") { setMode(mode: "dark" | "light") {
update(mode) pin(mode)
}, },
set(theme: string) { set(theme: string) {
setStore("active", theme) setStore("active", theme)