import { useTranslation } from "react-i18next"; import { useNavigate } from "react-router-dom"; import { AsyncImage, Button, TextField } from "@renderer/components"; import { formatDownloadProgress, steamUrlBuilder } from "@renderer/helpers"; import { useDownload, useLibrary } from "@renderer/hooks"; import type { Game } from "@types"; import { useEffect, useMemo, useRef, useState } from "react"; import { BinaryNotFoundModal } from "../shared-modals/binary-not-found-modal"; import * as styles from "./downloads.css"; import { DeleteModal } from "./delete-modal"; import { formatBytes } from "@renderer/utils"; export function Downloads() { const { library, updateLibrary } = useLibrary(); const { t } = useTranslation("downloads"); const navigate = useNavigate(); const gameToBeDeleted = useRef(null); const [filteredLibrary, setFilteredLibrary] = useState([]); const [showBinaryNotFoundModal, setShowBinaryNotFoundModal] = useState(false); const [showDeleteModal, setShowDeleteModal] = useState(false); const { game: gameDownloading, progress, isDownloading, numPeers, numSeeds, pauseDownload, resumeDownload, cancelDownload, deleteGame, isGameDeleting, } = useDownload(); const libraryWithDownloadedGamesOnly = useMemo(() => { return library.filter((game) => game.status); }, [library]); useEffect(() => { setFilteredLibrary(libraryWithDownloadedGamesOnly); }, [libraryWithDownloadedGamesOnly]); const openGameInstaller = (gameId: number) => window.electron.openGameInstaller(gameId).then((isBinaryInPath) => { if (!isBinaryInPath) setShowBinaryNotFoundModal(true); updateLibrary(); }); const removeGameFromDownload = (gameId: number) => window.electron.removeGameFromDownload(gameId).then(() => { updateLibrary(); }); const getFinalDownloadSize = (game: Game) => { const isGameDownloading = isDownloading && gameDownloading?.id === game?.id; if (!game) return "N/A"; if (game.fileSize) return formatBytes(game.fileSize); if (gameDownloading?.fileSize && isGameDownloading) return formatBytes(gameDownloading.fileSize); return game.repack?.fileSize ?? "N/A"; }; const getGameInfo = (game: Game) => { const isGameDownloading = isDownloading && gameDownloading?.id === game?.id; const finalDownloadSize = getFinalDownloadSize(game); if (isGameDeleting(game?.id)) { return

{t("deleting")}

; } if (isGameDownloading) { return ( <>

{progress}

{gameDownloading?.status !== "downloading" ? (

{t(gameDownloading?.status)}

) : ( <>

{formatBytes(gameDownloading?.bytesDownloaded)} /{" "} {finalDownloadSize}

{numPeers} peers / {numSeeds} seeds

)} ); } if (game?.status === "seeding") { return ( <>

{game?.repack.title}

{t("completed")}

); } if (game?.status === "cancelled") return

{t("cancelled")}

; if (game?.status === "downloading_metadata") return

{t("starting_download")}

; if (game?.status === "paused") { return ( <>

{formatDownloadProgress(game.progress)}

{t("paused")}

); } }; const openDeleteModal = (gameId: number) => { gameToBeDeleted.current = gameId; setShowDeleteModal(true); }; const getGameActions = (game: Game) => { const isGameDownloading = isDownloading && gameDownloading?.id === game?.id; const deleting = isGameDeleting(game.id); if (isGameDownloading) { return ( <> ); } if (game?.status === "paused") { return ( <> ); } if (game?.status === "seeding") { return ( <> ); } if (game?.status === "downloading_metadata") { return ( ); } return ( <> ); }; const handleFilter: React.ChangeEventHandler = (event) => { setFilteredLibrary( libraryWithDownloadedGamesOnly.filter((game) => game.title .toLowerCase() .includes(event.target.value.toLocaleLowerCase()) ) ); }; return (
setShowBinaryNotFoundModal(false)} /> setShowDeleteModal(false)} deleteGame={() => deleteGame(gameToBeDeleted.current).then(updateLibrary) } />
    {filteredLibrary.map((game) => { return (
  • {getGameInfo(game)}
    {getGameActions(game)}
  • ); })}
); }