fix: prevent auto-scrolling from stopping in chat (#28690)

Signed-off-by: Yuichiro Utsumi <utsumi.yuichiro@fujitsu.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
This commit is contained in:
Yuichiro Utsumi
2025-11-26 23:39:29 +09:00
committed by GitHub
parent af587f3869
commit 6b8c649876

View File

@@ -128,10 +128,17 @@ const Chat: FC<ChatProps> = ({
const chatFooterRef = useRef<HTMLDivElement>(null)
const chatFooterInnerRef = useRef<HTMLDivElement>(null)
const userScrolledRef = useRef(false)
const isAutoScrollingRef = useRef(false)
const handleScrollToBottom = useCallback(() => {
if (chatList.length > 1 && chatContainerRef.current && !userScrolledRef.current)
if (chatList.length > 1 && chatContainerRef.current && !userScrolledRef.current) {
isAutoScrollingRef.current = true
chatContainerRef.current.scrollTop = chatContainerRef.current.scrollHeight
requestAnimationFrame(() => {
isAutoScrollingRef.current = false
})
}
}, [chatList.length])
const handleWindowResize = useCallback(() => {
@@ -198,18 +205,31 @@ const Chat: FC<ChatProps> = ({
}, [handleScrollToBottom])
useEffect(() => {
const chatContainer = chatContainerRef.current
if (chatContainer) {
const setUserScrolled = () => {
// eslint-disable-next-line sonarjs/no-gratuitous-expressions
if (chatContainer) // its in event callback, chatContainer may be null
userScrolledRef.current = chatContainer.scrollHeight - chatContainer.scrollTop > chatContainer.clientHeight
}
chatContainer.addEventListener('scroll', setUserScrolled)
return () => chatContainer.removeEventListener('scroll', setUserScrolled)
const setUserScrolled = () => {
const container = chatContainerRef.current
if (!container) return
if (isAutoScrollingRef.current) return
const distanceToBottom = container.scrollHeight - container.clientHeight - container.scrollTop
const SCROLL_UP_THRESHOLD = 100
userScrolledRef.current = distanceToBottom > SCROLL_UP_THRESHOLD
}
const container = chatContainerRef.current
if (!container) return
container.addEventListener('scroll', setUserScrolled)
return () => container.removeEventListener('scroll', setUserScrolled)
}, [])
// Reset user scroll state when a new chat starts (length <= 1)
useEffect(() => {
if (chatList.length <= 1)
userScrolledRef.current = false
}, [chatList.length])
useEffect(() => {
if (!sidebarCollapseState)
setTimeout(() => handleWindowResize(), 200)