refactor: change game delete to soft delete

This commit is contained in:
JackEnx 2024-04-21 16:36:34 -03:00
parent 8343b66d67
commit 797f5ee0d8
17 changed files with 115 additions and 44 deletions

View File

@ -61,6 +61,9 @@ export class Game {
@JoinColumn() @JoinColumn()
repack: Repack; repack: Repack;
@Column("boolean", { default: false })
isDeleted: boolean;
@CreateDateColumn() @CreateDateColumn()
createdAt: Date; createdAt: Date;

View File

@ -10,13 +10,13 @@ import "./catalogue/search-games";
import "./hardware/get-disk-free-space"; import "./hardware/get-disk-free-space";
import "./library/add-game-to-library"; import "./library/add-game-to-library";
import "./library/close-game"; import "./library/close-game";
import "./library/delete-game-folder"; import "./torrenting/delete-game-folder";
import "./library/get-game-by-object-id"; import "./library/get-game-by-object-id";
import "./library/get-library"; import "./library/get-library";
import "./library/get-repackers-friendly-names"; import "./library/get-repackers-friendly-names";
import "./library/open-game"; import "./library/open-game";
import "./library/open-game-installer"; import "./library/open-game-installer";
import "./library/remove-game"; import "./library/remove-game-from-library";
import "./misc/get-or-cache-image"; import "./misc/get-or-cache-image";
import "./misc/open-external"; import "./misc/open-external";
import "./misc/show-open-dialog"; import "./misc/show-open-dialog";
@ -24,6 +24,7 @@ import "./torrenting/cancel-game-download";
import "./torrenting/pause-game-download"; import "./torrenting/pause-game-download";
import "./torrenting/resume-game-download"; import "./torrenting/resume-game-download";
import "./torrenting/start-game-download"; import "./torrenting/start-game-download";
import "./torrenting/remove-game-from-download";
import "./user-preferences/get-user-preferences"; import "./user-preferences/get-user-preferences";
import "./user-preferences/update-user-preferences"; import "./user-preferences/update-user-preferences";

View File

@ -13,15 +13,34 @@ const addGameToLibrary = async (
gameShop: GameShop, gameShop: GameShop,
executablePath: string executablePath: string
) => { ) => {
const iconUrl = await getImageBase64(await getSteamGameIconUrl(objectID)); const game = await gameRepository.findOne({
where: {
return gameRepository.insert({ objectID,
title, },
iconUrl,
objectID,
shop: gameShop,
executablePath,
}); });
if (game) {
return gameRepository.update(
{
id: game.id,
},
{
shop: gameShop,
executablePath,
isDeleted: false,
}
);
} else {
const iconUrl = await getImageBase64(await getSteamGameIconUrl(objectID));
return gameRepository.insert({
title,
iconUrl,
objectID,
shop: gameShop,
executablePath,
});
}
}; };
registerEvent(addGameToLibrary, { registerEvent(addGameToLibrary, {

View File

@ -9,6 +9,7 @@ const getGameByObjectID = async (
gameRepository.findOne({ gameRepository.findOne({
where: { where: {
objectID, objectID,
isDeleted: false,
}, },
relations: { relations: {
repack: true, repack: true,

View File

@ -8,6 +8,9 @@ import sortBy from "lodash/sortBy";
const getLibrary = async (_event: Electron.IpcMainInvokeEvent) => const getLibrary = async (_event: Electron.IpcMainInvokeEvent) =>
gameRepository gameRepository
.find({ .find({
where: {
isDeleted: false,
},
order: { order: {
createdAt: "desc", createdAt: "desc",
}, },

View File

@ -0,0 +1,13 @@
import { registerEvent } from "../register-event";
import { gameRepository } from "../../repository";
const removeGameFromLibrary = async (
_event: Electron.IpcMainInvokeEvent,
gameId: number
) => {
gameRepository.update({ id: gameId }, { isDeleted: true });
};
registerEvent(removeGameFromLibrary, {
name: "removeGameFromLibrary",
});

View File

@ -1,11 +0,0 @@
import { registerEvent } from "../register-event";
import { gameRepository } from "../../repository";
const removeGame = async (
_event: Electron.IpcMainInvokeEvent,
gameId: number
) => gameRepository.delete({ id: gameId });
registerEvent(removeGame, {
name: "removeGame",
});

View File

@ -25,14 +25,13 @@ const cancelGameDownload = async (
if (!game) return; if (!game) return;
gameRepository await gameRepository
.update( .update(
{ {
id: game.id, id: game.id,
}, },
{ {
status: GameStatus.Cancelled, status: GameStatus.Cancelled,
downloadPath: null,
bytesDownloaded: 0, bytesDownloaded: 0,
progress: 0, progress: 0,
} }

View File

@ -22,7 +22,10 @@ const deleteGameFolder = async (
if (!game) return; if (!game) return;
if (game.folderName) { if (game.folderName) {
const folderPath = path.join(await getDownloadsPath(), game.folderName); const folderPath = path.join(
game.downloadPath ?? (await getDownloadsPath()),
game.folderName
);
if (fs.existsSync(folderPath)) { if (fs.existsSync(folderPath)) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {

View File

@ -0,0 +1,34 @@
import { GameStatus } from "@main/constants";
import { gameRepository } from "@main/repository";
import { registerEvent } from "../register-event";
const removeGameFromDownload = async (
_event: Electron.IpcMainInvokeEvent,
gameId: number
) => {
const game = await gameRepository.findOne({
where: {
id: gameId,
status: GameStatus.Cancelled,
},
});
if (!game) return;
gameRepository.update(
{
id: game.id,
},
{
status: null,
downloadPath: null,
bytesDownloaded: 0,
progress: 0,
}
);
};
registerEvent(removeGameFromDownload, {
name: "removeGameFromDownload",
});

View File

@ -59,6 +59,7 @@ const startGameDownload = async (
status: GameStatus.DownloadingMetadata, status: GameStatus.DownloadingMetadata,
downloadPath: downloadsPath, downloadPath: downloadsPath,
repack: { id: repackId }, repack: { id: repackId },
isDeleted: false,
} }
); );
@ -71,13 +72,6 @@ const startGameDownload = async (
game.status = GameStatus.DownloadingMetadata; game.status = GameStatus.DownloadingMetadata;
writePipe.write({
action: "start",
game_id: game.id,
magnet: repack.magnet,
save_path: downloadsPath,
});
return game; return game;
} else { } else {
const iconUrl = await getImageBase64(await getSteamGameIconUrl(objectID)); const iconUrl = await getImageBase64(await getSteamGameIconUrl(objectID));

View File

@ -71,7 +71,10 @@ contextBridge.exposeInMainWorld("electron", {
openGame: (gameId: number, executablePath: string) => openGame: (gameId: number, executablePath: string) =>
ipcRenderer.invoke("openGame", gameId, executablePath), ipcRenderer.invoke("openGame", gameId, executablePath),
closeGame: (gameId: number) => ipcRenderer.invoke("closeGame", gameId), closeGame: (gameId: number) => ipcRenderer.invoke("closeGame", gameId),
removeGame: (gameId: number) => ipcRenderer.invoke("removeGame", gameId), removeGameFromLibrary: (gameId: number) =>
ipcRenderer.invoke("removeGameFromLibrary", gameId),
removeGameFromDownload: (gameId: number) =>
ipcRenderer.invoke("removeGameFromDownload", gameId),
deleteGameFolder: (gameId: number) => deleteGameFolder: (gameId: number) =>
ipcRenderer.invoke("deleteGameFolder", gameId), ipcRenderer.invoke("deleteGameFolder", gameId),
getGameByObjectID: (objectID: string) => getGameByObjectID: (objectID: string) =>

View File

@ -62,7 +62,8 @@ declare global {
openGameInstaller: (gameId: number) => Promise<boolean>; openGameInstaller: (gameId: number) => Promise<boolean>;
openGame: (gameId: number, executablePath: string) => Promise<void>; openGame: (gameId: number, executablePath: string) => Promise<void>;
closeGame: (gameId: number) => Promise<boolean>; closeGame: (gameId: number) => Promise<boolean>;
removeGame: (gameId: number) => Promise<void>; removeGameFromLibrary: (gameId: number) => Promise<void>;
removeGameFromDownload: (gameId: number) => Promise<vodi>;
deleteGameFolder: (gameId: number) => Promise<unknown>; deleteGameFolder: (gameId: number) => Promise<unknown>;
getGameByObjectID: (objectID: string) => Promise<Game | null>; getGameByObjectID: (objectID: string) => Promise<Game | null>;
onPlaytime: (cb: (gameId: number) => void) => () => Electron.IpcRenderer; onPlaytime: (cb: (gameId: number) => void) => () => Electron.IpcRenderer;

View File

@ -57,8 +57,8 @@ export function useDownload() {
deleteGame(gameId); deleteGame(gameId);
}); });
const removeGame = (gameId: number) => const removeGameFromDownload = (gameId: number) =>
window.electron.removeGame(gameId).then(() => { window.electron.removeGameFromDownload(gameId).then(() => {
updateLibrary(); updateLibrary();
}); });
@ -123,7 +123,7 @@ export function useDownload() {
pauseDownload, pauseDownload,
resumeDownload, resumeDownload,
cancelDownload, cancelDownload,
removeGame, removeGameFromDownload,
deleteGame, deleteGame,
isGameDeleting, isGameDeleting,
clearDownload: () => dispatch(clearDownload()), clearDownload: () => dispatch(clearDownload()),

View File

@ -12,5 +12,10 @@ export function useLibrary() {
.then((updatedLibrary) => dispatch(setLibrary(updatedLibrary))); .then((updatedLibrary) => dispatch(setLibrary(updatedLibrary)));
}, [dispatch]); }, [dispatch]);
return { library, updateLibrary }; const removeGameFromLibrary = (gameId: number) =>
window.electron.removeGameFromLibrary(gameId).then(() => {
updateLibrary();
});
return { library, updateLibrary, removeGameFromLibrary };
} }

View File

@ -52,8 +52,8 @@ export function Downloads() {
updateLibrary(); updateLibrary();
}); });
const removeGame = (gameId: number) => const removeGameFromDownload = (gameId: number) =>
window.electron.removeGame(gameId).then(() => { window.electron.removeGameFromDownload(gameId).then(() => {
updateLibrary(); updateLibrary();
}); });
@ -194,7 +194,7 @@ export function Downloads() {
</Button> </Button>
<Button <Button
onClick={() => removeGame(game.id)} onClick={() => removeGameFromDownload(game.id)}
theme="outline" theme="outline"
disabled={deleting} disabled={deleting}
> >

View File

@ -32,11 +32,11 @@ export function HeroPanelActions({
resumeDownload, resumeDownload,
pauseDownload, pauseDownload,
cancelDownload, cancelDownload,
removeGame, removeGameFromDownload,
isGameDeleting, isGameDeleting,
} = useDownload(); } = useDownload();
const { updateLibrary } = useLibrary(); const { updateLibrary, removeGameFromLibrary } = useLibrary();
const { t } = useTranslation("game_details"); const { t } = useTranslation("game_details");
@ -63,7 +63,7 @@ export function HeroPanelActions({
try { try {
if (game) { if (game) {
await removeGame(game.id); await removeGameFromLibrary(game.id);
} else { } else {
const gameExecutablePath = await selectGameExecutable(); const gameExecutablePath = await selectGameExecutable();
@ -101,6 +101,9 @@ export function HeroPanelActions({
} }
const gameExecutablePath = await selectGameExecutable(); const gameExecutablePath = await selectGameExecutable();
if (!gameExecutablePath) return;
window.electron.openGame(game.id, gameExecutablePath); window.electron.openGame(game.id, gameExecutablePath);
}; };
@ -187,7 +190,7 @@ export function HeroPanelActions({
{t("open_download_options")} {t("open_download_options")}
</Button> </Button>
<Button <Button
onClick={() => removeGame(game.id).then(getGame)} onClick={() => removeGameFromDownload(game.id).then(getGame)}
theme="outline" theme="outline"
disabled={deleting} disabled={deleting}
> >