Park remaining local WIP on main. TUI archived, CLI/kernel edits, glass. Sort later. Broken is fine.
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
preload = ["@neuron-tui/solid/preload"]
|
||||
|
||||
[test]
|
||||
preload = ["@neuron-tui/solid/preload"]
|
||||
@@ -52,9 +52,11 @@
|
||||
"@opencode-ai/plugin": "workspace:*",
|
||||
"@opencode-ai/sdk": "workspace:*",
|
||||
"@opencode-ai/ui": "workspace:*",
|
||||
"@opentui/core": "catalog:",
|
||||
"@opentui/keymap": "catalog:",
|
||||
"@opentui/solid": "catalog:",
|
||||
"@neuron-tui/core": "workspace:*",
|
||||
"@neuron-tui/core-darwin-arm64": "workspace:*",
|
||||
"@neuron-tui/keymap": "workspace:*",
|
||||
"@neuron-tui/solid": "workspace:*",
|
||||
"@neuron/glass": "workspace:*",
|
||||
"clipboardy": "4.0.0",
|
||||
"diff": "catalog:",
|
||||
"effect": "catalog:",
|
||||
@@ -1,6 +1,6 @@
|
||||
import { render, TimeToFirstDraw, useRenderer, useTerminalDimensions } from "@opentui/solid"
|
||||
import { render, TimeToFirstDraw, useRenderer, useTerminalDimensions } from "@neuron-tui/solid"
|
||||
import { registerOpencodeSpinner } from "./component/register-spinner"
|
||||
import { createDefaultOpenTuiKeymap } from "@opentui/keymap/opentui"
|
||||
import { createDefaultOpenTuiKeymap } from "@neuron-tui/keymap/opentui"
|
||||
import { Deferred, Effect } from "effect"
|
||||
import { Global } from "@opencode-ai/core/global"
|
||||
import { Flag } from "@opencode-ai/core/flag/flag"
|
||||
@@ -9,7 +9,8 @@ import { ClipboardProvider, useClipboard } from "./context/clipboard"
|
||||
import { ExitProvider, useExit } from "./context/exit"
|
||||
import { EpilogueProvider } from "./context/epilogue"
|
||||
import * as Selection from "./util/selection"
|
||||
import { createCliRenderer, MouseButton } from "@opentui/core"
|
||||
import { createCliRenderer, MouseButton } from "@neuron-tui/core"
|
||||
import { ziggy } from "./ziggy"
|
||||
import { RouteProvider, useRoute } from "./context/route"
|
||||
import {
|
||||
Switch,
|
||||
@@ -190,20 +191,28 @@ export const run = Effect.fn("Tui.run")(function* (input: TuiInput) {
|
||||
Effect.gen(function* () {
|
||||
const renderer = yield* Effect.acquireRelease(
|
||||
Effect.tryPromise({
|
||||
try: () =>
|
||||
createCliRenderer({
|
||||
try: () => {
|
||||
const width = Math.max(process.stdout.columns || 0, 80)
|
||||
const height = Math.max(process.stdout.rows || 0, 24)
|
||||
return createCliRenderer({
|
||||
width,
|
||||
height,
|
||||
backgroundColor: "#0a0a0a",
|
||||
externalOutputMode: "passthrough",
|
||||
useThread: false,
|
||||
present: ziggy,
|
||||
targetFps: 60,
|
||||
gatherStats: false,
|
||||
exitOnCtrlC: false,
|
||||
useKittyKeyboard: {},
|
||||
useKittyKeyboard: false,
|
||||
autoFocus: false,
|
||||
openConsoleOnError: false,
|
||||
useMouse: !Flag.OPENCODE_DISABLE_MOUSE && input.config.mouse,
|
||||
consoleOptions: {
|
||||
keyBindings: [{ name: "y", ctrl: true, action: "copy-selection" }],
|
||||
},
|
||||
}),
|
||||
})
|
||||
},
|
||||
catch: (error) => (error instanceof Error ? error : new Error(String(error))),
|
||||
}),
|
||||
(renderer) =>
|
||||
@@ -237,11 +246,8 @@ export const run = Effect.fn("Tui.run")(function* (input: TuiInput) {
|
||||
const pluginRuntime = createPluginRuntime()
|
||||
|
||||
yield* Effect.tryPromise(async () => {
|
||||
// Prewarm palette before ThemeProvider mounts so `system` theme avoids a first-paint fallback flash.
|
||||
void renderer.getPalette({ size: 16 }).catch(() => undefined)
|
||||
const mode = (await renderer.waitForThemeMode(1000)) ?? "dark"
|
||||
if (renderer.isDestroyed) return
|
||||
|
||||
const mode = "dark"
|
||||
await render(() => {
|
||||
return (
|
||||
<ExitProvider
|
||||
@@ -349,6 +355,7 @@ export const run = Effect.fn("Tui.run")(function* (input: TuiInput) {
|
||||
</ExitProvider>
|
||||
)
|
||||
}, renderer)
|
||||
renderer.start()
|
||||
})
|
||||
yield* Deferred.await(shutdown)
|
||||
return { epilogue: exit.epilogue, reason: exit.reason }
|
||||
@@ -367,6 +374,8 @@ function App(props: { onSnapshot?: () => Promise<string[]>; pluginHost: TuiPlugi
|
||||
const tuiConfig = useTuiConfig()
|
||||
const route = useRoute()
|
||||
const dimensions = useTerminalDimensions()
|
||||
const width = () => Math.max(dimensions().width || 0, 80)
|
||||
const height = () => Math.max(dimensions().height || 0, 24)
|
||||
const renderer = useRenderer()
|
||||
const dialog = useDialog()
|
||||
const local = useLocal()
|
||||
@@ -404,8 +413,8 @@ function App(props: { onSnapshot?: () => Promise<string[]>; pluginHost: TuiPlugi
|
||||
Slot: pluginRuntime.Slot,
|
||||
}),
|
||||
)
|
||||
const [ready, setReady] = createSignal(false)
|
||||
props.pluginHost
|
||||
const [ready, setReady] = createSignal(true)
|
||||
void props.pluginHost
|
||||
.start({
|
||||
api,
|
||||
config: tuiConfig,
|
||||
@@ -415,9 +424,6 @@ function App(props: { onSnapshot?: () => Promise<string[]>; pluginHost: TuiPlugi
|
||||
.catch((error) => {
|
||||
console.error("Failed to load TUI plugins", error)
|
||||
})
|
||||
.finally(() => {
|
||||
setReady(true)
|
||||
})
|
||||
|
||||
// Let selection copy/dismiss win ahead of normal bindings when explicit copy is required.
|
||||
const offSelectionKeys = keymap.intercept(
|
||||
@@ -1086,8 +1092,8 @@ function App(props: { onSnapshot?: () => Promise<string[]>; pluginHost: TuiPlugi
|
||||
|
||||
return (
|
||||
<box
|
||||
width={dimensions().width}
|
||||
height={dimensions().height}
|
||||
width={width()}
|
||||
height={height()}
|
||||
flexDirection="column"
|
||||
backgroundColor={theme.background}
|
||||
onMouseDown={(evt) => {
|
||||
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
@@ -1,4 +1,4 @@
|
||||
import { Audio, type AudioErrorContext, type AudioPlayOptions, type AudioSound, type AudioVoice } from "@opentui/core"
|
||||
import { Audio, type AudioErrorContext, type AudioPlayOptions, type AudioSound, type AudioVoice } from "@neuron-tui/core"
|
||||
import { readFile } from "node:fs/promises"
|
||||
|
||||
let audio: Audio | null | undefined
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { OptimizedBuffer, RGBA, TextAttributes } from "@opentui/core"
|
||||
import { OptimizedBuffer, RGBA, TextAttributes } from "@neuron-tui/core"
|
||||
import { go } from "../logo"
|
||||
|
||||
const PERIOD = 4600
|
||||
+3
-3
@@ -4,8 +4,8 @@ import {
|
||||
type OptimizedBuffer,
|
||||
type RenderContext,
|
||||
type RenderableOptions,
|
||||
} from "@opentui/core"
|
||||
import { extend, useRenderer } from "@opentui/solid"
|
||||
} from "@neuron-tui/core"
|
||||
import { extend, useRenderer } from "@neuron-tui/solid"
|
||||
import { onCleanup, onMount } from "solid-js"
|
||||
import { tint, useTheme } from "../context/theme"
|
||||
import { GoUpsellArtPainter } from "./bg-pulse-render"
|
||||
@@ -60,7 +60,7 @@ class GoUpsellArtRenderable extends FrameBufferRenderable {
|
||||
}
|
||||
}
|
||||
|
||||
declare module "@opentui/solid" {
|
||||
declare module "@neuron-tui/solid" {
|
||||
interface OpenTUIComponents {
|
||||
go_upsell_art: typeof GoUpsellArtRenderable
|
||||
}
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import { createResource, createMemo, createSignal } from "solid-js"
|
||||
import { TextAttributes } from "@opentui/core"
|
||||
import { TextAttributes } from "@neuron-tui/core"
|
||||
import { DialogSelect } from "../ui/dialog-select"
|
||||
import { useSDK } from "../context/sdk"
|
||||
import { useDialog } from "../ui/dialog"
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { TextAttributes } from "@opentui/core"
|
||||
import { TextAttributes } from "@neuron-tui/core"
|
||||
import { createMemo, createSignal, For } from "solid-js"
|
||||
import { InstallationChannel, InstallationVersion } from "@opencode-ai/core/installation/version"
|
||||
import { useTheme } from "../context/theme"
|
||||
+1
-1
@@ -4,7 +4,7 @@ import { useSync } from "../context/sync"
|
||||
import { map, pipe, entries, sortBy } from "remeda"
|
||||
import { DialogSelect, type DialogSelectRef, type DialogSelectOption } from "../ui/dialog-select"
|
||||
import { useTheme } from "../context/theme"
|
||||
import { TextAttributes } from "@opentui/core"
|
||||
import { TextAttributes } from "@neuron-tui/core"
|
||||
import { useSDK } from "../context/sdk"
|
||||
|
||||
function Status(props: { enabled: boolean; loading: boolean }) {
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { useTerminalDimensions } from "@opentui/solid"
|
||||
import { TextAttributes } from "@opentui/core"
|
||||
import { useTerminalDimensions } from "@neuron-tui/solid"
|
||||
import { TextAttributes } from "@neuron-tui/core"
|
||||
import { createMemo, createResource, createSignal, onMount, Show } from "solid-js"
|
||||
import path from "path"
|
||||
import { DialogSelect, type DialogSelectOption } from "../ui/dialog-select"
|
||||
+1
-1
@@ -7,7 +7,7 @@ import { useSDK } from "../context/sdk"
|
||||
import { DialogPrompt } from "../ui/dialog-prompt"
|
||||
import { Link } from "../ui/link"
|
||||
import { useTheme } from "../context/theme"
|
||||
import { TextAttributes } from "@opentui/core"
|
||||
import { TextAttributes } from "@neuron-tui/core"
|
||||
import type { ProviderAuthAuthorization, ProviderAuthMethod } from "@opencode-ai/sdk/v2"
|
||||
import { DialogModel } from "./dialog-model"
|
||||
import { useToast } from "../ui/toast"
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { RGBA, TextAttributes } from "@opentui/core"
|
||||
import { RGBA, TextAttributes } from "@neuron-tui/core"
|
||||
import open from "open"
|
||||
import { createSignal } from "solid-js"
|
||||
import { selectedForeground, useTheme } from "../context/theme"
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { TextAttributes } from "@opentui/core"
|
||||
import { TextAttributes } from "@neuron-tui/core"
|
||||
import { useTheme } from "../context/theme"
|
||||
import { useDialog } from "../ui/dialog"
|
||||
import { createStore } from "solid-js/store"
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { TextAttributes } from "@opentui/core"
|
||||
import { TextAttributes } from "@neuron-tui/core"
|
||||
import { DialogSelect, type DialogSelectOption } from "../ui/dialog-select"
|
||||
import { createResource, createMemo, createSignal } from "solid-js"
|
||||
import { useDialog } from "../ui/dialog"
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { TextAttributes } from "@opentui/core"
|
||||
import { TextAttributes } from "@neuron-tui/core"
|
||||
import { fileURLToPath } from "bun"
|
||||
import { useTheme } from "../context/theme"
|
||||
import { useDialog } from "../ui/dialog"
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { TextAttributes } from "@opentui/core"
|
||||
import { useKeyboard } from "@opentui/solid"
|
||||
import { TextAttributes } from "@neuron-tui/core"
|
||||
import { useKeyboard } from "@neuron-tui/solid"
|
||||
import type { VcsFileStatus } from "@opencode-ai/sdk/v2"
|
||||
import { createMemo, For } from "solid-js"
|
||||
import { createStore } from "solid-js/store"
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { TextAttributes } from "@opentui/core"
|
||||
import { TextAttributes } from "@neuron-tui/core"
|
||||
import { createStore } from "solid-js/store"
|
||||
import { For } from "solid-js"
|
||||
import { useTheme } from "../context/theme"
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { TextAttributes, type ScrollBoxRenderable } from "@opentui/core"
|
||||
import { useKeyboard, useTerminalDimensions } from "@opentui/solid"
|
||||
import { TextAttributes, type ScrollBoxRenderable } from "@neuron-tui/core"
|
||||
import { useKeyboard, useTerminalDimensions } from "@neuron-tui/solid"
|
||||
import { createSignal, For, Show } from "solid-js"
|
||||
import { getScrollAcceleration } from "../util/scroll"
|
||||
import { useClipboard } from "../context/clipboard"
|
||||
@@ -0,0 +1,27 @@
|
||||
import { createSignal } from "solid-js"
|
||||
import wordmark from "../assets/neuron-wordmark.png" with { type: "file" }
|
||||
|
||||
export function Logo() {
|
||||
const [failed, setFailed] = createSignal(false)
|
||||
|
||||
if (failed()) {
|
||||
return (
|
||||
<text selectable={false} fg="#f5e6c8">
|
||||
Neuron
|
||||
</text>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<box height={7}>
|
||||
<image
|
||||
source={wordmark}
|
||||
width={34}
|
||||
height={6}
|
||||
fit="fit"
|
||||
protocol="blocks"
|
||||
onError={() => setFailed(true)}
|
||||
/>
|
||||
</box>
|
||||
)
|
||||
}
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
import type { BoxRenderable, TextareaRenderable, ScrollBoxRenderable } from "@opentui/core"
|
||||
import type { BoxRenderable, TextareaRenderable, ScrollBoxRenderable } from "@neuron-tui/core"
|
||||
import { pathToFileURL } from "bun"
|
||||
import fuzzysort from "fuzzysort"
|
||||
import path from "path"
|
||||
@@ -16,7 +16,7 @@ import { useTuiConfig } from "../../config"
|
||||
import { useLocation } from "../../context/location"
|
||||
import { useTheme, selectedForeground } from "../../context/theme"
|
||||
import { SplitBorder } from "../../ui/border"
|
||||
import { useTerminalDimensions } from "@opentui/solid"
|
||||
import { useTerminalDimensions } from "@neuron-tui/solid"
|
||||
import { Locale } from "../../util/locale"
|
||||
import type { PromptInfo } from "../../prompt/history"
|
||||
import { useFrecency } from "../../prompt/frecency"
|
||||
+3
-3
@@ -7,8 +7,8 @@ import {
|
||||
decodePasteBytes,
|
||||
type KeyEvent,
|
||||
type Renderable,
|
||||
} from "@opentui/core"
|
||||
import type { CommandContext } from "@opentui/keymap"
|
||||
} from "@neuron-tui/core"
|
||||
import type { CommandContext } from "@neuron-tui/keymap"
|
||||
import { createEffect, createMemo, onMount, createSignal, onCleanup, on, Show, Switch, Match } from "solid-js"
|
||||
import { registerOpencodeSpinner } from "../register-spinner"
|
||||
import path from "path"
|
||||
@@ -36,7 +36,7 @@ import { expandPastedTextPlaceholders, expandTrackedPastedText } from "../../pro
|
||||
import { usePromptStash } from "../../prompt/stash"
|
||||
import { DialogStash } from "../dialog-stash"
|
||||
import { type AutocompleteRef, Autocomplete } from "./autocomplete"
|
||||
import { useRenderer, useTerminalDimensions, type JSX } from "@opentui/solid"
|
||||
import { useRenderer, useTerminalDimensions, type JSX } from "@neuron-tui/solid"
|
||||
import type { AssistantMessage, FilePart, UserMessage } from "@opencode-ai/sdk/v2"
|
||||
import { Locale } from "../../util/locale"
|
||||
import { errorMessage } from "../../util/error"
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { getComponentCatalogue } from "@opentui/solid/components"
|
||||
import { getComponentCatalogue } from "@neuron-tui/solid/components"
|
||||
import { registerSpinner } from "opentui-spinner/solid"
|
||||
|
||||
export function registerOpencodeSpinner() {
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
import { Show } from "solid-js"
|
||||
import { useTheme } from "../context/theme"
|
||||
import { useKV } from "../context/kv"
|
||||
import type { JSX } from "@opentui/solid"
|
||||
import type { RGBA } from "@opentui/core"
|
||||
import type { JSX } from "@neuron-tui/solid"
|
||||
import type { RGBA } from "@neuron-tui/core"
|
||||
import { registerOpencodeSpinner } from "./register-spinner"
|
||||
|
||||
registerOpencodeSpinner()
|
||||
@@ -1,6 +1,6 @@
|
||||
export * as TuiConfig from "."
|
||||
|
||||
import { createBindingLookup } from "@opentui/keymap/extras"
|
||||
import { createBindingLookup } from "@neuron-tui/keymap/extras"
|
||||
import { Schema } from "effect"
|
||||
import { createContext, type JSX, useContext } from "solid-js"
|
||||
import { TuiKeybind } from "./keybind"
|
||||
@@ -1,8 +1,8 @@
|
||||
export * as TuiKeybind from "./keybind"
|
||||
|
||||
import type { KeyEvent, Renderable } from "@opentui/core"
|
||||
import type { Binding } from "@opentui/keymap"
|
||||
import type { BindingCommandMap, BindingConfig, BindingDefaults } from "@opentui/keymap/extras"
|
||||
import type { KeyEvent, Renderable } from "@neuron-tui/core"
|
||||
import type { Binding } from "@neuron-tui/keymap"
|
||||
import type { BindingCommandMap, BindingConfig, BindingDefaults } from "@neuron-tui/keymap/extras"
|
||||
import { Schema } from "effect"
|
||||
|
||||
const KeyStroke = Schema.Struct({
|
||||
@@ -1,4 +1,4 @@
|
||||
import { createContext, Show, useContext, type ParentProps } from "solid-js"
|
||||
import { createContext, useContext, type ParentProps } from "solid-js"
|
||||
|
||||
export function createSimpleContext<T, Props extends Record<string, any>>(input: {
|
||||
name: string
|
||||
@@ -10,12 +10,7 @@ export function createSimpleContext<T, Props extends Record<string, any>>(input:
|
||||
context: ctx,
|
||||
provider: (props: ParentProps<Props>) => {
|
||||
const init = input.init(props)
|
||||
return (
|
||||
// @ts-expect-error
|
||||
<Show when={init.ready === undefined || init.ready === true}>
|
||||
<ctx.Provider value={init}>{props.children}</ctx.Provider>
|
||||
</Show>
|
||||
)
|
||||
return <ctx.Provider value={init}>{props.children}</ctx.Provider>
|
||||
},
|
||||
use() {
|
||||
const value = useContext(ctx)
|
||||
@@ -1,8 +1,6 @@
|
||||
import { createSignal, type Setter } from "solid-js"
|
||||
import { type Setter } from "solid-js"
|
||||
import { createStore, unwrap } from "solid-js/store"
|
||||
import { createSimpleContext } from "./helper"
|
||||
import { Flock } from "@opencode-ai/core/util/flock"
|
||||
import { Global } from "@opencode-ai/core/global"
|
||||
import { readJson, writeJsonAtomic } from "../util/persistence"
|
||||
import { useTuiPaths } from "./runtime"
|
||||
import path from "path"
|
||||
@@ -10,29 +8,19 @@ import path from "path"
|
||||
export const { use: useKV, provider: KVProvider } = createSimpleContext({
|
||||
name: "KV",
|
||||
init: () => {
|
||||
const paths = useTuiPaths()
|
||||
void Global.Path.state
|
||||
const file = path.join(paths.state, "kv.json")
|
||||
const lock = `tui-kv:${file}`
|
||||
const [ready, setReady] = createSignal(false)
|
||||
const file = path.join(useTuiPaths().state, "kv.json")
|
||||
const [store, setStore] = createStore<Record<string, any>>()
|
||||
// Queue same-process writes so rapid updates persist in order.
|
||||
let write = Promise.resolve()
|
||||
|
||||
Flock.withLock(lock, () => readJson<Record<string, unknown>>(file))
|
||||
void readJson<Record<string, unknown>>(file)
|
||||
.then((x) => {
|
||||
setStore(x)
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Failed to read KV state", { error })
|
||||
})
|
||||
.finally(() => {
|
||||
setReady(true)
|
||||
if (x && typeof x === "object") setStore(x)
|
||||
})
|
||||
.catch(() => {})
|
||||
|
||||
const result = {
|
||||
get ready() {
|
||||
return ready()
|
||||
return true
|
||||
},
|
||||
get store() {
|
||||
return store
|
||||
@@ -54,11 +42,7 @@ export const { use: useKV, provider: KVProvider } = createSimpleContext({
|
||||
set(key: string, value: any) {
|
||||
setStore(key, value)
|
||||
const snapshot = structuredClone(unwrap(store))
|
||||
write = write
|
||||
.then(() => Flock.withLock(lock, () => writeJsonAtomic(file, snapshot)))
|
||||
.catch((error) => {
|
||||
console.error("Failed to write KV state", { error })
|
||||
})
|
||||
write = write.then(() => writeJsonAtomic(file, snapshot)).catch(() => {})
|
||||
},
|
||||
}
|
||||
return result
|
||||
@@ -7,7 +7,7 @@ import path from "path"
|
||||
import { useTuiPaths } from "./runtime"
|
||||
import { useArgs } from "./args"
|
||||
import { useSDK } from "./sdk"
|
||||
import { RGBA } from "@opentui/core"
|
||||
import { RGBA } from "@neuron-tui/core"
|
||||
import { readJson, writeJsonAtomic } from "../util/persistence"
|
||||
import { useTheme } from "./theme"
|
||||
import { useToast } from "../ui/toast"
|
||||
@@ -562,8 +562,7 @@ export const {
|
||||
return store.status
|
||||
},
|
||||
get ready() {
|
||||
if (startup.skipInitialLoading) return true
|
||||
return store.status !== "loading"
|
||||
return true
|
||||
},
|
||||
get path() {
|
||||
return project.instance.path()
|
||||
@@ -1,5 +1,5 @@
|
||||
import { CliRenderEvents, SyntaxStyle, type TerminalColors } from "@opentui/core"
|
||||
import { useRenderer } from "@opentui/solid"
|
||||
import { CliRenderEvents, SyntaxStyle, type TerminalColors } from "@neuron-tui/core"
|
||||
import { useRenderer } from "@neuron-tui/solid"
|
||||
import {
|
||||
DEFAULT_THEMES,
|
||||
addTheme,
|
||||
@@ -94,7 +94,7 @@ const [store, setStore] = createStore<State>({
|
||||
mode: "dark",
|
||||
lock: undefined,
|
||||
active: "opencode",
|
||||
ready: false,
|
||||
ready: true,
|
||||
})
|
||||
|
||||
subscribeThemes((themes) => setStore("themes", themes))
|
||||
@@ -120,7 +120,6 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({
|
||||
draft.lock = lock
|
||||
const active = config.theme ?? kv.get("theme", "opencode")
|
||||
draft.active = typeof active === "string" ? active : "opencode"
|
||||
draft.ready = false
|
||||
}),
|
||||
)
|
||||
|
||||
@@ -144,7 +143,9 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
void Promise.allSettled([resolveSystemTheme(store.mode), syncCustomThemes()]).finally(() => {
|
||||
const done = Promise.allSettled([resolveSystemTheme(store.mode), syncCustomThemes()])
|
||||
const cap = new Promise((resolve) => setTimeout(resolve, 1000))
|
||||
void Promise.race([done, cap]).finally(() => {
|
||||
setStore("ready", true)
|
||||
})
|
||||
})
|
||||
@@ -153,24 +154,25 @@ export const { use: useTheme, provider: ThemeProvider } = createSimpleContext({
|
||||
let systemThemeMode: "dark" | "light" | undefined
|
||||
let hasResolvedSystemTheme = false
|
||||
function resolveSystemTheme(mode: "dark" | "light" = store.mode) {
|
||||
return renderer
|
||||
.getPalette({ size: 16 })
|
||||
.then((colors: TerminalColors) => {
|
||||
if (!colors.palette[0]) {
|
||||
if (hasResolvedSystemTheme) return
|
||||
setSystemTheme(undefined)
|
||||
if (store.active === "system") setStore("active", "opencode")
|
||||
return
|
||||
}
|
||||
const next = store.lock ?? terminalMode(colors) ?? mode
|
||||
if (store.mode !== next) setStore("mode", next)
|
||||
const signature = JSON.stringify(colors)
|
||||
hasResolvedSystemTheme = true
|
||||
if (store.themes.system && systemThemeSignature === signature && systemThemeMode === next) return
|
||||
systemThemeSignature = signature
|
||||
systemThemeMode = next
|
||||
setSystemTheme(generateSystem(colors, next))
|
||||
})
|
||||
return Promise.race([
|
||||
renderer.getPalette({ size: 16 }),
|
||||
new Promise<undefined>((resolve) => setTimeout(() => resolve(undefined), 800)),
|
||||
]).then((colors: TerminalColors | undefined) => {
|
||||
if (!colors?.palette[0]) {
|
||||
if (hasResolvedSystemTheme) return
|
||||
setSystemTheme(undefined)
|
||||
if (store.active === "system") setStore("active", "opencode")
|
||||
return
|
||||
}
|
||||
const next = store.lock ?? terminalMode(colors) ?? mode
|
||||
if (store.mode !== next) setStore("mode", next)
|
||||
const signature = JSON.stringify(colors)
|
||||
hasResolvedSystemTheme = true
|
||||
if (store.themes.system && systemThemeSignature === signature && systemThemeMode === next) return
|
||||
systemThemeSignature = signature
|
||||
systemThemeMode = next
|
||||
setSystemTheme(generateSystem(colors, next))
|
||||
})
|
||||
.catch(() => {
|
||||
if (hasResolvedSystemTheme) return
|
||||
setSystemTheme(undefined)
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { CliRenderer } from "@opentui/core"
|
||||
import type { CliRenderer } from "@neuron-tui/core"
|
||||
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs"
|
||||
import { readFile, rm, writeFile } from "node:fs/promises"
|
||||
import os from "node:os"
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/** @jsxImportSource @opentui/solid */
|
||||
import type { ColorInput, RGBA, ScrollBoxRenderable } from "@opentui/core"
|
||||
/** @jsxImportSource @neuron-tui/solid */
|
||||
import type { ColorInput, RGBA, ScrollBoxRenderable } from "@neuron-tui/core"
|
||||
import { Locale } from "../../util/locale"
|
||||
import { tint } from "../../context/theme"
|
||||
import { createEffect, createMemo, For, Match, Switch } from "solid-js"
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import type { BorderSides, ColorInput } from "@opentui/core"
|
||||
import type { JSX } from "@opentui/solid"
|
||||
import type { BorderSides, ColorInput } from "@neuron-tui/core"
|
||||
import type { JSX } from "@neuron-tui/solid"
|
||||
import { useTheme } from "../../context/theme"
|
||||
import { createContext, Show, splitProps, useContext } from "solid-js"
|
||||
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
/** @jsxImportSource @opentui/solid */
|
||||
/** @jsxImportSource @neuron-tui/solid */
|
||||
import type { TuiPlugin, TuiPluginApi, TuiRouteCurrent } from "@opencode-ai/plugin/tui"
|
||||
import type { SnapshotFileDiff, VcsFileDiff } from "@opencode-ai/sdk/v2"
|
||||
import {
|
||||
@@ -7,11 +7,11 @@ import {
|
||||
type BoxRenderable,
|
||||
type DiffRenderable,
|
||||
type ScrollBoxRenderable,
|
||||
} from "@opentui/core"
|
||||
} from "@neuron-tui/core"
|
||||
import { LANGUAGE_EXTENSIONS } from "../../util/filetype"
|
||||
import { useBindings, useCommandShortcut } from "../../keymap"
|
||||
import { useTheme } from "../../context/theme"
|
||||
import { useTerminalDimensions } from "@opentui/solid"
|
||||
import { useTerminalDimensions } from "@neuron-tui/solid"
|
||||
import path from "path"
|
||||
import { createEffect, createMemo, createResource, createSignal, For, Match, onCleanup, Show, Switch } from "solid-js"
|
||||
import { DiffViewerFileTree } from "./diff-viewer-file-tree"
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import type { TuiPlugin, TuiPluginApi, TuiPluginStatus } from "@opencode-ai/plugin/tui"
|
||||
import type { BuiltinTuiPlugin } from "../builtins"
|
||||
import { useTerminalDimensions } from "@opentui/solid"
|
||||
import { useTerminalDimensions } from "@neuron-tui/solid"
|
||||
import { fileURLToPath } from "url"
|
||||
import { DialogSelect, type DialogSelectOption } from "../../ui/dialog-select"
|
||||
import { Show, createEffect, createMemo, createSignal } from "solid-js"
|
||||
+4
-4
@@ -1,9 +1,9 @@
|
||||
/** @jsxImportSource @opentui/solid */
|
||||
import { RGBA, TextAttributes, type KeyEvent, type Renderable } from "@opentui/core"
|
||||
import { useTerminalDimensions } from "@opentui/solid"
|
||||
/** @jsxImportSource @neuron-tui/solid */
|
||||
import { RGBA, TextAttributes, type KeyEvent, type Renderable } from "@neuron-tui/core"
|
||||
import { useTerminalDimensions } from "@neuron-tui/solid"
|
||||
import { createEffect, createMemo, createSignal, For, Show } from "solid-js"
|
||||
import { useBindings, useKeymapSelector } from "../../keymap"
|
||||
import type { ActiveKey } from "@opentui/keymap"
|
||||
import type { ActiveKey } from "@neuron-tui/keymap"
|
||||
import type { TuiPlugin, TuiPluginApi } from "@opencode-ai/plugin/tui"
|
||||
import type { BuiltinTuiPlugin } from "../builtins"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { InputRenderable, TextareaRenderable, type CliRenderer, type KeyEvent, type Renderable } from "@opentui/core"
|
||||
import { InputRenderable, TextareaRenderable, type CliRenderer, type KeyEvent, type Renderable } from "@neuron-tui/core"
|
||||
import {
|
||||
registerBackspacePopsPendingSequence,
|
||||
registerBaseLayoutFallback,
|
||||
@@ -6,13 +6,13 @@ import {
|
||||
registerEscapeClearsPendingSequence,
|
||||
registerManagedTextareaLayer,
|
||||
registerTimedLeader,
|
||||
} from "@opentui/keymap/addons/opentui"
|
||||
import { stringifyKeyStroke, type Binding } from "@opentui/keymap"
|
||||
} from "@neuron-tui/keymap/addons/opentui"
|
||||
import { stringifyKeyStroke, type Binding } from "@neuron-tui/keymap"
|
||||
import {
|
||||
formatCommandBindings as formatCommandBindingsExtra,
|
||||
formatKeySequence as formatKeySequenceExtra,
|
||||
} from "@opentui/keymap/extras"
|
||||
import { KeymapProvider, useKeymap, useKeymapSelector, useBindings } from "@opentui/keymap/solid"
|
||||
} from "@neuron-tui/keymap/extras"
|
||||
import { KeymapProvider, useKeymap, useKeymapSelector, useBindings } from "@neuron-tui/keymap/solid"
|
||||
import { createMemo, type Accessor } from "solid-js"
|
||||
import { useTuiConfig } from "./config"
|
||||
import { TuiKeybind } from "./config/keybind"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user