mirror of
https://github.com/hydralauncher/hydra.git
synced 2025-02-14 20:22:10 +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 {
|
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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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"]);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -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"]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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"
|
||||||
|
);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<{
|
||||||
|
|
Loading…
Reference in a new issue