fix(webui): stabilize thread during IME input

This commit is contained in:
chengyongru
2026-08-03 16:41:08 +08:00
committed by chengyongru
parent ac216c3e94
commit eeecfac538
4 changed files with 73 additions and 0 deletions
@@ -1799,6 +1799,7 @@ export function ThreadComposer({
};
const onInput: React.FormEventHandler<HTMLTextAreaElement> = (e) => {
if ((e.nativeEvent as InputEvent).isComposing) return;
const el = e.currentTarget;
el.style.height = "auto";
el.style.height = `${Math.min(el.scrollHeight, 260)}px`;
@@ -186,6 +186,7 @@ export const ThreadViewport = forwardRef<ThreadViewportHandle, ThreadViewportPro
const pendingPromptJumpRef = useRef<string | null>(null);
const restoreScrollAfterPrependRef =
useRef<{ height: number; top: number } | null>(null);
const composerInputScrollTopRef = useRef<number | null>(null);
const composerDockHeightRef = useRef(0);
const [atBottom, setAtBottom] = useState(true);
const [composerDockHeight, setComposerDockHeight] = useState(0);
@@ -688,9 +689,23 @@ export const ThreadViewport = forwardRef<ThreadViewportHandle, ThreadViewportPro
data-testid="thread-composer-dock"
onInputCapture={(event) => {
if (event.target instanceof HTMLTextAreaElement) {
composerInputScrollTopRef.current = scrollRef.current?.scrollTop ?? null;
threadMotionRef.current?.handleComposerInput();
}
}}
onInput={(event) => {
if (!(event.target instanceof HTMLTextAreaElement)) return;
const previousScrollTop = composerInputScrollTopRef.current;
composerInputScrollTopRef.current = null;
const scrollEl = scrollRef.current;
if (scrollEl && previousScrollTop !== null) {
// Textarea autosizing briefly collapses to `height: auto` while
// measuring. Chrome can clamp the sibling thread scrollport in
// that intermediate layout; restore it before paint, then let
// ResizeObserver handle any real final composer height change.
scrollEl.scrollTop = previousScrollTop;
}
}}
className={cn(
"row-start-2 z-10 w-full",
hasMessages ? "relative bg-background" : "relative self-center",