import { useInfiniteQuery } from '@tanstack/react-query'; import { Link, useNavigate } from 'react-router-dom'; import { Icon } from '@/app/Icon'; import { getCallHistory, type CallHistoryItem } from '@/lib/api/calls'; import { avatarBgClass, avatarLetter } from '@/lib/avatar'; import { formatEventTimestamp } from '@/lib/messages/time'; import { useChatList } from '@/lib/tinode/hooks'; import { useCallStore } from '@/stores/calls'; function formatDuration(ms: number | undefined): string { const totalSeconds = Math.round((ms || 0) / 1000); return `${String(Math.floor(totalSeconds / 60)).padStart(2, '0')}:${String(totalSeconds % 60).padStart(2, '0')}`; } /** Direction-dependent, same reasoning as dispatch.ts's callResultDisplay: a `missed` result reads * as "未接听" from the callee's own history and "已取消" from the caller's. */ function statusLabel(item: CallHistoryItem): string { const result = item.result || item.status; const incoming = item.direction === 'incoming'; if (result === 'finished') return formatDuration(item.duration_ms); if (result === 'missed') return incoming ? '未接听' : '已取消'; if (result === 'declined') return '已拒绝'; if (result === 'disconnected') return '异常结束'; return result; } /** README §7 doesn't spec a dedicated call-history screen beyond the "最近通话" idea implicit in * NavRail's own 通话记录 entry -- this is a plain list off the confirmed real `GET /v1/im/calls` * endpoint, whose response shape (see calls.ts's own comment) turned out completely different * from the doc's own minimal example once checked live: `peer_user_id` (a real `usr...` id, unlike * `topic`, which comes back `p2p...`-hashed and unusable for navigation/re-dialing) is resolved to * a display name via the chat list, same lookup ChatListColumn itself uses. */ export function CallHistoryView() { const navigate = useNavigate(); const contacts = useChatList(); const query = useInfiniteQuery({ queryKey: ['call-history'], queryFn: ({ pageParam }) => getCallHistory(pageParam), initialPageParam: '', getNextPageParam: (lastPage) => lastPage.next_cursor || undefined, }); const items = query.data?.pages.flatMap((p) => p.items) ?? []; return (