fix(app): preserve command menu drafts (#37942)

Co-authored-by: Brendan Allan <14191578+Brendonovich@users.noreply.github.com>
This commit is contained in:
opencode-agent[bot]
2026-07-20 22:49:39 +08:00
committed by GitHub
co-authored by Brendan Allan
parent 70535a1bad
commit da312b009c
2 changed files with 62 additions and 9 deletions
@@ -0,0 +1,50 @@
import { expect, test } from "@playwright/test"
import { base64Encode } from "@opencode-ai/core/util/encode"
import { mockOpenCodeServer } from "../utils/mock-server"
import { expectAppVisible } from "../utils/waits"
const directory = "C:/OpenCode/PromptInputV2Editing"
const projectID = "proj_prompt_input_v2_editing"
const sessionID = "ses_prompt_input_v2_editing"
test("preserves the draft when a populated command menu triggers a built-in", async ({ page }) => {
await mockOpenCodeServer(page, {
directory,
project: {
id: projectID,
worktree: directory,
vcs: "git",
name: "prompt-input-v2-editing",
time: { created: 1700000000000, updated: 1700000000000 },
sandboxes: [],
},
provider: { all: [], connected: [], default: {} },
sessions: [
{
id: sessionID,
slug: "prompt-input-v2-editing",
projectID,
directory,
title: "Prompt input V2 editing",
version: "dev",
time: { created: 1700000000000, updated: 1700000000000 },
},
],
pageMessages: () => ({ items: [] }),
})
await page.addInitScript(() => {
localStorage.setItem("settings.v3", JSON.stringify({ general: { newLayoutDesigns: true } }))
})
await page.goto(`/${base64Encode(directory)}/session/${sessionID}`)
const composer = page.locator('[data-component="prompt-input-v2"]')
const input = composer.locator('[data-component="prompt-input"]')
await expectAppVisible(composer)
await input.fill("keep me")
await composer.getByRole("button", { name: "Add images and files" }).click()
await page.getByRole("menuitem", { name: "Commands" }).click()
await page.locator('[data-suggestion-id="model.choose"]').click()
await expect(input).toHaveText("keep me")
})
@@ -164,21 +164,24 @@ export function createPromptInputV2Controller(input: {
function dispatch(event: PromptInputV2InteractionEvent) {
const mode = state.mode
const result = transitionPromptInputV2(state, event, draft.state)
setState(reconcile(result.state))
result.commands.forEach(execute)
if (mode !== result.state.mode) {
if (result.state.mode === "shell") input.view.shell?.onOpen()
if (result.state.mode === "normal") input.view.shell?.onClose()
}
const action = event.type === "popover.select" ? input.onSuggestionSelect?.(event.item) : undefined
if (event.type === "popover.select") {
const action = input.onSuggestionSelect?.(event.item)
if (!action) return result.handled
if (event.item.kind === "command") {
if (!action || state.popover.type !== "command-menu") result.commands.forEach(execute)
if (action && event.item.kind === "command" && state.popover.type !== "command-menu") {
draft.setPrompt(
draft.state.prompt.filter((part): part is PromptInputV2Attachment => part.type === "image"),
0,
)
}
}
setState(reconcile(result.state))
if (event.type !== "popover.select") result.commands.forEach(execute)
if (mode !== result.state.mode) {
if (result.state.mode === "shell") input.view.shell?.onOpen()
if (result.state.mode === "normal") input.view.shell?.onClose()
}
if (event.type === "popover.select") {
if (!action) return result.handled
action()
}
return result.handled