From 229d5f1d6d44c0f375c3af776a8c0d30eeb5ded1 Mon Sep 17 00:00:00 2001 From: Philippe Rolet Date: Thu, 26 Oct 2023 14:19:52 +0200 Subject: [PATCH] Fix autoscroll in various situations (retrieval actions, citations...) (#2273) * listen to action changes for scroll * listen to citations and adapt to message length * explain it --- .../assistant/conversation/AgentMessage.tsx | 45 +++++++++++++++---- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/front/components/assistant/conversation/AgentMessage.tsx b/front/components/assistant/conversation/AgentMessage.tsx index 7425f8c7696b..124e377da1b0 100644 --- a/front/components/assistant/conversation/AgentMessage.tsx +++ b/front/components/assistant/conversation/AgentMessage.tsx @@ -64,6 +64,14 @@ export function AgentMessage({ const [isRetryHandlerProcessing, setIsRetryHandlerProcessing] = useState(false); + const [references, setReferences] = useState<{ + [key: string]: RetrievalDocumentType; + }>({}); + + const [activeReferences, setActiveReferences] = useState< + { index: number; document: RetrievalDocumentType }[] + >([]); + const shouldStream = (() => { if (message.status !== "created") { return false; @@ -185,17 +193,40 @@ export function AgentMessage({ } })(); + // Autoscroll is performed when a message is generating and the page is + // already scrolled down; but if the user has scrolled the page up after the + // start of the message, we do not want to scroll it back down. + // + // Checking the conversation is already at the bottom of the screen is done + // modulo a small margin (50px). This value is small because if large, it + // prevents user from scrolling up when the message continues generating + // (forces it back down), but it cannot be zero otherwise the scroll does not + // happen. + // + // Keeping a ref on the message's height, and accounting to the height + // difference when new parts of the message are generated, allows for the + // scroll to happen even if the newly generated parts are larger than 50px + // (e.g. citations) + const messageRef = useRef(null); + const messageHeight = useRef(null); useEffect(() => { + const previousHeight = messageHeight.current || 0; + messageHeight.current = messageRef.current?.scrollHeight || previousHeight; const mainTag = document.getElementById("main-content"); if (mainTag && agentMessageToRender.status === "created") { if ( mainTag.offsetHeight + mainTag.scrollTop >= - mainTag.scrollHeight - 50 + mainTag.scrollHeight - (50 + messageHeight.current - previousHeight) ) { mainTag.scrollTo(0, mainTag.scrollHeight); } } - }, [agentMessageToRender.content, agentMessageToRender.status]); + }, [ + agentMessageToRender.content, + agentMessageToRender.status, + agentMessageToRender.action, + activeReferences.length, + ]); // GenerationContext: to know if we are generating or not const generationContext = useContext(GenerationContext); @@ -240,12 +271,6 @@ export function AgentMessage({ }, ]; - const [references, setReferences] = useState<{ - [key: string]: RetrievalDocumentType; - }>({}); - const [activeReferences, setActiveReferences] = useState< - { index: number; document: RetrievalDocumentType }[] - >([]); function updateActiveReferences( document: RetrievalDocumentType, index: number @@ -286,7 +311,9 @@ export function AgentMessage({ reactions={reactions} enableEmojis={true} > - {renderMessage(agentMessageToRender, references, shouldStream)} +
+ {renderMessage(agentMessageToRender, references, shouldStream)} +
);