Open left drawer for selector and session shortcuts
This commit is contained in:
@@ -56,6 +56,11 @@ import SessionView from "../session/session-view"
|
|||||||
import { formatTokenTotal } from "../../lib/formatters"
|
import { formatTokenTotal } from "../../lib/formatters"
|
||||||
import { sseManager } from "../../lib/sse-manager"
|
import { sseManager } from "../../lib/sse-manager"
|
||||||
import { getLogger } from "../../lib/logger"
|
import { getLogger } from "../../lib/logger"
|
||||||
|
import {
|
||||||
|
SESSION_SIDEBAR_EVENT,
|
||||||
|
type SessionSidebarRequestAction,
|
||||||
|
type SessionSidebarRequestDetail,
|
||||||
|
} from "../../lib/session-sidebar-events"
|
||||||
|
|
||||||
const log = getLogger("session")
|
const log = getLogger("session")
|
||||||
|
|
||||||
@@ -217,6 +222,17 @@ const InstanceShell2: Component<InstanceShellProps> = (props) => {
|
|||||||
onCleanup(() => window.removeEventListener("resize", handleResize))
|
onCleanup(() => window.removeEventListener("resize", handleResize))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
if (typeof window === "undefined") return
|
||||||
|
const handler = (event: Event) => {
|
||||||
|
const detail = (event as CustomEvent<SessionSidebarRequestDetail>).detail
|
||||||
|
if (!detail || detail.instanceId !== props.instance.id) return
|
||||||
|
handleSidebarRequest(detail.action)
|
||||||
|
}
|
||||||
|
window.addEventListener(SESSION_SIDEBAR_EVENT, handler)
|
||||||
|
onCleanup(() => window.removeEventListener(SESSION_SIDEBAR_EVENT, handler))
|
||||||
|
})
|
||||||
|
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
if (typeof window === "undefined") return
|
if (typeof window === "undefined") return
|
||||||
window.localStorage.setItem(LEFT_DRAWER_STORAGE_KEY, sessionSidebarWidth().toString())
|
window.localStorage.setItem(LEFT_DRAWER_STORAGE_KEY, sessionSidebarWidth().toString())
|
||||||
@@ -322,6 +338,58 @@ const InstanceShell2: Component<InstanceShellProps> = (props) => {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const runAfterDrawerReady = (callback: (() => void) | undefined, attempts = 12) => {
|
||||||
|
if (!callback) return
|
||||||
|
if (leftDrawerContentEl()) {
|
||||||
|
requestAnimationFrame(() => callback())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (attempts <= 0) return
|
||||||
|
requestAnimationFrame(() => runAfterDrawerReady(callback, attempts - 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
const ensureLeftDrawerVisible = (callback?: () => void) => {
|
||||||
|
if (leftPinned()) {
|
||||||
|
runAfterDrawerReady(callback)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!leftOpen()) {
|
||||||
|
setLeftOpen(true)
|
||||||
|
measureDrawerHost()
|
||||||
|
}
|
||||||
|
runAfterDrawerReady(callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
const focusAgentSelectorControl = () => {
|
||||||
|
const agentTrigger = leftDrawerContentEl()?.querySelector("[data-agent-selector]") as HTMLElement | null
|
||||||
|
if (!agentTrigger) return
|
||||||
|
agentTrigger.focus()
|
||||||
|
setTimeout(() => agentTrigger.click(), 20)
|
||||||
|
}
|
||||||
|
|
||||||
|
const focusModelSelectorControl = () => {
|
||||||
|
const trigger = leftDrawerContentEl()?.querySelector(
|
||||||
|
"[data-model-selector-control] .selector-trigger",
|
||||||
|
) as HTMLElement | null
|
||||||
|
if (!trigger) return
|
||||||
|
trigger.focus()
|
||||||
|
setTimeout(() => trigger.click(), 20)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSidebarRequest = (action: SessionSidebarRequestAction) => {
|
||||||
|
if (action === "focus-agent-selector") {
|
||||||
|
ensureLeftDrawerVisible(() => focusAgentSelectorControl())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (action === "focus-model-selector") {
|
||||||
|
ensureLeftDrawerVisible(() => focusModelSelectorControl())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (action === "show-session-list") {
|
||||||
|
ensureLeftDrawerVisible()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const handleSessionSelect = (sessionId: string) => {
|
const handleSessionSelect = (sessionId: string) => {
|
||||||
setActiveSession(props.instance.id, sessionId)
|
setActiveSession(props.instance.id, sessionId)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,9 +18,11 @@ import type { MessageRecord } from "../../stores/message-v2/types"
|
|||||||
import { messageStoreBus } from "../../stores/message-v2/bus"
|
import { messageStoreBus } from "../../stores/message-v2/bus"
|
||||||
import { cleanupBlankSessions } from "../../stores/session-state"
|
import { cleanupBlankSessions } from "../../stores/session-state"
|
||||||
import { getLogger } from "../logger"
|
import { getLogger } from "../logger"
|
||||||
|
import { emitSessionSidebarRequest } from "../session-sidebar-events"
|
||||||
|
|
||||||
const log = getLogger("actions")
|
const log = getLogger("actions")
|
||||||
|
|
||||||
|
|
||||||
export interface UseCommandsOptions {
|
export interface UseCommandsOptions {
|
||||||
preferences: Accessor<Preferences>
|
preferences: Accessor<Preferences>
|
||||||
toggleShowThinkingBlocks: () => void
|
toggleShowThinkingBlocks: () => void
|
||||||
@@ -191,7 +193,10 @@ export function useCommands(options: UseCommandsOptions) {
|
|||||||
if (ids.length <= 1) return
|
if (ids.length <= 1) return
|
||||||
const current = ids.indexOf(activeSessionMap().get(instanceId) || "")
|
const current = ids.indexOf(activeSessionMap().get(instanceId) || "")
|
||||||
const next = (current + 1) % ids.length
|
const next = (current + 1) % ids.length
|
||||||
if (ids[next]) setActiveSession(instanceId, ids[next])
|
if (ids[next]) {
|
||||||
|
setActiveSession(instanceId, ids[next])
|
||||||
|
emitSessionSidebarRequest({ instanceId, action: "show-session-list" })
|
||||||
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -212,7 +217,10 @@ export function useCommands(options: UseCommandsOptions) {
|
|||||||
if (ids.length <= 1) return
|
if (ids.length <= 1) return
|
||||||
const current = ids.indexOf(activeSessionMap().get(instanceId) || "")
|
const current = ids.indexOf(activeSessionMap().get(instanceId) || "")
|
||||||
const prev = current <= 0 ? ids.length - 1 : current - 1
|
const prev = current <= 0 ? ids.length - 1 : current - 1
|
||||||
if (ids[prev]) setActiveSession(instanceId, ids[prev])
|
if (ids[prev]) {
|
||||||
|
setActiveSession(instanceId, ids[prev])
|
||||||
|
emitSessionSidebarRequest({ instanceId, action: "show-session-list" })
|
||||||
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -345,21 +353,9 @@ export function useCommands(options: UseCommandsOptions) {
|
|||||||
keywords: ["model", "llm", "ai"],
|
keywords: ["model", "llm", "ai"],
|
||||||
shortcut: { key: "M", meta: true, shift: true },
|
shortcut: { key: "M", meta: true, shift: true },
|
||||||
action: () => {
|
action: () => {
|
||||||
const modelInput = document.querySelector("[data-model-selector]") as HTMLInputElement
|
const instance = activeInstance()
|
||||||
if (modelInput) {
|
if (!instance) return
|
||||||
modelInput.focus()
|
emitSessionSidebarRequest({ instanceId: instance.id, action: "focus-model-selector" })
|
||||||
setTimeout(() => {
|
|
||||||
const event = new KeyboardEvent("keydown", {
|
|
||||||
key: "ArrowDown",
|
|
||||||
code: "ArrowDown",
|
|
||||||
keyCode: 40,
|
|
||||||
which: 40,
|
|
||||||
bubbles: true,
|
|
||||||
cancelable: true,
|
|
||||||
})
|
|
||||||
modelInput.dispatchEvent(event)
|
|
||||||
}, 10)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -371,21 +367,9 @@ export function useCommands(options: UseCommandsOptions) {
|
|||||||
keywords: ["agent", "mode"],
|
keywords: ["agent", "mode"],
|
||||||
shortcut: { key: "A", meta: true, shift: true },
|
shortcut: { key: "A", meta: true, shift: true },
|
||||||
action: () => {
|
action: () => {
|
||||||
const agentTrigger = document.querySelector("[data-agent-selector]") as HTMLElement
|
const instance = activeInstance()
|
||||||
if (agentTrigger) {
|
if (!instance) return
|
||||||
agentTrigger.focus()
|
emitSessionSidebarRequest({ instanceId: instance.id, action: "focus-agent-selector" })
|
||||||
setTimeout(() => {
|
|
||||||
const event = new KeyboardEvent("keydown", {
|
|
||||||
key: "Enter",
|
|
||||||
code: "Enter",
|
|
||||||
keyCode: 13,
|
|
||||||
which: 13,
|
|
||||||
bubbles: true,
|
|
||||||
cancelable: true,
|
|
||||||
})
|
|
||||||
agentTrigger.dispatchEvent(event)
|
|
||||||
}, 50)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
13
packages/ui/src/lib/session-sidebar-events.ts
Normal file
13
packages/ui/src/lib/session-sidebar-events.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
export type SessionSidebarRequestAction = "focus-agent-selector" | "focus-model-selector" | "show-session-list"
|
||||||
|
|
||||||
|
export interface SessionSidebarRequestDetail {
|
||||||
|
instanceId: string
|
||||||
|
action: SessionSidebarRequestAction
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SESSION_SIDEBAR_EVENT = "opencode:session-sidebar-request"
|
||||||
|
|
||||||
|
export function emitSessionSidebarRequest(detail: SessionSidebarRequestDetail) {
|
||||||
|
if (typeof window === "undefined") return
|
||||||
|
window.dispatchEvent(new CustomEvent<SessionSidebarRequestDetail>(SESSION_SIDEBAR_EVENT, { detail }))
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user