mirror of
https://github.com/hydralauncher/hydra.git
synced 2025-02-12 19:22:28 +00:00
feat: refactor game achievement table
This commit is contained in:
parent
f3a5f90bc7
commit
f98432f6c6
8 changed files with 44 additions and 48 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"]);
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -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"]
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -31,6 +31,7 @@ export const gameDetailsContext = createContext<GameDetailsContext>({
|
|||
showRepacksModal: false,
|
||||
showGameOptionsModal: false,
|
||||
stats: null,
|
||||
achievements: [],
|
||||
hasNSFWContentBlocked: false,
|
||||
setGameColor: () => {},
|
||||
selectGameExecutable: async () => null,
|
||||
|
|
|
@ -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"
|
||||
);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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<{
|
||||
|
|
Loading…
Reference in a new issue