LibreChat/client/src/components/Chat/Messages/MessagesView.tsx
Danny Avila 0e8041bcac
🔃 refactor: Streamline Navigation, Message Loading UX (#7118)
* chore: fix logging for illegal target endpoints in getEndpointFromSetup

* fix: prevent querying agent by ID for ephemeral agents

* refactor: reorder variable declarations in MessagesView for clarity

* fix: localize 'nothing found' message in MessagesView

* refactor: streamline navigation logic and enhance loading spinner component in ChatView

* refactor: simplify loading spinner logic in ChatView component

* fix: ensure message queries are invalidated after new conversation creation in HeaderNewChat, MobileNav, and NewChat components

* 🐛 First run dev mode will have error occur.

🐛 First run dev mode will have error occur.

* fix font-size localstorage presist bug

* Don't ping meilisearch if the search is disabled via env var

* simplify logic in search/enable endpoint

* refactor: simplify enable endpoint condition check

* feat: add useIdChangeEffect hook and integrate it into ChatRoute

---------

Co-authored-by: Ne0 <20765145+zeeklog@users.noreply.github.com>
Co-authored-by: TinyTin <garychangcn@hotmail.com>
Co-authored-by: Denis Palnitsky <denis.palnitsky@zendesk.com>
2025-04-28 18:18:13 -04:00

94 lines
3 KiB
TypeScript

import { useState } from 'react';
import { useRecoilValue } from 'recoil';
import { CSSTransition } from 'react-transition-group';
import type { TMessage } from 'librechat-data-provider';
import { useScreenshot, useMessageScrolling, useLocalize } from '~/hooks';
import ScrollToBottom from '~/components/Messages/ScrollToBottom';
import MultiMessage from './MultiMessage';
import { cn } from '~/utils';
import store from '~/store';
export default function MessagesView({
messagesTree: _messagesTree,
}: {
messagesTree?: TMessage[] | null;
}) {
const localize = useLocalize();
const fontSize = useRecoilValue(store.fontSize);
const { screenshotTargetRef } = useScreenshot();
const scrollButtonPreference = useRecoilValue(store.showScrollButton);
const [currentEditId, setCurrentEditId] = useState<number | string | null>(-1);
const {
conversation,
scrollableRef,
messagesEndRef,
showScrollButton,
handleSmoothToRef,
debouncedHandleScroll,
} = useMessageScrolling(_messagesTree);
const { conversationId } = conversation ?? {};
return (
<>
<div className="relative flex-1 overflow-hidden overflow-y-auto">
<div className="relative h-full">
<div
className="scrollbar-gutter-stable"
onScroll={debouncedHandleScroll}
ref={scrollableRef}
style={{
height: '100%',
overflowY: 'auto',
width: '100%',
}}
>
<div className="flex flex-col pb-9 dark:bg-transparent">
{(_messagesTree && _messagesTree.length == 0) || _messagesTree === null ? (
<div
className={cn(
'flex w-full items-center justify-center p-3 text-text-secondary',
fontSize,
)}
>
{localize('com_ui_nothing_found')}
</div>
) : (
<>
<div ref={screenshotTargetRef}>
<MultiMessage
key={conversationId}
messagesTree={_messagesTree}
messageId={conversationId ?? null}
setCurrentEditId={setCurrentEditId}
currentEditId={currentEditId ?? null}
/>
</div>
</>
)}
<div
id="messages-end"
className="group h-0 w-full flex-shrink-0"
ref={messagesEndRef}
/>
</div>
</div>
<CSSTransition
in={showScrollButton && scrollButtonPreference}
timeout={{
enter: 550,
exit: 700,
}}
classNames="scroll-animation"
unmountOnExit={true}
appear={true}
>
<ScrollToBottom scrollHandler={handleSmoothToRef} />
</CSSTransition>
</div>
</div>
</>
);
}