mirror of
https://github.com/anomalyco/opencode.git
synced 2026-11-14 03:56:55 +03:00
fix(tui): preserve selection under a stationary pointer (#47138)
This commit is contained in:
committed by
GitHub
Unverified
parent
b3733e9517
commit
cb852434b1
@@ -87,7 +87,6 @@ export function Autocomplete(props: {
|
||||
index: 0,
|
||||
selected: 0,
|
||||
visible: false as AutocompleteRef["visible"],
|
||||
input: "keyboard" as "keyboard" | "mouse",
|
||||
})
|
||||
|
||||
const [positionTick, setPositionTick] = createSignal(0)
|
||||
@@ -151,14 +150,6 @@ export function Autocomplete(props: {
|
||||
setSearch(next ? next : "")
|
||||
})
|
||||
|
||||
// When the filter changes due to how TUI works, the mousemove might still be triggered
|
||||
// via a synthetic event as the layout moves underneath the cursor. This is a workaround to make sure the input mode remains keyboard so
|
||||
// that the mouseover event doesn't trigger when filtering.
|
||||
createEffect(() => {
|
||||
filter()
|
||||
setStore("input", "keyboard")
|
||||
})
|
||||
|
||||
function insertPart(
|
||||
text: string,
|
||||
part:
|
||||
@@ -724,7 +715,6 @@ export function Autocomplete(props: {
|
||||
title: "Previous autocomplete item",
|
||||
group: "Autocomplete",
|
||||
run() {
|
||||
setStore("input", "keyboard")
|
||||
move(-1)
|
||||
},
|
||||
},
|
||||
@@ -733,7 +723,6 @@ export function Autocomplete(props: {
|
||||
title: "Next autocomplete item",
|
||||
group: "Autocomplete",
|
||||
run() {
|
||||
setStore("input", "keyboard")
|
||||
move(1)
|
||||
},
|
||||
},
|
||||
@@ -942,17 +931,8 @@ export function Autocomplete(props: {
|
||||
: undefined
|
||||
}
|
||||
flexDirection="row"
|
||||
onMouseMove={() => {
|
||||
setStore("input", "mouse")
|
||||
}}
|
||||
onMouseOver={() => {
|
||||
if (store.input !== "mouse") return
|
||||
moveTo(index)
|
||||
}}
|
||||
onMouseDown={() => {
|
||||
setStore("input", "mouse")
|
||||
moveTo(index)
|
||||
}}
|
||||
onMouseMove={() => moveTo(index)}
|
||||
onMouseDown={() => moveTo(index)}
|
||||
onMouseUp={() => select()}
|
||||
>
|
||||
<text
|
||||
|
||||
@@ -438,7 +438,7 @@ export function RunFormBody(props: {
|
||||
flexDirection="row"
|
||||
gap={1}
|
||||
alignItems="flex-start"
|
||||
onMouseOver={() => setState((previous) => formSetSelected(previous, index()))}
|
||||
onMouseMove={() => setState((previous) => formSetSelected(previous, index()))}
|
||||
backgroundColor={active() ? props.theme.formfieldFocusedBg : "transparent"}
|
||||
onMouseUp={() => choose(index())}
|
||||
>
|
||||
|
||||
@@ -54,7 +54,7 @@ function buttons(
|
||||
paddingLeft={1}
|
||||
paddingRight={1}
|
||||
backgroundColor={option === selected ? theme.actionFocusedBg : transparent}
|
||||
onMouseOver={() => {
|
||||
onMouseMove={() => {
|
||||
if (!disabled) onHover(option)
|
||||
}}
|
||||
onMouseUp={() => {
|
||||
|
||||
@@ -125,7 +125,7 @@ export function ShellTab(props: { sessionID: string }) {
|
||||
backgroundColor={
|
||||
active() ? theme.background.action.primary.focused : theme.background.action.primary.default
|
||||
}
|
||||
onMouseOver={() => setStore("selected", index())}
|
||||
onMouseMove={() => setStore("selected", index())}
|
||||
onMouseUp={() => {
|
||||
setStore("selected", index())
|
||||
open()
|
||||
|
||||
@@ -215,7 +215,7 @@ export function SubagentsTab(props: { sessionID: string }) {
|
||||
? theme.background.action.primary.selected
|
||||
: theme.background.action.primary.default
|
||||
}
|
||||
onMouseOver={() => setStore("selected", index())}
|
||||
onMouseMove={() => setStore("selected", index())}
|
||||
onMouseUp={() => {
|
||||
setStore("selected", index())
|
||||
navigate({ type: "session", sessionID: entry.sessionID })
|
||||
|
||||
@@ -84,7 +84,7 @@ export function TerminalsTab(props: { sessionID: string; visibleTerminalID?: str
|
||||
? theme.background.action.primary.selected
|
||||
: theme.background.action.primary.default
|
||||
}
|
||||
onMouseOver={() => setSelected(index())}
|
||||
onMouseMove={() => setSelected(index())}
|
||||
onMouseUp={() => {
|
||||
setSelected(index())
|
||||
select()
|
||||
|
||||
@@ -907,7 +907,7 @@ export function FormPrompt(props: { form: FormWithLocation }) {
|
||||
}
|
||||
return (
|
||||
<box
|
||||
onMouseOver={() => setStore("selected", i())}
|
||||
onMouseMove={() => setStore("selected", i())}
|
||||
onMouseDown={() => setStore("selected", i())}
|
||||
onMouseUp={() => {
|
||||
if (renderer.getSelection()?.getSelectedText()) return
|
||||
@@ -961,7 +961,7 @@ export function FormPrompt(props: { form: FormWithLocation }) {
|
||||
</For>
|
||||
<Show when={custom()}>
|
||||
<box
|
||||
onMouseOver={() => setStore("selected", rows().length)}
|
||||
onMouseMove={() => setStore("selected", rows().length)}
|
||||
onMouseDown={() => setStore("selected", rows().length)}
|
||||
onMouseUp={() => {
|
||||
if (renderer.getSelection()?.getSelectedText()) return
|
||||
|
||||
@@ -591,7 +591,7 @@ export function SessionQuestion<const T extends Record<string, string>>(props: {
|
||||
? theme.background.action.primary.focused
|
||||
: theme.background.action.primary.default
|
||||
}
|
||||
onMouseOver={() => setStore("selected", option)}
|
||||
onMouseMove={() => setStore("selected", option)}
|
||||
onMouseUp={() => {
|
||||
setStore("selected", option)
|
||||
props.onSelect(option)
|
||||
|
||||
@@ -112,7 +112,6 @@ export function DialogSelect<T>(props: DialogSelectProps<T>) {
|
||||
const [store, setStore] = createStore({
|
||||
selected: 0,
|
||||
filter: "",
|
||||
input: "keyboard" as "keyboard" | "mouse",
|
||||
})
|
||||
const [focusedAction, setFocusedAction] = createSignal<number>()
|
||||
const actionFocused = createMemo(() => focusedAction() !== undefined)
|
||||
@@ -201,12 +200,8 @@ export function DialogSelect<T>(props: DialogSelectProps<T>) {
|
||||
return result
|
||||
})
|
||||
|
||||
// When the filter changes due to how TUI works, the mousemove might still be triggered
|
||||
// via a synthetic event as the layout moves underneath the cursor. This is a workaround to make sure the input mode remains keyboard
|
||||
// that the mouseover event doesn't trigger when filtering.
|
||||
createEffect(() => {
|
||||
filtered()
|
||||
setStore("input", "keyboard")
|
||||
setFocusedAction(undefined)
|
||||
})
|
||||
|
||||
@@ -384,7 +379,6 @@ export function DialogSelect<T>(props: DialogSelectProps<T>) {
|
||||
|
||||
function submit() {
|
||||
if (props.locked) return
|
||||
setStore("input", "keyboard")
|
||||
const index = focusedAction()
|
||||
if (index !== undefined) {
|
||||
trigger(actionItems()[index])
|
||||
@@ -418,7 +412,6 @@ export function DialogSelect<T>(props: DialogSelectProps<T>) {
|
||||
title: "Previous item",
|
||||
group: "Dialog",
|
||||
run() {
|
||||
setStore("input", "keyboard")
|
||||
move(-1)
|
||||
},
|
||||
},
|
||||
@@ -427,7 +420,6 @@ export function DialogSelect<T>(props: DialogSelectProps<T>) {
|
||||
title: "Next item",
|
||||
group: "Dialog",
|
||||
run() {
|
||||
setStore("input", "keyboard")
|
||||
move(1)
|
||||
},
|
||||
},
|
||||
@@ -436,7 +428,6 @@ export function DialogSelect<T>(props: DialogSelectProps<T>) {
|
||||
title: "Page up",
|
||||
group: "Dialog",
|
||||
run() {
|
||||
setStore("input", "keyboard")
|
||||
move(-10)
|
||||
},
|
||||
},
|
||||
@@ -445,7 +436,6 @@ export function DialogSelect<T>(props: DialogSelectProps<T>) {
|
||||
title: "Page down",
|
||||
group: "Dialog",
|
||||
run() {
|
||||
setStore("input", "keyboard")
|
||||
move(10)
|
||||
},
|
||||
},
|
||||
@@ -455,7 +445,6 @@ export function DialogSelect<T>(props: DialogSelectProps<T>) {
|
||||
group: "Dialog",
|
||||
run() {
|
||||
if (props.locked) return
|
||||
setStore("input", "keyboard")
|
||||
moveTo(0)
|
||||
},
|
||||
},
|
||||
@@ -465,7 +454,6 @@ export function DialogSelect<T>(props: DialogSelectProps<T>) {
|
||||
group: "Dialog",
|
||||
run() {
|
||||
if (props.locked) return
|
||||
setStore("input", "keyboard")
|
||||
moveTo(flat().length - 1)
|
||||
},
|
||||
},
|
||||
@@ -538,7 +526,6 @@ export function DialogSelect<T>(props: DialogSelectProps<T>) {
|
||||
|
||||
function trigger(item: Action | undefined) {
|
||||
if (props.locked || !item || isActionDisabled(item)) return
|
||||
setStore("input", "keyboard")
|
||||
if (item.selection === "none") {
|
||||
item.onTrigger()
|
||||
return
|
||||
@@ -709,21 +696,16 @@ export function DialogSelect<T>(props: DialogSelectProps<T>) {
|
||||
position="relative"
|
||||
onMouseMove={() => {
|
||||
if (props.locked) return
|
||||
setStore("input", "mouse")
|
||||
setFocusedAction(undefined)
|
||||
const index = flat().findIndex((x) => isDeepEqual(x.value, option.value))
|
||||
if (index === -1 || index === store.selected) return
|
||||
moveTo(index)
|
||||
}}
|
||||
onMouseUp={() => {
|
||||
if (props.locked) return
|
||||
option.onSelect?.(dialog)
|
||||
props.onSelect?.(option)
|
||||
}}
|
||||
onMouseOver={() => {
|
||||
if (props.locked) return
|
||||
if (store.input !== "mouse") return
|
||||
const index = flat().findIndex((x) => isDeepEqual(x.value, option.value))
|
||||
if (index === -1) return
|
||||
moveTo(index)
|
||||
}}
|
||||
onMouseDown={() => {
|
||||
if (props.locked) return
|
||||
const index = flat().findIndex((x) => isDeepEqual(x.value, option.value))
|
||||
|
||||
Reference in New Issue
Block a user