From 939133fcc3b5b6a5974e314bb0bfe5f8059bf7bd Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Sat, 14 Sep 2024 15:29:52 -0300 Subject: [PATCH 1/2] feat: block executable 1:N game --- src/locales/en/translation.json | 4 +++- src/locales/pt-BR/translation.json | 4 +++- src/locales/pt-PT/translation.json | 4 +++- src/main/events/index.ts | 1 + src/main/events/library/verify-executable-path.ts | 13 +++++++++++++ src/preload/index.ts | 2 ++ src/renderer/src/declaration.d.ts | 1 + .../game-details/modals/game-options-modal.tsx | 13 +++++++++++-- 8 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 src/main/events/library/verify-executable-path.ts diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 73eadcd9..4b9bd61a 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -126,7 +126,9 @@ "stats": "Stats", "download_count": "Downloads", "player_count": "Active players", - "download_error": "This download option is not available" + "download_error": "This download option is not available", + "download": "Download", + "executable_path_in_use": "Executable already in use by \"{{game}}\"" }, "activation": { "title": "Activate Hydra", diff --git a/src/locales/pt-BR/translation.json b/src/locales/pt-BR/translation.json index ce5f4c6c..79d32ff7 100644 --- a/src/locales/pt-BR/translation.json +++ b/src/locales/pt-BR/translation.json @@ -122,7 +122,9 @@ "stats": "Estatísticas", "download_count": "Downloads", "player_count": "Jogadores ativos", - "download_error": "Essa opção de download falhou" + "download_error": "Essa opção de download falhou", + "download": "Baixar", + "executable_path_in_use": "Executável em uso por \"{{game}}\"" }, "activation": { "title": "Ativação", diff --git a/src/locales/pt-PT/translation.json b/src/locales/pt-PT/translation.json index cd4fc44c..f69ec184 100644 --- a/src/locales/pt-PT/translation.json +++ b/src/locales/pt-PT/translation.json @@ -111,7 +111,9 @@ "download_paused": "Transferência pausada", "last_downloaded_option": "Última opção transferida", "create_shortcut_success": "Atalho criado com sucesso", - "create_shortcut_error": "Erro ao criar atalho" + "create_shortcut_error": "Erro ao criar atalho", + "download": "Transferir", + "executable_path_in_use": "Executável em uso por \"{{game}}\"" }, "activation": { "title": "Ativação", diff --git a/src/main/events/index.ts b/src/main/events/index.ts index e271a19b..6c41f216 100644 --- a/src/main/events/index.ts +++ b/src/main/events/index.ts @@ -22,6 +22,7 @@ import "./library/open-game-executable-path"; import "./library/open-game-installer"; import "./library/open-game-installer-path"; import "./library/update-executable-path"; +import "./library/verify-executable-path"; import "./library/remove-game"; import "./library/remove-game-from-library"; import "./misc/open-external"; diff --git a/src/main/events/library/verify-executable-path.ts b/src/main/events/library/verify-executable-path.ts new file mode 100644 index 00000000..22295ac7 --- /dev/null +++ b/src/main/events/library/verify-executable-path.ts @@ -0,0 +1,13 @@ +import { gameRepository } from "@main/repository"; +import { registerEvent } from "../register-event"; + +const verifyExecutablePathInUse = async ( + _event: Electron.IpcMainInvokeEvent, + executablePath: string +) => { + return gameRepository.findOne({ + where: { executablePath }, + }); +}; + +registerEvent("verifyExecutablePathInUse", verifyExecutablePathInUse); diff --git a/src/preload/index.ts b/src/preload/index.ts index 51498d4f..bffdc5d4 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -75,6 +75,8 @@ contextBridge.exposeInMainWorld("electron", { ipcRenderer.invoke("createGameShortcut", id), updateExecutablePath: (id: number, executablePath: string) => ipcRenderer.invoke("updateExecutablePath", id, executablePath), + verifyExecutablePathInUse: (executablePath: string) => + ipcRenderer.invoke("verifyExecutablePathInUse", executablePath), getLibrary: () => ipcRenderer.invoke("getLibrary"), openGameInstaller: (gameId: number) => ipcRenderer.invoke("openGameInstaller", gameId), diff --git a/src/renderer/src/declaration.d.ts b/src/renderer/src/declaration.d.ts index 70d6d463..ee321408 100644 --- a/src/renderer/src/declaration.d.ts +++ b/src/renderer/src/declaration.d.ts @@ -71,6 +71,7 @@ declare global { ) => Promise; createGameShortcut: (id: number) => Promise; updateExecutablePath: (id: number, executablePath: string) => Promise; + verifyExecutablePathInUse: (executablePath: string) => Promise; getLibrary: () => Promise; openGameInstaller: (gameId: number) => Promise; openGameInstallerPath: (gameId: number) => Promise; diff --git a/src/renderer/src/pages/game-details/modals/game-options-modal.tsx b/src/renderer/src/pages/game-details/modals/game-options-modal.tsx index 313582fc..d1253318 100644 --- a/src/renderer/src/pages/game-details/modals/game-options-modal.tsx +++ b/src/renderer/src/pages/game-details/modals/game-options-modal.tsx @@ -57,8 +57,17 @@ export function GameOptionsModal({ const path = await selectGameExecutable(); if (path) { - await window.electron.updateExecutablePath(game.id, path); - updateGame(); + const gameUsingPath = + await window.electron.verifyExecutablePathInUse(path); + + if (gameUsingPath) { + showErrorToast( + t("executable_path_in_use", { game: gameUsingPath.title }) + ); + return; + } + + window.electron.updateExecutablePath(game.id, path).then(updateGame); } }; From e3fa4016672a936a539a13f0e7f0705ad97b4242 Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Sat, 14 Sep 2024 15:32:27 -0300 Subject: [PATCH 2/2] feat: show download button if game has no executable selected --- .../game-details/hero/hero-panel-actions.tsx | 68 +++++++++++++------ 1 file changed, 48 insertions(+), 20 deletions(-) diff --git a/src/renderer/src/pages/game-details/hero/hero-panel-actions.tsx b/src/renderer/src/pages/game-details/hero/hero-panel-actions.tsx index 795aa8af..323b3c8f 100644 --- a/src/renderer/src/pages/game-details/hero/hero-panel-actions.tsx +++ b/src/renderer/src/pages/game-details/hero/hero-panel-actions.tsx @@ -6,6 +6,7 @@ import { useTranslation } from "react-i18next"; import * as styles from "./hero-panel-actions.css"; import { gameDetailsContext } from "@renderer/context"; +import { DownloadIcon } from "@renderer/components/sidebar/download-icon"; export function HeroPanelActions() { const [toggleLibraryGameDisabled, setToggleLibraryGameDisabled] = @@ -25,6 +26,11 @@ export function HeroPanelActions() { selectGameExecutable, } = useContext(gameDetailsContext); + const { lastPacket } = useDownload(); + + const isGameDownloading = + game?.status === "active" && lastPacket?.game.id === game?.id; + const { updateLibrary } = useLibrary(); const { t } = useTranslation("game_details"); @@ -84,6 +90,47 @@ export function HeroPanelActions() { ); + const gameActionButton = () => { + if (isGameRunning) { + return ( + + ); + } + + if (game?.executablePath) { + return ( + + ); + } + + return ( + + ); + }; + if (repacks.length && !game) { return ( <> @@ -96,26 +143,7 @@ export function HeroPanelActions() { if (game) { return (
- {isGameRunning ? ( - - ) : ( - - )} + {gameActionButton()}