Spaces:
Sleeping
Sleeping
File size: 2,917 Bytes
edd2230 4af6326 bc1cf4e 4af6326 3ba9c0c 4af6326 db06845 3ba9c0c 4af6326 db06845 c7e97b5 4af6326 db06845 4af6326 c7e97b5 4af6326 c7e97b5 4af6326 f80b091 4af6326 db06845 c7e97b5 db06845 4af6326 db06845 c7e97b5 db06845 4af6326 f80b091 4af6326 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
'use client';
// import { ChatList } from '@/components/chat/ChatList';
import Composer from '@/components/chat/Composer';
import useVisionAgent from '@/lib/hooks/useVisionAgent';
import { useScrollAnchor } from '@/lib/hooks/useScrollAnchor';
import { useEffect } from 'react';
import { ChatWithMessages } from '@/lib/types';
import { ChatMessage } from './ChatMessage';
import { Button } from '../ui/Button';
import { cn } from '@/lib/utils';
import { IconArrowDown } from '../ui/Icons';
import { dbPostCreateMessage } from '@/lib/db/functions';
import { Card } from '../ui/Card';
export interface ChatListProps {
chat: ChatWithMessages;
userId?: string | null;
}
export const SCROLL_BOTTOM = 120;
const ChatList: React.FC<ChatListProps> = ({ chat, userId }) => {
const { id, messages: dbMessages, userId: chatUserId } = chat;
const { isLoading, data } = useVisionAgent(chat);
// Only login and chat owner can compose
const canCompose = !chatUserId || userId === chatUserId;
const { messagesRef, scrollRef, visibilityRef, isVisible, scrollToBottom } =
useScrollAnchor(SCROLL_BOTTOM);
// Scroll to bottom on init
useEffect(() => {
scrollToBottom();
}, [scrollToBottom]);
return (
<Card
className="size-full max-w-5xl overflow-auto relative"
ref={scrollRef}
>
<div className="overflow-auto h-full p-4 z-10" ref={messagesRef}>
{dbMessages.map((message, index) => {
const isLastMessage = index === dbMessages.length - 1;
return (
<ChatMessage
key={message.id}
message={message}
loading={isLastMessage && isLoading}
wipAssistantMessage={
isLastMessage && data.length > 0 ? data : undefined
}
/>
);
})}
<div
className="w-full"
style={{ height: SCROLL_BOTTOM }}
ref={visibilityRef}
/>
</div>
{canCompose && (
<div className="absolute bottom-4 w-full">
<Composer
// Use the last message mediaUrl as the initial mediaUrl
initMediaUrl={dbMessages[dbMessages.length - 1]?.mediaUrl}
disabled={isLoading}
onSubmit={async ({ input, mediaUrl: newMediaUrl }) => {
const messageInput = {
prompt: input,
mediaUrl: newMediaUrl,
};
await dbPostCreateMessage(id, messageInput);
}}
/>
</div>
)}
{/* Scroll to bottom Icon */}
<Button
size="icon"
className={cn(
'absolute bottom-3 right-3 transition-opacity duration-300 size-6',
isVisible ? 'opacity-0' : 'opacity-100',
)}
onClick={() => scrollToBottom()}
>
<IconArrowDown className="size-3" />
</Button>
</Card>
);
};
export default ChatList;
|