mirror of
https://github.com/hydralauncher/hydra.git
synced 2026-01-11 22:06:17 +00:00
feat: proper cleanup of unused assets
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { registerEvent } from "../register-event";
|
||||
import { HydraApi } from "@main/services";
|
||||
import { gamesSublevel, levelKeys } from "@main/level";
|
||||
import { gamesSublevel, gamesShopAssetsSublevel, levelKeys } from "@main/level";
|
||||
import type { GameShop } from "@types";
|
||||
|
||||
const removeGameFromLibrary = async (
|
||||
@@ -12,15 +12,62 @@ const removeGameFromLibrary = async (
|
||||
const game = await gamesSublevel.get(gameKey);
|
||||
|
||||
if (game) {
|
||||
await gamesSublevel.put(gameKey, {
|
||||
// Collect asset paths that need to be cleaned up before marking as deleted
|
||||
const assetPathsToDelete: string[] = [];
|
||||
|
||||
const assetUrls = game.shop === "custom"
|
||||
? [game.iconUrl, game.logoImageUrl, game.libraryHeroImageUrl]
|
||||
: [game.customIconUrl, game.customLogoImageUrl, game.customHeroImageUrl];
|
||||
|
||||
assetUrls.forEach(url => {
|
||||
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("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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -18,6 +18,30 @@ const updateCustomGame = async (
|
||||
throw new Error("Game not found");
|
||||
}
|
||||
|
||||
// Collect old asset paths that will be replaced
|
||||
const oldAssetPaths: string[] = [];
|
||||
|
||||
if (existingGame.iconUrl && iconUrl && existingGame.iconUrl !== iconUrl && existingGame.iconUrl.startsWith("local:")) {
|
||||
oldAssetPaths.push(existingGame.iconUrl.replace("local:", ""));
|
||||
}
|
||||
if (existingGame.iconUrl && !iconUrl && existingGame.iconUrl.startsWith("local:")) {
|
||||
oldAssetPaths.push(existingGame.iconUrl.replace("local:", ""));
|
||||
}
|
||||
|
||||
if (existingGame.logoImageUrl && logoImageUrl && existingGame.logoImageUrl !== logoImageUrl && existingGame.logoImageUrl.startsWith("local:")) {
|
||||
oldAssetPaths.push(existingGame.logoImageUrl.replace("local:", ""));
|
||||
}
|
||||
if (existingGame.logoImageUrl && !logoImageUrl && existingGame.logoImageUrl.startsWith("local:")) {
|
||||
oldAssetPaths.push(existingGame.logoImageUrl.replace("local:", ""));
|
||||
}
|
||||
|
||||
if (existingGame.libraryHeroImageUrl && libraryHeroImageUrl && existingGame.libraryHeroImageUrl !== libraryHeroImageUrl && existingGame.libraryHeroImageUrl.startsWith("local:")) {
|
||||
oldAssetPaths.push(existingGame.libraryHeroImageUrl.replace("local:", ""));
|
||||
}
|
||||
if (existingGame.libraryHeroImageUrl && !libraryHeroImageUrl && existingGame.libraryHeroImageUrl.startsWith("local:")) {
|
||||
oldAssetPaths.push(existingGame.libraryHeroImageUrl.replace("local:", ""));
|
||||
}
|
||||
|
||||
const updatedGame = {
|
||||
...existingGame,
|
||||
title,
|
||||
@@ -43,6 +67,20 @@ const updateCustomGame = async (
|
||||
await gamesShopAssetsSublevel.put(gameKey, updatedAssets);
|
||||
}
|
||||
|
||||
// Manually delete specific old asset files instead of running full cleanup
|
||||
if (oldAssetPaths.length > 0) {
|
||||
const fs = await import("fs");
|
||||
for (const assetPath of oldAssetPaths) {
|
||||
try {
|
||||
if (fs.existsSync(assetPath)) {
|
||||
await fs.promises.unlink(assetPath);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn(`Failed to delete old asset ${assetPath}:`, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return updatedGame;
|
||||
};
|
||||
|
||||
|
||||
@@ -18,6 +18,21 @@ const updateGameCustomAssets = async (
|
||||
throw new Error("Game not found");
|
||||
}
|
||||
|
||||
// Collect old custom asset paths that will be replaced
|
||||
const oldAssetPaths: string[] = [];
|
||||
|
||||
const assetPairs = [
|
||||
{ existing: existingGame.customIconUrl, new: customIconUrl },
|
||||
{ existing: existingGame.customLogoImageUrl, new: customLogoImageUrl },
|
||||
{ existing: existingGame.customHeroImageUrl, new: customHeroImageUrl }
|
||||
];
|
||||
|
||||
assetPairs.forEach(({ existing, new: newUrl }) => {
|
||||
if (existing && newUrl !== undefined && existing !== newUrl && existing.startsWith("local:")) {
|
||||
oldAssetPaths.push(existing.replace("local:", ""));
|
||||
}
|
||||
});
|
||||
|
||||
const updatedGame = {
|
||||
...existingGame,
|
||||
title,
|
||||
@@ -39,6 +54,20 @@ const updateGameCustomAssets = async (
|
||||
await gamesShopAssetsSublevel.put(gameKey, updatedAssets);
|
||||
}
|
||||
|
||||
// Manually delete specific old custom asset files instead of running full cleanup
|
||||
if (oldAssetPaths.length > 0) {
|
||||
const fs = await import("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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return updatedGame;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user