import { useEffect, useState } from 'react' import { Link } from 'react-router-dom' import { Clock, Play, Trash2 } from 'lucide-react' import toast from 'react-hot-toast' import { historyAPI } from '../api/history' import { imageURL } from '../api/client' import { confirmAction } from '../components/confirmAction' import { isRemoteEmbyID } from '../utils/remoteEmby' import type { HistoryItem, Media } from '../types' function fmtDuration(ms: number): string { if (!ms || ms <= 0) return '—' const sec = Math.floor(ms / 1000) const h = Math.floor(sec / 3600) const m = Math.floor((sec % 3600) / 60) return h > 0 ? `${h}h ${m}m` : `${m}m` } // WatchHistoryPage shows a full paginated view of the user's playback // history with progress bars and resume links. export function WatchHistoryPage() { const [items, setItems] = useState([]) const [loading, setLoading] = useState(true) const [busy, setBusy] = useState('') const load = () => { setLoading(true) historyAPI .list(200) .then(setItems) .catch((err: unknown) => { const msg = (err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? '加载观看历史失败' toast.error(msg) }) .finally(() => setLoading(false)) } useEffect(() => { load() }, []) const removeOne = async (id: string) => { if (!(await confirmAction({ title: '移除观看历史', message: '确定移除此条观看历史?不会删除媒体文件。', confirmText: '移除' }))) return setBusy(id) try { await historyAPI.remove(id) setItems((prev) => prev.filter((item) => item.id !== id)) toast.success('已移除观看历史') } catch (err: unknown) { const msg = (err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? '移除观看历史失败' toast.error(msg) } finally { setBusy('') } } const clearByStatus = async (status: 'completed' | 'incomplete') => { const label = status === 'completed' ? '已看完' : '未看完' if (!(await confirmAction({ title: '清除观看历史', message: `确定清除所有${label}的观看历史?不会删除媒体文件。`, confirmText: '清除' }))) return setBusy(status) try { await historyAPI.clear(undefined, status) setItems((prev) => prev.filter((item) => status === 'completed' ? !item.completed : item.completed)) toast.success(`已清除${label}记录`) } catch (err: unknown) { const msg = (err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? `清除${label}记录失败` toast.error(msg) } finally { setBusy('') } } return (

观看历史

{loading &&

加载中…

} {!loading && items.length === 0 && (

暂无观看记录。

)}
{items.map((h) => { const m: Media = h.media || ({ id: h.media_id, title: isRemoteEmbyID(h.media_id) ? '远程媒体' : h.media_id, poster_url: '', updated_at: h.watched_at, } as Media) const progress = h.duration_ms > 0 ? h.position_ms / h.duration_ms : 0 return (
{m.poster_url ? ( {m.title} ) : null}
{m.title}
{fmtDuration(h.position_ms)} / {fmtDuration(h.duration_ms)} {new Date(h.watched_at).toLocaleString()} {h.completed && ( 已看完 )}
继续
) })}
) }