fix(app): enable composer shortcuts on drafts (#33956)

This commit is contained in:
Brendan Allan
2026-06-26 04:05:36 +08:00
committed by GitHub
parent b60c0a5e8c
commit fae100fe72
4 changed files with 74 additions and 49 deletions
+3
View File
@@ -13,6 +13,7 @@ import {
SessionComposerRegion, SessionComposerRegion,
} from "@/pages/session/composer" } from "@/pages/session/composer"
import { useSessionKey } from "@/pages/session/session-layout" import { useSessionKey } from "@/pages/session/session-layout"
import { useComposerCommands } from "@/pages/session/use-composer-commands"
/** /**
* The `/new-session` draft page. Unlike `session.tsx`, this only renders the prompt * The `/new-session` draft page. Unlike `session.tsx`, this only renders the prompt
@@ -28,6 +29,8 @@ export default function NewSessionPage() {
const route = useSessionKey() const route = useSessionKey()
const [searchParams, setSearchParams] = useSearchParams<{ draftId?: string; prompt?: string }>() const [searchParams, setSearchParams] = useSearchParams<{ draftId?: string; prompt?: string }>()
useComposerCommands()
let inputRef: HTMLDivElement | undefined let inputRef: HTMLDivElement | undefined
const composer = createSessionComposerState() const composer = createSessionComposerState()
+2
View File
@@ -63,6 +63,7 @@ import { useSessionLayout } from "@/pages/session/session-layout"
import { syncSessionModel } from "@/pages/session/session-model-helpers" import { syncSessionModel } from "@/pages/session/session-model-helpers"
import { SessionSidePanel } from "@/pages/session/session-side-panel" import { SessionSidePanel } from "@/pages/session/session-side-panel"
import { TerminalPanel } from "@/pages/session/terminal-panel" import { TerminalPanel } from "@/pages/session/terminal-panel"
import { useComposerCommands } from "@/pages/session/use-composer-commands"
import { useSessionCommands } from "@/pages/session/use-session-commands" import { useSessionCommands } from "@/pages/session/use-session-commands"
import { useSessionHashScroll } from "@/pages/session/use-session-hash-scroll" import { useSessionHashScroll } from "@/pages/session/use-session-hash-scroll"
import { Identifier } from "@/utils/id" import { Identifier } from "@/utils/id"
@@ -783,6 +784,7 @@ export default function Page() {
inputRef?.focus() inputRef?.focus()
} }
useComposerCommands()
useSessionCommands({ useSessionCommands({
navigateMessageByOffset, navigateMessageByOffset,
setActiveMessage, setActiveMessage,
@@ -0,0 +1,69 @@
import { useCommand, type CommandOption } from "@/context/command"
import { useLanguage } from "@/context/language"
import { useLocal } from "@/context/local"
import { useSettings } from "@/context/settings"
import { useDialog } from "@opencode-ai/ui/context/dialog"
import { useSessionLayout } from "./session-layout"
import { createSessionOwnership } from "./session-ownership"
const withCategory = (category: string) => {
return (option: Omit<CommandOption, "category">): CommandOption => ({
...option,
category,
})
}
export const useComposerCommands = () => {
const command = useCommand()
const dialog = useDialog()
const language = useLanguage()
const local = useLocal()
const settings = useSettings()
const { sessionKey } = useSessionLayout()
const sessionOwnership = createSessionOwnership(sessionKey)
const modelCommand = withCategory(language.t("command.category.model"))
const agentCommand = withCategory(language.t("command.category.agent"))
const chooseModel = async () => {
const owner = sessionOwnership.capture()
const { DialogSelectModel } = await import("@/components/dialog-select-model")
owner.run(() => {
void dialog.show(() => <DialogSelectModel model={local.model} />)
})
}
command.register("composer", () => [
modelCommand({
id: "model.choose",
title: language.t("command.model.choose"),
description: language.t("command.model.choose.description"),
keybind: "mod+'",
slash: "model",
onSelect: chooseModel,
}),
modelCommand({
id: "model.variant.cycle",
title: language.t("command.model.variant.cycle"),
description: language.t("command.model.variant.cycle.description"),
keybind: "shift+mod+d",
onSelect: () => local.model.variant.cycle(),
}),
agentCommand({
id: "agent.cycle",
title: language.t("command.agent.cycle"),
description: language.t("command.agent.cycle.description"),
keybind: "mod+.",
slash: "agent",
disabled: !settings.visibility.customAgents(),
onSelect: () => local.agent.move(1),
}),
agentCommand({
id: "agent.cycle.reverse",
title: language.t("command.agent.cycle.reverse"),
description: language.t("command.agent.cycle.reverse.description"),
keybind: "shift+mod+.",
disabled: !settings.visibility.customAgents(),
onSelect: () => local.agent.move(-1),
}),
])
}
@@ -136,9 +136,7 @@ export const useSessionCommands = (actions: SessionCommandContext) => {
const contextCommand = withCategory(language.t("command.category.context")) const contextCommand = withCategory(language.t("command.category.context"))
const viewCommand = withCategory(language.t("command.category.view")) const viewCommand = withCategory(language.t("command.category.view"))
const terminalCommand = withCategory(language.t("command.category.terminal")) const terminalCommand = withCategory(language.t("command.category.terminal"))
const modelCommand = withCategory(language.t("command.category.model"))
const mcpCommand = withCategory(language.t("command.category.mcp")) const mcpCommand = withCategory(language.t("command.category.mcp"))
const agentCommand = withCategory(language.t("command.category.agent"))
const permissionsCommand = withCategory(language.t("command.category.permissions")) const permissionsCommand = withCategory(language.t("command.category.permissions"))
const isAutoAcceptActive = () => { const isAutoAcceptActive = () => {
@@ -271,13 +269,6 @@ export const useSessionCommands = (actions: SessionCommandContext) => {
view().terminal.open() view().terminal.open()
} }
const chooseModel = () => {
void openDialog(
() => import("@/components/dialog-select-model"),
(x) => dialog.show(() => <x.DialogSelectModel model={local.model} />),
)
}
const chooseMcp = () => { const chooseMcp = () => {
void openDialog( void openDialog(
() => import("@/components/dialog-select-mcp"), () => import("@/components/dialog-select-mcp"),
@@ -555,24 +546,6 @@ export const useSessionCommands = (actions: SessionCommandContext) => {
}), }),
] ]
const modelCmds = () => [
modelCommand({
id: "model.choose",
title: language.t("command.model.choose"),
description: language.t("command.model.choose.description"),
keybind: "mod+'",
slash: "model",
onSelect: chooseModel,
}),
modelCommand({
id: "model.variant.cycle",
title: language.t("command.model.variant.cycle"),
description: language.t("command.model.variant.cycle.description"),
keybind: "shift+mod+d",
onSelect: () => local.model.variant.cycle(),
}),
]
const mcpCmds = () => [ const mcpCmds = () => [
mcpCommand({ mcpCommand({
id: "mcp.toggle", id: "mcp.toggle",
@@ -584,26 +557,6 @@ export const useSessionCommands = (actions: SessionCommandContext) => {
}), }),
] ]
const agentCmds = () => [
agentCommand({
id: "agent.cycle",
title: language.t("command.agent.cycle"),
description: language.t("command.agent.cycle.description"),
keybind: "mod+.",
slash: "agent",
disabled: !settings.visibility.customAgents(),
onSelect: () => local.agent.move(1),
}),
agentCommand({
id: "agent.cycle.reverse",
title: language.t("command.agent.cycle.reverse"),
description: language.t("command.agent.cycle.reverse.description"),
keybind: "shift+mod+.",
disabled: !settings.visibility.customAgents(),
onSelect: () => local.agent.move(-1),
}),
]
const permissionsCmds = () => [ const permissionsCmds = () => [
permissionsCommand({ permissionsCommand({
id: "permissions.autoaccept", id: "permissions.autoaccept",
@@ -624,9 +577,7 @@ export const useSessionCommands = (actions: SessionCommandContext) => {
...viewCmds(), ...viewCmds(),
...terminalCmds(), ...terminalCmds(),
...messageCmds(), ...messageCmds(),
...modelCmds(),
...mcpCmds(), ...mcpCmds(),
...agentCmds(),
...permissionsCmds(), ...permissionsCmds(),
]) ])
} }