perf(app): reduce streaming rerenders and scroll churn (#67)

Amp-Thread-ID: https://ampcode.com/threads/T-019c793a-d087-762a-882a-8cc11e6101db

Co-authored-by: Ubuntu <ubuntu@dev-yk.tail388b2e.ts.net>
This commit is contained in:
YK
2026-02-22 13:09:49 +07:00
committed by GitHub
co-authored by Ubuntu
parent 55b450c8b9
commit 8bcfde8184
3 changed files with 107 additions and 19 deletions
@@ -107,6 +107,8 @@ export function AgentStreamView({
const hasScrolledInitially = useRef(false);
const hasAutoScrolledOnce = useRef(false);
const isNearBottomRef = useRef(true);
const pendingAutoScrollFrameRef = useRef<number | null>(null);
const pendingAutoScrollAnimatedRef = useRef(false);
const streamItemCountRef = useRef(0);
const streamScrollbarMetrics = useWebDesktopScrollbarMetrics();
const [expandedInlineToolCallIds, setExpandedInlineToolCallIds] = useState<Set<string>>(new Set());
@@ -214,6 +216,35 @@ export function AgentStreamView({
[]
);
const scheduleAutoScroll = useCallback(
({ animated }: { animated: boolean }) => {
pendingAutoScrollAnimatedRef.current =
pendingAutoScrollAnimatedRef.current || animated;
if (pendingAutoScrollFrameRef.current !== null) {
return;
}
pendingAutoScrollFrameRef.current = requestAnimationFrame(() => {
pendingAutoScrollFrameRef.current = null;
const shouldAnimate = pendingAutoScrollAnimatedRef.current;
pendingAutoScrollAnimatedRef.current = false;
scrollToBottomInternal({ animated: shouldAnimate });
});
},
[scrollToBottomInternal]
);
useEffect(() => {
return () => {
if (pendingAutoScrollFrameRef.current !== null) {
cancelAnimationFrame(pendingAutoScrollFrameRef.current);
pendingAutoScrollFrameRef.current = null;
}
pendingAutoScrollAnimatedRef.current = false;
};
}, []);
useEffect(() => {
if (streamItems.length === 0) {
return;
@@ -233,9 +264,9 @@ export function AgentStreamView({
}
const shouldAnimate = hasScrolledInitially.current;
scrollToBottomInternal({ animated: shouldAnimate });
scheduleAutoScroll({ animated: shouldAnimate });
hasScrolledInitially.current = true;
}, [streamItems, scrollToBottomInternal]);
}, [streamItems, scheduleAutoScroll]);
function scrollToBottom() {
scrollToBottomInternal({ animated: true });