feat: refactor game achievement table

This commit is contained in:
Zamitto 2024-09-24 17:31:49 -03:00
parent f3a5f90bc7
commit f98432f6c6
8 changed files with 44 additions and 48 deletions

View file

@ -1,20 +1,15 @@
import { import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
Column,
Entity,
JoinColumn,
OneToOne,
PrimaryGeneratedColumn,
} from "typeorm";
import type { Game } from "./game.entity";
@Entity("game_achievement") @Entity("game_achievement")
export class GameAchievement { export class GameAchievement {
@PrimaryGeneratedColumn() @PrimaryGeneratedColumn()
id: number; id: number;
@OneToOne("Game", "achievements") @Column("text")
@JoinColumn() objectId: string;
game: Game;
@Column("text")
shop: string;
@Column("text", { nullable: true }) @Column("text", { nullable: true })
unlockedAchievements: string; unlockedAchievements: string;

View file

@ -12,7 +12,6 @@ import { Repack } from "./repack.entity";
import type { GameShop, GameStatus } from "@types"; import type { GameShop, GameStatus } from "@types";
import { Downloader } from "@shared"; import { Downloader } from "@shared";
import type { DownloadQueue } from "./download-queue.entity"; import type { DownloadQueue } from "./download-queue.entity";
import { GameAchievement } from "./game-achievements.entity";
@Entity("game") @Entity("game")
export class Game { export class Game {
@ -77,9 +76,6 @@ export class Game {
@JoinColumn() @JoinColumn()
repack: Repack; repack: Repack;
@OneToOne("GameAchievement", "game")
achievements: GameAchievement;
@OneToOne("DownloadQueue", "game") @OneToOne("DownloadQueue", "game")
downloadQueue: DownloadQueue; downloadQueue: DownloadQueue;

View file

@ -1,23 +1,19 @@
import type { GameShop } from "@types"; import type { GameAchievement, GameShop } from "@types";
import { registerEvent } from "../register-event"; import { registerEvent } from "../register-event";
import { HydraApi } from "@main/services"; import { HydraApi } from "@main/services";
import { gameAchievementRepository, gameRepository } from "@main/repository"; import { gameAchievementRepository, gameRepository } from "@main/repository";
import { GameAchievement } from "@main/entity";
const getGameAchievements = async ( const getGameAchievements = async (
_event: Electron.IpcMainInvokeEvent, _event: Electron.IpcMainInvokeEvent,
objectId: string, objectId: string,
shop: GameShop shop: GameShop
): Promise<GameAchievement[]> => { ): Promise<GameAchievement[]> => {
const game = await gameRepository.findOne({ const [game, cachedAchievements] = await Promise.all([
where: { objectID: objectId, shop }, gameRepository.findOne({
relations: { where: { objectID: objectId, shop },
achievements: true, }),
}, gameAchievementRepository.findOne({ where: { objectId, shop } }),
}); ]);
const cachedAchievements = game?.achievements?.achievements;
const apiAchievement = HydraApi.get( const apiAchievement = HydraApi.get(
"/games/achievements", "/games/achievements",
@ -28,10 +24,11 @@ const getGameAchievements = async (
if (game) { if (game) {
gameAchievementRepository.upsert( gameAchievementRepository.upsert(
{ {
game: { id: game.id }, objectId,
shop,
achievements: JSON.stringify(achievements), achievements: JSON.stringify(achievements),
}, },
["game"] ["objectId", "shop"]
); );
} }
@ -39,12 +36,12 @@ const getGameAchievements = async (
}) })
.catch(() => []); .catch(() => []);
const gameAchievements = cachedAchievements const gameAchievements = cachedAchievements?.achievements
? JSON.parse(cachedAchievements) ? JSON.parse(cachedAchievements.achievements)
: await apiAchievement; : await apiAchievement;
const unlockedAchievements = JSON.parse( const unlockedAchievements = JSON.parse(
game?.achievements?.unlockedAchievements || "[]" cachedAchievements?.unlockedAchievements || "[]"
) as { name: string; unlockTime: number }[]; ) as { name: string; unlockTime: number }[];
return gameAchievements return gameAchievements

View file

@ -6,10 +6,11 @@ export const CreateGameAchievement: HydraMigration = {
up: (knex: Knex) => { up: (knex: Knex) => {
return knex.schema.createTable("game_achievement", (table) => { return knex.schema.createTable("game_achievement", (table) => {
table.increments("id").primary(); table.increments("id").primary();
table.integer("gameId").notNullable().unique(); table.text("objectId").notNullable();
table.text("shop").notNullable();
table.text("achievements"); table.text("achievements");
table.text("unlockedAchievements"); table.text("unlockedAchievements");
table.foreign("gameId").references("game.id").onDelete("CASCADE"); table.unique(["objectId", "shop"]);
}); });
}, },

View file

@ -9,17 +9,18 @@ export const saveAllLocalSteamAchivements = async () => {
for (const key of Object.keys(gameAchievementFiles)) { for (const key of Object.keys(gameAchievementFiles)) {
const objectId = key; const objectId = key;
const game = await gameRepository.findOne({ const [game, localAchievements] = await Promise.all([
where: { objectID: objectId }, gameRepository.findOne({
}); where: { objectID: objectId, shop: "steam", isDeleted: false },
}),
gameAchievementRepository.findOne({
where: { objectId, shop: "steam" },
}),
]);
if (!game) continue; if (!game) continue;
const savedGameAchievements = await gameAchievementRepository.findOneBy({ if (!localAchievements || !localAchievements.achievements) {
game: game,
});
if (!savedGameAchievements || !savedGameAchievements.achievements) {
HydraApi.get( HydraApi.get(
"/games/achievements", "/games/achievements",
{ {
@ -31,10 +32,11 @@ export const saveAllLocalSteamAchivements = async () => {
.then((achievements) => { .then((achievements) => {
return gameAchievementRepository.upsert( return gameAchievementRepository.upsert(
{ {
game: { id: game.id }, objectId,
shop: "steam",
achievements: JSON.stringify(achievements), achievements: JSON.stringify(achievements),
}, },
["game"] ["objectId", "shop"]
); );
}) })
.catch(console.log); .catch(console.log);
@ -58,12 +60,13 @@ export const saveAllLocalSteamAchivements = async () => {
} }
} }
await gameAchievementRepository.upsert( gameAchievementRepository.upsert(
{ {
game: { id: game.id }, objectId,
shop: "steam",
unlockedAchievements: JSON.stringify(unlockedAchievements), unlockedAchievements: JSON.stringify(unlockedAchievements),
}, },
["game"] ["objectId", "shop"]
); );
} }
}; };

View file

@ -31,6 +31,7 @@ export const gameDetailsContext = createContext<GameDetailsContext>({
showRepacksModal: false, showRepacksModal: false,
showGameOptionsModal: false, showGameOptionsModal: false,
stats: null, stats: null,
achievements: [],
hasNSFWContentBlocked: false, hasNSFWContentBlocked: false,
setGameColor: () => {}, setGameColor: () => {},
selectGameExecutable: async () => null, selectGameExecutable: async () => null,

View file

@ -70,7 +70,10 @@ export function useDate() {
format: (timestamp: number): string => { format: (timestamp: number): string => {
const locale = getDateLocale(); const locale = getDateLocale();
return format(timestamp, locale == enUS ? "MM/dd/yyyy - HH:mm" : "dd/MM/yyyy - HH:mm"); return format(
timestamp,
locale == enUS ? "MM/dd/yyyy - HH:mm" : "dd/MM/yyyy - HH:mm"
);
}, },
}; };
} }

View file

@ -7,7 +7,7 @@ import * as styles from "./sidebar.css";
import { gameDetailsContext } from "@renderer/context"; import { gameDetailsContext } from "@renderer/context";
import { useDate, useFormat } from "@renderer/hooks"; import { useDate, useFormat } from "@renderer/hooks";
import { DownloadIcon, PeopleIcon } from "@primer/octicons-react"; import { DownloadIcon, PeopleIcon } from "@primer/octicons-react";
import { SPACING_UNIT, vars } from "@renderer/theme.css"; import { SPACING_UNIT } from "@renderer/theme.css";
export function Sidebar() { export function Sidebar() {
const [_howLongToBeat, _setHowLongToBeat] = useState<{ const [_howLongToBeat, _setHowLongToBeat] = useState<{