import React, { useRef, useCallback, useState, useEffect } from "react"; import { ArrowRightFromLine, ChevronDown } from 'lucide-react'; import { Switch } from 'antd'; import { MessageRenderer } from "./MessageRenderer"; import { InputBar } from "./InputBar"; import { useMessages } from "./useMessages"; import { DateDivider } from "./DateDivider"; import { LoadMoreButton } from "./LoadMoreButton"; import { ChatMessage } from "./types"; interface SmartChatBoxProps { isSmartChatBoxOpen: boolean; setIsSmartChatBoxOpen: (v: boolean) => void; projectId: string; userId: number; previewVideoUrl?: string | null; previewVideoId?: string | null; onClearPreview?: () => void; setIsFocusChatInput?: (v: boolean) => void; } interface MessageGroup { date: number; messages: ChatMessage[]; } function BackToLatestButton({ onClick }: { onClick: () => void }) { return ( ); } export default function SmartChatBox({ isSmartChatBoxOpen, setIsSmartChatBoxOpen, projectId, userId, previewVideoUrl, previewVideoId, onClearPreview, setIsFocusChatInput }: SmartChatBoxProps) { // 消息列表引用 const listRef = useRef(null); const [isAtBottom, setIsAtBottom] = useState(true); // 检查是否滚动到底部 const checkIfAtBottom = useCallback(() => { if (listRef.current) { const { scrollHeight, scrollTop, clientHeight } = listRef.current; // 考虑一个小的误差范围(10px) const isBottom = scrollHeight - scrollTop - clientHeight <= 10; setIsAtBottom(isBottom); } }, []); // 处理滚动事件 const handleScroll = useCallback(() => { checkIfAtBottom(); }, [checkIfAtBottom]); useEffect(() => { console.log('previewVideoUrl', previewVideoUrl); console.log('previewVideoId', previewVideoId); }, [previewVideoUrl, previewVideoId]); // 监听滚动事件 useEffect(() => { const listElement = listRef.current; if (listElement) { listElement.addEventListener('scroll', handleScroll); return () => { listElement.removeEventListener('scroll', handleScroll); }; } }, [handleScroll]); // 处理消息更新时的滚动 const handleMessagesUpdate = useCallback((shouldScroll: boolean) => { if (shouldScroll && listRef.current) { listRef.current.scrollTo({ top: listRef.current.scrollHeight, behavior: "smooth" }); } // 更新底部状态 checkIfAtBottom(); }, [checkIfAtBottom]); // 使用消息管理 hook const [ { messages, isLoading, error, hasMore, loadMoreMessages, backToLatest, isViewingHistory }, { sendMessage }, { enabled: systemPush, toggle: toggleSystemPush } ] = useMessages({ config: { projectId, userId }, onMessagesUpdate: handleMessagesUpdate }); // 按日期分组消息 const groupedMessages = React.useMemo(() => { const groups: MessageGroup[] = []; messages.forEach(message => { const messageDate = new Date(message.createdAt).setHours(0, 0, 0, 0); const existingGroup = groups.find(group => { const groupDate = new Date(group.date).setHours(0, 0, 0, 0); return groupDate === messageDate; }); if (existingGroup) { existingGroup.messages.push(message); } else { groups.push({ date: messageDate, messages: [message] }); } }); return groups.sort((a, b) => a.date - b.date); }, [messages]); return (
{/* Header */}
Chat {/* System push toggle */}
setIsSmartChatBoxOpen(false)} />
{/* Message list */}
{/* Load more button */} {hasMore && ( )} {/* Messages grouped by date */}
{groupedMessages.map((group) => ( {group.messages.map((message) => ( ))} ))}
{/* Loading indicator */} {isLoading && !hasMore && (
)} {/* Back to latest button */} {isViewingHistory && !isAtBottom && ( )}
{/* Input */} { if (url === previewVideoUrl && id === previewVideoId) { onClearPreview?.(); } }} initialVideoUrl={previewVideoUrl || undefined} initialVideoId={previewVideoId || undefined} setIsFocusChatInput={setIsFocusChatInput} />
); }