Skip to content

Commit d3debc1

Browse files
authored
manually lock/unlock theme mode (#18905)
1 parent 34f43ff commit d3debc1

2 files changed

Lines changed: 46 additions & 7 deletions

File tree

packages/opencode/src/cli/cmd/tui/app.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ function App() {
212212
const command = useCommandDialog()
213213
const sdk = useSDK()
214214
const toast = useToast()
215-
const { theme, mode, setMode } = useTheme()
215+
const { theme, mode, setMode, locked, lock, unlock } = useTheme()
216216
const sync = useSync()
217217
const exit = useExit()
218218
const promptRef = usePromptRef()
@@ -557,14 +557,24 @@ function App() {
557557
category: "System",
558558
},
559559
{
560-
title: "Toggle appearance",
560+
title: "Toggle Theme Mode",
561561
value: "theme.switch_mode",
562562
onSelect: (dialog) => {
563563
setMode(mode() === "dark" ? "light" : "dark")
564564
dialog.clear()
565565
},
566566
category: "System",
567567
},
568+
{
569+
title: locked() ? "Unlock Theme Mode" : "Lock Theme Mode",
570+
value: "theme.mode.lock",
571+
onSelect: (dialog) => {
572+
if (locked()) unlock()
573+
else lock()
574+
dialog.clear()
575+
},
576+
category: "System",
577+
},
568578
{
569579
title: "Help",
570580
value: "help.show",

packages/opencode/src/cli/cmd/tui/context/theme.tsx

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -283,9 +283,15 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({
283283
const renderer = useRenderer()
284284
const config = useTuiConfig()
285285
const kv = useKV()
286+
const pick = (value: unknown) => {
287+
if (value === "dark" || value === "light") return value
288+
return
289+
}
290+
const lock = pick(kv.get("theme_mode_lock"))
286291
const [store, setStore] = createStore({
287292
themes: DEFAULT_THEMES,
288-
mode: kv.get("theme_mode", props.mode),
293+
mode: lock ?? pick(kv.get("theme_mode", props.mode)) ?? props.mode,
294+
lock,
289295
active: (config.theme ?? kv.get("theme", "opencode")) as string,
290296
ready: false,
291297
})
@@ -345,16 +351,30 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({
345351
})
346352
}
347353

348-
function update(mode: "dark" | "light") {
354+
function apply(mode: "dark" | "light") {
355+
kv.set("theme_mode", mode)
349356
if (store.mode === mode) return
350357
setStore("mode", mode)
351-
kv.set("theme_mode", mode)
352358
renderer.clearPaletteCache()
353359
resolveSystemTheme(mode)
354360
}
355361

362+
function pin(mode: "dark" | "light" = store.mode) {
363+
setStore("lock", mode)
364+
kv.set("theme_mode_lock", mode)
365+
apply(mode)
366+
}
367+
368+
function free() {
369+
setStore("lock", undefined)
370+
kv.set("theme_mode_lock", undefined)
371+
const mode = renderer.themeMode
372+
if (mode) apply(mode)
373+
}
374+
356375
const handle = (mode: "dark" | "light") => {
357-
update(mode)
376+
if (store.lock) return
377+
apply(mode)
358378
}
359379
renderer.on(CliRenderEvents.THEME_MODE, handle)
360380
onCleanup(() => {
@@ -390,8 +410,17 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({
390410
mode() {
391411
return store.mode
392412
},
413+
locked() {
414+
return store.lock !== undefined
415+
},
416+
lock() {
417+
pin(store.mode)
418+
},
419+
unlock() {
420+
free()
421+
},
393422
setMode(mode: "dark" | "light") {
394-
update(mode)
423+
pin(mode)
395424
},
396425
set(theme: string) {
397426
setStore("active", theme)

0 commit comments

Comments
 (0)