### What problem does this PR solve? Fix: Fixed the issue where the agent's chat box could not automatically scroll to the bottom #3221 ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)tags/v0.20.1
| @@ -353,7 +353,12 @@ export const useHandleMessageInputChange = () => { | |||
| export const useSelectDerivedMessages = () => { | |||
| const [derivedMessages, setDerivedMessages] = useState<IMessage[]>([]); | |||
| const ref = useScrollToBottom(derivedMessages); | |||
| const messageContainerRef = useRef<HTMLDivElement>(null); | |||
| const { scrollRef, scrollToBottom } = useScrollToBottom( | |||
| derivedMessages, | |||
| messageContainerRef, | |||
| ); | |||
| const addNewestQuestion = useCallback( | |||
| (message: Message, answer: string = '') => { | |||
| @@ -492,7 +497,8 @@ export const useSelectDerivedMessages = () => { | |||
| }, [setDerivedMessages]); | |||
| return { | |||
| ref, | |||
| scrollRef, | |||
| messageContainerRef, | |||
| derivedMessages, | |||
| setDerivedMessages, | |||
| addNewestQuestion, | |||
| @@ -503,6 +509,7 @@ export const useSelectDerivedMessages = () => { | |||
| addNewestOneAnswer, | |||
| removeMessagesAfterCurrentMessage, | |||
| removeAllMessages, | |||
| scrollToBottom, | |||
| }; | |||
| }; | |||
| @@ -22,7 +22,8 @@ import { useAwaitCompentData } from '../hooks/use-chat-logic'; | |||
| function AgentChatBox() { | |||
| const { | |||
| value, | |||
| ref, | |||
| scrollRef, | |||
| messageContainerRef, | |||
| sendLoading, | |||
| derivedMessages, | |||
| handleInputChange, | |||
| @@ -59,7 +60,7 @@ function AgentChatBox() { | |||
| return ( | |||
| <> | |||
| <section className="flex flex-1 flex-col px-5 h-[90vh]"> | |||
| <div className="flex-1 overflow-auto"> | |||
| <div className="flex-1 overflow-auto" ref={messageContainerRef}> | |||
| <div> | |||
| {/* <Spin spinning={sendLoading}> */} | |||
| {derivedMessages?.map((message, i) => { | |||
| @@ -106,7 +107,7 @@ function AgentChatBox() { | |||
| })} | |||
| {/* </Spin> */} | |||
| </div> | |||
| <div ref={ref.scrollRef} /> | |||
| <div ref={scrollRef} /> | |||
| </div> | |||
| <NextMessageInput | |||
| value={value} | |||
| @@ -198,12 +198,14 @@ export const useSendAgentMessage = ( | |||
| const prologue = useGetBeginNodePrologue(); | |||
| const { | |||
| derivedMessages, | |||
| ref, | |||
| scrollRef, | |||
| messageContainerRef, | |||
| removeLatestMessage, | |||
| removeMessageById, | |||
| addNewestOneQuestion, | |||
| addNewestOneAnswer, | |||
| removeAllMessages, | |||
| scrollToBottom, | |||
| } = useSelectDerivedMessages(); | |||
| const { addEventList: addEventListFun } = useContext(AgentChatLogContext); | |||
| const { | |||
| @@ -303,7 +305,18 @@ export const useSendAgentMessage = ( | |||
| }); | |||
| } | |||
| addNewestOneQuestion({ ...msgBody, files: fileList }); | |||
| }, [value, done, addNewestOneQuestion, fileList, setValue, sendMessage]); | |||
| setTimeout(() => { | |||
| scrollToBottom(); | |||
| }, 100); | |||
| }, [ | |||
| value, | |||
| done, | |||
| addNewestOneQuestion, | |||
| fileList, | |||
| setValue, | |||
| sendMessage, | |||
| scrollToBottom, | |||
| ]); | |||
| useEffect(() => { | |||
| const { content, id } = findMessageFromList(answerList); | |||
| @@ -337,7 +350,8 @@ export const useSendAgentMessage = ( | |||
| value, | |||
| sendLoading: !done, | |||
| derivedMessages, | |||
| ref, | |||
| scrollRef, | |||
| messageContainerRef, | |||
| handlePressEnter, | |||
| handleInputChange, | |||
| removeMessageById, | |||
| @@ -1,7 +1,6 @@ | |||
| import MessageItem from '@/components/message-item'; | |||
| import { MessageType } from '@/constants/chat'; | |||
| import { Flex, Spin } from 'antd'; | |||
| import { useRef } from 'react'; | |||
| import { | |||
| useCreateConversationBeforeUploadDocument, | |||
| useGetFileIcon, | |||
| @@ -19,7 +18,6 @@ import { | |||
| useFetchNextDialog, | |||
| useGetChatSearchParams, | |||
| } from '@/hooks/chat-hooks'; | |||
| import { useScrollToBottom } from '@/hooks/logic-hooks'; | |||
| import { useFetchUserInfo } from '@/hooks/user-setting-hooks'; | |||
| import { buildMessageUuidWithRole } from '@/utils/chat'; | |||
| import { memo } from 'react'; | |||
| @@ -34,10 +32,10 @@ const ChatContainer = ({ controller }: IProps) => { | |||
| const { data: conversation } = useFetchNextConversation(); | |||
| const { data: currentDialog } = useFetchNextDialog(); | |||
| const messageContainerRef = useRef<HTMLDivElement>(null); | |||
| const { | |||
| value, | |||
| ref, | |||
| scrollRef, | |||
| messageContainerRef, | |||
| loading, | |||
| sendLoading, | |||
| derivedMessages, | |||
| @@ -47,10 +45,6 @@ const ChatContainer = ({ controller }: IProps) => { | |||
| removeMessageById, | |||
| stopOutputMessage, | |||
| } = useSendNextMessage(controller); | |||
| const { scrollRef, isAtBottom, scrollToBottom } = useScrollToBottom( | |||
| derivedMessages, | |||
| messageContainerRef, | |||
| ); | |||
| const { visible, hideModal, documentId, selectedChunk, clickDocumentButton } = | |||
| useClickDrawer(); | |||
| @@ -61,11 +55,6 @@ const ChatContainer = ({ controller }: IProps) => { | |||
| const { createConversationBeforeUploadDocument } = | |||
| useCreateConversationBeforeUploadDocument(); | |||
| const handleSend = (msg) => { | |||
| // your send logic | |||
| setTimeout(scrollToBottom, 0); | |||
| }; | |||
| return ( | |||
| <> | |||
| <Flex flex={1} className={styles.chatContainer} vertical> | |||
| @@ -291,7 +291,8 @@ export const useSetConversation = () => { | |||
| export const useSelectNextMessages = () => { | |||
| const { | |||
| ref, | |||
| scrollRef, | |||
| messageContainerRef, | |||
| setDerivedMessages, | |||
| derivedMessages, | |||
| addNewestAnswer, | |||
| @@ -335,7 +336,8 @@ export const useSelectNextMessages = () => { | |||
| }, [conversation.message, conversationId, setDerivedMessages, isNew]); | |||
| return { | |||
| ref, | |||
| scrollRef, | |||
| messageContainerRef, | |||
| derivedMessages, | |||
| loading, | |||
| addNewestAnswer, | |||
| @@ -371,7 +373,8 @@ export const useSendNextMessage = (controller: AbortController) => { | |||
| api.completeConversation, | |||
| ); | |||
| const { | |||
| ref, | |||
| scrollRef, | |||
| messageContainerRef, | |||
| derivedMessages, | |||
| loading, | |||
| addNewestAnswer, | |||
| @@ -499,7 +502,8 @@ export const useSendNextMessage = (controller: AbortController) => { | |||
| regenerateMessage, | |||
| sendLoading: !done, | |||
| loading, | |||
| ref, | |||
| scrollRef, | |||
| messageContainerRef, | |||
| derivedMessages, | |||
| removeMessageById, | |||
| stopOutputMessage, | |||
| @@ -50,7 +50,8 @@ const ChatContainer = () => { | |||
| handleInputChange, | |||
| value, | |||
| sendLoading, | |||
| ref, | |||
| scrollRef, | |||
| messageContainerRef, | |||
| derivedMessages, | |||
| hasError, | |||
| stopOutputMessage, | |||
| @@ -149,6 +150,7 @@ const ChatContainer = () => { | |||
| className={cn( | |||
| 'flex flex-1 flex-col overflow-auto scrollbar-auto m-auto w-5/6', | |||
| )} | |||
| ref={messageContainerRef} | |||
| > | |||
| <div> | |||
| {derivedMessages?.map((message, i) => { | |||
| @@ -203,7 +205,7 @@ const ChatContainer = () => { | |||
| ); | |||
| })} | |||
| </div> | |||
| <div ref={ref.scrollRef} /> | |||
| <div ref={scrollRef} /> | |||
| </div> | |||
| <div className="flex w-full justify-center mb-8"> | |||
| <div className="w-5/6"> | |||