mirror of
https://github.com/hydralauncher/hydra.git
synced 2025-01-23 21:44:55 +03:00
feat: refactor
This commit is contained in:
parent
3dcdcae9a7
commit
c8022896a6
@ -1,23 +1,81 @@
|
|||||||
import type {
|
import type {
|
||||||
AchievementData,
|
AchievementData,
|
||||||
GameAchievement,
|
|
||||||
GameShop,
|
GameShop,
|
||||||
|
RemoteUnlockedAchievement,
|
||||||
UnlockedAchievement,
|
UnlockedAchievement,
|
||||||
|
UserAchievement,
|
||||||
} from "@types";
|
} from "@types";
|
||||||
import { registerEvent } from "../register-event";
|
import { registerEvent } from "../register-event";
|
||||||
import {
|
import {
|
||||||
gameAchievementRepository,
|
gameAchievementRepository,
|
||||||
userAuthRepository,
|
userPreferencesRepository,
|
||||||
} from "@main/repository";
|
} from "@main/repository";
|
||||||
import { getGameAchievementData } from "@main/services/achievements/get-game-achievement-data";
|
import { getGameAchievementData } from "@main/services/achievements/get-game-achievement-data";
|
||||||
import { HydraApi } from "@main/services";
|
import { HydraApi, logger } from "@main/services";
|
||||||
|
|
||||||
const getAchievements = async (
|
const getAchievementLocalUser = async (shop: string, objectId: string) => {
|
||||||
|
const cachedAchievements = await gameAchievementRepository.findOne({
|
||||||
|
where: { objectId, shop },
|
||||||
|
});
|
||||||
|
|
||||||
|
const achievementsData: AchievementData[] = cachedAchievements?.achievements
|
||||||
|
? JSON.parse(cachedAchievements.achievements)
|
||||||
|
: await getGameAchievementData(objectId, shop);
|
||||||
|
|
||||||
|
const unlockedAchievements = JSON.parse(
|
||||||
|
cachedAchievements?.unlockedAchievements || "[]"
|
||||||
|
) as UnlockedAchievement[];
|
||||||
|
|
||||||
|
return achievementsData
|
||||||
|
.map((achievementData) => {
|
||||||
|
logger.info("unclockedAchievements", unlockedAchievements);
|
||||||
|
|
||||||
|
const unlockedAchiementData = unlockedAchievements.find(
|
||||||
|
(localAchievement) => {
|
||||||
|
return (
|
||||||
|
localAchievement.name.toUpperCase() ==
|
||||||
|
achievementData.name.toUpperCase()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const icongray = achievementData.icongray.endsWith("/")
|
||||||
|
? achievementData.icon
|
||||||
|
: achievementData.icongray;
|
||||||
|
|
||||||
|
if (unlockedAchiementData) {
|
||||||
|
return {
|
||||||
|
...achievementData,
|
||||||
|
unlocked: true,
|
||||||
|
unlockTime: unlockedAchiementData.unlockTime,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...achievementData,
|
||||||
|
unlocked: false,
|
||||||
|
unlockTime: null,
|
||||||
|
icon: icongray,
|
||||||
|
} as UserAchievement;
|
||||||
|
})
|
||||||
|
.sort((a, b) => {
|
||||||
|
if (a.unlocked && !b.unlocked) return -1;
|
||||||
|
if (!a.unlocked && b.unlocked) return 1;
|
||||||
|
if (a.unlocked && b.unlocked) {
|
||||||
|
return b.unlockTime! - a.unlockTime!;
|
||||||
|
}
|
||||||
|
return Number(a.hidden) - Number(b.hidden);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const getAchievementsRemoteUser = async (
|
||||||
shop: string,
|
shop: string,
|
||||||
objectId: string,
|
objectId: string,
|
||||||
userId?: string
|
userId: string
|
||||||
) => {
|
) => {
|
||||||
const userAuth = await userAuthRepository.findOne({ where: { userId } });
|
const userPreferences = await userPreferencesRepository.findOne({
|
||||||
|
where: { id: 1 },
|
||||||
|
});
|
||||||
|
|
||||||
const cachedAchievements = await gameAchievementRepository.findOne({
|
const cachedAchievements = await gameAchievementRepository.findOne({
|
||||||
where: { objectId, shop },
|
where: { objectId, shop },
|
||||||
@ -27,31 +85,9 @@ const getAchievements = async (
|
|||||||
? JSON.parse(cachedAchievements.achievements)
|
? JSON.parse(cachedAchievements.achievements)
|
||||||
: await getGameAchievementData(objectId, shop);
|
: await getGameAchievementData(objectId, shop);
|
||||||
|
|
||||||
if (!userId || userAuth) {
|
const unlockedAchievements = await HydraApi.get<RemoteUnlockedAchievement[]>(
|
||||||
const unlockedAchievements = JSON.parse(
|
|
||||||
cachedAchievements?.unlockedAchievements || "[]"
|
|
||||||
) as UnlockedAchievement[];
|
|
||||||
|
|
||||||
return { achievementsData, unlockedAchievements };
|
|
||||||
}
|
|
||||||
|
|
||||||
const unlockedAchievements = await HydraApi.get<UnlockedAchievement[]>(
|
|
||||||
`/users/${userId}/games/achievements`,
|
`/users/${userId}/games/achievements`,
|
||||||
{ shop, objectId, language: "en" }
|
{ shop, objectId, language: userPreferences?.language || "en" }
|
||||||
);
|
|
||||||
|
|
||||||
return { achievementsData, unlockedAchievements };
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getGameAchievements = async (
|
|
||||||
objectId: string,
|
|
||||||
shop: GameShop,
|
|
||||||
userId?: string
|
|
||||||
): Promise<GameAchievement[]> => {
|
|
||||||
const { achievementsData, unlockedAchievements } = await getAchievements(
|
|
||||||
shop,
|
|
||||||
objectId,
|
|
||||||
userId
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return achievementsData
|
return achievementsData
|
||||||
@ -74,7 +110,6 @@ export const getGameAchievements = async (
|
|||||||
...achievementData,
|
...achievementData,
|
||||||
unlocked: true,
|
unlocked: true,
|
||||||
unlockTime: unlockedAchiementData.unlockTime,
|
unlockTime: unlockedAchiementData.unlockTime,
|
||||||
icongray,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,8 +117,8 @@ export const getGameAchievements = async (
|
|||||||
...achievementData,
|
...achievementData,
|
||||||
unlocked: false,
|
unlocked: false,
|
||||||
unlockTime: null,
|
unlockTime: null,
|
||||||
icongray,
|
icon: icongray,
|
||||||
} as GameAchievement;
|
} as UserAchievement;
|
||||||
})
|
})
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
if (a.unlocked && !b.unlocked) return -1;
|
if (a.unlocked && !b.unlocked) return -1;
|
||||||
@ -95,12 +130,24 @@ export const getGameAchievements = async (
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getGameAchievements = async (
|
||||||
|
objectId: string,
|
||||||
|
shop: GameShop,
|
||||||
|
userId?: string
|
||||||
|
): Promise<UserAchievement[]> => {
|
||||||
|
if (!userId) {
|
||||||
|
return getAchievementLocalUser(shop, objectId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return getAchievementsRemoteUser(shop, objectId, userId);
|
||||||
|
};
|
||||||
|
|
||||||
const getGameAchievementsEvent = async (
|
const getGameAchievementsEvent = async (
|
||||||
_event: Electron.IpcMainInvokeEvent,
|
_event: Electron.IpcMainInvokeEvent,
|
||||||
objectId: string,
|
objectId: string,
|
||||||
shop: GameShop,
|
shop: GameShop,
|
||||||
userId?: string
|
userId?: string
|
||||||
): Promise<GameAchievement[]> => {
|
): Promise<UserAchievement[]> => {
|
||||||
return getGameAchievements(objectId, shop, userId);
|
return getGameAchievements(objectId, shop, userId);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -12,11 +12,11 @@ import { useAppDispatch, useAppSelector, useDownload } from "@renderer/hooks";
|
|||||||
|
|
||||||
import type {
|
import type {
|
||||||
Game,
|
Game,
|
||||||
GameAchievement,
|
|
||||||
GameRepack,
|
GameRepack,
|
||||||
GameShop,
|
GameShop,
|
||||||
GameStats,
|
GameStats,
|
||||||
ShopDetails,
|
ShopDetails,
|
||||||
|
UserAchievement,
|
||||||
} from "@types";
|
} from "@types";
|
||||||
|
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
@ -64,7 +64,7 @@ export function GameDetailsContextProvider({
|
|||||||
shop,
|
shop,
|
||||||
}: GameDetailsContextProps) {
|
}: GameDetailsContextProps) {
|
||||||
const [shopDetails, setShopDetails] = useState<ShopDetails | null>(null);
|
const [shopDetails, setShopDetails] = useState<ShopDetails | null>(null);
|
||||||
const [achievements, setAchievements] = useState<GameAchievement[]>([]);
|
const [achievements, setAchievements] = useState<UserAchievement[]>([]);
|
||||||
const [game, setGame] = useState<Game | null>(null);
|
const [game, setGame] = useState<Game | null>(null);
|
||||||
const [hasNSFWContentBlocked, setHasNSFWContentBlocked] = useState(false);
|
const [hasNSFWContentBlocked, setHasNSFWContentBlocked] = useState(false);
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import type {
|
import type {
|
||||||
Game,
|
Game,
|
||||||
GameAchievement,
|
|
||||||
GameRepack,
|
GameRepack,
|
||||||
GameShop,
|
GameShop,
|
||||||
GameStats,
|
GameStats,
|
||||||
ShopDetails,
|
ShopDetails,
|
||||||
|
UserAchievement,
|
||||||
} from "@types";
|
} from "@types";
|
||||||
|
|
||||||
export interface GameDetailsContext {
|
export interface GameDetailsContext {
|
||||||
@ -20,7 +20,7 @@ export interface GameDetailsContext {
|
|||||||
showRepacksModal: boolean;
|
showRepacksModal: boolean;
|
||||||
showGameOptionsModal: boolean;
|
showGameOptionsModal: boolean;
|
||||||
stats: GameStats | null;
|
stats: GameStats | null;
|
||||||
achievements: GameAchievement[];
|
achievements: UserAchievement[];
|
||||||
hasNSFWContentBlocked: boolean;
|
hasNSFWContentBlocked: boolean;
|
||||||
setGameColor: React.Dispatch<React.SetStateAction<string>>;
|
setGameColor: React.Dispatch<React.SetStateAction<string>>;
|
||||||
selectGameExecutable: () => Promise<string | null>;
|
selectGameExecutable: () => Promise<string | null>;
|
||||||
|
3
src/renderer/src/declaration.d.ts
vendored
3
src/renderer/src/declaration.d.ts
vendored
@ -28,6 +28,7 @@ import type {
|
|||||||
GameAchievement,
|
GameAchievement,
|
||||||
GameArtifact,
|
GameArtifact,
|
||||||
LudusaviBackup,
|
LudusaviBackup,
|
||||||
|
UserAchievement,
|
||||||
} from "@types";
|
} from "@types";
|
||||||
import type { AxiosProgressEvent } from "axios";
|
import type { AxiosProgressEvent } from "axios";
|
||||||
import type { DiskSpace } from "check-disk-space";
|
import type { DiskSpace } from "check-disk-space";
|
||||||
@ -68,7 +69,7 @@ declare global {
|
|||||||
objectId: string,
|
objectId: string,
|
||||||
shop: GameShop,
|
shop: GameShop,
|
||||||
userId?: string
|
userId?: string
|
||||||
) => Promise<GameAchievement[]>;
|
) => Promise<UserAchievement[]>;
|
||||||
onAchievementUnlocked: (
|
onAchievementUnlocked: (
|
||||||
cb: (
|
cb: (
|
||||||
objectId: string,
|
objectId: string,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { setHeaderTitle } from "@renderer/features";
|
import { setHeaderTitle } from "@renderer/features";
|
||||||
import { useAppDispatch, useDate } from "@renderer/hooks";
|
import { useAppDispatch, useDate } from "@renderer/hooks";
|
||||||
import { steamUrlBuilder } from "@shared";
|
import { steamUrlBuilder } from "@shared";
|
||||||
import type { GameAchievement, GameShop } from "@types";
|
import type { GameShop, UserAchievement } from "@types";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useNavigate, useSearchParams } from "react-router-dom";
|
import { useNavigate, useSearchParams } from "react-router-dom";
|
||||||
@ -28,7 +28,7 @@ export function Achievement() {
|
|||||||
|
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
const [achievements, setAchievements] = useState<GameAchievement[]>([]);
|
const [achievements, setAchievements] = useState<UserAchievement[]>([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (objectId && shop) {
|
if (objectId && shop) {
|
||||||
@ -130,9 +130,7 @@ export function Achievement() {
|
|||||||
className={styles.listItemImage({
|
className={styles.listItemImage({
|
||||||
unlocked: achievement.unlocked,
|
unlocked: achievement.unlocked,
|
||||||
})}
|
})}
|
||||||
src={
|
src={achievement.icon}
|
||||||
achievement.unlocked ? achievement.icon : achievement.icongray
|
|
||||||
}
|
|
||||||
alt={achievement.displayName}
|
alt={achievement.displayName}
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
/>
|
/>
|
||||||
|
@ -91,11 +91,7 @@ export function Sidebar() {
|
|||||||
className={styles.listItemImage({
|
className={styles.listItemImage({
|
||||||
unlocked: achievement.unlocked,
|
unlocked: achievement.unlocked,
|
||||||
})}
|
})}
|
||||||
src={
|
src={achievement.icon}
|
||||||
achievement.unlocked
|
|
||||||
? achievement.icon
|
|
||||||
: achievement.icongray
|
|
||||||
}
|
|
||||||
alt={achievement.displayName}
|
alt={achievement.displayName}
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
/>
|
/>
|
||||||
|
@ -37,15 +37,34 @@ export interface AchievementData {
|
|||||||
hidden: boolean;
|
hidden: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface UserAchievement {
|
||||||
|
name: string;
|
||||||
|
hidden: boolean;
|
||||||
|
displayName: string;
|
||||||
|
description?: string;
|
||||||
|
unlocked: boolean;
|
||||||
|
unlockTime: number | null;
|
||||||
|
icon: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RemoteUnlockedAchievement {
|
||||||
|
name: string;
|
||||||
|
hidden: boolean;
|
||||||
|
icon: string;
|
||||||
|
displayName: string;
|
||||||
|
description?: string;
|
||||||
|
unlockTime: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface GameAchievement {
|
export interface GameAchievement {
|
||||||
name: string;
|
name: string;
|
||||||
|
hidden: boolean;
|
||||||
displayName: string;
|
displayName: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
unlocked: boolean;
|
unlocked: boolean;
|
||||||
unlockTime: number | null;
|
unlockTime: number | null;
|
||||||
icon: string;
|
icon: string;
|
||||||
icongray: string;
|
icongray: string;
|
||||||
hidden: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ShopDetails = SteamAppDetails & {
|
export type ShopDetails = SteamAppDetails & {
|
||||||
|
Loading…
Reference in New Issue
Block a user