first commit

This commit is contained in:
Hydra 2024-04-18 08:46:06 +01:00
commit f1bdec484e
165 changed files with 20993 additions and 0 deletions

View file

@ -0,0 +1,3 @@
export * from "./use-download";
export * from "./use-library";
export * from "./redux";

View file

@ -0,0 +1,7 @@
import { useDispatch, useSelector } from "react-redux";
import type { TypedUseSelectorHook } from "react-redux";
import type { AppDispatch, RootState } from "@renderer/store";
export const useAppDispatch: () => AppDispatch = useDispatch;
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;

View file

@ -0,0 +1,33 @@
import { formatDistance } from "date-fns";
import type { FormatDistanceOptions } from "date-fns";
import { ptBR, enUS, es, fr } from "date-fns/locale";
import { useTranslation } from "react-i18next";
export function useDate() {
const { i18n } = useTranslation();
const getDateLocale = () => {
if (i18n.language.startsWith("pt")) return ptBR;
if (i18n.language.startsWith("es")) return es;
if (i18n.language.startsWith("fr")) return fr;
return enUS;
};
return {
formatDistance: (
date: string | number | Date,
baseDate: string | number | Date,
options?: FormatDistanceOptions
) => {
try {
return formatDistance(date, baseDate, {
...options,
locale: getDateLocale(),
});
} catch (err) {
return "";
}
},
};
}

View file

@ -0,0 +1,134 @@
import { addMilliseconds } from "date-fns";
import prettyBytes from "pretty-bytes";
import { formatDownloadProgress } from "@renderer/helpers";
import { useLibrary } from "./use-library";
import { useAppDispatch, useAppSelector } from "./redux";
import {
addPacket,
clearDownload,
setGameDeleting,
removeGameFromDeleting,
} from "@renderer/features";
import type { GameShop, TorrentProgress } from "@types";
import { useDate } from "./use-date";
export function useDownload() {
const { updateLibrary } = useLibrary();
const { formatDistance } = useDate();
const { packets, gamesWithDeletionInProgress } = useAppSelector(
(state) => state.download
);
const dispatch = useAppDispatch();
const lastPacket = packets.at(-1);
const startDownload = (
repackId: number,
objectID: string,
title: string,
shop: GameShop
) =>
window.electron
.startGameDownload(repackId, objectID, title, shop)
.then((game) => {
dispatch(clearDownload());
updateLibrary();
return game;
});
const pauseDownload = (gameId: number) =>
window.electron.pauseGameDownload(gameId).then(() => {
dispatch(clearDownload());
updateLibrary();
});
const resumeDownload = (gameId: number) =>
window.electron.resumeGameDownload(gameId).then(() => {
updateLibrary();
});
const cancelDownload = (gameId: number) =>
window.electron.cancelGameDownload(gameId).then(() => {
dispatch(clearDownload());
updateLibrary();
deleteGame(gameId);
});
const removeGame = (gameId: number) =>
window.electron.removeGame(gameId).then(() => {
updateLibrary();
});
const isVerifying = ["downloading_metadata", "checking_files"].includes(
lastPacket?.game.status
);
const getETA = () => {
if (isVerifying || !isFinite(lastPacket?.timeRemaining)) {
return "";
}
try {
return formatDistance(
addMilliseconds(new Date(), lastPacket?.timeRemaining ?? 1),
new Date(),
{ addSuffix: true }
);
} catch (err) {
return "";
}
};
const getProgress = () => {
if (lastPacket?.game.status === "checking_files") {
return formatDownloadProgress(lastPacket?.game.fileVerificationProgress);
}
return formatDownloadProgress(lastPacket?.game.progress);
};
const deleteGame = (gameId: number) =>
window.electron
.cancelGameDownload(gameId)
.then(() => {
dispatch(setGameDeleting(gameId));
return window.electron.deleteGameFolder(gameId);
})
.catch(() => {})
.finally(() => {
updateLibrary();
dispatch(removeGameFromDeleting(gameId));
});
const isGameDeleting = (gameId: number) => {
return gamesWithDeletionInProgress.includes(gameId);
};
return {
game: lastPacket?.game,
bytesDownloaded: lastPacket?.game.bytesDownloaded,
fileSize: lastPacket?.game.fileSize,
isVerifying,
gameId: lastPacket?.game.id,
downloadSpeed: `${prettyBytes(lastPacket?.downloadSpeed ?? 0, {
bits: true,
})}/s`,
isDownloading: Boolean(lastPacket),
progress: getProgress(),
numPeers: lastPacket?.numPeers,
numSeeds: lastPacket?.numSeeds,
eta: getETA(),
startDownload,
pauseDownload,
resumeDownload,
cancelDownload,
removeGame,
deleteGame,
isGameDeleting,
clearDownload: () => dispatch(clearDownload()),
addPacket: (packet: TorrentProgress) => dispatch(addPacket(packet)),
};
}

View file

@ -0,0 +1,16 @@
import { useCallback } from "react";
import { useAppDispatch, useAppSelector } from "./redux";
import { setLibrary } from "@renderer/features";
export function useLibrary() {
const dispatch = useAppDispatch();
const library = useAppSelector((state) => state.library.value);
const updateLibrary = useCallback(async () => {
return window.electron
.getLibrary()
.then((updatedLibrary) => dispatch(setLibrary(updatedLibrary)));
}, [dispatch]);
return { library, updateLibrary };
}