From 47a5f4d32762f2f43ca0ebfd6251862e62d4f3a8 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Tue, 17 Dec 2024 11:10:25 -0300 Subject: [PATCH 01/26] feat: add reset achievements modal --- src/locales/en/translation.json | 5 +- src/locales/pt-BR/translation.json | 5 +- .../modals/game-options-modal.tsx | 19 ++++++++ .../modals/reset-achievements-modal.tsx | 46 +++++++++++++++++++ 4 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 src/renderer/src/pages/game-details/modals/reset-achievements-modal.tsx diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 940e3185..f2adae8b 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -168,7 +168,10 @@ "select_folder": "Select folder", "backup_from": "Backup from {{date}}", "custom_backup_location_set": "Custom backup location set", - "no_directory_selected": "No directory selected" + "no_directory_selected": "No directory selected", + "reset_achievements": "Reset achievements", + "reset_achievements_description": "This will reset all achievements for {{game}}", + "reset_achievements_title": "Are you sure?" }, "activation": { "title": "Activate Hydra", diff --git a/src/locales/pt-BR/translation.json b/src/locales/pt-BR/translation.json index e724cdc3..30d8f322 100644 --- a/src/locales/pt-BR/translation.json +++ b/src/locales/pt-BR/translation.json @@ -164,7 +164,10 @@ "select_folder": "Selecione a pasta", "manage_files_description": "Gerencie quais arquivos serão feitos backup", "clear": "Limpar", - "no_directory_selected": "Nenhum diretório selecionado" + "no_directory_selected": "Nenhum diretório selecionado", + "reset_achievements": "Resetar conquistas", + "reset_achievements_description": "Isso irá resetar todas as conquistas de {{game}}", + "reset_achievements_title": "Tem certeza?" }, "activation": { "title": "Ativação", 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 e5c83ec4..0d1fdc2c 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 @@ -7,6 +7,7 @@ import { gameDetailsContext } from "@renderer/context"; import { DeleteGameModal } from "@renderer/pages/downloads/delete-game-modal"; import { useDownload, useToast } from "@renderer/hooks"; import { RemoveGameFromLibraryModal } from "./remove-from-library-modal"; +import { ResetAchievementsModal } from "./reset-achievements-modal"; import { FileDirectoryIcon, FileIcon } from "@primer/octicons-react"; export interface GameOptionsModalProps { @@ -29,6 +30,8 @@ export function GameOptionsModal({ const [showDeleteModal, setShowDeleteModal] = useState(false); const [showRemoveGameModal, setShowRemoveGameModal] = useState(false); + const [showResetAchievementsModal, setShowResetAchievementsModal] = + useState(false); const { removeGameInstaller, @@ -134,6 +137,13 @@ export function GameOptionsModal({ game={game} /> + setShowResetAchievementsModal(false)} + // resetAchievements={handleResetAchievements} + game={game} + /> + {t("remove_from_library")} + + + + + + + + ); +} From ac6eb247df4cfe5d57172bc10fbda0ccefbc31b1 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Tue, 17 Dec 2024 13:15:55 -0300 Subject: [PATCH 02/26] feat: implement reset game achievements functionality --- src/main/events/index.ts | 1 + .../events/library/reset-game-achievements.ts | 52 +++++++++++++++++++ src/preload/index.ts | 2 + src/renderer/src/declaration.d.ts | 2 +- .../modals/game-options-modal.tsx | 7 ++- .../modals/reset-achievements-modal.tsx | 6 +-- 6 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 src/main/events/library/reset-game-achievements.ts diff --git a/src/main/events/index.ts b/src/main/events/index.ts index eff62531..e26ed91c 100644 --- a/src/main/events/index.ts +++ b/src/main/events/index.ts @@ -25,6 +25,7 @@ import "./library/verify-executable-path"; import "./library/remove-game"; import "./library/remove-game-from-library"; import "./library/select-game-wine-prefix"; +import "./library/reset-game-achievements"; import "./misc/open-checkout"; import "./misc/open-external"; import "./misc/show-open-dialog"; diff --git a/src/main/events/library/reset-game-achievements.ts b/src/main/events/library/reset-game-achievements.ts new file mode 100644 index 00000000..7780c3ed --- /dev/null +++ b/src/main/events/library/reset-game-achievements.ts @@ -0,0 +1,52 @@ +import { gameAchievementRepository, gameRepository } from "@main/repository"; +import { registerEvent } from "../register-event"; +import { findAchievementFiles } from "@main/services/achievements/find-achivement-files"; +import fs from "fs"; +import { WindowManager } from "@main/services"; +import { getUnlockedAchievements } from "../user/get-unlocked-achievements"; + +const resetGameAchievements = async ( + _event: Electron.IpcMainInvokeEvent, + gameId: number +) => { + const game = await gameRepository.findOne({ where: { id: gameId } }); + + if (!game) return; + + const achievementFiles = findAchievementFiles(game); + + if (achievementFiles.length) { + try { + await Promise.all( + achievementFiles.map(async (achievementFile) => { + await fs.promises.rm(achievementFile.filePath, { recursive: true }); + }) + ); + } catch (error) { + console.error(error); + } + } + + await gameAchievementRepository.update( + { objectId: game.objectID }, + { + unlockedAchievements: null, + achievements: null, + } + ); + + // TODO: remove from db + + const gameAchievements = await getUnlockedAchievements( + game.objectID, + game.shop, + false + ); + + WindowManager.mainWindow?.webContents.send( + `on-update-achievements-${game.objectID}-${game.shop}`, + gameAchievements + ); +}; + +registerEvent("resetGameAchievements", resetGameAchievements); diff --git a/src/preload/index.ts b/src/preload/index.ts index f9d19644..d100228f 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -110,6 +110,8 @@ contextBridge.exposeInMainWorld("electron", { ipcRenderer.invoke("deleteGameFolder", gameId), getGameByObjectId: (objectId: string) => ipcRenderer.invoke("getGameByObjectId", objectId), + resetGameAchievements: (gameId: number) => + ipcRenderer.invoke("resetGameAchievements", gameId), onGamesRunning: ( cb: ( gamesRunning: Pick[] diff --git a/src/renderer/src/declaration.d.ts b/src/renderer/src/declaration.d.ts index 93c423e0..343c3ffe 100644 --- a/src/renderer/src/declaration.d.ts +++ b/src/renderer/src/declaration.d.ts @@ -105,7 +105,7 @@ declare global { ) => void ) => () => Electron.IpcRenderer; onLibraryBatchComplete: (cb: () => void) => () => Electron.IpcRenderer; - + resetGameAchievements: (gameId: number) => Promise; /* User preferences */ getUserPreferences: () => Promise; updateUserPreferences: ( 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 0d1fdc2c..c4592e13 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 @@ -122,6 +122,11 @@ export function GameOptionsModal({ const shouldShowWinePrefixConfiguration = window.electron.platform === "linux"; + const handleResetAchievements = async () => { + await window.electron.resetGameAchievements(game.id); + updateGame(); + }; + return ( <> setShowResetAchievementsModal(false)} - // resetAchievements={handleResetAchievements} + resetAchievements={handleResetAchievements} game={game} /> diff --git a/src/renderer/src/pages/game-details/modals/reset-achievements-modal.tsx b/src/renderer/src/pages/game-details/modals/reset-achievements-modal.tsx index 409fedbe..d8861076 100644 --- a/src/renderer/src/pages/game-details/modals/reset-achievements-modal.tsx +++ b/src/renderer/src/pages/game-details/modals/reset-achievements-modal.tsx @@ -7,19 +7,19 @@ interface ResetAchievementsModalProps { visible: boolean; game: Game; onClose: () => void; -// resetAchievements: () => Promise; + resetAchievements: () => Promise; } export function ResetAchievementsModal({ onClose, game, visible, -// resetAchievements, + resetAchievements, }: ResetAchievementsModalProps) { const { t } = useTranslation("game_details"); const handleResetAchievements = async () => { - // await resetAchievements(); + await resetAchievements(); onClose(); }; From afcfcbf4828314fd09ec886e37881c8d4e8d8ed8 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Tue, 17 Dec 2024 13:55:45 -0300 Subject: [PATCH 03/26] refactor: clean up reset game achievements logic --- src/main/events/library/reset-game-achievements.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/events/library/reset-game-achievements.ts b/src/main/events/library/reset-game-achievements.ts index 7780c3ed..25344076 100644 --- a/src/main/events/library/reset-game-achievements.ts +++ b/src/main/events/library/reset-game-achievements.ts @@ -31,7 +31,6 @@ const resetGameAchievements = async ( { objectId: game.objectID }, { unlockedAchievements: null, - achievements: null, } ); @@ -40,7 +39,7 @@ const resetGameAchievements = async ( const gameAchievements = await getUnlockedAchievements( game.objectID, game.shop, - false + true ); WindowManager.mainWindow?.webContents.send( From bfdc2787d46dd24487bd24d31d8de1349ca3a0a6 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Thu, 2 Jan 2025 06:14:56 -0300 Subject: [PATCH 04/26] feat: remove hame achievements from remote db --- src/main/events/library/reset-game-achievements.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/events/library/reset-game-achievements.ts b/src/main/events/library/reset-game-achievements.ts index 25344076..2a1dc11d 100644 --- a/src/main/events/library/reset-game-achievements.ts +++ b/src/main/events/library/reset-game-achievements.ts @@ -4,6 +4,7 @@ import { findAchievementFiles } from "@main/services/achievements/find-achivemen import fs from "fs"; import { WindowManager } from "@main/services"; import { getUnlockedAchievements } from "../user/get-unlocked-achievements"; +import { HydraApi } from "@main/services/hydra-api"; const resetGameAchievements = async ( _event: Electron.IpcMainInvokeEvent, @@ -34,7 +35,11 @@ const resetGameAchievements = async ( } ); - // TODO: remove from db + try { + await HydraApi.delete(`/profile/games/${game.remoteId}/achievements`); + } catch (error) { + console.error(error); + } const gameAchievements = await getUnlockedAchievements( game.objectID, From 10766526c51b6910765bf720454812374e628755 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Thu, 2 Jan 2025 06:28:32 -0300 Subject: [PATCH 05/26] refactor: streamline resetGameAchievements with a single try catch --- .../events/library/reset-game-achievements.ts | 49 +++++++++---------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/src/main/events/library/reset-game-achievements.ts b/src/main/events/library/reset-game-achievements.ts index 2a1dc11d..ca858460 100644 --- a/src/main/events/library/reset-game-achievements.ts +++ b/src/main/events/library/reset-game-achievements.ts @@ -10,47 +10,44 @@ const resetGameAchievements = async ( _event: Electron.IpcMainInvokeEvent, gameId: number ) => { - const game = await gameRepository.findOne({ where: { id: gameId } }); + try { + const game = await gameRepository.findOne({ where: { id: gameId } }); - if (!game) return; + if (!game) return; - const achievementFiles = findAchievementFiles(game); + const achievementFiles = findAchievementFiles(game); - if (achievementFiles.length) { - try { + if (achievementFiles.length) { await Promise.all( achievementFiles.map(async (achievementFile) => { await fs.promises.rm(achievementFile.filePath, { recursive: true }); }) ); - } catch (error) { - console.error(error); } - } - await gameAchievementRepository.update( - { objectId: game.objectID }, - { - unlockedAchievements: null, - } - ); + await gameAchievementRepository.update( + { objectId: game.objectID }, + { + unlockedAchievements: null, + } + ); - try { await HydraApi.delete(`/profile/games/${game.remoteId}/achievements`); + + const gameAchievements = await getUnlockedAchievements( + game.objectID, + game.shop, + true + ); + + WindowManager.mainWindow?.webContents.send( + `on-update-achievements-${game.objectID}-${game.shop}`, + gameAchievements + ); + } catch (error) { console.error(error); } - - const gameAchievements = await getUnlockedAchievements( - game.objectID, - game.shop, - true - ); - - WindowManager.mainWindow?.webContents.send( - `on-update-achievements-${game.objectID}-${game.shop}`, - gameAchievements - ); }; registerEvent("resetGameAchievements", resetGameAchievements); From addc2a74d32761d4679cb93d58cda1802d11b5d8 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Thu, 2 Jan 2025 06:28:45 -0300 Subject: [PATCH 06/26] lint --- src/main/events/library/reset-game-achievements.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/events/library/reset-game-achievements.ts b/src/main/events/library/reset-game-achievements.ts index ca858460..5d16f270 100644 --- a/src/main/events/library/reset-game-achievements.ts +++ b/src/main/events/library/reset-game-achievements.ts @@ -44,7 +44,6 @@ const resetGameAchievements = async ( `on-update-achievements-${game.objectID}-${game.shop}`, gameAchievements ); - } catch (error) { console.error(error); } From 9849fbb31ce39f97d9cd5d0f29e270baaf72134c Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Thu, 2 Jan 2025 06:36:55 -0300 Subject: [PATCH 07/26] refactor: change ResetAchievementsModalProps to use Readonly type for better immutability --- .../pages/game-details/modals/reset-achievements-modal.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/renderer/src/pages/game-details/modals/reset-achievements-modal.tsx b/src/renderer/src/pages/game-details/modals/reset-achievements-modal.tsx index d8861076..b053060f 100644 --- a/src/renderer/src/pages/game-details/modals/reset-achievements-modal.tsx +++ b/src/renderer/src/pages/game-details/modals/reset-achievements-modal.tsx @@ -3,12 +3,12 @@ import { Button, Modal } from "@renderer/components"; import * as styles from "./remove-from-library-modal.css"; import type { Game } from "@types"; -interface ResetAchievementsModalProps { +type ResetAchievementsModalProps = Readonly<{ visible: boolean; game: Game; onClose: () => void; resetAchievements: () => Promise; -} +}>; export function ResetAchievementsModal({ onClose, From 52c159fe511536e6139773ce18ceee4ddb8e52e2 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Thu, 2 Jan 2025 09:34:28 -0300 Subject: [PATCH 08/26] fix: replace console.error with achievementsLogger.error --- src/main/events/library/reset-game-achievements.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/events/library/reset-game-achievements.ts b/src/main/events/library/reset-game-achievements.ts index 5d16f270..5006f075 100644 --- a/src/main/events/library/reset-game-achievements.ts +++ b/src/main/events/library/reset-game-achievements.ts @@ -2,7 +2,7 @@ import { gameAchievementRepository, gameRepository } from "@main/repository"; import { registerEvent } from "../register-event"; import { findAchievementFiles } from "@main/services/achievements/find-achivement-files"; import fs from "fs"; -import { WindowManager } from "@main/services"; +import { achievementsLogger, WindowManager } from "@main/services"; import { getUnlockedAchievements } from "../user/get-unlocked-achievements"; import { HydraApi } from "@main/services/hydra-api"; @@ -45,7 +45,7 @@ const resetGameAchievements = async ( gameAchievements ); } catch (error) { - console.error(error); + achievementsLogger.error(error); } }; From e2f798c627cc932a82be8012be60bc1b8e432df3 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Thu, 2 Jan 2025 09:35:05 -0300 Subject: [PATCH 09/26] refactor: simplify resetGameAchievements by replacing Promise.all with a for loop --- src/main/events/library/reset-game-achievements.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/events/library/reset-game-achievements.ts b/src/main/events/library/reset-game-achievements.ts index 5006f075..763c0674 100644 --- a/src/main/events/library/reset-game-achievements.ts +++ b/src/main/events/library/reset-game-achievements.ts @@ -18,11 +18,9 @@ const resetGameAchievements = async ( const achievementFiles = findAchievementFiles(game); if (achievementFiles.length) { - await Promise.all( - achievementFiles.map(async (achievementFile) => { - await fs.promises.rm(achievementFile.filePath, { recursive: true }); - }) - ); + for (const achievementFile of achievementFiles) { + await fs.promises.rm(achievementFile.filePath); + } } await gameAchievementRepository.update( From 9672e649e41d0ed55ebde7237deaf4a0556f91a2 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Thu, 2 Jan 2025 09:36:09 -0300 Subject: [PATCH 10/26] feat: log deleted achievement files --- src/main/events/library/reset-game-achievements.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/events/library/reset-game-achievements.ts b/src/main/events/library/reset-game-achievements.ts index 763c0674..d7ea13cd 100644 --- a/src/main/events/library/reset-game-achievements.ts +++ b/src/main/events/library/reset-game-achievements.ts @@ -18,6 +18,11 @@ const resetGameAchievements = async ( const achievementFiles = findAchievementFiles(game); if (achievementFiles.length) { + achievementsLogger.info( + `deleting achievement files: ${achievementFiles + .map((file) => file.filePath) + .join(", ")}` + ); for (const achievementFile of achievementFiles) { await fs.promises.rm(achievementFile.filePath); } From f3d617a13a20e784ad89d4c6e21104a411e0733c Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Thu, 2 Jan 2025 09:37:23 -0300 Subject: [PATCH 11/26] feat: log response after deleting game achievements --- src/main/events/library/reset-game-achievements.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/events/library/reset-game-achievements.ts b/src/main/events/library/reset-game-achievements.ts index d7ea13cd..3fa6e0a8 100644 --- a/src/main/events/library/reset-game-achievements.ts +++ b/src/main/events/library/reset-game-achievements.ts @@ -35,7 +35,8 @@ const resetGameAchievements = async ( } ); - await HydraApi.delete(`/profile/games/${game.remoteId}/achievements`); + await HydraApi.delete(`/profile/games/${game.remoteId}/achievements`).then( + (res) => console.info(res)); const gameAchievements = await getUnlockedAchievements( game.objectID, From 257a71d62665a681314119b0bcb1d0dd896b2303 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Thu, 2 Jan 2025 09:37:58 -0300 Subject: [PATCH 12/26] fix: change console.info to console.log --- src/main/events/library/reset-game-achievements.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/events/library/reset-game-achievements.ts b/src/main/events/library/reset-game-achievements.ts index 3fa6e0a8..3677fc65 100644 --- a/src/main/events/library/reset-game-achievements.ts +++ b/src/main/events/library/reset-game-achievements.ts @@ -36,7 +36,8 @@ const resetGameAchievements = async ( ); await HydraApi.delete(`/profile/games/${game.remoteId}/achievements`).then( - (res) => console.info(res)); + (res) => console.log(res) + ); const gameAchievements = await getUnlockedAchievements( game.objectID, From 8cf549ff05e8e0b286681ef4f336c770f36a846b Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Fri, 3 Jan 2025 12:16:32 -0300 Subject: [PATCH 13/26] refactor: enhance logging in resetGameAchievement --- .../events/library/reset-game-achievements.ts | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/main/events/library/reset-game-achievements.ts b/src/main/events/library/reset-game-achievements.ts index 3677fc65..cfd0dc8a 100644 --- a/src/main/events/library/reset-game-achievements.ts +++ b/src/main/events/library/reset-game-achievements.ts @@ -2,9 +2,8 @@ import { gameAchievementRepository, gameRepository } from "@main/repository"; import { registerEvent } from "../register-event"; import { findAchievementFiles } from "@main/services/achievements/find-achivement-files"; import fs from "fs"; -import { achievementsLogger, WindowManager } from "@main/services"; +import { achievementsLogger, HydraApi, WindowManager } from "@main/services"; import { getUnlockedAchievements } from "../user/get-unlocked-achievements"; -import { HydraApi } from "@main/services/hydra-api"; const resetGameAchievements = async ( _event: Electron.IpcMainInvokeEvent, @@ -18,12 +17,8 @@ const resetGameAchievements = async ( const achievementFiles = findAchievementFiles(game); if (achievementFiles.length) { - achievementsLogger.info( - `deleting achievement files: ${achievementFiles - .map((file) => file.filePath) - .join(", ")}` - ); for (const achievementFile of achievementFiles) { + achievementsLogger.log(`deleting ${achievementFile.filePath}`); await fs.promises.rm(achievementFile.filePath); } } @@ -35,9 +30,9 @@ const resetGameAchievements = async ( } ); - await HydraApi.delete(`/profile/games/${game.remoteId}/achievements`).then( - (res) => console.log(res) - ); + await HydraApi.delete(`/profile/games/${game.remoteId}/achievements`) + .catch((err) => achievementsLogger.error(err)) + .then((res) => achievementsLogger.log(res)); const gameAchievements = await getUnlockedAchievements( game.objectID, From 93b86f8c6c1df579eb9586cb254361134f2269a0 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Fri, 3 Jan 2025 12:38:06 -0300 Subject: [PATCH 14/26] refactor: improve reset achievements handling and modal state management --- .../game-details/modals/game-options-modal.tsx | 15 ++++++++++----- .../modals/reset-achievements-modal.tsx | 10 ++++++---- 2 files changed, 16 insertions(+), 9 deletions(-) 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 5289870e..346f4700 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 @@ -31,10 +31,10 @@ export function GameOptionsModal({ const [showDeleteModal, setShowDeleteModal] = useState(false); const [showRemoveGameModal, setShowRemoveGameModal] = useState(false); + const [launchOptions, setLaunchOptions] = useState(game.launchOptions ?? ""); const [showResetAchievementsModal, setShowResetAchievementsModal] = useState(false); - - const [launchOptions, setLaunchOptions] = useState(game.launchOptions ?? ""); + const [isDeleting, setIsDeleting] = useState(false); const { removeGameInstaller, @@ -146,8 +146,13 @@ export function GameOptionsModal({ window.electron.platform === "linux"; const handleResetAchievements = async () => { - await window.electron.resetGameAchievements(game.id); - updateGame(); + setIsDeleting(true); + try { + await window.electron.resetGameAchievements(game.id); + } finally { + await updateGame(); + setIsDeleting(false); + } }; const shouldShowLaunchOptionsConfiguration = false; @@ -333,7 +338,7 @@ export function GameOptionsModal({ diff --git a/src/renderer/src/pages/game-details/modals/reset-achievements-modal.tsx b/src/renderer/src/pages/game-details/modals/reset-achievements-modal.tsx index b053060f..642d32ba 100644 --- a/src/renderer/src/pages/game-details/modals/reset-achievements-modal.tsx +++ b/src/renderer/src/pages/game-details/modals/reset-achievements-modal.tsx @@ -2,7 +2,6 @@ import { useTranslation } from "react-i18next"; import { Button, Modal } from "@renderer/components"; import * as styles from "./remove-from-library-modal.css"; import type { Game } from "@types"; - type ResetAchievementsModalProps = Readonly<{ visible: boolean; game: Game; @@ -19,18 +18,21 @@ export function ResetAchievementsModal({ const { t } = useTranslation("game_details"); const handleResetAchievements = async () => { - await resetAchievements(); - onClose(); + try { + await resetAchievements(); + } finally { + onClose(); + } }; return (
From b68fe300ba8325d2c711983f61c5cc052dbdd08f Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Fri, 3 Jan 2025 17:24:37 -0300 Subject: [PATCH 16/26] refactor: rename state variable for clarity --- .../src/pages/game-details/modals/game-options-modal.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 b2d47dcb..e751a67b 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 @@ -34,7 +34,7 @@ export function GameOptionsModal({ const [launchOptions, setLaunchOptions] = useState(game.launchOptions ?? ""); const [showResetAchievementsModal, setShowResetAchievementsModal] = useState(false); - const [isDeleting, setIsDeleting] = useState(false); + const [isDeletingAchievements, setIsDeletingAchievements] = useState(false); const { removeGameInstaller, @@ -146,12 +146,12 @@ export function GameOptionsModal({ window.electron.platform === "linux"; const handleResetAchievements = async () => { - setIsDeleting(true); + setIsDeletingAchievements(true); try { await window.electron.resetGameAchievements(game.id); } finally { await updateGame(); - setIsDeleting(false); + setIsDeletingAchievements(false); } }; @@ -338,7 +338,7 @@ export function GameOptionsModal({ From ef3bf9890353996baabdf75a99263b3bd829b599 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Fri, 3 Jan 2025 17:36:55 -0300 Subject: [PATCH 17/26] feat: add success and error toast --- src/locales/en/translation.json | 4 +++- src/locales/pt-BR/translation.json | 4 +++- src/main/events/library/reset-game-achievements.ts | 3 ++- .../src/pages/game-details/modals/game-options-modal.tsx | 5 ++++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 3aea8fac..4e3dcb37 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -182,7 +182,9 @@ "no_write_permission": "Cannot download into this directory. Click here to learn more.", "reset_achievements": "Reset achievements", "reset_achievements_description": "This will reset all achievements for {{game}}", - "reset_achievements_title": "Are you sure?" + "reset_achievements_title": "Are you sure?", + "reset_achievements_success": "Achievements successfully reset", + "reset_achievements_error": "Failed to reset achievements" }, "activation": { "title": "Activate Hydra", diff --git a/src/locales/pt-BR/translation.json b/src/locales/pt-BR/translation.json index b6f2360b..2a80084f 100644 --- a/src/locales/pt-BR/translation.json +++ b/src/locales/pt-BR/translation.json @@ -170,7 +170,9 @@ "no_directory_selected": "Nenhum diretório selecionado", "reset_achievements": "Resetar conquistas", "reset_achievements_description": "Isso irá resetar todas as conquistas de {{game}}", - "reset_achievements_title": "Tem certeza?" + "reset_achievements_title": "Tem certeza?", + "reset_achievements_success": "Conquistas resetadas com sucesso", + "reset_achievements_error": "Falha ao resetar conquistas" }, "activation": { "title": "Ativação", diff --git a/src/main/events/library/reset-game-achievements.ts b/src/main/events/library/reset-game-achievements.ts index cfd0dc8a..eb55a412 100644 --- a/src/main/events/library/reset-game-achievements.ts +++ b/src/main/events/library/reset-game-achievements.ts @@ -30,7 +30,7 @@ const resetGameAchievements = async ( } ); - await HydraApi.delete(`/profile/games/${game.remoteId}/achievements`) + await HydraApi.delete(`/profile/games/achievements/${game.remoteId}`) .catch((err) => achievementsLogger.error(err)) .then((res) => achievementsLogger.log(res)); @@ -46,6 +46,7 @@ const resetGameAchievements = async ( ); } catch (error) { achievementsLogger.error(error); + throw error; } }; 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 e751a67b..fad02a96 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 @@ -149,8 +149,11 @@ export function GameOptionsModal({ setIsDeletingAchievements(true); try { await window.electron.resetGameAchievements(game.id); - } finally { await updateGame(); + showSuccessToast(t("reset_achievements_success")); + } catch (error) { + showErrorToast(t("reset_achievements_error")); + } finally { setIsDeletingAchievements(false); } }; From 2ddda4e4d225860a5d5b77850db3c096cc61217d Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Fri, 3 Jan 2025 17:56:13 -0300 Subject: [PATCH 18/26] refactor: remove error logging --- src/main/events/library/reset-game-achievements.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/events/library/reset-game-achievements.ts b/src/main/events/library/reset-game-achievements.ts index eb55a412..17e00d5d 100644 --- a/src/main/events/library/reset-game-achievements.ts +++ b/src/main/events/library/reset-game-achievements.ts @@ -31,7 +31,6 @@ const resetGameAchievements = async ( ); await HydraApi.delete(`/profile/games/achievements/${game.remoteId}`) - .catch((err) => achievementsLogger.error(err)) .then((res) => achievementsLogger.log(res)); const gameAchievements = await getUnlockedAchievements( From e6d76a5dbeaaa56c21a196cb50b31d12e16e4045 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Fri, 3 Jan 2025 17:56:39 -0300 Subject: [PATCH 19/26] lint --- src/main/events/library/reset-game-achievements.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/events/library/reset-game-achievements.ts b/src/main/events/library/reset-game-achievements.ts index 17e00d5d..4d591a5d 100644 --- a/src/main/events/library/reset-game-achievements.ts +++ b/src/main/events/library/reset-game-achievements.ts @@ -30,8 +30,9 @@ const resetGameAchievements = async ( } ); - await HydraApi.delete(`/profile/games/achievements/${game.remoteId}`) - .then((res) => achievementsLogger.log(res)); + await HydraApi.delete(`/profile/games/achievements/${game.remoteId}`).then( + (res) => achievementsLogger.log(res) + ); const gameAchievements = await getUnlockedAchievements( game.objectID, From 190ddeb46ea30087f78d2c76dc1b24e727054ab5 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Fri, 3 Jan 2025 18:22:13 -0300 Subject: [PATCH 20/26] refactor: improve logging for deleted game achievements --- src/main/events/library/reset-game-achievements.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/events/library/reset-game-achievements.ts b/src/main/events/library/reset-game-achievements.ts index 4d591a5d..25b9e6d7 100644 --- a/src/main/events/library/reset-game-achievements.ts +++ b/src/main/events/library/reset-game-achievements.ts @@ -31,7 +31,7 @@ const resetGameAchievements = async ( ); await HydraApi.delete(`/profile/games/achievements/${game.remoteId}`).then( - (res) => achievementsLogger.log(res) + () => achievementsLogger.log(`Deleted achievements from ${game.remoteId} - ${game.objectID} - ${game.title}`) ); const gameAchievements = await getUnlockedAchievements( From 50616955003f6b75dd6780fa0303ac9960d33b19 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Fri, 3 Jan 2025 18:22:25 -0300 Subject: [PATCH 21/26] lint --- src/main/events/library/reset-game-achievements.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/events/library/reset-game-achievements.ts b/src/main/events/library/reset-game-achievements.ts index 25b9e6d7..8d52a3a6 100644 --- a/src/main/events/library/reset-game-achievements.ts +++ b/src/main/events/library/reset-game-achievements.ts @@ -31,7 +31,10 @@ const resetGameAchievements = async ( ); await HydraApi.delete(`/profile/games/achievements/${game.remoteId}`).then( - () => achievementsLogger.log(`Deleted achievements from ${game.remoteId} - ${game.objectID} - ${game.title}`) + () => + achievementsLogger.log( + `Deleted achievements from ${game.remoteId} - ${game.objectID} - ${game.title}` + ) ); const gameAchievements = await getUnlockedAchievements( From 2df57b071dab55d85bb6623c5cd740b5ac17fc20 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Fri, 3 Jan 2025 18:50:02 -0300 Subject: [PATCH 22/26] feat: disable reset achievement button if has no achievements --- .../src/pages/game-details/modals/game-options-modal.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) 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 fad02a96..3afc3870 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 @@ -26,7 +26,7 @@ export function GameOptionsModal({ const { showSuccessToast, showErrorToast } = useToast(); - const { updateGame, setShowRepacksModal, repacks, selectGameExecutable } = + const { updateGame, setShowRepacksModal, repacks, selectGameExecutable, achievements } = useContext(gameDetailsContext); const [showDeleteModal, setShowDeleteModal] = useState(false); @@ -43,6 +43,10 @@ export function GameOptionsModal({ cancelDownload, } = useDownload(); + const hasAchievements = + (achievements?.filter((achievement) => achievement.unlocked).length ?? 0) > + 0; + const deleting = isGameDeleting(game.id); const { lastPacket } = useDownload(); @@ -341,7 +345,7 @@ export function GameOptionsModal({ From 3efb1425b9835f191f8221e5902c6fc7cb522b2f Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Fri, 3 Jan 2025 18:50:13 -0300 Subject: [PATCH 23/26] lint --- .../src/pages/game-details/modals/game-options-modal.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) 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 3afc3870..a677e4b9 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 @@ -26,8 +26,13 @@ export function GameOptionsModal({ const { showSuccessToast, showErrorToast } = useToast(); - const { updateGame, setShowRepacksModal, repacks, selectGameExecutable, achievements } = - useContext(gameDetailsContext); + const { + updateGame, + setShowRepacksModal, + repacks, + selectGameExecutable, + achievements, + } = useContext(gameDetailsContext); const [showDeleteModal, setShowDeleteModal] = useState(false); const [showRemoveGameModal, setShowRemoveGameModal] = useState(false); From cade56bb128c8da09301d2d2ddd1996624c96de0 Mon Sep 17 00:00:00 2001 From: Hachi-R Date: Fri, 3 Jan 2025 19:15:31 -0300 Subject: [PATCH 24/26] feat: disable reset achievements button if user is not logged in --- .../pages/game-details/modals/game-options-modal.tsx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) 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 a677e4b9..b06de28a 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 @@ -5,7 +5,7 @@ import type { Game } from "@types"; import * as styles from "./game-options-modal.css"; import { gameDetailsContext } from "@renderer/context"; import { DeleteGameModal } from "@renderer/pages/downloads/delete-game-modal"; -import { useDownload, useToast } from "@renderer/hooks"; +import { useDownload, useToast, useUserDetails } from "@renderer/hooks"; import { RemoveGameFromLibraryModal } from "./remove-from-library-modal"; import { ResetAchievementsModal } from "./reset-achievements-modal"; import { FileDirectoryIcon, FileIcon } from "@primer/octicons-react"; @@ -48,6 +48,8 @@ export function GameOptionsModal({ cancelDownload, } = useDownload(); + const { userDetails } = useUserDetails(); + const hasAchievements = (achievements?.filter((achievement) => achievement.unlocked).length ?? 0) > 0; @@ -350,7 +352,12 @@ export function GameOptionsModal({ From 87acdea5abb4a495d668417807e4b5d34ac05d04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9D=97=A6=F0=9D=97=B5=F0=9D=97=9F=F0=9D=97=B2?= =?UTF-8?q?=F0=9D=97=BF=F0=9D=97=A3?= <75412448+mikropsoft@users.noreply.github.com> Date: Sun, 5 Jan 2025 21:08:52 +0300 Subject: [PATCH 25/26] Update TR Locales --- src/locales/tr/translation.json | 425 +++++++++++++++++++++++++++----- 1 file changed, 361 insertions(+), 64 deletions(-) diff --git a/src/locales/tr/translation.json b/src/locales/tr/translation.json index 6757fdf5..8d0e7811 100644 --- a/src/locales/tr/translation.json +++ b/src/locales/tr/translation.json @@ -1,131 +1,428 @@ { "language_name": "Türkçe", + "app": { + "successfully_signed_in": "Başarıyla giriş yapıldı" + }, "home": { - "featured": "Öne çıkan", - "surprise_me": "Şaşırt beni", - "no_results": "Sonuç bulunamadı" + "featured": "Öne Çıkanlar", + "surprise_me": "Beni Şaşırt", + "no_results": "Sonuç bulunamadı", + "start_typing": "Aramak için yazmaya başlayın...", + "hot": "Şu anda popüler", + "weekly": "📅 Haftanın en iyi oyunları", + "achievements": "🏆 Tamamlanacak oyunlar" }, "sidebar": { "catalogue": "Katalog", - "downloads": "İndirmeler", + "downloads": "İndirilenler", "settings": "Ayarlar", - "my_library": "Kütüphane", - "downloading_metadata": "{{title}} (Metadata indiriliyor…)", - "paused": "{{title}} (Duraklatıldı)", + "my_library": "Kütüphanem", + "downloading_metadata": "{{title}} (Meta verileri indiriliyor…)", + "paused": "{{title}} (Durduruldu)", "downloading": "{{title}} ({{percentage}} - İndiriliyor…)", "filter": "Kütüphaneyi filtrele", - "home": "Ana menü" + "home": "Ana Sayfa", + "queued": "{{title}} (Sırada)", + "game_has_no_executable": "Oyun için bir çalıştırılabilir dosya seçilmedi", + "sign_in": "Giriş yap", + "friends": "Arkadaşlar", + "need_help": "Yardıma mı ihtiyacınız var?" }, "header": { - "search": "Ara", - "home": "Ana menü", + "search": "Oyunları ara", + "home": "Ana Sayfa", "catalogue": "Katalog", - "downloads": "İndirmeler", + "downloads": "İndirilenler", "search_results": "Arama sonuçları", - "settings": "Ayarlar" + "settings": "Ayarlar", + "version_available_install": "Sürüm {{version}} mevcut. Yüklemek ve yeniden başlatmak için buraya tıklayın.", + "version_available_download": "Sürüm {{version}} mevcut. İndirmek için buraya tıklayın." }, "bottom_panel": { - "no_downloads_in_progress": "İndirilen bir şey yok", - "downloading_metadata": "{{title}} metadatası indiriliyor…", - "downloading": "{{title}} indiriliyor… ({{percentage}} tamamlandı) - Bitiş {{eta}} - {{speed}}" + "no_downloads_in_progress": "Devam eden indirme yok", + "downloading_metadata": "{{title}} meta verileri indiriliyor…", + "downloading": "{{title}} indiriliyor… ({{percentage}} tamamlandı) - Tamamlama: {{eta}} - Hız: {{speed}}", + "calculating_eta": "{{title}} indiriliyor… ({{percentage}} tamamlandı) - Kalan süre hesaplanıyor…", + "checking_files": "{{title}} dosyaları kontrol ediliyor… ({{percentage}} tamamlandı)" }, "catalogue": { - "next_page": "Sonraki sayfa", - "previous_page": "Önceki sayfa" + "search": "Filtrele…", + "developers": "Geliştiriciler", + "genres": "Türler", + "tags": "Etiketler", + "publishers": "Yayıncılar", + "download_sources": "İndirme kaynakları", + "result_count": "{{resultCount}} sonuç", + "filter_count": "{{filterCount}} mevcut", + "clear_filters": "{{filterCount}} seçili filtreyi temizle" }, "game_details": { "open_download_options": "İndirme seçeneklerini aç", "download_options_zero": "İndirme seçeneği yok", "download_options_one": "{{count}} indirme seçeneği", "download_options_other": "{{count}} indirme seçeneği", - "updated_at": "{{updated_at}} güncellendi", - "install": "İndir", + "updated_at": "{{updated_at}} tarihinde güncellendi", + "install": "Yükle", "resume": "Devam et", - "pause": "Duraklat", + "pause": "Durdur", "cancel": "İptal et", - "remove": "Sil", - "space_left_on_disk": "Diskte {{space}} yer kaldı", - "eta": "Bitiş {{eta}}", - "downloading_metadata": "Metadata indiriliyor…", - "filter": "Repackleri filtrele", + "remove": "Kaldır", + "space_left_on_disk": "Diskte {{space}} boş alan kaldı", + "eta": "{{eta}} tahmini bitiş", + "calculating_eta": "Kalan süre hesaplanıyor…", + "downloading_metadata": "Meta veriler indiriliyor…", + "filter": "Paketleri filtrele", "requirements": "Sistem gereksinimleri", "minimum": "Minimum", "recommended": "Önerilen", - "release_date": "{{date}} tarihinde çıktı", - "publisher": "{{publisher}} tarihinde yayınlandı", - "hours": "saatler", - "minutes": "dakikalar", + "paused": "Durduruldu", + "release_date": "{{date}} tarihinde yayımlandı", + "publisher": "{{publisher}} tarafından yayımlandı", + "hours": "saat", + "minutes": "dakika", "amount_hours": "{{amount}} saat", "amount_minutes": "{{amount}} dakika", - "accuracy": "%{{accuracy}} doğruluk", + "accuracy": "{{accuracy}}% doğruluk", "add_to_library": "Kütüphaneye ekle", "remove_from_library": "Kütüphaneden kaldır", - "no_downloads": "İndirme yok", - "play_time": "{{amount}} oynandı", - "last_time_played": "Son oynanan {{period}}", - "not_played_yet": "Bu {{title}} hiç oynanmadı", - "next_suggestion": "Sıradaki öneri", + "no_downloads": "İndirilebilir içerik yok", + "play_time": "{{amount}} süre oynandı", + "last_time_played": "Son oynama {{period}} önce", + "not_played_yet": "{{title}} henüz oynanmadı", + "next_suggestion": "Sonraki öneri", "play": "Oyna", - "deleting": "Installer siliniyor…", + "deleting": "Yükleyici siliniyor…", "close": "Kapat", - "playing_now": "Şimdi oynanıyor", + "playing_now": "Şu anda oynanıyor", "change": "Değiştir", - "repacks_modal_description": "İndirmek istediğiiniz repacki seçin", - "select_folder_hint": "Varsayılan klasörü değiştirmek için ulaşmanız gereken ayar", - "download_now": "Şimdi" + "repacks_modal_description": "İndirmek istediğiniz paketi seçin", + "select_folder_hint": "Varsayılan klasörü değiştirmek için <0>Ayarlar bölümüne gidin", + "download_now": "Şimdi indir", + "no_shop_details": "Mağaza bilgileri alınamadı.", + "download_options": "İndirme seçenekleri", + "download_path": "İndirme yolu", + "previous_screenshot": "Önceki ekran görüntüsü", + "next_screenshot": "Sonraki ekran görüntüsü", + "screenshot": "{{number}} ekran görüntüsü", + "open_screenshot": "{{number}} ekran görüntüsünü aç", + "download_settings": "İndirme ayarları", + "downloader": "İndirici", + "select_executable": "Seç", + "no_executable_selected": "Hiçbir çalıştırılabilir dosya seçilmedi", + "open_folder": "Klasörü aç", + "open_download_location": "İndirilen dosyaları gör", + "create_shortcut": "Masaüstü kısayolu oluştur", + "clear": "Temizle", + "remove_files": "Dosyaları kaldır", + "remove_from_library_title": "Emin misiniz?", + "remove_from_library_description": "Bu işlem {{game}} oyununu kütüphanenizden kaldıracaktır", + "options": "Seçenekler", + "executable_section_title": "Çalıştırılabilir dosya", + "executable_section_description": "\"Oyna\" tıklandığında çalıştırılacak dosyanın yolu", + "downloads_secion_title": "İndirmeler", + "downloads_section_description": "Bu oyun için güncellemeleri veya diğer sürümleri kontrol edin", + "danger_zone_section_title": "Tehlike bölgesi", + "danger_zone_section_description": "Bu oyunu kütüphanenizden veya Hydra tarafından indirilen dosyaları kaldırın", + "download_in_progress": "İndirme devam ediyor", + "download_paused": "İndirme durduruldu", + "last_downloaded_option": "Son indirilen seçenek", + "create_shortcut_success": "Kısayol başarıyla oluşturuldu", + "create_shortcut_error": "Kısayol oluşturulurken hata oluştu", + "nsfw_content_title": "Bu oyun uygunsuz içerik içeriyor", + "nsfw_content_description": "{{title}} her yaş için uygun olmayabilecek içeriklere sahiptir. Devam etmek istediğinizden emin misiniz?", + "allow_nsfw_content": "Devam et", + "refuse_nsfw_content": "Geri dön", + "stats": "İstatistikler", + "download_count": "İndirme sayısı", + "player_count": "Aktif oyuncular", + "download_error": "Bu indirme seçeneği mevcut değil", + "download": "İndir", + "executable_path_in_use": "\"{{game}}\" tarafından kullanılan çalıştırılabilir dosya", + "warning": "Uyarı:", + "hydra_needs_to_remain_open": "Bu indirmenin tamamlanması için Hydra açık kalmalıdır. Eğer Hydra kapanırsa, ilerleme kaydedilmez.", + "achievements": "Başarılar", + "achievements_count": "Başarılar {{unlockedCount}}/{{achievementsCount}}", + "cloud_save": "Bulut kaydı", + "cloud_save_description": "İlerlemenizi buluta kaydedin ve herhangi bir cihazda oynamaya devam edin", + "backups": "Yedekler", + "install_backup": "Yükle", + "delete_backup": "Sil", + "create_backup": "Yeni yedek oluştur", + "last_backup_date": "{{date}} tarihindeki son yedek", + "no_backup_preview": "Bu oyun için kayıtlı oyun bulunamadı", + "restoring_backup": "Yedek geri yükleniyor ({{progress}} tamamlandı)…", + "uploading_backup": "Yedek yükleniyor…", + "no_backups": "Bu oyun için henüz bir yedek oluşturmadınız", + "backup_uploaded": "Yedek yüklendi", + "backup_deleted": "Yedek silindi", + "backup_restored": "Yedek geri yüklendi", + "see_all_achievements": "Tüm başarıları gör", + "sign_in_to_see_achievements": "Başarıları görmek için giriş yapın", + "mapping_method_automatic": "Otomatik", + "mapping_method_manual": "Manuel", + "mapping_method_label": "Eşleme yöntemi", + "files_automatically_mapped": "Dosyalar otomatik olarak eşlendi", + "no_backups_created": "Bu oyun için yedek oluşturulmadı", + "manage_files": "Dosyaları yönet", + "loading_save_preview": "Kayıtlı oyunlar aranıyor…", + "wine_prefix": "Wine Prefix", + "wine_prefix_description": "Bu oyunu çalıştırmak için kullanılan Wine Prefix", + "launch_options": "Başlatma Seçenekleri", + "launch_options_description": "İleri düzey kullanıcılar, başlatma seçeneklerine değişiklikler girebilir (deneysel özellik)", + "launch_options_placeholder": "Belirtilen bir parametre yok", + "no_download_option_info": "Bilgi mevcut değil", + "backup_deletion_failed": "Yedek silinemedi", + "max_number_of_artifacts_reached": "Bu oyun için maksimum yedek sayısına ulaşıldı", + "achievements_not_sync": "Başarılarınızı senkronize etmeyi öğrenin", + "manage_files_description": "Hangi dosyaların yedeklenip geri yükleneceğini yönetin", + "select_folder": "Klasör seç", + "backup_from": "{{date}} tarihinden yedek", + "custom_backup_location_set": "Özel yedekleme konumu ayarlandı", + "no_directory_selected": "Bir dizin seçilmedi", + "no_write_permission": "Bu dizine indirme yapılamaz. Daha fazla bilgi için buraya tıklayın.", + "reset_achievements": "Başarıları sıfırla", + "reset_achievements_description": "Bu işlem {{game}} için tüm başarıları sıfırlar", + "reset_achievements_title": "Emin misiniz?", + "reset_achievements_success": "Başarılar başarıyla sıfırlandı", + "reset_achievements_error": "Başarılar sıfırlanamadı" }, "activation": { - "title": "Hydra'yı aktif et", - "installation_id": "Kurulum ID'si:", - "enter_activation_code": "Aktifleştirme kodunuzu girin", - "message": "Bunu nerede soracağınızı bilmiyorsanız, buna sahip olmamanız gerekiyor.", - "activate": "Aktif et", + "title": "Hydra'yı Aktive Et", + "installation_id": "Kurulum Kimliği:", + "enter_activation_code": "Aktivasyon kodunuzu girin", + "message": "Bunu nereden soracağınızı bilmiyorsanız, bu sizin için olmamalı.", + "activate": "Aktive Et", "loading": "Yükleniyor…" }, "downloads": { - "resume": "Devam et", + "resume": "Devam Et", "pause": "Duraklat", - "eta": "Bitiş {{eta}}", + "eta": "Tamamlama {{eta}}", "paused": "Duraklatıldı", "verifying": "Doğrulanıyor…", "completed": "Tamamlandı", - "cancel": "İptal et", - "filter": "Yüklü oyunları filtrele", + "removed": "İndirilmedi", + "cancel": "İptal Et", + "filter": "İndirilen oyunları filtrele", "remove": "Kaldır", "downloading_metadata": "Metadata indiriliyor…", - "deleting": "Installer siliniyor…", - "delete": "Installer'ı sil", + "deleting": "Yükleyici siliniyor…", + "delete": "Yükleyiciyi kaldır", "delete_modal_title": "Emin misiniz?", - "delete_modal_description": "Bu bilgisayarınızdan tüm kurulum dosyalarını silecek", - "install": "Kur" + "delete_modal_description": "Bu işlem, tüm kurulum dosyalarını bilgisayarınızdan kaldıracaktır", + "install": "Kur", + "download_in_progress": "Devam ediyor", + "queued_downloads": "Sıradaki indirmeler", + "downloads_completed": "Tamamlananlar", + "queued": "Sırada", + "no_downloads_title": "Bomboş", + "no_downloads_description": "Henüz Hydra ile hiçbir şey indirmediniz, ancak başlamak için asla geç değil.", + "checking_files": "Dosyalar kontrol ediliyor…", + "seeding": "Paylaşılıyor", + "stop_seeding": "Paylaşımı durdur", + "resume_seeding": "Paylaşımı sürdür", + "options": "Yönet" }, "settings": { "downloads_path": "İndirme yolu", "change": "Güncelle", "notifications": "Bildirimler", - "enable_download_notifications": "Bir indirme bittiğinde", - "enable_repack_list_notifications": "Yeni bir repack eklendiğinde" + "enable_download_notifications": "Bir indirme tamamlandığında", + "enable_repack_list_notifications": "Yeni bir repack eklendiğinde", + "real_debrid_api_token_label": "Real-Debrid API anahtarı", + "quit_app_instead_hiding": "Hydra'yı kapatırken gizlemeyin", + "launch_with_system": "Hydra'yı sistem başlatıldığında çalıştır", + "general": "Genel", + "behavior": "Davranış", + "download_sources": "İndirme kaynakları", + "language": "Dil", + "real_debrid_api_token": "API Anahtarı", + "enable_real_debrid": "Real-Debrid'i Etkinleştir", + "real_debrid_description": "Real-Debrid, yalnızca internet hızınızla sınırlı olarak hızlı dosya indirmenizi sağlayan sınırsız bir indirici.", + "real_debrid_invalid_token": "Geçersiz API anahtarı", + "real_debrid_api_token_hint": "API anahtarınızı <0>buradan alabilirsiniz", + "real_debrid_free_account_error": "\"{{username}}\" hesabı ücretsiz bir hesaptır. Lütfen Real-Debrid abonesi olun", + "real_debrid_linked_message": "\"{{username}}\" hesabı bağlandı", + "save_changes": "Değişiklikleri Kaydet", + "changes_saved": "Değişiklikler başarıyla kaydedildi", + "download_sources_description": "Hydra, indirme bağlantılarını bu kaynaklardan alacak. Kaynak URL, indirme bağlantılarını içeren bir .json dosyasına doğrudan bir bağlantı olmalıdır.", + "validate_download_source": "Doğrula", + "remove_download_source": "Kaldır", + "add_download_source": "Kaynak ekle", + "download_count_zero": "İndirme seçeneği yok", + "download_count_one": "{{countFormatted}} indirme seçeneği", + "download_count_other": "{{countFormatted}} indirme seçeneği", + "download_source_url": "İndirme kaynağı URL'si", + "add_download_source_description": ".json dosyasının URL'sini girin", + "download_source_up_to_date": "Güncel", + "download_source_errored": "Hatalı", + "sync_download_sources": "Kaynakları senkronize et", + "removed_download_source": "İndirme kaynağı kaldırıldı", + "added_download_source": "İndirme kaynağı eklendi", + "download_sources_synced": "Tüm indirme kaynakları senkronize edildi", + "insert_valid_json_url": "Geçerli bir JSON URL'si girin", + "found_download_option_zero": "Hiçbir indirme seçeneği bulunamadı", + "found_download_option_one": "{{countFormatted}} indirme seçeneği bulundu", + "found_download_option_other": "{{countFormatted}} indirme seçeneği bulundu", + "import": "İçe aktar", + "public": "Herkese açık", + "private": "Gizli", + "friends_only": "Sadece arkadaşlar", + "privacy": "Gizlilik", + "profile_visibility": "Profil görünürlüğü", + "profile_visibility_description": "Profilinizi ve kütüphanenizi kimlerin görebileceğini seçin", + "required_field": "Bu alan gereklidir", + "source_already_exists": "Bu kaynak zaten eklenmiş", + "must_be_valid_url": "Kaynak geçerli bir URL olmalıdır", + "blocked_users": "Engellenen kullanıcılar", + "user_unblocked": "Kullanıcının engeli kaldırıldı", + "enable_achievement_notifications": "Bir başarı kilidi açıldığında", + "launch_minimized": "Hydra'yı küçültülmüş başlat", + "disable_nsfw_alert": "NSFW uyarısını devre dışı bırak", + "seed_after_download_complete": "İndirme tamamlandıktan sonra paylaş", + "show_hidden_achievement_description": "Gizli başarı açıklamalarını kilitlenmeden önce göster" }, "notifications": { "download_complete": "İndirme tamamlandı", - "game_ready_to_install": "{{title}} kuruluma hazır", + "game_ready_to_install": "{{title}} kurulmaya hazır", "repack_list_updated": "Repack listesi güncellendi", - "repack_count_one": "{{count}} yeni repack eklendi", - "repack_count_other": "{{count}} yeni repack eklendi" + "repack_count_one": "{{count}} repack eklendi", + "repack_count_other": "{{count}} repack eklendi", + "new_update_available": "Sürüm {{version}} mevcut", + "restart_to_install_update": "Güncellemeyi yüklemek için Hydra'yı yeniden başlatın", + "notification_achievement_unlocked_title": "{{game}} için başarı kilidi açıldı", + "notification_achievement_unlocked_body": "{{achievement}} ve diğer {{count}} başarılar açıldı" }, "system_tray": { - "open": "Hydra'yı aç", + "open": "Hydra'yı Aç", "quit": "Çık" }, "game_card": { - "no_downloads": "İndirme mevcut değil" + "no_downloads": "İndirilebilir içerik bulunmuyor" }, "binary_not_found_modal": { - "title": "Programlar yüklü değil", - "description": "Sisteminizde Wine veya Lutris çalıştırılabiliri bulunamadı", - "instructions": "Oyunları düzgün şekilde çalıştırmak için Linux distronuza bunlardan birini nasıl yükleyebileceğinize bakın" + "title": "Programlar Yüklü Değil", + "description": "Wine veya Lutris çalıştırılabilir dosyaları sisteminizde bulunamadı", + "instructions": "Oyunun normal çalışabilmesi için bunlardan herhangi birini Linux dağıtımınıza uygun şekilde nasıl kuracağınızı kontrol edin" }, "modal": { - "close": "Kapat tuşu" + "close": "Kapat düğmesi" + }, + "forms": { + "toggle_password_visibility": "Şifre görünürlüğünü değiştir" + }, + "user_profile": { + "amount_hours": "{{amount}} saat", + "amount_minutes": "{{amount}} dakika", + "last_time_played": "Son oynanma {{period}}", + "activity": "Son Etkinlik", + "library": "Kütüphane", + "total_play_time": "Toplam oynama süresi", + "no_recent_activity_title": "Hmmm… burada bir şey yok", + "no_recent_activity_description": "Son zamanlarda hiç oyun oynamamışsınız. Bunu değiştirmenin zamanı geldi!", + "display_name": "Görünen isim", + "saving": "Kaydediliyor", + "save": "Kaydet", + "edit_profile": "Profili Düzenle", + "saved_successfully": "Başarıyla kaydedildi", + "try_again": "Lütfen tekrar deneyin", + "sign_out_modal_title": "Emin misiniz?", + "cancel": "İptal", + "successfully_signed_out": "Başarıyla çıkış yapıldı", + "sign_out": "Çıkış yap", + "playing_for": "{{amount}} oynanıyor", + "sign_out_modal_text": "Kütüphaneniz mevcut hesabınıza bağlı. Çıkış yaptığınızda kütüphaneniz görünür olmayacak ve herhangi bir ilerleme kaydedilmeyecek. Çıkışa devam etmek istiyor musunuz?", + "add_friends": "Arkadaş Ekle", + "add": "Ekle", + "friend_code": "Arkadaş kodu", + "see_profile": "Profili gör", + "sending": "Gönderiliyor", + "friend_request_sent": "Arkadaşlık isteği gönderildi", + "friends": "Arkadaşlar", + "friends_list": "Arkadaş listesi", + "user_not_found": "Kullanıcı bulunamadı", + "block_user": "Kullanıcıyı engelle", + "add_friend": "Arkadaş ekle", + "request_sent": "İstek gönderildi", + "request_received": "İstek alındı", + "accept_request": "İsteği kabul et", + "ignore_request": "İsteği yok say", + "cancel_request": "İsteği iptal et", + "undo_friendship": "Arkadaşlığı sonlandır", + "request_accepted": "İstek kabul edildi", + "user_blocked_successfully": "Kullanıcı başarıyla engellendi", + "user_block_modal_text": "Bu işlem {{displayName}} adlı kullanıcıyı engelleyecek", + "blocked_users": "Engellenen kullanıcılar", + "unblock": "Engeli kaldır", + "no_friends_added": "Hiç arkadaş eklemediniz", + "pending": "Bekliyor", + "no_pending_invites": "Bekleyen davetiniz yok", + "no_blocked_users": "Engellenmiş kullanıcı yok", + "friend_code_copied": "Arkadaş kodu kopyalandı", + "undo_friendship_modal_text": "Bu işlem {{displayName}} ile arkadaşlığınızı sonlandıracak", + "privacy_hint": "Bunu kimin görebileceğini ayarlamak için <0>Ayarlar bölümüne gidin", + "locked_profile": "Bu profil gizli", + "image_process_failure": "Görüntü işleme başarısız oldu", + "required_field": "Bu alan gerekli", + "displayname_min_length": "Görünen isim en az 3 karakter uzunluğunda olmalıdır", + "displayname_max_length": "Görünen isim en fazla 50 karakter uzunluğunda olabilir", + "report_profile": "Bu profili bildir", + "report_reason": "Bu profili neden bildiriyorsunuz?", + "report_description": "Ek bilgi", + "report_description_placeholder": "Ek bilgi", + "report": "Bildir", + "report_reason_hate": "Nefret söylemi", + "report_reason_sexual_content": "Cinsel içerik", + "report_reason_violence": "Şiddet", + "report_reason_spam": "Spam", + "report_reason_other": "Diğer", + "profile_reported": "Profil bildirildi", + "your_friend_code": "Arkadaş kodunuz:", + "upload_banner": "Afiş yükle", + "uploading_banner": "Afiş yükleniyor…", + "background_image_updated": "Arka plan görüntüsü güncellendi", + "stats": "İstatistikler", + "achievements": "Başarılar", + "games": "Oyunlar", + "top_percentile": "En üst {{percentile}}%", + "ranking_updated_weekly": "Sıralama haftalık olarak güncellenir", + "playing": "{{game}} oynanıyor", + "achievements_unlocked": "Başarılar açıldı", + "earned_points": "Kazanılan puanlar", + "show_achievements_on_profile": "Başarılarınızı profilinizde gösterin", + "show_points_on_profile": "Kazandığınız puanları profilinizde gösterin" + }, + "achievement": { + "achievement_unlocked": "Başarı açıldı", + "user_achievements": "{{displayName}}'in Başarıları", + "your_achievements": "Başarılarınız", + "unlocked_at": "Açılma zamanı: {{date}}", + "subscription_needed": "Bu içeriği görmek için bir Hydra Cloud aboneliği gereklidir", + "new_achievements_unlocked": "{{gameCount}} oyundan {{achievementCount}} yeni başarı açıldı", + "achievement_progress": "{{unlockedCount}}/{{totalCount}} başarı", + "achievements_unlocked_for_game": "{{gameTitle}} oyunu için {{achievementCount}} yeni başarı açıldı", + "hidden_achievement_tooltip": "Bu gizli bir başarıdır", + "achievement_earn_points": "Bu başarı ile {{points}} puan kazanın", + "earned_points": "Kazanılan puanlar:", + "available_points": "Mevcut puanlar:", + "how_to_earn_achievements_points": "Başarı puanları nasıl kazanılır?" + }, + "hydra_cloud": { + "subscription_tour_title": "Hydra Cloud Aboneliği", + "subscribe_now": "Şimdi abone olun", + "cloud_saving": "Bulut kaydetme", + "cloud_achievements": "Başarılarınızı buluta kaydedin", + "animated_profile_picture": "Animasyonlu profil resimleri", + "premium_support": "Premium Destek", + "show_and_compare_achievements": "Başarılarınızı diğer kullanıcılarla karşılaştırın ve gösterin", + "animated_profile_banner": "Animasyonlu profil afişi", + "hydra_cloud": "Hydra Cloud", + "hydra_cloud_feature_found": "Bir Hydra Cloud özelliği keşfettiniz!", + "learn_more": "Daha Fazla Bilgi Edinin" } } + + + + + From ab2d8c351bfd02c02371b6b0a08d65450cb68b37 Mon Sep 17 00:00:00 2001 From: Zamitto <167933696+zamitto@users.noreply.github.com> Date: Sun, 5 Jan 2025 15:37:25 -0300 Subject: [PATCH 26/26] Removing excessive new lines --- src/locales/tr/translation.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/locales/tr/translation.json b/src/locales/tr/translation.json index 8d0e7811..6fa89c03 100644 --- a/src/locales/tr/translation.json +++ b/src/locales/tr/translation.json @@ -421,8 +421,3 @@ "learn_more": "Daha Fazla Bilgi Edinin" } } - - - - -