|
1 | 1 | import { SyntaxStyle, RGBA, type TerminalColors } from "@opentui/core" |
2 | | -import { createMemo } from "solid-js" |
| 2 | +import path from "path" |
| 3 | +import { createEffect, createMemo, onMount } from "solid-js" |
3 | 4 | import { useSync } from "@tui/context/sync" |
4 | 5 | import { createSimpleContext } from "./helper" |
5 | 6 | import aura from "./theme/aura.json" with { type: "json" } |
@@ -27,7 +28,9 @@ import vesper from "./theme/vesper.json" with { type: "json" } |
27 | 28 | import zenburn from "./theme/zenburn.json" with { type: "json" } |
28 | 29 | import { useKV } from "./kv" |
29 | 30 | import { useRenderer } from "@opentui/solid" |
30 | | -import { createStore } from "solid-js/store" |
| 31 | +import { createStore, produce } from "solid-js/store" |
| 32 | +import { Global } from "@/global" |
| 33 | +import { Filesystem } from "@/util/filesystem" |
31 | 34 |
|
32 | 35 | type Theme = { |
33 | 36 | primary: RGBA |
@@ -144,6 +147,17 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({ |
144 | 147 | themes: DEFAULT_THEMES, |
145 | 148 | mode: props.mode, |
146 | 149 | active: (sync.data.config.theme ?? kv.get("theme", "opencode")) as string, |
| 150 | + ready: false, |
| 151 | + }) |
| 152 | + |
| 153 | + createEffect(async () => { |
| 154 | + const custom = await getCustomThemes() |
| 155 | + setStore( |
| 156 | + produce((draft) => { |
| 157 | + Object.assign(draft.themes, custom) |
| 158 | + draft.ready = true |
| 159 | + }), |
| 160 | + ) |
147 | 161 | }) |
148 | 162 |
|
149 | 163 | const renderer = useRenderer() |
@@ -187,12 +201,39 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({ |
187 | 201 | kv.set("theme", theme) |
188 | 202 | }, |
189 | 203 | get ready() { |
190 | | - return sync.ready |
| 204 | + return store.ready |
191 | 205 | }, |
192 | 206 | } |
193 | 207 | }, |
194 | 208 | }) |
195 | 209 |
|
| 210 | +const CUSTOM_THEME_GLOB = new Bun.Glob("themes/*.json") |
| 211 | +async function getCustomThemes() { |
| 212 | + const directories = [ |
| 213 | + Global.Path.config, |
| 214 | + ...(await Array.fromAsync( |
| 215 | + Filesystem.up({ |
| 216 | + targets: [".opencode"], |
| 217 | + start: process.cwd(), |
| 218 | + }), |
| 219 | + )), |
| 220 | + ] |
| 221 | + |
| 222 | + const result: Record<string, ThemeJson> = {} |
| 223 | + for (const dir of directories) { |
| 224 | + for await (const item of CUSTOM_THEME_GLOB.scan({ |
| 225 | + absolute: true, |
| 226 | + followSymlinks: true, |
| 227 | + dot: true, |
| 228 | + cwd: dir, |
| 229 | + })) { |
| 230 | + const name = path.basename(item, ".json") |
| 231 | + result[name] = await Bun.file(item).json() |
| 232 | + } |
| 233 | + } |
| 234 | + return result |
| 235 | +} |
| 236 | + |
196 | 237 | function generateSystem(colors: TerminalColors, mode: "dark" | "light"): ThemeJson { |
197 | 238 | const bg = RGBA.fromHex(colors.defaultBackground ?? colors.palette[0]!) |
198 | 239 | const fg = RGBA.fromHex(colors.defaultForeground ?? colors.palette[7]!) |
|
0 commit comments