From 4469cecc4e42e4d98a452d39de8f25b3389350b4 Mon Sep 17 00:00:00 2001 From: Brendan Allan <14191578+Brendonovich@users.noreply.github.com> Date: Mon, 27 Jul 2026 17:15:57 +0800 Subject: [PATCH] refactor(app): move prompt effects into controller (#39073) --- .../app/src/components/prompt-input-v2.tsx | 129 ++++++++---------- packages/app/src/pages/session.tsx | 11 +- 2 files changed, 63 insertions(+), 77 deletions(-) diff --git a/packages/app/src/components/prompt-input-v2.tsx b/packages/app/src/components/prompt-input-v2.tsx index 4ea8ad1ee06..113019ed0ac 100644 --- a/packages/app/src/components/prompt-input-v2.tsx +++ b/packages/app/src/components/prompt-input-v2.tsx @@ -5,7 +5,7 @@ import { ButtonV2 } from "@opencode-ai/ui/v2/button-v2" import { Icon } from "@opencode-ai/ui/v2/icon" import { KeybindV2 } from "@opencode-ai/ui/v2/keybind-v2" import { TooltipV2 } from "@opencode-ai/ui/v2/tooltip-v2" -import type { Prompt, ReferenceInfo } from "@opencode-ai/sdk/v2/client" +import type { ReferenceInfo } from "@opencode-ai/sdk/v2/client" import { createEffect, createMemo, on, Show } from "solid-js" import { ModelSelectorPopoverV2 } from "@/components/dialog-select-model" import { DialogSelectModelUnpaidV2 } from "@/components/dialog-select-model-unpaid-v2" @@ -37,11 +37,9 @@ export type PromptInputV2ComposerProps = { class?: string controller: PromptInputV2ComposerController borderUnderlay?: boolean - edit?: PromptInputProps["edit"] - onEditLoaded?: PromptInputProps["onEditLoaded"] } -export type PromptInputV2ControllerProps = Omit +export type PromptInputV2ControllerProps = Omit export type PromptInputV2ComposerController = PromptInputV2Interaction & { readonly model: PromptInputProps["controls"]["model"] } @@ -51,9 +49,6 @@ export function PromptInputV2Composer(props: PromptInputV2ComposerProps) { const command = useCommand() const language = useLanguage() - useCommands(props) - useEditHandler(props) - return (
{ - const prompt = usePrompt() - - createEffect( - on( - () => props.edit?.id, - (id) => { - const edit = props.edit - if (!id || !edit) return - prompt.context.items().forEach((item) => prompt.context.remove(item.key)) - edit.context.forEach((item) => - prompt.context.add({ - type: item.type, - path: item.path, - selection: item.selection, - comment: item.comment, - commentID: item.commentID, - commentOrigin: item.commentOrigin, - preview: item.preview, - }), - ) - props.controller.dispatch({ type: "mode.normal" }) - props.controller.resetHistory() - prompt.set(edit.prompt, promptLength(edit.prompt)) - props.controller.restoreFocus() - props.onEditLoaded?.() - }, - { defer: true }, - ), - ) -} - -const useCommands = (props: PromptInputV2ComposerProps) => { - const command = useCommand() - const language = useLanguage() - - command.register("prompt-input", () => [ - { - id: "file.attach", - title: language.t("prompt.action.attachFile"), - category: language.t("command.category.file"), - keybind: "mod+u", - disabled: props.controller.state.mode !== "normal", - onSelect: () => props.controller.attach(), - }, - { - id: "prompt.mode.shell", - title: language.t("command.prompt.mode.shell"), - category: language.t("command.category.session"), - keybind: "mod+shift+x", - disabled: props.controller.state.mode === "shell", - onSelect: () => props.controller.dispatch({ type: "mode.shell" }), - }, - { - id: "prompt.mode.normal", - title: language.t("command.prompt.mode.normal"), - category: language.t("command.category.session"), - keybind: "mod+shift+e", - disabled: props.controller.state.mode === "normal", - onSelect: () => props.controller.dispatch({ type: "mode.normal" }), - }, - ]) -} - export function usePromptInputV2Controller(props: PromptInputV2ControllerProps): PromptInputV2ComposerController { const sdk = useSDK() const sync = useSync() @@ -472,6 +403,62 @@ export function usePromptInputV2Controller(props: PromptInputV2ControllerProps): }, }) Object.defineProperty(controller, "model", { get: () => props.controls.model }) + + command.register("prompt-input", () => [ + { + id: "file.attach", + title: language.t("prompt.action.attachFile"), + category: language.t("command.category.file"), + keybind: "mod+u", + disabled: controller.state.mode !== "normal", + onSelect: () => controller.attach(), + }, + { + id: "prompt.mode.shell", + title: language.t("command.prompt.mode.shell"), + category: language.t("command.category.session"), + keybind: "mod+shift+x", + disabled: controller.state.mode === "shell", + onSelect: () => controller.dispatch({ type: "mode.shell" }), + }, + { + id: "prompt.mode.normal", + title: language.t("command.prompt.mode.normal"), + category: language.t("command.category.session"), + keybind: "mod+shift+e", + disabled: controller.state.mode === "normal", + onSelect: () => controller.dispatch({ type: "mode.normal" }), + }, + ]) + + createEffect( + on( + () => props.edit?.id, + (id) => { + const edit = props.edit + if (!id || !edit) return + prompt.context.items().forEach((item) => prompt.context.remove(item.key)) + edit.context.forEach((item) => + prompt.context.add({ + type: item.type, + path: item.path, + selection: item.selection, + comment: item.comment, + commentID: item.commentID, + commentOrigin: item.commentOrigin, + preview: item.preview, + }), + ) + controller.dispatch({ type: "mode.normal" }) + controller.resetHistory() + prompt.set(edit.prompt, promptLength(edit.prompt)) + controller.restoreFocus() + props.onEditLoaded?.() + }, + { defer: true }, + ), + ) + return controller as PromptInputV2ComposerController } diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx index d4dd6ff7efb..e8b643f8858 100644 --- a/packages/app/src/pages/session.tsx +++ b/packages/app/src/pages/session.tsx @@ -2217,6 +2217,10 @@ export default function Page() { comments.clear() resumeScroll() }, + get edit() { + return editingFollowup() + }, + onEditLoaded: clearFollowupEdit, shouldQueue: queueEnabled, onQueue: queueFollowup, onAbort: () => { @@ -2226,12 +2230,7 @@ export default function Page() { }, }) return ( - + ) }}