import { useEffect, useState } from "react"; import { Button } from "@/components/ui/button"; import { Trash2, ExternalLink, Search, ArrowUpDown, History } from "lucide-react"; import { Badge } from "@/components/ui/badge"; import { Input } from "@/components/ui/input"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, } from "@/components/ui/pagination"; import { GetDownloadHistory, ClearDownloadHistory } from "../../wailsjs/go/main/App"; import { openExternal } from "@/lib/utils"; const formatDate = (timestamp: number) => { const date = new Date(timestamp * 1000); const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); const hours = String(date.getHours()).padStart(2, '0'); const minutes = String(date.getMinutes()).padStart(2, '0'); const seconds = String(date.getSeconds()).padStart(2, '0'); return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; }; interface HistoryItem { id: string; spotify_id: string; title: string; artists: string; album: string; duration_str: string; cover_url: string; quality: string; format: string; path: string; timestamp: number; } export function HistoryPage() { const [history, setHistory] = useState([]); const [filteredHistory, setFilteredHistory] = useState([]); const [showClearConfirm, setShowClearConfirm] = useState(false); const [searchQuery, setSearchQuery] = useState(""); const [sortBy, setSortBy] = useState("default"); const [currentPage, setCurrentPage] = useState(1); const ITEMS_PER_PAGE = 50; const fetchHistory = async () => { try { const items = await GetDownloadHistory(); setHistory(items || []); } catch (err) { console.error("Failed to fetch history:", err); } }; useEffect(() => { fetchHistory(); const interval = setInterval(fetchHistory, 5000); return () => clearInterval(interval); }, []); useEffect(() => { let result = [...history]; if (searchQuery) { const query = searchQuery.toLowerCase(); result = result.filter(item => item.title.toLowerCase().includes(query) || item.artists.toLowerCase().includes(query) || item.album.toLowerCase().includes(query)); } const parseDuration = (str: string) => { const parts = str.split(':').map(Number); if (parts.length === 2) return parts[0] * 60 + parts[1]; if (parts.length === 3) return parts[0] * 3600 + parts[1] * 60 + parts[2]; return 0; }; result.sort((a, b) => { switch (sortBy) { case "default": case "date_desc": return b.timestamp - a.timestamp; case "date_asc": return a.timestamp - b.timestamp; case "title_asc": return a.title.localeCompare(b.title); case "title_desc": return b.title.localeCompare(a.title); case "artist_asc": return a.artists.localeCompare(b.artists); case "artist_desc": return b.artists.localeCompare(a.artists); case "duration_asc": return parseDuration(a.duration_str) - parseDuration(b.duration_str); case "duration_desc": return parseDuration(b.duration_str) - parseDuration(a.duration_str); default: return 0; } }); setFilteredHistory(result); setCurrentPage(1); }, [history, searchQuery, sortBy]); const totalPages = Math.ceil(filteredHistory.length / ITEMS_PER_PAGE); const startIndex = (currentPage - 1) * ITEMS_PER_PAGE; const paginatedHistory = filteredHistory.slice(startIndex, startIndex + ITEMS_PER_PAGE); const getPaginationPages = (current: number, total: number): (number | 'ellipsis')[] => { if (total <= 10) { return Array.from({ length: total }, (_, i) => i + 1); } const pages: (number | 'ellipsis')[] = []; pages.push(1); if (current <= 7) { for (let i = 2; i <= 10; i++) pages.push(i); pages.push('ellipsis'); pages.push(total); } else if (current >= total - 7) { pages.push('ellipsis'); for (let i = total - 9; i <= total; i++) pages.push(i); } else { pages.push('ellipsis'); pages.push(current - 1); pages.push(current); pages.push(current + 1); pages.push('ellipsis'); pages.push(total); } return pages; }; const handleClearHistory = async () => { await ClearDownloadHistory(); fetchHistory(); setShowClearConfirm(false); }; return (

Download History

{history.length > 0 && ( {history.length.toLocaleString('en-US')} )}
setSearchQuery(e.target.value)} className="pl-8 h-9"/>
{paginatedHistory.length === 0 ? (

No download history

Your downloaded tracks will appear here.

) : ( {paginatedHistory.map((item, index) => ())}
# Title Album Format Dur Downloaded At Link
{startIndex + index + 1}
{item.album} { (e.target as HTMLImageElement).src = "https://placehold.co/300?text=No+Cover"; }}/>
{item.title} {item.artists}
{item.album}
{item.format} {item.quality && {item.quality}}
{item.duration_str} {formatDate(item.timestamp)}
)}
{totalPages > 1 && ( { e.preventDefault(); if (currentPage > 1) setCurrentPage(currentPage - 1); }} className={currentPage === 1 ? "pointer-events-none opacity-50" : "cursor-pointer"}/> {getPaginationPages(currentPage, totalPages).map((page, index) => (page === 'ellipsis' ? ( ) : ( { e.preventDefault(); setCurrentPage(page); }} isActive={currentPage === page} className="cursor-pointer"> {page} )))} { e.preventDefault(); if (currentPage < totalPages) setCurrentPage(currentPage + 1); }} className={currentPage === totalPages ? "pointer-events-none opacity-50" : "cursor-pointer"}/> )} Clear Download History? This will remove all entries from your download history. This action cannot be undone. Note: The actual downloaded files will NOT be deleted.
); }