mirror of
https://github.com/hydralauncher/hydra.git
synced 2026-01-25 20:01:03 +00:00
Feat: Custom Games
This commit is contained in:
@@ -14,6 +14,8 @@ import "./catalogue/get-developers";
|
||||
import "./hardware/get-disk-free-space";
|
||||
import "./hardware/check-folder-write-permission";
|
||||
import "./library/add-game-to-library";
|
||||
import "./library/add-custom-game-to-library";
|
||||
import "./library/update-custom-game";
|
||||
import "./library/add-game-to-favorites";
|
||||
import "./library/remove-game-from-favorites";
|
||||
import "./library/create-game-shortcut";
|
||||
|
||||
68
src/main/events/library/add-custom-game-to-library.ts
Normal file
68
src/main/events/library/add-custom-game-to-library.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { registerEvent } from "../register-event";
|
||||
import {
|
||||
gamesSublevel,
|
||||
gamesShopAssetsSublevel,
|
||||
levelKeys,
|
||||
} from "@main/level";
|
||||
import { randomUUID } from "crypto";
|
||||
import type { GameShop } from "@types";
|
||||
|
||||
|
||||
const addCustomGameToLibrary = async (
|
||||
_event: Electron.IpcMainInvokeEvent,
|
||||
title: string,
|
||||
executablePath: string,
|
||||
iconUrl?: string,
|
||||
logoImageUrl?: string,
|
||||
libraryHeroImageUrl?: string
|
||||
) => {
|
||||
const objectId = randomUUID();
|
||||
const shop: GameShop = "custom";
|
||||
const gameKey = levelKeys.game(shop, objectId);
|
||||
|
||||
const existingGames = await gamesSublevel.iterator().all();
|
||||
const existingGame = existingGames.find(([_key, game]) =>
|
||||
game.executablePath === executablePath && !game.isDeleted
|
||||
);
|
||||
|
||||
if (existingGame) {
|
||||
throw new Error("A game with this executable path already exists in your library");
|
||||
}
|
||||
|
||||
const assets = {
|
||||
objectId,
|
||||
shop,
|
||||
title,
|
||||
iconUrl: iconUrl || null,
|
||||
libraryHeroImageUrl: libraryHeroImageUrl || "",
|
||||
libraryImageUrl: iconUrl || "",
|
||||
logoImageUrl: logoImageUrl || "",
|
||||
logoPosition: null,
|
||||
coverImageUrl: iconUrl || "",
|
||||
};
|
||||
await gamesShopAssetsSublevel.put(gameKey, assets);
|
||||
|
||||
const game = {
|
||||
title,
|
||||
iconUrl: iconUrl || null,
|
||||
logoImageUrl: logoImageUrl || null,
|
||||
libraryHeroImageUrl: libraryHeroImageUrl || null,
|
||||
objectId,
|
||||
shop,
|
||||
remoteId: null,
|
||||
isDeleted: false,
|
||||
playTimeInMilliseconds: 0,
|
||||
lastTimePlayed: null,
|
||||
executablePath,
|
||||
launchOptions: null,
|
||||
favorite: false,
|
||||
automaticCloudSync: false,
|
||||
hasManuallyUpdatedPlaytime: false,
|
||||
};
|
||||
|
||||
await gamesSublevel.put(gameKey, game);
|
||||
|
||||
return game;
|
||||
};
|
||||
|
||||
registerEvent("addCustomGameToLibrary", addCustomGameToLibrary);
|
||||
@@ -13,16 +13,20 @@ const changeGamePlaytime = async (
|
||||
const gameKey = levelKeys.game(shop, objectId);
|
||||
const game = await gamesSublevel.get(gameKey);
|
||||
if (!game) return;
|
||||
await HydraApi.put(`/profile/games/${shop}/${objectId}/playtime`, {
|
||||
playTimeInSeconds,
|
||||
});
|
||||
|
||||
if (game.remoteId) {
|
||||
await HydraApi.put(`/profile/games/${shop}/${objectId}/playtime`, {
|
||||
playTimeInSeconds,
|
||||
});
|
||||
}
|
||||
|
||||
await gamesSublevel.put(gameKey, {
|
||||
...game,
|
||||
playTimeInMilliseconds: playTimeInSeconds * 1000,
|
||||
hasManuallyUpdatedPlaytime: true,
|
||||
});
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to update game favorite status: ${error}`);
|
||||
throw new Error(`Failed to update game playtime: ${error}`);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
53
src/main/events/library/update-custom-game.ts
Normal file
53
src/main/events/library/update-custom-game.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { registerEvent } from "../register-event";
|
||||
import {
|
||||
gamesSublevel,
|
||||
gamesShopAssetsSublevel,
|
||||
levelKeys,
|
||||
} from "@main/level";
|
||||
import type { GameShop } from "@types";
|
||||
|
||||
const updateCustomGame = async (
|
||||
_event: Electron.IpcMainInvokeEvent,
|
||||
shop: GameShop,
|
||||
objectId: string,
|
||||
title: string,
|
||||
iconUrl?: string,
|
||||
logoImageUrl?: string,
|
||||
libraryHeroImageUrl?: string
|
||||
) => {
|
||||
const gameKey = levelKeys.game(shop, objectId);
|
||||
|
||||
const existingGame = await gamesSublevel.get(gameKey);
|
||||
if (!existingGame) {
|
||||
throw new Error("Game not found");
|
||||
}
|
||||
|
||||
const updatedGame = {
|
||||
...existingGame,
|
||||
title,
|
||||
iconUrl: iconUrl || null,
|
||||
logoImageUrl: logoImageUrl || null,
|
||||
libraryHeroImageUrl: libraryHeroImageUrl || null,
|
||||
};
|
||||
|
||||
await gamesSublevel.put(gameKey, updatedGame);
|
||||
|
||||
const existingAssets = await gamesShopAssetsSublevel.get(gameKey);
|
||||
if (existingAssets) {
|
||||
const updatedAssets = {
|
||||
...existingAssets,
|
||||
title,
|
||||
iconUrl: iconUrl || null,
|
||||
libraryHeroImageUrl: libraryHeroImageUrl || "",
|
||||
libraryImageUrl: iconUrl || "",
|
||||
logoImageUrl: logoImageUrl || "",
|
||||
coverImageUrl: iconUrl || "",
|
||||
};
|
||||
|
||||
await gamesShopAssetsSublevel.put(gameKey, updatedAssets);
|
||||
}
|
||||
|
||||
return updatedGame;
|
||||
};
|
||||
|
||||
registerEvent("updateCustomGame", updateCustomGame);
|
||||
Reference in New Issue
Block a user