fix(app): restore prompt cursor on focus (#34175)

This commit is contained in:
Brendan Allan 2026-06-30 18:40:20 +08:00 committed by GitHub
commit 3aa2860058
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -214,6 +214,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
let fileInputRef: HTMLInputElement | undefined let fileInputRef: HTMLInputElement | undefined
let scrollRef!: HTMLDivElement let scrollRef!: HTMLDivElement
let slashPopoverRef!: HTMLDivElement let slashPopoverRef!: HTMLDivElement
let restoreEndOnFocus = true
const mirror = { input: false } const mirror = { input: false }
const inset = 56 const inset = 56
@ -593,6 +594,16 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
}) })
} }
const handleFocus = () => {
if (!restoreEndOnFocus) return
restoreEndOnFocus = false
requestAnimationFrame(() => {
if (document.activeElement !== editorRef) return
setCursorPosition(editorRef, prompt.cursor() ?? promptLength(prompt.current()))
queueScroll()
})
}
const renderEditorWithCursor = (parts: Prompt) => { const renderEditorWithCursor = (parts: Prompt) => {
const cursor = currentCursor() const cursor = currentCursor()
renderEditor(parts) renderEditor(parts)
@ -1380,6 +1391,11 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
})) }))
const newSession = () => props.variant === "new-session" const newSession = () => props.variant === "new-session"
const bindEditorRef = (el: HTMLDivElement) => {
editorRef = el
restoreEndOnFocus = true
props.ref?.(el)
}
const showAgentControl = createMemo(() => props.controls.agents.visible && props.controls.agents.options.length > 0) const showAgentControl = createMemo(() => props.controls.agents.visible && props.controls.agents.options.length > 0)
const agentControlState = createMemo<ComposerAgentControlState>(() => ({ const agentControlState = createMemo<ComposerAgentControlState>(() => ({
title: language.t("command.agent.cycle"), title: language.t("command.agent.cycle"),
@ -1463,10 +1479,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
<div class="relative max-h-[180px] overflow-y-auto no-scrollbar" ref={(el) => (scrollRef = el)}> <div class="relative max-h-[180px] overflow-y-auto no-scrollbar" ref={(el) => (scrollRef = el)}>
<div <div
data-component="prompt-input" data-component="prompt-input"
ref={(el) => { ref={bindEditorRef}
editorRef = el
props.ref?.(el)
}}
role="textbox" role="textbox"
aria-multiline="true" aria-multiline="true"
aria-label={designPlaceholder()} aria-label={designPlaceholder()}
@ -1481,6 +1494,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
onPaste={handlePaste} onPaste={handlePaste}
onCompositionStart={handleCompositionStart} onCompositionStart={handleCompositionStart}
onCompositionEnd={handleCompositionEnd} onCompositionEnd={handleCompositionEnd}
onFocus={handleFocus}
onBlur={handleBlur} onBlur={handleBlur}
onKeyDown={handleKeyDown} onKeyDown={handleKeyDown}
classList={{ classList={{
@ -1501,7 +1515,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
</div> </div>
</div> </div>
<div class="flex h-11 items-center px-2"> <div class="flex h-11 items-center px-2">
<div class="flex min-w-0 flex-1 items-center gap-0"> <div class="flex min-w-0 flex-1 items-center gap-1">
{fileAttachmentInput()} {fileAttachmentInput()}
<TooltipV2 <TooltipV2
placement="top" placement="top"
@ -1644,10 +1658,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
> >
<div <div
data-component="prompt-input" data-component="prompt-input"
ref={(el) => { ref={bindEditorRef}
editorRef = el
props.ref?.(el)
}}
role="textbox" role="textbox"
aria-multiline="true" aria-multiline="true"
aria-label={placeholder()} aria-label={placeholder()}
@ -1662,6 +1673,7 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
onPaste={handlePaste} onPaste={handlePaste}
onCompositionStart={handleCompositionStart} onCompositionStart={handleCompositionStart}
onCompositionEnd={handleCompositionEnd} onCompositionEnd={handleCompositionEnd}
onFocus={handleFocus}
onBlur={handleBlur} onBlur={handleBlur}
onKeyDown={handleKeyDown} onKeyDown={handleKeyDown}
classList={{ classList={{