diff options
| author | Adam <[email protected]> | 2026-01-07 06:54:48 -0600 |
|---|---|---|
| committer | Adam <[email protected]> | 2026-01-20 07:33:44 -0600 |
| commit | df094a10ff1f1a95f66abc6bdccfa69080480afa (patch) | |
| tree | ff48a40af84df86e8f675c12f55e930df89f947e /packages/app/src/context | |
| parent | de3641e8ebfd6d6d0262289136e970b1ddea54b2 (diff) | |
| download | opencode-df094a10ff1f1a95f66abc6bdccfa69080480afa.tar.gz opencode-df094a10ff1f1a95f66abc6bdccfa69080480afa.zip | |
wip(app): settings
Diffstat (limited to 'packages/app/src/context')
| -rw-r--r-- | packages/app/src/context/command.tsx | 55 | ||||
| -rw-r--r-- | packages/app/src/context/settings.tsx | 5 |
2 files changed, 50 insertions, 10 deletions
diff --git a/packages/app/src/context/command.tsx b/packages/app/src/context/command.tsx index d8dc13e23..7986e7509 100644 --- a/packages/app/src/context/command.tsx +++ b/packages/app/src/context/command.tsx @@ -1,9 +1,26 @@ import { createMemo, createSignal, onCleanup, onMount, type Accessor } from "solid-js" import { createSimpleContext } from "@opencode-ai/ui/context" import { useDialog } from "@opencode-ai/ui/context/dialog" +import { useSettings } from "@/context/settings" const IS_MAC = typeof navigator === "object" && /(Mac|iPod|iPhone|iPad)/.test(navigator.platform) +const PALETTE_ID = "command.palette" +const DEFAULT_PALETTE_KEYBIND = "mod+shift+p" +const SUGGESTED_PREFIX = "suggested." + +function actionId(id: string) { + if (!id.startsWith(SUGGESTED_PREFIX)) return id + return id.slice(SUGGESTED_PREFIX.length) +} + +function normalizeKey(key: string) { + if (key === ",") return "comma" + if (key === "+") return "plus" + if (key === " ") return "space" + return key.toLowerCase() +} + export type KeybindConfig = string export interface Keybind { @@ -73,7 +90,7 @@ export function parseKeybind(config: string): Keybind[] { } export function matchKeybind(keybinds: Keybind[], event: KeyboardEvent): boolean { - const eventKey = event.key.toLowerCase() + const eventKey = normalizeKey(event.key) for (const kb of keybinds) { const keyMatch = kb.key === eventKey @@ -105,15 +122,18 @@ export function formatKeybind(config: string): string { if (kb.meta) parts.push(IS_MAC ? "⌘" : "Meta") if (kb.key) { - const arrows: Record<string, string> = { + const keys: Record<string, string> = { arrowup: "↑", arrowdown: "↓", arrowleft: "←", arrowright: "→", + comma: ",", + plus: "+", + space: "Space", } + const key = kb.key.toLowerCase() const displayKey = - arrows[kb.key.toLowerCase()] ?? - (kb.key.length === 1 ? kb.key.toUpperCase() : kb.key.charAt(0).toUpperCase() + kb.key.slice(1)) + keys[key] ?? (key.length === 1 ? key.toUpperCase() : key.charAt(0).toUpperCase() + key.slice(1)) parts.push(displayKey) } @@ -124,9 +144,17 @@ export const { use: useCommand, provider: CommandProvider } = createSimpleContex name: "Command", init: () => { const dialog = useDialog() + const settings = useSettings() const [registrations, setRegistrations] = createSignal<Accessor<CommandOption[]>[]>([]) const [suspendCount, setSuspendCount] = createSignal(0) + const bind = (id: string, def: KeybindConfig | undefined) => { + const custom = settings.keybinds.get(actionId(id)) + const config = custom ?? def + if (!config || config === "none") return + return config + } + const options = createMemo(() => { const seen = new Set<string>() const all: CommandOption[] = [] @@ -139,15 +167,20 @@ export const { use: useCommand, provider: CommandProvider } = createSimpleContex } } - const suggested = all.filter((x) => x.suggested && !x.disabled) + const resolved = all.map((opt) => ({ + ...opt, + keybind: bind(opt.id, opt.keybind), + })) + + const suggested = resolved.filter((x) => x.suggested && !x.disabled) return [ ...suggested.map((x) => ({ ...x, - id: "suggested." + x.id, + id: SUGGESTED_PREFIX + x.id, category: "Suggested", })), - ...all, + ...resolved, ] }) @@ -169,7 +202,7 @@ export const { use: useCommand, provider: CommandProvider } = createSimpleContex const handleKeyDown = (event: KeyboardEvent) => { if (suspended() || dialog.active) return - const paletteKeybinds = parseKeybind("mod+shift+p") + const paletteKeybinds = parseKeybind(settings.keybinds.get(PALETTE_ID) ?? DEFAULT_PALETTE_KEYBIND) if (matchKeybind(paletteKeybinds, event)) { event.preventDefault() showPalette() @@ -209,7 +242,11 @@ export const { use: useCommand, provider: CommandProvider } = createSimpleContex run(id, source) }, keybind(id: string) { - const option = options().find((x) => x.id === id || x.id === "suggested." + id) + if (id === PALETTE_ID) { + return formatKeybind(settings.keybinds.get(PALETTE_ID) ?? DEFAULT_PALETTE_KEYBIND) + } + + const option = options().find((x) => x.id === id || x.id === SUGGESTED_PREFIX + id) if (!option?.keybind) return "" return formatKeybind(option.keybind) }, diff --git a/packages/app/src/context/settings.tsx b/packages/app/src/context/settings.tsx index 4160d1b70..b44b4e143 100644 --- a/packages/app/src/context/settings.tsx +++ b/packages/app/src/context/settings.tsx @@ -1,4 +1,4 @@ -import { createStore } from "solid-js/store" +import { createStore, reconcile } from "solid-js/store" import { createEffect, createMemo } from "solid-js" import { createSimpleContext } from "@opencode-ai/ui/context" import { persisted } from "@/utils/persist" @@ -115,6 +115,9 @@ export const { use: useSettings, provider: SettingsProvider } = createSimpleCont reset(action: string) { setStore("keybinds", action, undefined!) }, + resetAll() { + setStore("keybinds", reconcile({})) + }, }, permissions: { autoApprove: createMemo(() => store.permissions?.autoApprove ?? defaultSettings.permissions.autoApprove), |
