import { useCallback, useEffect, useRef, useState } from 'react'; import { AvatarPicker } from './AvatarPicker'; import type { SessionSummary } from '../types'; import { getSessionListLabel, groupSessionsByDate } from '../utils/sessions'; function formatSessionTime(iso?: string): string { if (!iso) return ''; const date = new Date(iso); if (Number.isNaN(date.getTime())) return ''; const now = new Date(); const isToday = date.getFullYear() === now.getFullYear() && date.getMonth() === now.getMonth() && date.getDate() === now.getDate(); if (isToday) { return date.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }); } return date.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' }); } function CloseIcon() { return ( ); } type HistorySidebarProps = { open: boolean; sessions: SessionSummary[]; activeSessionId?: string; loading: boolean; loadingMore: boolean; hasMore: boolean; searchQuery: string; onClose: () => void; onSelect: (sessionId: string) => void; onNew: () => void; onDelete: (sessionId: string) => void; onLoadMore: () => void; onSearchChange: (query: string) => void; }; export function HistorySidebar({ open, sessions, activeSessionId, loading, loadingMore, hasMore, searchQuery, onClose, onSelect, onNew, onDelete, onLoadMore, onSearchChange, }: HistorySidebarProps) { const bodyRef = useRef(null); const [pendingDeleteId, setPendingDeleteId] = useState(null); const [pendingSelectId, setPendingSelectId] = useState(null); useEffect(() => { if (open) { setPendingDeleteId(null); setPendingSelectId(null); } }, [open, sessions.length]); const handleScroll = useCallback(() => { const el = bodyRef.current; if (!el) return; const nearBottom = el.scrollHeight - el.scrollTop - el.clientHeight < 80; if (nearBottom && hasMore && !loadingMore && !loading) { onLoadMore(); } }, [hasMore, loading, loadingMore, onLoadMore]); const handleDeleteClick = useCallback((sessionId: string) => { setPendingSelectId(null); setPendingDeleteId(sessionId); }, []); const handleConfirmDelete = useCallback( (sessionId: string) => { setPendingDeleteId(null); onDelete(sessionId); }, [onDelete], ); const handleCancelDelete = useCallback(() => { setPendingDeleteId(null); }, []); const handleSelectClick = useCallback( (sessionId: string) => { if (pendingDeleteId === sessionId) return; if (activeSessionId === sessionId) { setPendingSelectId(null); onSelect(sessionId); return; } if (pendingSelectId === sessionId) { setPendingSelectId(null); onSelect(sessionId); return; } setPendingSelectId(sessionId); }, [activeSessionId, onSelect, pendingDeleteId, pendingSelectId], ); if (!open) return null; const sessionGroups = groupSessionsByDate(sessions); return ( <>
{loading && sessions.length === 0 ? (
加载中…
) : sessions.length === 0 ? (
{searchQuery ? '没有找到相关历史标题' : '暂无历史对话'}
) : ( <> {sessionGroups.map((group) => (
{group.label}
    {group.sessions.map((item) => { const label = getSessionListLabel(item); const isPending = pendingDeleteId === item.id; const isPendingSelect = pendingSelectId === item.id; return (
  • {isPending ? (
    ) : ( )}
  • ); })}
))} {loadingMore &&
加载更多历史…
} {!loadingMore && hasMore &&
向下滚动加载更多…
} )}
); }