import { Loader2 } from "lucide-react"; import { useEffect, useRef } from "react"; import { Button } from "../button"; import ChatActions from "./chat-actions"; import ChatMessage from "./chat-message"; import { ChatHandler } from "./chat.interface"; import { useClientConfig } from "./hooks/use-config"; export default function ChatMessages( props: Pick< ChatHandler, "messages" | "isLoading" | "reload" | "stop" | "append" >, ) { const { starterQuestions } = useClientConfig(); const scrollableChatContainerRef = useRef(null); const messageLength = props.messages.length; const lastMessage = props.messages[messageLength - 1]; const scrollToBottom = () => { if (scrollableChatContainerRef.current) { scrollableChatContainerRef.current.scrollTop = scrollableChatContainerRef.current.scrollHeight; } }; const isLastMessageFromAssistant = messageLength > 0 && lastMessage?.role !== "user"; const showReload = props.reload && !props.isLoading && isLastMessageFromAssistant; const showStop = props.stop && props.isLoading; // `isPending` indicate // that stream response is not yet received from the server, // so we show a loading indicator to give a better UX. const isPending = props.isLoading && !isLastMessageFromAssistant; useEffect(() => { scrollToBottom(); }, [messageLength, lastMessage]); return (
{props.messages.map((m, i) => { const isLoadingMessage = i === messageLength - 1 && props.isLoading; return ( ); })} {isPending && (
)}
{(showReload || showStop) && (
)} {!messageLength && starterQuestions?.length && props.append && (
{starterQuestions.map((question, i) => ( ))}
)}
); }