diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index a4426d2c..c94a6053 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -340,6 +340,7 @@ "user_achievements": "{{displayName}}'s Achievements", "your_achievements": "Your Achievements", "unlocked_at": "Unlocked at:", - "subscription_needed": "A Hydra Cloud subscription is needed to see this content" + "subscription_needed": "A Hydra Cloud subscription is needed to see this content", + "new_achievements_unlocked": "Unlocked {{achievementCount}} new achievements from {{gameCount}} games" } } diff --git a/src/locales/pt-BR/translation.json b/src/locales/pt-BR/translation.json index 77ebe906..85523328 100644 --- a/src/locales/pt-BR/translation.json +++ b/src/locales/pt-BR/translation.json @@ -342,6 +342,7 @@ "your_achievements": "Suas Conquistas", "user_achievements": "Conquistas de {{displayName}}", "unlocked_at": "Desbloqueado em:", - "subscription_needed": "Você precisa de uma assinatura Hydra Cloud para visualizar este conteúdo" + "subscription_needed": "Você precisa de uma assinatura Hydra Cloud para visualizar este conteúdo", + "new_achievements_unlocked": "{{achievementCount}} novas conquistas de {{gameCount}} jogos" } } diff --git a/src/locales/pt-PT/translation.json b/src/locales/pt-PT/translation.json index dac181ee..423c4518 100644 --- a/src/locales/pt-PT/translation.json +++ b/src/locales/pt-PT/translation.json @@ -284,6 +284,7 @@ "achievement": { "achievement_unlocked": "Conquista desbloqueada", "unlocked_at": "Desbloqueado em:", - "subscription_needed": "Você precisa de uma assinatura Hydra Cloud para visualizar este conteúdo" + "subscription_needed": "Você precisa de uma assinatura Hydra Cloud para visualizar este conteúdo", + "new_achievements_unlocked": "Encontradas {{achievementCount}} novas conquistas de {{gameCount}} jogos" } } diff --git a/src/main/services/achievements/achievement-watcher-manager.ts b/src/main/services/achievements/achievement-watcher-manager.ts index ea06dfd9..2345e3be 100644 --- a/src/main/services/achievements/achievement-watcher-manager.ts +++ b/src/main/services/achievements/achievement-watcher-manager.ts @@ -13,6 +13,7 @@ import type { AchievementFile, UnlockedAchievement } from "@types"; import { achievementsLogger } from "../logger"; import { Cracker } from "@shared"; import { IsNull, Not } from "typeorm"; +import { WindowManager } from "../window-manager"; const fileStats: Map = new Map(); const fltFiles: Map> = new Map(); @@ -136,6 +137,8 @@ const processAchievementFileDiff = async ( if (unlockedAchievements.length) { return mergeAchievements(game, unlockedAchievements, true); } + + return 0; }; export class AchievementWatcherManager { @@ -234,11 +237,16 @@ export class AchievementWatcherManager { }; public static preSearchAchievements = async () => { - if (process.platform === "win32") { - await this.preSearchAchievementsWindows(); - } else { - await this.preSearchAchievementsWithWine(); - } + const newAchievementsCount = + process.platform === "win32" + ? await this.preSearchAchievementsWindows() + : await this.preSearchAchievementsWithWine(); + + WindowManager.notificationWindow?.webContents.send( + "on-combined-achievements-unlocked", + newAchievementsCount.filter((achievements) => achievements).length, + newAchievementsCount.reduce((acc, val) => acc + val, 0) + ); this.hasFinishedMergingWithRemote = true; }; diff --git a/src/main/services/achievements/find-achivement-files.ts b/src/main/services/achievements/find-achivement-files.ts index 5b1237b3..9195c13a 100644 --- a/src/main/services/achievements/find-achivement-files.ts +++ b/src/main/services/achievements/find-achivement-files.ts @@ -201,10 +201,10 @@ const getPathFromCracker = (cracker: Cracker) => { if (cracker === Cracker.flt) { return [ - { - folderPath: path.join(appData, "FLT"), - fileLocation: ["stats"], - }, + // { + // folderPath: path.join(appData, "FLT"), + // fileLocation: ["stats"], + // }, ]; } diff --git a/src/main/services/achievements/merge-achievements.ts b/src/main/services/achievements/merge-achievements.ts index 8dce5aa8..05899e23 100644 --- a/src/main/services/achievements/merge-achievements.ts +++ b/src/main/services/achievements/merge-achievements.ts @@ -117,7 +117,7 @@ export const mergeAchievements = async ( const mergedLocalAchievements = unlockedAchievements.concat(newAchievements); if (game.remoteId) { - return HydraApi.put( + await HydraApi.put( "/profile/games/achievements", { id: game.remoteId, @@ -141,12 +141,14 @@ export const mergeAchievements = async ( publishNotification ); }); + } else { + await saveAchievementsOnLocal( + game.objectID, + game.shop, + mergedLocalAchievements, + publishNotification + ); } - return saveAchievementsOnLocal( - game.objectID, - game.shop, - mergedLocalAchievements, - publishNotification - ); + return newAchievements.length; }; diff --git a/src/preload/index.ts b/src/preload/index.ts index 6d541b0b..d75045ac 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -68,6 +68,18 @@ contextBridge.exposeInMainWorld("electron", { return () => ipcRenderer.removeListener("on-achievement-unlocked", listener); }, + onCombinedAchievementsUnlocked: ( + cb: (gameCount: number, achievementsCount: number) => void + ) => { + const listener = ( + _event: Electron.IpcRendererEvent, + gameCount: number, + achievementCount: number + ) => cb(gameCount, achievementCount); + ipcRenderer.on("on-combined-achievements-unlocked", listener); + return () => + ipcRenderer.removeListener("on-combined-achievements-unlocked", listener); + }, onUpdateAchievements: ( objectId: string, shop: GameShop, diff --git a/src/renderer/src/declaration.d.ts b/src/renderer/src/declaration.d.ts index 31ff375e..68e22d67 100644 --- a/src/renderer/src/declaration.d.ts +++ b/src/renderer/src/declaration.d.ts @@ -73,6 +73,9 @@ declare global { achievements?: { displayName: string; iconUrl: string }[] ) => void ) => () => Electron.IpcRenderer; + onCombinedAchievementsUnlocked: ( + cb: (gameCount: number, achievementCount: number) => void + ) => () => Electron.IpcRenderer; onUpdateAchievements: ( objectId: string, shop: GameShop, diff --git a/src/renderer/src/pages/achievements/notification/achievement-notification.tsx b/src/renderer/src/pages/achievements/notification/achievement-notification.tsx index d33cb231..ec8e2d8a 100644 --- a/src/renderer/src/pages/achievements/notification/achievement-notification.tsx +++ b/src/renderer/src/pages/achievements/notification/achievement-notification.tsx @@ -31,6 +31,31 @@ export function AchievementNotification() { return audio; }, []); + useEffect(() => { + const unsubscribe = window.electron.onCombinedAchievementsUnlocked( + (gameCount, achievementCount) => { + if (gameCount === 0 || achievementCount === 0) return; + + setAchievements([ + { + displayName: t("new_achievements_unlocked", { + gameCount, + achievementCount, + }), + iconUrl: + "https://avatars.githubusercontent.com/u/164102380?s=400&u=01a13a7b4f0c642f7e547b8e1d70440ea06fa750&v=4", + }, + ]); + + audio.play(); + } + ); + + return () => { + unsubscribe(); + }; + }, [audio]); + useEffect(() => { const unsubscribe = window.electron.onAchievementUnlocked( (_object, _shop, achievements) => {