fix: grow composer with dictation transcript like typed text
The dictation overlay is absolutely positioned over the composer, so the transcript could not expand it — long dictations clipped after two lines. ComposerDictation now measures the transcript text block (not the flex-1 container, which would feed the composer's own height back and creep a few px per update) and reports it to ChatInput, which feeds it into the textarea autosize: same line cap as typing, transcript area scrolls past it and follows the newest words. Idle/unmount releases the height, and an idle sibling instance (mobile footer + wrapper engine) can no longer zero the active one's report.
This commit is contained in:
@@ -2819,6 +2819,15 @@ const ChatInputComponent: React.FC<ChatInputProps> = ({ onOpenSettings, scrollTo
|
||||
}
|
||||
}, [agents, currentAgentName, currentSessionId, setAgent, saveSessionAgentSelection]);
|
||||
|
||||
// Height the dictation transcript needs (null when idle): the overlay sits
|
||||
// absolutely over the composer, so the underlying textarea must grow for
|
||||
// the composer to grow — feed this into the autosize below.
|
||||
const dictationContentHeightRef = React.useRef<number | null>(null);
|
||||
const [dictationContentHeight, setDictationContentHeight] = React.useState<number | null>(null);
|
||||
const handleDictationContentHeightChange = React.useCallback((height: number | null) => {
|
||||
setDictationContentHeight((prev) => (prev === height ? prev : height));
|
||||
}, []);
|
||||
|
||||
const adjustTextareaHeight = React.useCallback((options?: { allowShrink?: boolean }) => {
|
||||
const textarea = textareaRef.current;
|
||||
if (!textarea) {
|
||||
@@ -2854,7 +2863,8 @@ const ChatInputComponent: React.FC<ChatInputProps> = ({ onOpenSettings, scrollTo
|
||||
const targetLineHeight = Number.isNaN(lineHeight) ? fallbackLineHeight : lineHeight;
|
||||
const maxHeight = targetLineHeight * MAX_VISIBLE_TEXTAREA_LINES + paddingTotal;
|
||||
const scrollHeight = textarea.scrollHeight || textarea.offsetHeight;
|
||||
const nextHeight = Math.min(scrollHeight, maxHeight);
|
||||
const dictationHeight = dictationContentHeightRef.current ?? 0;
|
||||
const nextHeight = Math.min(Math.max(scrollHeight, dictationHeight), maxHeight);
|
||||
|
||||
textarea.style.height = `${nextHeight}px`;
|
||||
textarea.style.maxHeight = `${maxHeight}px`;
|
||||
@@ -2876,6 +2886,13 @@ const ChatInputComponent: React.FC<ChatInputProps> = ({ onOpenSettings, scrollTo
|
||||
adjustTextareaHeight({ allowShrink });
|
||||
}, [adjustTextareaHeight, message, isMobile]);
|
||||
|
||||
React.useLayoutEffect(() => {
|
||||
dictationContentHeightRef.current = dictationContentHeight;
|
||||
// Growing transcript never shrinks mid-recording (matches typing);
|
||||
// dictation ending (null) releases the height back to the message.
|
||||
adjustTextareaHeight({ allowShrink: dictationContentHeight === null });
|
||||
}, [adjustTextareaHeight, dictationContentHeight]);
|
||||
|
||||
const updateAutocompleteState = React.useCallback((
|
||||
value: string,
|
||||
cursorPosition: number,
|
||||
@@ -5363,6 +5380,7 @@ const ChatInputComponent: React.FC<ChatInputProps> = ({ onOpenSettings, scrollTo
|
||||
sendIconSizeClass={sendIconSizeClass}
|
||||
onInsert={handleDictationInsert}
|
||||
onInsertAndSend={handleDictationInsertAndSend}
|
||||
onContentHeightChange={handleDictationContentHeightChange}
|
||||
/>
|
||||
<ComposerActionButtons
|
||||
isMobile={isMobile}
|
||||
@@ -5402,6 +5420,7 @@ const ChatInputComponent: React.FC<ChatInputProps> = ({ onOpenSettings, scrollTo
|
||||
onInsert={handleDictationInsert}
|
||||
onInsertAndSend={handleDictationInsertAndSend}
|
||||
onActiveChange={handleMobileDictationActiveChange}
|
||||
onContentHeightChange={handleDictationContentHeightChange}
|
||||
renderTrigger={false}
|
||||
topAccessory={mobileComposerHandle}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user