From 490c47c13c451c859c459b5c299dbf384f767980 Mon Sep 17 00:00:00 2001 From: Ariane Emory Date: Wed, 18 Feb 2026 16:10:30 -0500 Subject: [PATCH 1/2] Fix viewport jumping when navigating in session list after marking for deletion The scroll calculation in moveTo() was happening synchronously before the re-render from setToDelete(undefined) completed its layout pass. Wrapping the scroll logic in setTimeout ensures positions are updated. --- .../src/cli/cmd/tui/ui/dialog-select.tsx | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx b/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx index 151f73cf7c0..321d7efdcaa 100644 --- a/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx +++ b/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx @@ -161,26 +161,28 @@ export function DialogSelect(props: DialogSelectProps) { setStore("selected", next) const option = selected() if (option) props.onMove?.(option) - if (!scroll) return - const target = scroll.getChildren().find((child) => { - return child.id === JSON.stringify(selected()?.value) - }) - if (!target) return - const y = target.y - scroll.y - if (center) { - const centerOffset = Math.floor(scroll.height / 2) - scroll.scrollBy(y - centerOffset) - } else { - if (y >= scroll.height) { - scroll.scrollBy(y - scroll.height + 1) - } - if (y < 0) { - scroll.scrollBy(y) - if (isDeepEqual(flat()[0].value, selected()?.value)) { - scroll.scrollTo(0) + setTimeout(() => { + if (!scroll) return + const target = scroll.getChildren().find((child) => { + return child.id === JSON.stringify(selected()?.value) + }) + if (!target) return + const y = target.y - scroll.y + if (center) { + const centerOffset = Math.floor(scroll.height / 2) + scroll.scrollBy(y - centerOffset) + } else { + if (y >= scroll.height) { + scroll.scrollBy(y - scroll.height + 1) + } + if (y < 0) { + scroll.scrollBy(y) + if (isDeepEqual(flat()[0].value, selected()?.value)) { + scroll.scrollTo(0) + } } } - } + }, 0) } const keybind = useKeybind() From 50656e22da5e46b1259a84c5aaf135557458a383 Mon Sep 17 00:00:00 2001 From: Ariane Emory Date: Wed, 18 Feb 2026 23:19:50 -0500 Subject: [PATCH 2/2] Fix: prevent selection jump after session deletion --- packages/opencode/src/cli/cmd/tui/context/keybind.tsx | 2 +- packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/opencode/src/cli/cmd/tui/context/keybind.tsx b/packages/opencode/src/cli/cmd/tui/context/keybind.tsx index 0dbbbc6f9ee..ede5ecca572 100644 --- a/packages/opencode/src/cli/cmd/tui/context/keybind.tsx +++ b/packages/opencode/src/cli/cmd/tui/context/keybind.tsx @@ -15,7 +15,7 @@ export const { use: useKeybind, provider: KeybindProvider } = createSimpleContex const keybinds = createMemo(() => { return pipe( sync.data.config.keybinds ?? {}, - mapValues((value) => Keybind.parse(value)), + mapValues((value) => (value ? Keybind.parse(value) : [])), ) }) const [store, setStore] = createStore({ diff --git a/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx b/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx index 321d7efdcaa..1e448a243ba 100644 --- a/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx +++ b/packages/opencode/src/cli/cmd/tui/ui/dialog-select.tsx @@ -140,6 +140,7 @@ export function DialogSelect(props: DialogSelectProps) { if (filter.length > 0) { moveTo(0, true) } else if (current) { + if (isDeepEqual(selected()?.value, current)) return const currentIndex = flat().findIndex((opt) => isDeepEqual(opt.value, current)) if (currentIndex >= 0) { moveTo(currentIndex, true)