mirror of
https://fastgit.cc/https://github.com/anomalyco/opencode
synced 2026-04-21 21:31:53 +08:00
fix use mouse + tabs
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
import type { ScrollBoxRenderable } from "@opentui/core"
|
||||
import { useKeyboard } from "@opentui/solid"
|
||||
import "opentui-spinner/solid"
|
||||
import { For, createMemo, createSignal } from "solid-js"
|
||||
import { For, createMemo } from "solid-js"
|
||||
import { SPINNER_FRAMES } from "../tui/component/spinner"
|
||||
import { RunEntryContent, sameEntryGroup } from "./scrollback.writer"
|
||||
import type { FooterSubagentDetail, FooterSubagentTab, RunDiffStyle } from "./types"
|
||||
@@ -39,10 +39,7 @@ export function RunFooterSubagentTabs(props: {
|
||||
tabs: FooterSubagentTab[]
|
||||
selected?: string
|
||||
theme: RunFooterTheme
|
||||
onToggle: (sessionID: string) => void
|
||||
}) {
|
||||
const [hover, setHover] = createSignal<string>()
|
||||
|
||||
return (
|
||||
<box
|
||||
id="run-direct-footer-subagent-tabs"
|
||||
@@ -55,25 +52,11 @@ export function RunFooterSubagentTabs(props: {
|
||||
flexShrink={0}
|
||||
>
|
||||
<box flexDirection="row" gap={3} flexShrink={1} flexGrow={1}>
|
||||
{props.tabs.map((tab) => {
|
||||
{props.tabs.map((tab, index) => {
|
||||
const active = () => props.selected === tab.sessionID
|
||||
const hovered = () => hover() === tab.sessionID
|
||||
const emphasized = () => active() || hovered()
|
||||
const slot = String(index + 1)
|
||||
return (
|
||||
<box
|
||||
paddingRight={1}
|
||||
onMouseOver={() => {
|
||||
setHover(tab.sessionID)
|
||||
}}
|
||||
onMouseOut={() => {
|
||||
if (hover() === tab.sessionID) {
|
||||
setHover(undefined)
|
||||
}
|
||||
}}
|
||||
onMouseUp={() => {
|
||||
props.onToggle(tab.sessionID)
|
||||
}}
|
||||
>
|
||||
<box paddingRight={1}>
|
||||
<box flexDirection="row" gap={1} width="100%">
|
||||
{tab.status === "running" ? (
|
||||
<box flexShrink={0}>
|
||||
@@ -84,8 +67,8 @@ export function RunFooterSubagentTabs(props: {
|
||||
{statusIcon(tab.status)}
|
||||
</text>
|
||||
)}
|
||||
<text fg={emphasized() ? props.theme.text : props.theme.muted} wrapMode="none" truncate>
|
||||
{tab.label}
|
||||
<text fg={active() ? props.theme.text : props.theme.muted} wrapMode="none" truncate>
|
||||
{`[${slot}] ${tab.label}`}
|
||||
</text>
|
||||
</box>
|
||||
</box>
|
||||
@@ -125,9 +108,9 @@ export function RunFooterSubagentBody(props: {
|
||||
return
|
||||
}
|
||||
|
||||
if (event.name === "tab") {
|
||||
if (event.name === "tab" && !event.shift) {
|
||||
event.preventDefault()
|
||||
props.onCycle(event.shift ? -1 : 1)
|
||||
props.onCycle(1)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
// All state comes from the parent RunFooter through SolidJS signals.
|
||||
// The view itself is stateless except for derived memos.
|
||||
/** @jsxImportSource @opentui/solid */
|
||||
import { useTerminalDimensions } from "@opentui/solid"
|
||||
import { useKeyboard, useTerminalDimensions } from "@opentui/solid"
|
||||
import { Match, Show, Switch, createEffect, createMemo, createSignal } from "solid-js"
|
||||
import "opentui-spinner/solid"
|
||||
import { createColors, createFrames } from "../tui/ui/spinner"
|
||||
@@ -76,6 +76,24 @@ type RunFooterViewProps = {
|
||||
onSubagentSelect?: (sessionID: string | undefined) => void
|
||||
}
|
||||
|
||||
function subagentShortcut(event: {
|
||||
name: string
|
||||
ctrl?: boolean
|
||||
meta?: boolean
|
||||
shift?: boolean
|
||||
super?: boolean
|
||||
}): number | undefined {
|
||||
if (!event.ctrl || event.meta || event.super) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!/^[1-9]$/.test(event.name)) {
|
||||
return
|
||||
}
|
||||
|
||||
return Number(event.name) - 1
|
||||
}
|
||||
|
||||
export { TEXTAREA_MIN_ROWS, TEXTAREA_MAX_ROWS } from "./footer.prompt"
|
||||
|
||||
export function RunFooterView(props: RunFooterViewProps) {
|
||||
@@ -211,6 +229,23 @@ export function RunFooterView(props: RunFooterViewProps) {
|
||||
})
|
||||
const menu = createMemo(() => prompt() && composer.visible())
|
||||
|
||||
useKeyboard((event) => {
|
||||
if (active().type !== "prompt") {
|
||||
return
|
||||
}
|
||||
|
||||
const slot = subagentShortcut(event)
|
||||
if (slot !== undefined) {
|
||||
const next = tabs()[slot]
|
||||
if (!next) {
|
||||
return
|
||||
}
|
||||
|
||||
event.preventDefault()
|
||||
toggleTab(next.sessionID)
|
||||
}
|
||||
})
|
||||
|
||||
createEffect(() => {
|
||||
const current = route()
|
||||
if (current.type === "composer") {
|
||||
@@ -245,7 +280,7 @@ export function RunFooterView(props: RunFooterViewProps) {
|
||||
<box id="run-direct-footer-top-spacer" width="100%" height={1} flexShrink={0} backgroundColor="transparent" />
|
||||
|
||||
<Show when={showTabs()}>
|
||||
<RunFooterSubagentTabs tabs={tabs()} selected={selected()} theme={theme()} onToggle={toggleTab} />
|
||||
<RunFooterSubagentTabs tabs={tabs()} selected={selected()} theme={theme()} />
|
||||
</Show>
|
||||
|
||||
<Show
|
||||
|
||||
@@ -154,7 +154,7 @@ export async function createRuntimeLifecycle(input: LifecycleInput): Promise<Lif
|
||||
const renderer = await createCliRenderer({
|
||||
targetFps: 30,
|
||||
maxFps: 60,
|
||||
useMouse: true,
|
||||
useMouse: false,
|
||||
autoFocus: false,
|
||||
openConsoleOnError: false,
|
||||
exitOnCtrlC: false,
|
||||
|
||||
Reference in New Issue
Block a user