mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 16:02:32 +00:00
Cancel composer focus frames from root cleanup (#3452)
This commit is contained in:
@@ -41,6 +41,7 @@ type RepoOption = React.ComponentProps<typeof RepoCombobox>['repos'][number]
|
||||
type NewWorkspaceComposerCardProps = {
|
||||
containerClassName?: string
|
||||
composerRef?: React.RefObject<HTMLDivElement | null>
|
||||
onComposerNodeChange?: (node: HTMLDivElement | null) => void
|
||||
nameInputRef?: React.RefObject<HTMLInputElement | null>
|
||||
quickAgent: TuiAgent | null
|
||||
onQuickAgentChange: (agent: TuiAgent | null) => void
|
||||
@@ -205,6 +206,7 @@ function useComposerFileDragOver(): {
|
||||
export default function NewWorkspaceComposerCard({
|
||||
containerClassName,
|
||||
composerRef,
|
||||
onComposerNodeChange,
|
||||
nameInputRef,
|
||||
quickAgent,
|
||||
onQuickAgentChange,
|
||||
@@ -281,7 +283,19 @@ export default function NewWorkspaceComposerCard({
|
||||
nameInputFocusFrameRef.current = null
|
||||
}, [])
|
||||
|
||||
React.useEffect(() => cancelNameInputFocusFrame, [cancelNameInputFocusFrame])
|
||||
const setComposerNode = React.useCallback(
|
||||
(node: HTMLDivElement | null): void => {
|
||||
// Why: the queued repo-picker focus is only valid while this composer exists.
|
||||
if (!node) {
|
||||
cancelNameInputFocusFrame()
|
||||
}
|
||||
if (composerRef) {
|
||||
composerRef.current = node
|
||||
}
|
||||
onComposerNodeChange?.(node)
|
||||
},
|
||||
[cancelNameInputFocusFrame, composerRef, onComposerNodeChange]
|
||||
)
|
||||
|
||||
const focusNameInput = React.useCallback(() => {
|
||||
// Why: after the repo picker commits a choice, moving focus to the name
|
||||
@@ -313,7 +327,7 @@ export default function NewWorkspaceComposerCard({
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={composerRef}
|
||||
ref={setComposerNode}
|
||||
// Why: preload classifies native OS file drops by the nearest
|
||||
// `data-native-file-drop-target` marker in the composedPath. Tagging
|
||||
// the composer root makes drops anywhere on the card route to the
|
||||
|
||||
@@ -100,7 +100,14 @@ function QuickTabBody({
|
||||
active: boolean
|
||||
}): React.JSX.Element {
|
||||
const settings = useAppStore((s) => s.settings)
|
||||
const { cardProps, composerRef, nameInputRef, submitQuick, createDisabled } = useComposerState({
|
||||
const {
|
||||
cardProps,
|
||||
composerRef,
|
||||
onComposerNodeChange,
|
||||
nameInputRef,
|
||||
submitQuick,
|
||||
createDisabled
|
||||
} = useComposerState({
|
||||
initialName: modalData.prefilledName ?? '',
|
||||
// Why: the modal is quick-create only now, so prompt-prefill state is
|
||||
// intentionally ignored even if older callers still send it.
|
||||
@@ -219,6 +226,7 @@ function QuickTabBody({
|
||||
</DialogHeader>
|
||||
<NewWorkspaceComposerCard
|
||||
composerRef={composerRef}
|
||||
onComposerNodeChange={onComposerNodeChange}
|
||||
nameInputRef={nameInputRef}
|
||||
quickAgent={quickAgent}
|
||||
onQuickAgentChange={handleQuickAgentChange}
|
||||
|
||||
@@ -212,6 +212,7 @@ export type UseComposerStateResult = {
|
||||
/** Ref the consumer should attach to the composer wrapper so the global
|
||||
* Enter-to-submit handler can scope its behavior to the visible composer. */
|
||||
composerRef: React.RefObject<HTMLDivElement | null>
|
||||
onComposerNodeChange: (node: HTMLDivElement | null) => void
|
||||
promptTextareaRef: React.RefObject<HTMLTextAreaElement | null>
|
||||
nameInputRef: React.RefObject<HTMLInputElement | null>
|
||||
submit: () => Promise<void>
|
||||
@@ -514,7 +515,16 @@ export function useComposerState(options: UseComposerStateOptions): UseComposerS
|
||||
promptCaretFrameRef.current = null
|
||||
}, [])
|
||||
|
||||
useEffect(() => cancelPromptCaretFrame, [cancelPromptCaretFrame])
|
||||
const handleComposerNodeChange = useCallback(
|
||||
(node: HTMLDivElement | null): void => {
|
||||
// Why: the queued caret restoration targets composer descendants and
|
||||
// must be canceled as soon as the composer root leaves the DOM.
|
||||
if (!node) {
|
||||
cancelPromptCaretFrame()
|
||||
}
|
||||
},
|
||||
[cancelPromptCaretFrame]
|
||||
)
|
||||
|
||||
const hookCheckRef = useRef<{
|
||||
key: string
|
||||
@@ -2329,6 +2339,7 @@ export function useComposerState(options: UseComposerStateOptions): UseComposerS
|
||||
return {
|
||||
cardProps,
|
||||
composerRef,
|
||||
onComposerNodeChange: handleComposerNodeChange,
|
||||
promptTextareaRef,
|
||||
nameInputRef,
|
||||
submit,
|
||||
|
||||
Reference in New Issue
Block a user