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 {
Column,
Entity,
JoinColumn,
OneToOne,
PrimaryGeneratedColumn,
} from "typeorm";
import type { Game } from "./game.entity";
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
@Entity("game_achievement")
export class GameAchievement {
@PrimaryGeneratedColumn()
id: number;
@OneToOne("Game", "achievements")
@JoinColumn()
game: Game;
@Column("text")
objectId: string;
@Column("text")
shop: string;
@Column("text", { nullable: true })
unlockedAchievements: string;

View file

@ -12,7 +12,6 @@ import { Repack } from "./repack.entity";
import type { GameShop, GameStatus } from "@types";
import { Downloader } from "@shared";
import type { DownloadQueue } from "./download-queue.entity";
import { GameAchievement } from "./game-achievements.entity";
@Entity("game")
export class Game {
@ -77,9 +76,6 @@ export class Game {
@JoinColumn()
repack: Repack;
@OneToOne("GameAchievement", "game")
achievements: GameAchievement;
@OneToOne("DownloadQueue", "game")
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 { HydraApi } from "@main/services";
import { gameAchievementRepository, gameRepository } from "@main/repository";
import { GameAchievement } from "@main/entity";
const getGameAchievements = async (
_event: Electron.IpcMainInvokeEvent,
objectId: string,
shop: GameShop
): Promise<GameAchievement[]> => {
const game = await gameRepository.findOne({
where: { objectID: objectId, shop },
relations: {
achievements: true,
},
});
const cachedAchievements = game?.achievements?.achievements;
const [game, cachedAchievements] = await Promise.all([
gameRepository.findOne({
where: { objectID: objectId, shop },
}),
gameAchievementRepository.findOne({ where: { objectId, shop } }),
]);
const apiAchievement = HydraApi.get(
"/games/achievements",
@ -28,10 +24,11 @@ const getGameAchievements = async (
if (game) {
gameAchievementRepository.upsert(
{
game: { id: game.id },
objectId,
shop,
achievements: JSON.stringify(achievements),
},
["game"]
["objectId", "shop"]
);
}
@ -39,12 +36,12 @@ const getGameAchievements = async (
})
.catch(() => []);
const gameAchievements = cachedAchievements
? JSON.parse(cachedAchievements)
const gameAchievements = cachedAchievements?.achievements
? JSON.parse(cachedAchievements.achievements)
: await apiAchievement;
const unlockedAchievements = JSON.parse(
game?.achievements?.unlockedAchievements || "[]"
cachedAchievements?.unlockedAchievements || "[]"
) as { name: string; unlockTime: number }[];
return gameAchievements

View file

@ -6,10 +6,11 @@ export const CreateGameAchievement: HydraMigration = {
up: (knex: Knex) => {
return knex.schema.createTable("game_achievement", (table) => {
table.increments("id").primary();
table.integer("gameId").notNullable().unique();
table.text("objectId").notNullable();
table.text("shop").notNullable();
table.text("achievements");
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)) {
const objectId = key;
const game = await gameRepository.findOne({
where: { objectID: objectId },
});
const [game, localAchievements] = await Promise.all([
gameRepository.findOne({
where: { objectID: objectId, shop: "steam", isDeleted: false },
}),
gameAchievementRepository.findOne({
where: { objectId, shop: "steam" },
}),
]);
if (!game) continue;
const savedGameAchievements = await gameAchievementRepository.findOneBy({
game: game,
});
if (!savedGameAchievements || !savedGameAchievements.achievements) {
if (!localAchievements || !localAchievements.achievements) {
HydraApi.get(
"/games/achievements",
{
@ -31,10 +32,11 @@ export const saveAllLocalSteamAchivements = async () => {
.then((achievements) => {
return gameAchievementRepository.upsert(
{
game: { id: game.id },
objectId,
shop: "steam",
achievements: JSON.stringify(achievements),
},
["game"]
["objectId", "shop"]
);
})
.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),
},
["game"]
["objectId", "shop"]
);
}
};

View file

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

View file

@ -70,7 +70,10 @@ export function useDate() {
format: (timestamp: number): string => {
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 { useDate, useFormat } from "@renderer/hooks";
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() {
const [_howLongToBeat, _setHowLongToBeat] = useState<{