import { useLayoutEffect, useState, useRef, useCallback } 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 { CSSTransition } from 'react-transition-group'; import { useChatContext } from '~/Providers'; import MultiMessage from './MultiMessage'; export default function MessagesView({ messagesTree: _messagesTree, Header, }: { messagesTree?: TMessage[] | null; Header?: ReactNode; }) { const timeoutIdRef = useRef(); const scrollableRef = useRef(null); const messagesEndRef = useRef(null); const [showScrollButton, setShowScrollButton] = useState(false); const [currentEditId, setCurrentEditId] = useState(-1); const { conversation, setAbortScroll } = useChatContext(); const { conversationId } = conversation ?? {}; const { screenshotTargetRef } = useScreenshot(); const checkIfAtBottom = useCallback(() => { if (!scrollableRef.current) { return; } 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); }, }); return (
{(_messagesTree && _messagesTree?.length == 0) || _messagesTree === null ? (
Nothing found
) : ( <> {Header && Header}
)}
{() => showScrollButton && }
); }