mirror of
https://github.com/hydralauncher/hydra.git
synced 2026-01-31 14:51:02 +00:00
feat: add functionality to manage download queue with new actions and translations
This commit is contained in:
96
src/main/events/torrenting/add-game-to-queue.ts
Normal file
96
src/main/events/torrenting/add-game-to-queue.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
import { registerEvent } from "../register-event";
|
||||
import type { Download, StartGameDownloadPayload } from "@types";
|
||||
import { HydraApi, logger } from "@main/services";
|
||||
import { createGame } from "@main/services/library-sync";
|
||||
import {
|
||||
downloadsSublevel,
|
||||
gamesShopAssetsSublevel,
|
||||
gamesSublevel,
|
||||
levelKeys,
|
||||
} from "@main/level";
|
||||
|
||||
const addGameToQueue = async (
|
||||
_event: Electron.IpcMainInvokeEvent,
|
||||
payload: StartGameDownloadPayload
|
||||
) => {
|
||||
const {
|
||||
objectId,
|
||||
title,
|
||||
shop,
|
||||
downloadPath,
|
||||
downloader,
|
||||
uri,
|
||||
automaticallyExtract,
|
||||
} = payload;
|
||||
|
||||
const gameKey = levelKeys.game(shop, objectId);
|
||||
|
||||
const game = await gamesSublevel.get(gameKey);
|
||||
const gameAssets = await gamesShopAssetsSublevel.get(gameKey);
|
||||
|
||||
await downloadsSublevel.del(gameKey);
|
||||
|
||||
if (game) {
|
||||
await gamesSublevel.put(gameKey, {
|
||||
...game,
|
||||
isDeleted: false,
|
||||
});
|
||||
} else {
|
||||
await gamesSublevel.put(gameKey, {
|
||||
title,
|
||||
iconUrl: gameAssets?.iconUrl ?? null,
|
||||
libraryHeroImageUrl: gameAssets?.libraryHeroImageUrl ?? null,
|
||||
logoImageUrl: gameAssets?.logoImageUrl ?? null,
|
||||
objectId,
|
||||
shop,
|
||||
remoteId: null,
|
||||
playTimeInMilliseconds: 0,
|
||||
lastTimePlayed: null,
|
||||
isDeleted: false,
|
||||
});
|
||||
}
|
||||
|
||||
const download: Download = {
|
||||
shop,
|
||||
objectId,
|
||||
status: "paused",
|
||||
progress: 0,
|
||||
bytesDownloaded: 0,
|
||||
downloadPath,
|
||||
downloader,
|
||||
uri,
|
||||
folderName: null,
|
||||
fileSize: null,
|
||||
shouldSeed: false,
|
||||
timestamp: Date.now(),
|
||||
queued: true,
|
||||
extracting: false,
|
||||
automaticallyExtract,
|
||||
extractionProgress: 0,
|
||||
};
|
||||
|
||||
try {
|
||||
await downloadsSublevel.put(gameKey, download);
|
||||
|
||||
const updatedGame = await gamesSublevel.get(gameKey);
|
||||
|
||||
await Promise.all([
|
||||
createGame(updatedGame!).catch(() => {}),
|
||||
HydraApi.post(`/games/${shop}/${objectId}/download`, null, {
|
||||
needsAuth: false,
|
||||
}).catch(() => {}),
|
||||
]);
|
||||
|
||||
return { ok: true };
|
||||
} catch (err: unknown) {
|
||||
logger.error("Failed to add game to queue", err);
|
||||
|
||||
if (err instanceof Error) {
|
||||
return { ok: false, error: err.message };
|
||||
}
|
||||
|
||||
return { ok: false };
|
||||
}
|
||||
};
|
||||
|
||||
registerEvent("addGameToQueue", addGameToQueue);
|
||||
@@ -1,3 +1,4 @@
|
||||
import "./add-game-to-queue";
|
||||
import "./cancel-game-download";
|
||||
import "./check-debrid-availability";
|
||||
import "./pause-game-download";
|
||||
@@ -5,3 +6,4 @@ import "./pause-game-seed";
|
||||
import "./resume-game-download";
|
||||
import "./resume-game-seed";
|
||||
import "./start-game-download";
|
||||
import "./update-download-queue-position";
|
||||
|
||||
67
src/main/events/torrenting/update-download-queue-position.ts
Normal file
67
src/main/events/torrenting/update-download-queue-position.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { registerEvent } from "../register-event";
|
||||
import { downloadsSublevel, levelKeys } from "@main/level";
|
||||
import { GameShop } from "@types";
|
||||
import { orderBy } from "lodash-es";
|
||||
|
||||
const updateDownloadQueuePosition = async (
|
||||
_event: Electron.IpcMainInvokeEvent,
|
||||
shop: GameShop,
|
||||
objectId: string,
|
||||
direction: "up" | "down"
|
||||
) => {
|
||||
const gameKey = levelKeys.game(shop, objectId);
|
||||
|
||||
const download = await downloadsSublevel.get(gameKey);
|
||||
|
||||
if (!download || !download.queued || download.status !== "paused") {
|
||||
return false;
|
||||
}
|
||||
|
||||
const allDownloads = await downloadsSublevel.values().all();
|
||||
|
||||
const queuedDownloads = orderBy(
|
||||
allDownloads.filter((d) => d.status === "paused" && d.queued),
|
||||
"timestamp",
|
||||
"desc"
|
||||
);
|
||||
|
||||
const currentIndex = queuedDownloads.findIndex(
|
||||
(d) => d.shop === shop && d.objectId === objectId
|
||||
);
|
||||
|
||||
if (currentIndex === -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const targetIndex = direction === "up" ? currentIndex - 1 : currentIndex + 1;
|
||||
|
||||
if (targetIndex < 0 || targetIndex >= queuedDownloads.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const currentDownload = queuedDownloads[currentIndex];
|
||||
const adjacentDownload = queuedDownloads[targetIndex];
|
||||
|
||||
const currentKey = levelKeys.game(
|
||||
currentDownload.shop,
|
||||
currentDownload.objectId
|
||||
);
|
||||
const adjacentKey = levelKeys.game(
|
||||
adjacentDownload.shop,
|
||||
adjacentDownload.objectId
|
||||
);
|
||||
|
||||
const tempTimestamp = currentDownload.timestamp;
|
||||
await downloadsSublevel.put(currentKey, {
|
||||
...currentDownload,
|
||||
timestamp: adjacentDownload.timestamp,
|
||||
});
|
||||
await downloadsSublevel.put(adjacentKey, {
|
||||
...adjacentDownload,
|
||||
timestamp: tempTimestamp,
|
||||
});
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
registerEvent("updateDownloadQueuePosition", updateDownloadQueuePosition);
|
||||
Reference in New Issue
Block a user