fixed tmux system theme loading

This commit is contained in:
2026-02-05 14:20:51 -05:00
parent e239b33042
commit 3d156403c7
3 changed files with 99 additions and 48 deletions

View File

@@ -1,5 +1,4 @@
import { createSignal } from "solid-js";
import { useRenderer } from "@opentui/solid";
import { Layout } from "./components/Layout";
import { Navigation } from "./components/Navigation";
import { TabNavigation } from "./components/TabNavigation";

View File

@@ -9,7 +9,7 @@ import { generateSyntax, generateSubtleSyntax } from "../utils/syntax-highlighte
import { resolveTerminalTheme, loadThemes } from "../utils/theme"
import { createSimpleContext } from "./helper"
import { setupThemeSignalHandler, emitThemeChanged, emitThemeModeChanged } from "../utils/theme-observer"
import type { RGBA, TerminalColors } from "@opentui/core"
import { createTerminalPalette, type RGBA, type TerminalColors } from "@opentui/core"
type ThemeResolved = {
primary: RGBA
@@ -121,11 +121,58 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({
})
}
function resolveSystemTheme() {
renderer
.getPalette({ size: 16 })
.then((colors) => {
if (!colors.palette[0]) {
async function waitForCapabilities(timeoutMs = 300) {
if (renderer.capabilities) return
await new Promise<void>((resolve) => {
let done = false
const onCaps = () => {
if (done) return
done = true
renderer.off("capabilities", onCaps)
clearTimeout(timer)
resolve()
}
const timer = setTimeout(() => {
if (done) return
done = true
renderer.off("capabilities", onCaps)
resolve()
}, timeoutMs)
renderer.on("capabilities", onCaps)
})
}
async function resolveSystemTheme() {
if (process.env.TMUX) {
await waitForCapabilities()
}
let colors: TerminalColors | null = null
try {
colors = await renderer.getPalette({ size: 16 })
} catch {
colors = null
}
if (!colors?.palette?.[0] && process.env.TMUX) {
const writeOut = (renderer as unknown as { writeOut?: (data: string | Buffer) => boolean }).writeOut
const writeFn = typeof writeOut === "function" ? writeOut.bind(renderer) : process.stdout.write.bind(process.stdout)
const detector = createTerminalPalette(process.stdin, process.stdout, writeFn, true)
try {
const tmuxColors = await detector.detect({ size: 16, timeout: 1200 })
if (tmuxColors?.palette?.[0]) {
colors = tmuxColors
}
} finally {
detector.cleanup()
}
}
const hasPalette = Boolean(colors?.palette?.some((value) => Boolean(value)))
const hasDefaultColors = Boolean(colors?.defaultBackground || colors?.defaultForeground)
if (!hasPalette && !hasDefaultColors) {
// No system colors available, fall back to default
// This happens when the terminal doesn't support OSC palette queries
// (e.g., running inside tmux, or on unsupported terminals)
@@ -139,6 +186,8 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({
}
return
}
if (colors) {
setStore(
produce((draft) => {
draft.system = colors
@@ -147,18 +196,7 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({
}
})
)
})
.catch(() => {
// On error, fall back to default theme if using system
if (store.active === "system") {
setStore(
produce((draft) => {
draft.active = "opencode"
draft.ready = true
})
)
}
})
}
onMount(init)

View File

@@ -1,4 +1,10 @@
import { render } from "@opentui/solid"
// Hack: Force TERM to tmux-256color when running in tmux to enable
// correct palette detection in @opentui/core
if (process.env.TMUX && !process.env.TERM?.includes("tmux")) {
process.env.TERM = "tmux-256color"
}
import { render, useRenderer } from "@opentui/solid"
import { App } from "./App"
import { ThemeProvider } from "./context/ThemeContext"
import { ToastProvider, Toast } from "./ui/toast"
@@ -6,7 +12,14 @@ import { KeybindProvider } from "./context/KeybindContext"
import { DialogProvider } from "./ui/dialog"
import { CommandProvider } from "./ui/command"
function RendererSetup(props: { children: unknown }) {
const renderer = useRenderer()
renderer.disableStdoutInterception()
return props.children
}
render(() => (
<RendererSetup>
<ToastProvider>
<ThemeProvider mode="dark">
<KeybindProvider>
@@ -19,4 +32,5 @@ render(() => (
</KeybindProvider>
</ThemeProvider>
</ToastProvider>
</RendererSetup>
))