diff --git a/src/main/events/catalogue/get-game-achievements.ts b/src/main/events/catalogue/get-game-achievements.ts index 3325b3c0..acd7a4a6 100644 --- a/src/main/events/catalogue/get-game-achievements.ts +++ b/src/main/events/catalogue/get-game-achievements.ts @@ -2,7 +2,7 @@ import type { GameShop } from "@types"; import { registerEvent } from "../register-event"; import { HydraApi } from "@main/services"; -import { gameRepository } from "@main/repository"; +import { gameAchievementRepository, gameRepository } from "@main/repository"; import { GameAchievement } from "@main/entity"; const getGameAchievements = async ( @@ -16,31 +16,60 @@ const getGameAchievements = async ( achievements: true, }, }); - const gameAchievements = await HydraApi.get( + + const cachedAchievements = game?.achievements?.achievements; + + const apiAchievement = HydraApi.get( "/games/achievements", { objectId, shop }, { needsAuth: false } - ); + ) + .then((achievements) => { + if (game) { + gameAchievementRepository.upsert( + { + game: { id: game.id }, + achievements: JSON.stringify(achievements), + }, + ["game"] + ); + } + + return achievements; + }) + .catch(() => []); + + const gameAchievements = cachedAchievements + ? JSON.parse(cachedAchievements) + : await apiAchievement; const unlockedAchievements = JSON.parse( game?.achievements?.unlockedAchievements || "[]" ) as { name: string; unlockTime: number }[]; - return gameAchievements.map((achievement) => { - const unlockedAchiement = unlockedAchievements.find((localAchievement) => { - return localAchievement.name == achievement.name; + return gameAchievements + .map((achievement) => { + const unlockedAchiement = unlockedAchievements.find( + (localAchievement) => { + return localAchievement.name == achievement.name; + } + ); + + if (unlockedAchiement) { + return { + ...achievement, + unlocked: true, + unlockTime: unlockedAchiement.unlockTime * 1000, + }; + } + + return { ...achievement, unlocked: false, unlockTime: null }; + }) + .sort((a, b) => { + if (a.unlocked && !b.unlocked) return -1; + if (!a.unlocked && b.unlocked) return 1; + return b.unlockTime - a.unlockTime; }); - - if (unlockedAchiement) { - return { - ...achievement, - unlocked: true, - unlockTime: unlockedAchiement.unlockTime * 1000, - }; - } - - return { ...achievement, unlocked: false, unlockTime: null }; - }); }; registerEvent("getGameAchievements", getGameAchievements); diff --git a/src/main/services/achievements/services/save-all-local-steam-achivements.ts b/src/main/services/achievements/services/save-all-local-steam-achivements.ts index dad2c2b8..6db5f96a 100644 --- a/src/main/services/achievements/services/save-all-local-steam-achivements.ts +++ b/src/main/services/achievements/services/save-all-local-steam-achivements.ts @@ -48,7 +48,6 @@ export const saveAllLocalSteamAchivements = async () => { ); console.log(achievementFile.filePath); - console.log(localAchievementFile); for (const a of Object.keys(localAchievementFile)) { // TODO: use checkUnlockedAchievements after refactoring it to be generic diff --git a/src/renderer/src/hooks/use-date.ts b/src/renderer/src/hooks/use-date.ts index 01f55610..3657a76e 100644 --- a/src/renderer/src/hooks/use-date.ts +++ b/src/renderer/src/hooks/use-date.ts @@ -1,4 +1,4 @@ -import { formatDistance, subMilliseconds } from "date-fns"; +import { format, formatDistance, subMilliseconds } from "date-fns"; import type { FormatDistanceOptions } from "date-fns"; import { ptBR, @@ -67,5 +67,10 @@ export function useDate() { return ""; } }, + + format: (timestamp: number): string => { + const locale = getDateLocale(); + return format(timestamp, locale == enUS ? "MM/dd/yyyy - HH:mm" : "dd/MM/yyyy - HH:mm"); + }, }; } diff --git a/src/renderer/src/pages/game-details/sidebar/sidebar.tsx b/src/renderer/src/pages/game-details/sidebar/sidebar.tsx index 624b27c4..dee44b1f 100644 --- a/src/renderer/src/pages/game-details/sidebar/sidebar.tsx +++ b/src/renderer/src/pages/game-details/sidebar/sidebar.tsx @@ -5,8 +5,9 @@ import { Button } from "@renderer/components"; import * as styles from "./sidebar.css"; import { gameDetailsContext } from "@renderer/context"; -import { useFormat } from "@renderer/hooks"; +import { useDate, useFormat } from "@renderer/hooks"; import { DownloadIcon, PeopleIcon } from "@primer/octicons-react"; +import { SPACING_UNIT, vars } from "@renderer/theme.css"; export function Sidebar() { const [_howLongToBeat, _setHowLongToBeat] = useState<{ @@ -21,6 +22,7 @@ export function Sidebar() { useContext(gameDetailsContext); const { t } = useTranslation("game_details"); + const { format } = useDate(); const { numberFormatter } = useFormat(); @@ -46,16 +48,42 @@ export function Sidebar() { isLoading={howLongToBeat.isLoading} /> */} - {achievements.map((achievement, index) => ( -
- -

{achievement.displayName}

- {achievement.unlockTime && - new Date(achievement.unlockTime).toDateString()} + {achievements.length && ( +
+ {achievements.map((achievement, index) => ( +
+ +
+

{achievement.displayName}

+ {achievement.unlockTime && format(achievement.unlockTime)} +
+
+ ))}
- ))} + )} {stats && ( <>