chore: adding download sorting

This commit is contained in:
Chubby Granny Chaser
2025-02-01 23:52:12 +00:00
parent 7fed104afd
commit 7e54a6d0a9
15 changed files with 141 additions and 66 deletions

View File

@@ -282,6 +282,7 @@ export function App() {
message={toast.message}
type={toast.type}
onClose={handleToastClose}
duration={toast.duration}
/>
</div>

View File

@@ -40,7 +40,9 @@ declare global {
interface Electron {
/* Torrenting */
startGameDownload: (payload: StartGameDownloadPayload) => Promise<void>;
startGameDownload: (
payload: StartGameDownloadPayload
) => Promise<{ ok: boolean; error?: string }>;
cancelGameDownload: (shop: GameShop, objectId: string) => Promise<void>;
pauseGameDownload: (shop: GameShop, objectId: string) => Promise<void>;
resumeGameDownload: (shop: GameShop, objectId: string) => Promise<void>;

View File

@@ -6,6 +6,7 @@ export interface ToastState {
title: string;
message?: string;
type: ToastProps["type"];
duration?: number;
visible: boolean;
}
@@ -13,6 +14,7 @@ const initialState: ToastState = {
title: "",
message: "",
type: "success",
duration: 5000,
visible: false,
};
@@ -24,6 +26,7 @@ export const toastSlice = createSlice({
state.title = action.payload.title;
state.message = action.payload.message;
state.type = action.payload.type;
state.duration = action.payload.duration ?? 5000;
state.visible = true;
},
closeToast: (state) => {

View File

@@ -29,10 +29,11 @@ export function useDownload() {
const startDownload = async (payload: StartGameDownloadPayload) => {
dispatch(clearDownload());
const game = await window.electron.startGameDownload(payload);
const response = await window.electron.startGameDownload(payload);
await updateLibrary();
return game;
if (response.ok) updateLibrary();
return response;
};
const pauseDownload = async (shop: GameShop, objectId: string) => {

View File

@@ -6,12 +6,13 @@ export function useToast() {
const dispatch = useAppDispatch();
const showSuccessToast = useCallback(
(title: string, message?: string) => {
(title: string, message?: string, duration?: number) => {
dispatch(
showToast({
title,
message,
type: "success",
duration,
})
);
},
@@ -19,12 +20,13 @@ export function useToast() {
);
const showErrorToast = useCallback(
(title: string, message?: string) => {
(title: string, message?: string, duration?: number) => {
dispatch(
showToast({
title,
message,
type: "error",
duration,
})
);
},
@@ -32,12 +34,13 @@ export function useToast() {
);
const showWarningToast = useCallback(
(title: string, message?: string) => {
(title: string, message?: string, duration?: number) => {
dispatch(
showToast({
title,
message,
type: "warning",
duration,
})
);
},

View File

@@ -8,7 +8,7 @@ import * as styles from "./downloads.css";
import { DeleteGameModal } from "./delete-game-modal";
import { DownloadGroup } from "./download-group";
import type { GameShop, LibraryGame, SeedingStatus } from "@types";
import { orderBy } from "lodash-es";
import { orderBy, sortBy } from "lodash-es";
import { ArrowDownIcon } from "@primer/octicons-react";
export default function Downloads() {
@@ -58,21 +58,24 @@ export default function Downloads() {
complete: [],
};
const result = library.reduce((prev, next) => {
/* Game has been manually added to the library or has been canceled */
if (!next.download?.status || next.download?.status === "removed")
return prev;
const result = sortBy(library, (game) => game.download?.timestamp).reduce(
(prev, next) => {
/* Game has been manually added to the library or has been canceled */
if (!next.download?.status || next.download?.status === "removed")
return prev;
/* Is downloading */
if (lastPacket?.gameId === next.id)
return { ...prev, downloading: [...prev.downloading, next] };
/* Is downloading */
if (lastPacket?.gameId === next.id)
return { ...prev, downloading: [...prev.downloading, next] };
/* Is either queued or paused */
if (next.download.queued || next.download?.status === "paused")
return { ...prev, queued: [...prev.queued, next] };
/* Is either queued or paused */
if (next.download.queued || next.download?.status === "paused")
return { ...prev, queued: [...prev.queued, next] };
return { ...prev, complete: [...prev.complete, next] };
}, initialValue);
return { ...prev, complete: [...prev.complete, next] };
},
initialValue
);
const queued = orderBy(result.queued, (game) => game.download?.timestamp, [
"desc",

View File

@@ -102,19 +102,23 @@ export default function GameDetails() {
downloader: Downloader,
downloadPath: string
) => {
await startDownload({
const response = await startDownload({
repackId: repack.id,
objectId: objectId!,
title: gameTitle,
downloader,
shop: shop as GameShop,
shop,
downloadPath,
uri: selectRepackUri(repack, downloader),
});
await updateGame();
setShowRepacksModal(false);
setShowGameOptionsModal(false);
if (response.ok) {
await updateGame();
setShowRepacksModal(false);
setShowGameOptionsModal(false);
}
return response;
};
const handleNSFWContentRefuse = () => {
@@ -123,10 +127,7 @@ export default function GameDetails() {
};
return (
<CloudSyncContextProvider
objectId={objectId!}
shop={shop! as GameShop}
>
<CloudSyncContextProvider objectId={objectId!} shop={shop}>
<CloudSyncContextConsumer>
{({
showCloudSyncModal,

View File

@@ -18,7 +18,7 @@ export interface DownloadSettingsModalProps {
repack: GameRepack,
downloader: Downloader,
downloadPath: string
) => Promise<void>;
) => Promise<{ ok: boolean; error?: string }>;
repack: GameRepack | null;
}
@@ -27,7 +27,7 @@ export function DownloadSettingsModal({
onClose,
startDownload,
repack,
}: DownloadSettingsModalProps) {
}: Readonly<DownloadSettingsModalProps>) {
const { t } = useTranslation("game_details");
const { showErrorToast } = useToast();
@@ -117,20 +117,30 @@ export function DownloadSettingsModal({
}
};
const handleStartClick = () => {
const handleStartClick = async () => {
if (repack) {
setDownloadStarting(true);
startDownload(repack, selectedDownloader!, selectedPath)
.then(() => {
try {
const response = await startDownload(
repack,
selectedDownloader!,
selectedPath
);
if (response.ok) {
onClose();
})
.catch((error) => {
showErrorToast(t("download_error"), error.message);
})
.finally(() => {
setDownloadStarting(false);
});
return;
} else if (response.error) {
showErrorToast(t("download_error"), t(response.error), 4_000);
}
} catch (error) {
if (error instanceof Error) {
showErrorToast(t("download_error"), error.message, 4_000);
}
} finally {
setDownloadStarting(false);
}
}
};

View File

@@ -19,7 +19,7 @@ export interface RepacksModalProps {
repack: GameRepack,
downloader: Downloader,
downloadPath: string
) => Promise<void>;
) => Promise<{ ok: boolean; error?: string }>;
onClose: () => void;
}
@@ -27,7 +27,7 @@ export function RepacksModal({
visible,
startDownload,
onClose,
}: RepacksModalProps) {
}: Readonly<RepacksModalProps>) {
const [filteredRepacks, setFilteredRepacks] = useState<GameRepack[]>([]);
const [repack, setRepack] = useState<GameRepack | null>(null);
const [showSelectFolderModal, setShowSelectFolderModal] = useState(false);
@@ -111,7 +111,7 @@ export function RepacksModal({
<p style={{ fontSize: "12px" }}>
{repack.fileSize} - {repack.repacker} -{" "}
{repack.uploadDate ? formatDate(repack.uploadDate!) : ""}
{repack.uploadDate ? formatDate(repack.uploadDate) : ""}
</p>
</Button>
);