refactor hero panel

This commit is contained in:
Zamitto 2024-06-07 10:31:37 -03:00
parent 7013f7c65d
commit 81a3ede4bd
4 changed files with 62 additions and 192 deletions

View File

@ -1,30 +1,18 @@
import { GearIcon, NoEntryIcon, PlusCircleIcon } from "@primer/octicons-react";
import { BinaryNotFoundModal } from "../../shared-modals/binary-not-found-modal";
import { Button } from "@renderer/components";
import { useAppSelector, useDownload, useLibrary } from "@renderer/hooks";
import { useContext, useState } from "react";
import { useTranslation } from "react-i18next";
import * as styles from "./hero-panel-actions.css";
import { gameDetailsContext } from "../game-details.context";
import { Downloader } from "@shared";
import { GameOptionsModal } from "../modals/game-options-modal";
export function HeroPanelActions() {
const [toggleLibraryGameDisabled, setToggleLibraryGameDisabled] =
useState(false);
const [showBinaryNotFoundModal, setShowBinaryNotFoundModal] = useState(false);
const [showGameOptionsModal, setShowGameOptionsModal] = useState(false);
const {
resumeDownload,
pauseDownload,
cancelDownload,
removeGameFromLibrary,
isGameDeleting,
} = useDownload();
const { removeGameFromLibrary, isGameDeleting } = useDownload();
const {
game,
@ -89,15 +77,6 @@ export function HeroPanelActions() {
}
};
const openGameInstaller = () => {
if (game) {
window.electron.openGameInstaller(game.id).then((isBinaryInPath) => {
if (!isBinaryInPath) setShowBinaryNotFoundModal(true);
updateLibrary();
});
}
};
const openGame = async () => {
if (game) {
if (game.executablePath) {
@ -140,52 +119,6 @@ export function HeroPanelActions() {
</Button>
);
if (game?.status === "active" && game?.progress !== 1) {
return (
<>
<Button
onClick={() => pauseDownload(game.id).then(updateGame)}
theme="outline"
className={styles.heroPanelAction}
>
{t("pause")}
</Button>
<Button
onClick={() => cancelDownload(game.id).then(updateGame)}
theme="outline"
className={styles.heroPanelAction}
>
{t("cancel")}
</Button>
</>
);
}
if (game?.status === "paused") {
return (
<>
<Button
onClick={() => resumeDownload(game.id).then(updateGame)}
theme="outline"
className={styles.heroPanelAction}
disabled={
game.downloader === Downloader.RealDebrid &&
!userPreferences?.realDebridApiToken
}
>
{t("resume")}
</Button>
<Button
onClick={() => cancelDownload(game.id).then(updateGame)}
theme="outline"
className={styles.heroPanelAction}
>
{t("cancel")}
</Button>
</>
);
}
if (game?.status === "removed") {
return (
<>
@ -207,13 +140,7 @@ export function HeroPanelActions() {
return (
<>
{toggleGameOnLibraryButton}
<Button
onClick={openRepacksModal}
theme="outline"
className={styles.heroPanelAction}
>
{t("open_download_options")}
</Button>
{showDownloadOptionsButton}
</>
);
}
@ -242,26 +169,6 @@ export function HeroPanelActions() {
<div className={styles.separator} />
{game?.progress === 1 && game?.folderName && (
<>
<BinaryNotFoundModal
visible={showBinaryNotFoundModal}
onClose={() => setShowBinaryNotFoundModal(false)}
/>
<Button
onClick={openGameInstaller}
theme="outline"
disabled={deleting || isGameRunning}
className={styles.heroPanelAction}
>
{t("install")}
</Button>
</>
)}
{game.progress === 1 && !game.downloadPath && showDownloadOptionsButton}
{game.progress !== 1 && toggleGameOnLibraryButton}
{isGameRunning ? (

View File

@ -1,7 +1,8 @@
import { useContext, useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { useDate } from "@renderer/hooks";
import * as styles from "./hero-panel.css";
import { formatDownloadProgress } from "@renderer/helpers";
import { useDate, useDownload } from "@renderer/hooks";
import { gameDetailsContext } from "../game-details.context";
const MAX_MINUTES_TO_SHOW_IN_PLAYTIME = 120;
@ -46,8 +47,50 @@ export function HeroPanelPlaytime() {
return t("amount_hours", { amount: numberFormatter.format(hours) });
};
if (!game?.lastTimePlayed) {
return <p>{t("not_played_yet", { title: game?.title })}</p>;
const { progress, lastPacket } = useDownload();
const isGameDownloading =
game?.status === "active" && lastPacket?.game.id === game?.id;
if (!game) return;
let downloadContent: JSX.Element | null = null;
if (game.status === "active") {
if (lastPacket?.isDownloadingMetadata && isGameDownloading) {
downloadContent = <p>{t("downloading_metadata")}</p>;
} else if (game.progress !== 1) {
downloadContent = (
<p className={styles.downloadDetailsRow}>
{isGameDownloading ? progress : formatDownloadProgress(game.progress)}
</p>
);
}
}
if (!game.lastTimePlayed) {
return (
<>
<p>{t("not_played_yet", { title: game?.title })}</p>
{downloadContent}
</>
);
}
if (isGameRunning) {
return (
<>
{downloadContent || (
<p>
{t("play_time", {
amount: formatPlayTime(),
})}
</p>
)}
<p>{t("playing_now")}</p>
</>
);
}
return (
@ -58,9 +101,7 @@ export function HeroPanelPlaytime() {
})}
</p>
{isGameRunning ? (
<p>{t("playing_now")}</p>
) : (
{downloadContent || (
<p>
{t("last_time_played", {
period: lastTimePlayed,

View File

@ -1,14 +1,9 @@
import { format } from "date-fns";
import { useContext, useMemo } from "react";
import { useContext } from "react";
import { useTranslation } from "react-i18next";
import Color from "color";
import { useDownload } from "@renderer/hooks";
import { formatDownloadProgress } from "@renderer/helpers";
import { HeroPanelActions } from "./hero-panel-actions";
import { Downloader, formatBytes } from "@shared";
import * as styles from "./hero-panel.css";
import { HeroPanelPlaytime } from "./hero-panel-playtime";
import { gameDetailsContext } from "../game-details.context";
@ -18,99 +13,31 @@ export function HeroPanel() {
const { game, repacks, gameColor } = useContext(gameDetailsContext);
const { progress, eta, lastPacket, isGameDeleting } = useDownload();
const finalDownloadSize = useMemo(() => {
if (game?.fileSize) return formatBytes(game.fileSize);
if (lastPacket?.game.fileSize && game?.status === "active")
return formatBytes(lastPacket?.game.fileSize);
return "N/A";
}, [game, lastPacket?.game]);
const { lastPacket } = useDownload();
const isGameDownloading =
game?.status === "active" && lastPacket?.game.id === game?.id;
const getInfo = () => {
if (isGameDeleting(game?.id ?? -1)) return <p>{t("deleting")}</p>;
if (!game) {
const [latestRepack] = repacks;
if (game && (game.progress === 1 || !game.status)) {
return <HeroPanelPlaytime />;
}
if (latestRepack) {
const lastUpdate = format(latestRepack.uploadDate!, "dd/MM/yyyy");
const repacksCount = repacks.length;
if (game?.status === "active") {
if (lastPacket?.isDownloadingMetadata && isGameDownloading) {
return (
<>
<p>{progress}</p>
<p>{t("downloading_metadata")}</p>
<p>{t("updated_at", { updated_at: lastUpdate })}</p>
<p>{t("download_options", { count: repacksCount })}</p>
</>
);
}
const sizeDownloaded = formatBytes(
lastPacket?.game?.bytesDownloaded ?? game?.bytesDownloaded
);
const showPeers =
game?.downloader === Downloader.Torrent &&
lastPacket?.numPeers !== undefined;
return (
<>
<p className={styles.downloadDetailsRow}>
{isGameDownloading
? progress
: formatDownloadProgress(game?.progress)}
<small>{eta ? t("eta", { eta }) : t("calculating_eta")}</small>
</p>
<p className={styles.downloadDetailsRow}>
<span>
{sizeDownloaded} / {finalDownloadSize}
</span>
{showPeers && (
<small>
{lastPacket?.numPeers} peers / {lastPacket?.numSeeds} seeds
</small>
)}
</p>
</>
);
return <p>{t("no_downloads")}</p>;
}
if (game?.status === "paused") {
const formattedProgress = formatDownloadProgress(game.progress);
return (
<>
<p className={styles.downloadDetailsRow}>
{formattedProgress} <small>{t("paused")}</small>
</p>
<p>
{formatBytes(game.bytesDownloaded)} / {finalDownloadSize}
</p>
</>
);
}
const [latestRepack] = repacks;
if (latestRepack) {
const lastUpdate = format(latestRepack.uploadDate!, "dd/MM/yyyy");
const repacksCount = repacks.length;
return (
<>
<p>{t("updated_at", { updated_at: lastUpdate })}</p>
<p>{t("download_options", { count: repacksCount })}</p>
</>
);
}
return <p>{t("no_downloads")}</p>;
return <HeroPanelPlaytime />;
};
const backgroundColor = gameColor

View File

@ -4,12 +4,7 @@ import { Button, Modal, TextField } from "@renderer/components";
import type { Game } from "@types";
import * as styles from "./game-options-modal.css";
import { gameDetailsContext } from "../game-details.context";
import {
FileDirectoryOpenFillIcon,
FileSymlinkFileIcon,
PencilIcon,
TrashIcon,
} from "@primer/octicons-react";
import { TrashIcon } from "@primer/octicons-react";
import { DeleteGameModal } from "@renderer/pages/downloads/delete-game-modal";
import { useDownload } from "@renderer/hooks";