mirror of
https://github.com/hydralauncher/hydra.git
synced 2025-03-09 15:40:26 +00:00
first commit
This commit is contained in:
commit
f1bdec484e
165 changed files with 20993 additions and 0 deletions
3
src/renderer/hooks/index.ts
Normal file
3
src/renderer/hooks/index.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
export * from "./use-download";
|
||||
export * from "./use-library";
|
||||
export * from "./redux";
|
7
src/renderer/hooks/redux.ts
Normal file
7
src/renderer/hooks/redux.ts
Normal 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;
|
33
src/renderer/hooks/use-date.ts
Normal file
33
src/renderer/hooks/use-date.ts
Normal 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 "";
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
134
src/renderer/hooks/use-download.ts
Normal file
134
src/renderer/hooks/use-download.ts
Normal 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)),
|
||||
};
|
||||
}
|
16
src/renderer/hooks/use-library.ts
Normal file
16
src/renderer/hooks/use-library.ts
Normal 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 };
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue