diff --git a/src/main/events/library/remove-game-from-library.ts b/src/main/events/library/remove-game-from-library.ts index a9c0d272..438aa39a 100644 --- a/src/main/events/library/remove-game-from-library.ts +++ b/src/main/events/library/remove-game-from-library.ts @@ -1,7 +1,69 @@ import { registerEvent } from "../register-event"; import { HydraApi } from "@main/services"; import { gamesSublevel, gamesShopAssetsSublevel, levelKeys } from "@main/level"; -import type { GameShop } from "@types"; +import type { GameShop, Game } from "@types"; + +const collectAssetPathsToDelete = (game: Game): string[] => { + const assetPathsToDelete: string[] = []; + + const assetUrls = + game.shop === "custom" + ? [game.iconUrl, game.logoImageUrl, game.libraryHeroImageUrl] + : [ + game.customIconUrl, + game.customLogoImageUrl, + game.customHeroImageUrl, + ]; + + for (const url of assetUrls) { + if (url?.startsWith("local:")) { + assetPathsToDelete.push(url.replace("local:", "")); + } + } + + return assetPathsToDelete; +}; + +const updateGameAsDeleted = async (game: Game, gameKey: string): Promise => { + const updatedGame = { + ...game, + isDeleted: true, + executablePath: null, + ...(game.shop !== "custom" && { + customIconUrl: null, + customLogoImageUrl: null, + customHeroImageUrl: null, + }), + }; + + await gamesSublevel.put(gameKey, updatedGame); +}; + +const resetShopAssets = async (gameKey: string): Promise => { + const existingAssets = await gamesShopAssetsSublevel.get(gameKey); + if (existingAssets) { + const resetAssets = { + ...existingAssets, + title: existingAssets.title, + }; + await gamesShopAssetsSublevel.put(gameKey, resetAssets); + } +}; + +const deleteAssetFiles = async (assetPathsToDelete: string[]): Promise => { + if (assetPathsToDelete.length === 0) return; + + const fs = await import("node:fs"); + for (const assetPath of assetPathsToDelete) { + try { + if (fs.existsSync(assetPath)) { + await fs.promises.unlink(assetPath); + } + } catch (error) { + console.warn(`Failed to delete asset ${assetPath}:`, error); + } + } +}; const removeGameFromLibrary = async ( _event: Electron.IpcMainInvokeEvent, @@ -11,66 +73,21 @@ const removeGameFromLibrary = async ( const gameKey = levelKeys.game(shop, objectId); const game = await gamesSublevel.get(gameKey); - if (game) { - // Collect asset paths that need to be cleaned up before marking as deleted - const assetPathsToDelete: string[] = []; + if (!game) return; - const assetUrls = - game.shop === "custom" - ? [game.iconUrl, game.logoImageUrl, game.libraryHeroImageUrl] - : [ - game.customIconUrl, - game.customLogoImageUrl, - game.customHeroImageUrl, - ]; + const assetPathsToDelete = collectAssetPathsToDelete(game); + + await updateGameAsDeleted(game, gameKey); - for (const url of assetUrls) { - if (url?.startsWith("local:")) { - assetPathsToDelete.push(url.replace("local:", "")); - } - } - - const updatedGame = { - ...game, - isDeleted: true, - executablePath: null, - ...(game.shop !== "custom" && { - customIconUrl: null, - customLogoImageUrl: null, - customHeroImageUrl: null, - }), - }; - - await gamesSublevel.put(gameKey, updatedGame); - - if (game.shop !== "custom") { - const existingAssets = await gamesShopAssetsSublevel.get(gameKey); - if (existingAssets) { - const resetAssets = { - ...existingAssets, - title: existingAssets.title, - }; - await gamesShopAssetsSublevel.put(gameKey, resetAssets); - } - } - - if (game?.remoteId) { - HydraApi.delete(`/profile/games/${game.remoteId}`).catch(() => {}); - } - - if (assetPathsToDelete.length > 0) { - const fs = await import("node:fs"); - for (const assetPath of assetPathsToDelete) { - try { - if (fs.existsSync(assetPath)) { - await fs.promises.unlink(assetPath); - } - } catch (error) { - console.warn(`Failed to delete asset ${assetPath}:`, error); - } - } - } + if (game.shop !== "custom") { + await resetShopAssets(gameKey); } + + if (game?.remoteId) { + HydraApi.delete(`/profile/games/${game.remoteId}`).catch(() => {}); + } + + await deleteAssetFiles(assetPathsToDelete); }; registerEvent("removeGameFromLibrary", removeGameFromLibrary); diff --git a/src/main/events/library/update-game-custom-assets.ts b/src/main/events/library/update-game-custom-assets.ts index 4e86bbc0..2138af3a 100644 --- a/src/main/events/library/update-game-custom-assets.ts +++ b/src/main/events/library/update-game-custom-assets.ts @@ -1,23 +1,13 @@ import { registerEvent } from "../register-event"; import { gamesSublevel, gamesShopAssetsSublevel, levelKeys } from "@main/level"; -import type { GameShop } from "@types"; +import type { GameShop, Game } from "@types"; -const updateGameCustomAssets = async ( - _event: Electron.IpcMainInvokeEvent, - shop: GameShop, - objectId: string, - title: string, +const collectOldAssetPaths = ( + existingGame: Game, customIconUrl?: string | null, customLogoImageUrl?: string | null, customHeroImageUrl?: string | null -) => { - const gameKey = levelKeys.game(shop, objectId); - - const existingGame = await gamesSublevel.get(gameKey); - if (!existingGame) { - throw new Error("Game not found"); - } - +): string[] => { const oldAssetPaths: string[] = []; const assetPairs = [ @@ -37,6 +27,17 @@ const updateGameCustomAssets = async ( } } + return oldAssetPaths; +}; + +const updateGameData = async ( + gameKey: string, + existingGame: Game, + title: string, + customIconUrl?: string | null, + customLogoImageUrl?: string | null, + customHeroImageUrl?: string | null +): Promise => { const updatedGame = { ...existingGame, title, @@ -46,29 +47,70 @@ const updateGameCustomAssets = async ( }; await gamesSublevel.put(gameKey, updatedGame); + return updatedGame; +}; +const updateShopAssets = async (gameKey: string, title: string): Promise => { const existingAssets = await gamesShopAssetsSublevel.get(gameKey); if (existingAssets) { const updatedAssets = { ...existingAssets, title, }; - await gamesShopAssetsSublevel.put(gameKey, updatedAssets); } +}; - if (oldAssetPaths.length > 0) { - const fs = await import("node:fs"); - for (const assetPath of oldAssetPaths) { - try { - if (fs.existsSync(assetPath)) { - await fs.promises.unlink(assetPath); - } - } catch (error) { - console.warn(`Failed to delete old custom asset ${assetPath}:`, error); +const deleteOldAssetFiles = async (oldAssetPaths: string[]): Promise => { + if (oldAssetPaths.length === 0) return; + + const fs = await import("node:fs"); + for (const assetPath of oldAssetPaths) { + try { + if (fs.existsSync(assetPath)) { + await fs.promises.unlink(assetPath); } + } catch (error) { + console.warn(`Failed to delete old custom asset ${assetPath}:`, error); } } +}; + +const updateGameCustomAssets = async ( + _event: Electron.IpcMainInvokeEvent, + shop: GameShop, + objectId: string, + title: string, + customIconUrl?: string | null, + customLogoImageUrl?: string | null, + customHeroImageUrl?: string | null +) => { + const gameKey = levelKeys.game(shop, objectId); + + const existingGame = await gamesSublevel.get(gameKey); + if (!existingGame) { + throw new Error("Game not found"); + } + + const oldAssetPaths = collectOldAssetPaths( + existingGame, + customIconUrl, + customLogoImageUrl, + customHeroImageUrl + ); + + const updatedGame = await updateGameData( + gameKey, + existingGame, + title, + customIconUrl, + customLogoImageUrl, + customHeroImageUrl + ); + + await updateShopAssets(gameKey, title); + + await deleteOldAssetFiles(oldAssetPaths); return updatedGame; };