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