"use client"; import { useCallback, useEffect, useRef } from "react"; import { Loader2 } from "lucide-react"; import { ConversationSummary } from "@/features/agent/types"; import { ConversationListItem } from "./ConversationListItem"; import { Button } from "@/components/ui/button"; interface ConversationListProps { conversations: ConversationSummary[]; selectedConversationId: number | null; onSelect: (id: number) => void; searchQuery: string; hasMore?: boolean; loadingMore?: boolean; onLoadMore?: () => void; } export function ConversationList({ conversations, selectedConversationId, onSelect, searchQuery, hasMore = false, loadingMore = false, onLoadMore, }: ConversationListProps) { const scrollRootRef = useRef(null); const sentinelRef = useRef(null); const handleLoadMore = useCallback(() => { if (!hasMore || loadingMore || searchQuery.trim() || !onLoadMore) { return; } onLoadMore(); }, [hasMore, loadingMore, onLoadMore, searchQuery]); useEffect(() => { const root = scrollRootRef.current; const sentinel = sentinelRef.current; if (!root || !sentinel || !onLoadMore || searchQuery.trim()) { return; } const observer = new IntersectionObserver( (entries) => { if (entries.some((entry) => entry.isIntersecting)) { handleLoadMore(); } }, { root, rootMargin: "120px", threshold: 0 } ); observer.observe(sentinel); return () => observer.disconnect(); }, [handleLoadMore, onLoadMore, searchQuery, conversations.length]); if (conversations.length === 0) { return (
{searchQuery ? "未找到匹配的对话" : "暂无对话"}
); } return (
{conversations.map((conversation) => ( ))} {!searchQuery.trim() && hasMore ? (
{loadingMore ? ( ) : ( )}
) : null}
); }