import { useEffect } from "react"; import { ProxyImage } from "@/components/custom/proxyImage"; import { AspectRatio } from "@/components/ui/aspect-ratio"; import { Button } from "@/components/ui/button"; import { Separator } from "@/components/ui/separator"; import { toast } from "sonner"; import { useCurrentVideoMetadataStore, useDownloadActionStatesStore, useLibraryPageStatesStore } from "@/services/store"; import { formatBitrate, formatCodec, formatDurationString, formatFileSize, paginate } from "@/utils"; import { ArrowUpRightIcon, AudioLines, CircleArrowDown, Clock, File, FileAudio2, FileQuestion, FileVideo2, FolderInput, ListVideo, Music, Play, Search, Trash2, Video } from "lucide-react"; import { invoke } from "@tauri-apps/api/core"; import * as fs from "@tauri-apps/plugin-fs"; import { dirname } from "@tauri-apps/api/path"; import { DownloadState } from "@/types/download"; import { useQueryClient } from "@tanstack/react-query"; import { useDeleteDownloadState } from "@/services/mutations"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from "@/components/ui/alert-dialog"; import { Checkbox } from "@/components/ui/checkbox"; import { Label } from "@/components/ui/label"; import { useNavigate } from "react-router-dom"; import { useLogger } from "@/helpers/use-logger"; import { Empty, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle } from "@/components/ui/empty"; import PaginationBar from "@/components/custom/paginationBar"; interface CompletedDownloadProps { state: DownloadState; } interface CompletedDownloadsProps { downloads: DownloadState[]; } export function CompletedDownload({ state }: CompletedDownloadProps) { const downloadActions = useDownloadActionStatesStore(state => state.downloadActions); const setIsDeleteFileChecked = useDownloadActionStatesStore(state => state.setIsDeleteFileChecked); const queryClient = useQueryClient(); const downloadStateDeleter = useDeleteDownloadState(); const navigate = useNavigate(); const LOG = useLogger(); const openFile = async (filePath: string | null, app: string | null) => { if (filePath && await fs.exists(filePath)) { try { await invoke('open_file_with_app', { filePath: filePath, appName: app }).then(() => { toast.info(`${app === 'explorer' ? 'Revealing' : 'Opening'} file`, { description: `${app === 'explorer' ? 'Revealing' : 'Opening'} the file ${app === 'explorer' ? 'in' : 'with'} ${app ? app : 'default app'}.`, }) }); } catch (e) { console.error(e); toast.error(`Failed to ${app === 'explorer' ? 'reveal' : 'open'} file`, { description: `An error occurred while trying to ${app === 'explorer' ? 'reveal' : 'open'} the file.`, }) } } else { toast.info("File unavailable", { description: `The file you are trying to ${app === 'explorer' ? 'reveal' : 'open'} does not exist.`, }) } } const removeFromDownloads = async (downloadState: DownloadState, delete_file: boolean) => { if (delete_file && downloadState.filepath) { const isMutilplePlaylistItems = downloadState.playlist_id !== null && downloadState.playlist_indices !== null && downloadState.playlist_indices.includes(','); if (isMutilplePlaylistItems) { const dirPath = await dirname(downloadState.filepath); try { if (await fs.exists(dirPath)) { await fs.remove(dirPath, { recursive: true }); } else { console.error(`Directory not found: "${dirPath}"`); } } catch (e) { console.error(e); } } else { try { if (await fs.exists(downloadState.filepath)) { await fs.remove(downloadState.filepath); } else { console.error(`File not found: "${downloadState.filepath}"`); } } catch (e) { console.error(e); } } } downloadStateDeleter.mutate(downloadState.download_id, { onSuccess: (data) => { console.log("Download State deleted successfully:", data); queryClient.invalidateQueries({ queryKey: ['download-states'] }); if (delete_file && downloadState.filepath) { toast.success("Deleted from downloads", { description: `The download for ${isMutilplePlaylistItems ? 'playlist ' : ''}"${isMutilplePlaylistItems ? downloadState.playlist_title : downloadState.title}" has been deleted successfully.`, }); } else { toast.success("Removed from downloads", { description: `The download for ${isMutilplePlaylistItems ? 'playlist ' : ''}"${isMutilplePlaylistItems ? downloadState.playlist_title : downloadState.title}" has been removed successfully.`, }); } }, onError: (error) => { console.error("Failed to delete download state:", error); if (delete_file && downloadState.filepath) { toast.error("Failed to delete download", { description: `An error occurred while trying to delete the download for ${isMutilplePlaylistItems ? 'playlist ' : ''}"${isMutilplePlaylistItems ? downloadState.playlist_title : downloadState.title}".`, }); } else { toast.error("Failed to remove download", { description: `An error occurred while trying to remove the download for ${isMutilplePlaylistItems ? 'playlist ' : ''}"${isMutilplePlaylistItems ? downloadState.playlist_title : downloadState.title}".`, }); } } }) } const handleSearch = async (url: string, isPlaylist: boolean) => { try { LOG.info('NEODLP', `Received search request from library for URL: ${url}`); navigate('/'); const { setRequestedUrl, setAutoSubmitSearch } = useCurrentVideoMetadataStore.getState(); setRequestedUrl(url); setAutoSubmitSearch(true); toast.info(`Initiating ${isPlaylist ? 'Playlist' : 'Video'} Search`, { description: `Initiating search for the selected ${isPlaylist ? 'playlist' : 'video'}.`, }); } catch (e) { console.error(e); toast.error("Failed to initiate search", { description: "An error occurred while trying to initiate the search.", }); } } const itemActionStates = downloadActions[state.download_id] || { isResuming: false, isPausing: false, isCanceling: false, isDeleteFileChecked: false, }; const isPlaylist = state.playlist_id !== null && state.playlist_indices !== null; const isMutilplePlaylistItems = isPlaylist && state.playlist_indices && state.playlist_indices.includes(','); return (
{isMutilplePlaylistItems ? state.playlist_channel ?? 'unknown' : state.channel ?? 'unknown'} {state.host ? <>• {state.host}> : 'unknown'}