From 2b7ab9def4f5404ae9f4c0f4a0649dcd474869c1 Mon Sep 17 00:00:00 2001 From: Subhamoy Biswas Date: Fri, 9 Jan 2026 23:40:35 +0530 Subject: [PATCH] feat: added clear, copy log buttons and pagination in completed downloads --- src/App.tsx | 2 +- src/components/custom/paginationBar.tsx | 81 +++++++++++++++++++ src/components/navbar.tsx | 39 ++++++++- .../pages/library/completedDownloads.tsx | 31 +++++-- src/helpers/use-downloader.ts | 4 +- src/pages/library.tsx | 3 +- src/services/store.ts | 4 +- src/types/download.ts | 18 +++++ src/types/store.ts | 2 + src/utils.ts | 45 ++++++++++- 10 files changed, 214 insertions(+), 15 deletions(-) create mode 100644 src/components/custom/paginationBar.tsx diff --git a/src/App.tsx b/src/App.tsx index 789f754..ae34e94 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -309,7 +309,7 @@ export default function App({ children }: { children: React.ReactNode }) { useEffect(() => { if (isSuccessFetchingDownloadStates && downloadStates) { - console.log("Download States fetched successfully:", downloadStates); + // console.log("Download States fetched successfully:", downloadStates); setDownloadStates(downloadStates); } }, [downloadStates, isSuccessFetchingDownloadStates, setDownloadStates]); diff --git a/src/components/custom/paginationBar.tsx b/src/components/custom/paginationBar.tsx new file mode 100644 index 0000000..8a85111 --- /dev/null +++ b/src/components/custom/paginationBar.tsx @@ -0,0 +1,81 @@ +import { Paginated } from "@/types/download"; +import { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious } from "@/components/ui/pagination"; + +export default function PaginationBar({ + paginatedData, + setPage, +}: { + paginatedData: Paginated; + setPage: (page: number) => void; +}) { + return ( + + + + setPage(paginatedData.prev_page ?? paginatedData.first_page)} + aria-disabled={!paginatedData.prev_page} + className={!paginatedData.prev_page ? 'pointer-events-none opacity-50' : 'cursor-pointer'} + /> + + + {paginatedData.pages.map((link, index, array) => { + const currentPage = paginatedData.current_page; + const pageNumber = link.page!; + + // Show first page, last page, current page, and 2 pages around current + const showPage = + pageNumber === 1 || + pageNumber === paginatedData.last_page || + Math.abs(pageNumber - currentPage) <= 1; + + // Show ellipsis if there's a gap + const prevVisiblePage = array + .slice(0, index) + .reverse() + .find((prevLink) => { + const prevPageNum = prevLink.page!; + return ( + prevPageNum === 1 || + prevPageNum === paginatedData.last_page || + Math.abs(prevPageNum - currentPage) <= 1 + ); + })?.page; + + const showEllipsis = showPage && prevVisiblePage && pageNumber - prevVisiblePage > 1; + + if (!showPage) return null; + + return ( +
+ {showEllipsis && ( + + + + )} + {showPage && ( + + setPage(link.page)} + isActive={link.active} + > + {link.label} + + + )} +
+ ); + })} + + + setPage(paginatedData.next_page ?? paginatedData.last_page)} + aria-disabled={!paginatedData.next_page} + className={!paginatedData.next_page ? 'pointer-events-none opacity-50' : 'cursor-pointer'} + /> + +
+
+ ) +} diff --git a/src/components/navbar.tsx b/src/components/navbar.tsx index 1b7ebea..cc1d666 100644 --- a/src/components/navbar.tsx +++ b/src/components/navbar.tsx @@ -1,15 +1,26 @@ +import { useState } from "react"; import { useLocation } from "react-router-dom"; import { SidebarTrigger } from "@/components/ui/sidebar"; import { getRouteName } from "@/utils"; import { Button } from "@/components/ui/button"; -import { Terminal } from "lucide-react"; +import { BrushCleaning, Check, Copy, Terminal } from "lucide-react"; import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"; -import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"; +import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"; import { useLogger } from "@/helpers/use-logger"; +import { writeText } from "@tauri-apps/plugin-clipboard-manager"; export default function Navbar() { + const [copied, setCopied] = useState(false); const location = useLocation(); - const logs = useLogger().getLogs(); + const logger = useLogger(); + const logs = logger.getLogs(); + const logText = logs.map(log => `${new Date(log.timestamp).toLocaleTimeString()} [${log.level.toUpperCase()}] ${log.context}: ${log.message}`).join('\n'); + + const handleCopyLogs = async () => { + await writeText(logText); + setCopied(true); + setTimeout(() => setCopied(false), 1500); + } return (