Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 4 additions & 13 deletions packages/opencode/src/cli/cmd/tui/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ function App(props: { onSnapshot?: () => Promise<string[]> }) {
const sdk = useSDK()
const toast = useToast()
const themeState = useTheme()
const { theme, mode, setMode, locked, lock, unlock } = themeState
const { theme, mode, setMode, locked, lock, unlock, scheme, setScheme } = themeState
const sync = useSync()
const exit = useExit()
const promptRef = usePromptRef()
Expand Down Expand Up @@ -673,20 +673,11 @@ function App(props: { onSnapshot?: () => Promise<string[]> }) {
category: "System",
},
{
title: "Toggle theme mode",
title: `Theme mode: ${scheme()}`,
value: "theme.switch_mode",
onSelect: (dialog) => {
setMode(mode() === "dark" ? "light" : "dark")
dialog.clear()
},
category: "System",
},
{
title: locked() ? "Unlock theme mode" : "Lock theme mode",
value: "theme.mode.lock",
onSelect: (dialog) => {
if (locked()) unlock()
else lock()
const next = scheme() === "auto" ? "dark" : scheme() === "dark" ? "light" : "auto"
setScheme(next)
dialog.clear()
},
category: "System",
Expand Down
64 changes: 41 additions & 23 deletions packages/opencode/src/cli/cmd/tui/context/theme.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,12 @@ export const DEFAULT_THEMES: Record<string, ThemeJson> = {
carbonfox,
}

type Scheme = "auto" | "dark" | "light"

type State = {
themes: Record<string, ThemeJson>
mode: "dark" | "light"
lock: "dark" | "light" | undefined
scheme: Scheme
active: string
ready: boolean
}
Expand Down Expand Up @@ -154,7 +156,7 @@ function syncThemes() {
const [store, setStore] = createStore<State>({
themes: listThemes(),
mode: "dark",
lock: undefined,
scheme: "auto",
active: "opencode",
ready: false,
})
Expand Down Expand Up @@ -306,17 +308,31 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({
const renderer = useRenderer()
const config = useTuiConfig()
const kv = useKV()
const pick = (value: unknown) => {
const pickMode = (value: unknown) => {
if (value === "dark" || value === "light") return value
return
}

const pickScheme = (value: unknown): Scheme | undefined => {
if (value === "auto" || value === "dark" || value === "light") return value
return
}

setStore(
produce((draft) => {
const lock = pick(kv.get("theme_mode_lock"))
const mode = pick(kv.get("theme_mode", props.mode))
draft.mode = lock ?? mode ?? props.mode
draft.lock = lock
// Read scheme from KV, falling back to legacy theme_mode_lock for backward compat
const saved = pickScheme(kv.get("theme_scheme"))
const legacy = pickMode(kv.get("theme_mode_lock"))
const scheme = saved ?? (legacy ? legacy : "auto")
draft.scheme = scheme

const mode = pickMode(kv.get("theme_mode", props.mode))
if (scheme === "auto") {
draft.mode = mode ?? props.mode
} else {
draft.mode = scheme
}

const active = config.theme ?? kv.get("theme", "opencode")
draft.active = typeof active === "string" ? active : "opencode"
draft.ready = false
Expand Down Expand Up @@ -380,21 +396,19 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({
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)
function setScheme(scheme: Scheme) {
setStore("scheme", scheme)
kv.set("theme_scheme", scheme)
if (scheme === "auto") {
const mode = renderer.themeMode
if (mode) apply(mode)
} else {
apply(scheme)
}
}

const handle = (mode: "dark" | "light") => {
if (store.lock) return
if (store.scheme !== "auto") return
apply(mode)
}
renderer.on(CliRenderEvents.THEME_MODE, handle)
Expand Down Expand Up @@ -451,17 +465,21 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({
mode() {
return store.mode
},
scheme() {
return store.scheme
},
setScheme,
locked() {
return store.lock !== undefined
return store.scheme !== "auto"
},
lock() {
pin(store.mode)
setScheme(store.mode)
},
unlock() {
free()
setScheme("auto")
},
setMode(mode: "dark" | "light") {
pin(mode)
setScheme(mode)
},
set(theme: string) {
if (!hasTheme(theme)) return false
Expand Down
Loading