diff --git a/packages/opencode/src/cli/cmd/tui/context/kv.tsx b/packages/opencode/src/cli/cmd/tui/context/kv.tsx index 651c2dbc0c7..b0b96af0145 100644 --- a/packages/opencode/src/cli/cmd/tui/context/kv.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/kv.tsx @@ -10,10 +10,12 @@ export const { use: useKV, provider: KVProvider } = createSimpleContext({ const [ready, setReady] = createSignal(false) const [store, setStore] = createStore>() const file = Bun.file(path.join(Global.Path.state, "kv.json")) + let rawData: Record = {} file .json() .then((x) => { + rawData = x setStore(x) }) .catch(() => {}) @@ -44,7 +46,8 @@ export const { use: useKV, provider: KVProvider } = createSimpleContext({ }, set(key: string, value: any) { setStore(key, value) - Bun.write(file, JSON.stringify(store, null, 2)) + rawData[key] = value + Bun.write(file, JSON.stringify(rawData, null, 2)) }, } return result diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx index 4ffe91558ed..d59a7e9f1af 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/sidebar.tsx @@ -1,13 +1,11 @@ import { useSync } from "@tui/context/sync" -import { createMemo, For, Show, Switch, Match } from "solid-js" +import { createEffect, createMemo, For, Show, Switch, Match } from "solid-js" import { createStore } from "solid-js/store" import { useTheme } from "../../context/theme" import { Locale } from "@/util/locale" import path from "path" import type { AssistantMessage } from "@opencode-ai/sdk/v2" -import { Global } from "@/global" import { Installation } from "@/installation" -import { useKeybind } from "../../context/keybind" import { useDirectory } from "../../context/directory" import { useKV } from "../../context/kv" import { TodoItem } from "../../component/todo-item" @@ -15,6 +13,8 @@ import { TodoItem } from "../../component/todo-item" export function Sidebar(props: { sessionID: string; overlay?: boolean }) { const sync = useSync() const { theme } = useTheme() + const directory = useDirectory() + const kv = useKV() const session = createMemo(() => sync.session.get(props.sessionID)!) const diff = createMemo(() => sync.data.session_diff[props.sessionID] ?? []) const todo = createMemo(() => sync.data.todo[props.sessionID] ?? []) @@ -27,6 +27,24 @@ export function Sidebar(props: { sessionID: string; overlay?: boolean }) { lsp: true, }) + // Load saved sidebar expansion states from KV store when ready + createEffect(() => { + if (kv.ready) { + setExpanded({ + mcp: kv.get("sidebar_expanded_mcp", true), + diff: kv.get("sidebar_expanded_diff", true), + todo: kv.get("sidebar_expanded_todo", true), + lsp: kv.get("sidebar_expanded_lsp", true), + }) + } + }) + + // Wrapper that persists expansion state to KV store + const setExpandedWithPersist = (key: "mcp" | "diff" | "todo" | "lsp", value: boolean) => { + setExpanded(key, value) + kv.set(`sidebar_expanded_${key}`, value) + } + // Sort MCP servers alphabetically for consistent display order const mcpEntries = createMemo(() => Object.entries(sync.data.mcp).sort(([a], [b]) => a.localeCompare(b))) @@ -60,9 +78,6 @@ export function Sidebar(props: { sessionID: string; overlay?: boolean }) { } }) - const directory = useDirectory() - const kv = useKV() - const hasProviders = createMemo(() => sync.data.provider.some((x) => x.id !== "opencode" || Object.values(x.models).some((y) => y.cost?.input !== 0)), ) @@ -103,7 +118,7 @@ export function Sidebar(props: { sessionID: string; overlay?: boolean }) { mcpEntries().length > 2 && setExpanded("mcp", !expanded.mcp)} + onMouseDown={() => mcpEntries().length > 2 && setExpandedWithPersist("mcp", !expanded.mcp)} > 2}> {expanded.mcp ? "▼" : "▶"} @@ -163,7 +178,7 @@ export function Sidebar(props: { sessionID: string; overlay?: boolean }) { sync.data.lsp.length > 2 && setExpanded("lsp", !expanded.lsp)} + onMouseDown={() => sync.data.lsp.length > 2 && setExpandedWithPersist("lsp", !expanded.lsp)} > 2}> {expanded.lsp ? "▼" : "▶"} @@ -207,7 +222,7 @@ export function Sidebar(props: { sessionID: string; overlay?: boolean }) { todo().length > 2 && setExpanded("todo", !expanded.todo)} + onMouseDown={() => todo().length > 2 && setExpandedWithPersist("todo", !expanded.todo)} > 2}> {expanded.todo ? "▼" : "▶"} @@ -226,7 +241,7 @@ export function Sidebar(props: { sessionID: string; overlay?: boolean }) { diff().length > 2 && setExpanded("diff", !expanded.diff)} + onMouseDown={() => diff().length > 2 && setExpandedWithPersist("diff", !expanded.diff)} > 2}> {expanded.diff ? "▼" : "▶"}