fix: improve chat window scroll behavior when user scrolls back to bottom

- Re-enable auto-scroll when user scrolls down while at bottom
- Increase atBottomThreshold from 10px to 50px for more forgiving detection
- Auto-scroll on new messages if user is at bottom, even if auto-scroll is disabled
- Handle row height changes better when user is at bottom

This fixes the issue where the chat window would jump randomly and miss messages
when the user scrolled up and then back down during API calls.

Fixes #6852
This commit is contained in:
Roo Code 2025-08-08 16:16:17 +00:00
parent ad0e33e2d9
commit 6f8af78918

View file

@ -1377,20 +1377,31 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
const handleRowHeightChange = useCallback(
(isTaller: boolean) => {
// Only auto-scroll if we're supposed to be following the conversation
if (!disableAutoScrollRef.current) {
if (isTaller) {
scrollToBottomSmooth()
} else {
setTimeout(() => scrollToBottomAuto(), 0)
}
} else if (isAtBottom) {
// If auto-scroll is disabled but we're at the bottom,
// the user likely wants to follow along, so scroll anyway
if (isTaller) {
scrollToBottomSmooth()
} else {
setTimeout(() => scrollToBottomAuto(), 0)
}
}
},
[scrollToBottomSmooth, scrollToBottomAuto],
[scrollToBottomSmooth, scrollToBottomAuto, isAtBottom],
)
useEffect(() => {
let timer: ReturnType<typeof setTimeout> | undefined
if (!disableAutoScrollRef.current) {
// Auto-scroll on new messages if auto-scroll is enabled OR if we're at the bottom
// This ensures we follow the conversation when the user is actively reading at the bottom
if (!disableAutoScrollRef.current || isAtBottom) {
timer = setTimeout(() => scrollToBottomSmooth(), 50)
}
return () => {
@ -1398,18 +1409,27 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
clearTimeout(timer)
}
}
}, [groupedMessages.length, scrollToBottomSmooth])
}, [groupedMessages.length, scrollToBottomSmooth, isAtBottom])
const handleWheel = useCallback((event: Event) => {
const wheelEvent = event as WheelEvent
const handleWheel = useCallback(
(event: Event) => {
const wheelEvent = event as WheelEvent
if (wheelEvent.deltaY && wheelEvent.deltaY < 0) {
if (scrollContainerRef.current?.contains(wheelEvent.target as Node)) {
// User scrolled up
disableAutoScrollRef.current = true
if (wheelEvent.deltaY) {
if (scrollContainerRef.current?.contains(wheelEvent.target as Node)) {
if (wheelEvent.deltaY < 0) {
// User scrolled up - disable auto-scroll
disableAutoScrollRef.current = true
} else if (wheelEvent.deltaY > 0 && isAtBottom) {
// User scrolled down and we're at bottom - re-enable auto-scroll
// This helps when user scrolls down to catch up with messages
disableAutoScrollRef.current = false
}
}
}
}
}, [])
},
[isAtBottom],
)
useEvent("wheel", handleWheel, window, { passive: true }) // passive improves scrolling performance
@ -1876,11 +1896,14 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
atBottomStateChange={(isAtBottom: boolean) => {
setIsAtBottom(isAtBottom)
if (isAtBottom) {
// Re-enable auto-scroll when we reach the bottom
disableAutoScrollRef.current = false
}
// Show scroll-to-bottom button only when auto-scroll is disabled and not at bottom
setShowScrollToBottom(disableAutoScrollRef.current && !isAtBottom)
}}
atBottomThreshold={10}
// Increase threshold to be more forgiving about what counts as "at bottom"
atBottomThreshold={50}
initialTopMostItemIndex={groupedMessages.length - 1}
/>
</div>