mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-17 17:00:15 +01:00
refactor: Consolidate Message Scrolling & other Logic to Custom Hooks 🔄 (#1257)
* refactor: remove unnecessary drilling/invoking of ScrollToBottom - feat: useMessageScrolling: consolidates all scrolling logic to hook - feat: useMessageHelpers: creates message utilities and consolidates logic from UI component * fix: ensure automatic scrolling is triggered by messagesTree re-render and is throttled
This commit is contained in:
parent
ebd23f7295
commit
4674a54c70
12 changed files with 208 additions and 169 deletions
|
|
@ -1,10 +1,9 @@
|
|||
import { useLayoutEffect, useState, useRef, useCallback } from 'react';
|
||||
import { useState } from 'react';
|
||||
import type { ReactNode } from 'react';
|
||||
import type { TMessage } from 'librechat-data-provider';
|
||||
import ScrollToBottom from '~/components/Messages/ScrollToBottom';
|
||||
import { useScreenshot, useScrollToRef } from '~/hooks';
|
||||
import { useScreenshot, useMessageScrolling } from '~/hooks';
|
||||
import { CSSTransition } from 'react-transition-group';
|
||||
import { useChatContext } from '~/Providers';
|
||||
import MultiMessage from './MultiMessage';
|
||||
|
||||
export default function MessagesView({
|
||||
|
|
@ -14,54 +13,19 @@ export default function MessagesView({
|
|||
messagesTree?: TMessage[] | null;
|
||||
Header?: ReactNode;
|
||||
}) {
|
||||
const timeoutIdRef = useRef<NodeJS.Timeout>();
|
||||
const scrollableRef = useRef<HTMLDivElement | null>(null);
|
||||
const messagesEndRef = useRef<HTMLDivElement | null>(null);
|
||||
const [showScrollButton, setShowScrollButton] = useState(false);
|
||||
const [currentEditId, setCurrentEditId] = useState<number | string | null>(-1);
|
||||
const { conversation, setAbortScroll } = useChatContext();
|
||||
const { conversationId } = conversation ?? {};
|
||||
|
||||
const { screenshotTargetRef } = useScreenshot();
|
||||
const [currentEditId, setCurrentEditId] = useState<number | string | null>(-1);
|
||||
|
||||
const checkIfAtBottom = useCallback(() => {
|
||||
if (!scrollableRef.current) {
|
||||
return;
|
||||
}
|
||||
const {
|
||||
conversation,
|
||||
scrollableRef,
|
||||
messagesEndRef,
|
||||
showScrollButton,
|
||||
handleSmoothToRef,
|
||||
debouncedHandleScroll,
|
||||
} = useMessageScrolling(_messagesTree);
|
||||
|
||||
const { scrollTop, scrollHeight, clientHeight } = scrollableRef.current;
|
||||
const diff = Math.abs(scrollHeight - scrollTop);
|
||||
const percent = Math.abs(clientHeight - diff) / clientHeight;
|
||||
const hasScrollbar = scrollHeight > clientHeight && percent >= 0.15;
|
||||
setShowScrollButton(hasScrollbar);
|
||||
}, [scrollableRef]);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
const scrollableElement = scrollableRef.current;
|
||||
if (!scrollableElement) {
|
||||
return;
|
||||
}
|
||||
const timeoutId = setTimeout(checkIfAtBottom, 650);
|
||||
|
||||
return () => {
|
||||
clearTimeout(timeoutId);
|
||||
};
|
||||
}, [checkIfAtBottom]);
|
||||
|
||||
const debouncedHandleScroll = useCallback(() => {
|
||||
clearTimeout(timeoutIdRef.current);
|
||||
timeoutIdRef.current = setTimeout(checkIfAtBottom, 100);
|
||||
}, [checkIfAtBottom]);
|
||||
|
||||
const scrollCallback = () => setShowScrollButton(false);
|
||||
const { scrollToRef: scrollToBottom, handleSmoothToRef } = useScrollToRef({
|
||||
targetRef: messagesEndRef,
|
||||
callback: scrollCallback,
|
||||
smoothCallback: () => {
|
||||
scrollCallback();
|
||||
setAbortScroll(false);
|
||||
},
|
||||
});
|
||||
const { conversationId } = conversation ?? {};
|
||||
|
||||
return (
|
||||
<div className="flex-1 overflow-hidden overflow-y-auto">
|
||||
|
|
@ -86,9 +50,8 @@ export default function MessagesView({
|
|||
<div ref={screenshotTargetRef}>
|
||||
<MultiMessage
|
||||
key={conversationId} // avoid internal state mixture
|
||||
messageId={conversationId ?? null}
|
||||
messagesTree={_messagesTree}
|
||||
scrollToBottom={scrollToBottom}
|
||||
messageId={conversationId ?? null}
|
||||
setCurrentEditId={setCurrentEditId}
|
||||
currentEditId={currentEditId ?? null}
|
||||
/>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue