Skip to content

Commit 546899c

Browse files
committed
Fix uncancelled requestAnimationFrame in send message handlers
Track pending send-scroll animation frame IDs in a ref and cancel them both when a new send triggers another RAF and on component unmount, restoring the careful resource management pattern used elsewhere in the component.
1 parent f34a717 commit 546899c

File tree

1 file changed

+18
-2
lines changed

1 file changed

+18
-2
lines changed

apps/web/src/components/ChatView.tsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,7 @@ export default function ChatView(props: ChatViewProps) {
700700
const attachmentPreviewHandoffByMessageIdRef = useRef<Record<string, string[]>>({});
701701
const attachmentPreviewPromotionInFlightByMessageIdRef = useRef<Record<string, true>>({});
702702
const sendInFlightRef = useRef(false);
703+
const pendingSendScrollFrameRef = useRef<number | null>(null);
703704
const terminalOpenByThreadRef = useRef<Record<string, boolean>>({});
704705

705706
const terminalState = useTerminalStateStore((state) =>
@@ -1176,6 +1177,13 @@ export default function ChatView(props: ChatViewProps) {
11761177
}
11771178
};
11781179
}, [clearAttachmentPreviewHandoffs]);
1180+
useEffect(() => {
1181+
return () => {
1182+
if (pendingSendScrollFrameRef.current != null) {
1183+
cancelAnimationFrame(pendingSendScrollFrameRef.current);
1184+
}
1185+
};
1186+
}, []);
11791187
const handoffAttachmentPreviews = useCallback((messageId: MessageId, previewUrls: string[]) => {
11801188
if (previewUrls.length === 0) return;
11811189

@@ -2423,7 +2431,11 @@ export default function ChatView(props: ChatViewProps) {
24232431
]);
24242432
// Sending a message should always bring the latest user turn into view.
24252433
isAtEndRef.current = true;
2426-
requestAnimationFrame(() => {
2434+
if (pendingSendScrollFrameRef.current != null) {
2435+
cancelAnimationFrame(pendingSendScrollFrameRef.current);
2436+
}
2437+
pendingSendScrollFrameRef.current = requestAnimationFrame(() => {
2438+
pendingSendScrollFrameRef.current = null;
24272439
legendListRef.current?.scrollToEnd?.({ animated: true });
24282440
setShowScrollToBottom(false);
24292441
});
@@ -2818,7 +2830,11 @@ export default function ChatView(props: ChatViewProps) {
28182830
},
28192831
]);
28202832
isAtEndRef.current = true;
2821-
requestAnimationFrame(() => {
2833+
if (pendingSendScrollFrameRef.current != null) {
2834+
cancelAnimationFrame(pendingSendScrollFrameRef.current);
2835+
}
2836+
pendingSendScrollFrameRef.current = requestAnimationFrame(() => {
2837+
pendingSendScrollFrameRef.current = null;
28222838
legendListRef.current?.scrollToEnd?.({ animated: true });
28232839
setShowScrollToBottom(false);
28242840
});

0 commit comments

Comments
 (0)