mirror of
https://github.com/hydralauncher/hydra.git
synced 2026-01-11 13:56:16 +00:00
feat: refactor assets in game details page
This commit is contained in:
@@ -34,8 +34,8 @@ const getGameShopDetails = async (
|
||||
gamesShopAssetsSublevel.get(levelKeys.game(shop, objectId)),
|
||||
]);
|
||||
|
||||
const appDetails: Promise<ShopDetailsWithAssets | null> =
|
||||
getLocalizedSteamAppDetails(objectId, language).then((result) => {
|
||||
const appDetails = getLocalizedSteamAppDetails(objectId, language).then(
|
||||
(result) => {
|
||||
if (result) {
|
||||
result.name = cachedAssets?.title ?? result.name;
|
||||
|
||||
@@ -47,21 +47,22 @@ const getGameShopDetails = async (
|
||||
|
||||
return {
|
||||
...result,
|
||||
...cachedAssets,
|
||||
assets: cachedAssets ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
if (cachedData) {
|
||||
return {
|
||||
...cachedData,
|
||||
...cachedAssets,
|
||||
assets: cachedAssets ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
return Promise.resolve(appDetails);
|
||||
return appDetails;
|
||||
}
|
||||
|
||||
throw new Error("Not implemented");
|
||||
|
||||
@@ -28,12 +28,6 @@ export function Hero() {
|
||||
});
|
||||
}, [i18n.language]);
|
||||
|
||||
const handleClick = async (game: TrendingGame) => {
|
||||
await window.electron.saveGameShopAssets(game.objectId, game.shop, game);
|
||||
|
||||
navigate(game.uri);
|
||||
};
|
||||
|
||||
if (isLoading) {
|
||||
return <Skeleton className="hero" />;
|
||||
}
|
||||
@@ -42,7 +36,7 @@ export function Hero() {
|
||||
return featuredGameDetails.map((game) => (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleClick(game)}
|
||||
onClick={() => navigate(game.uri)}
|
||||
className="hero"
|
||||
key={game.uri}
|
||||
>
|
||||
|
||||
@@ -21,7 +21,7 @@ import type {
|
||||
GameShop,
|
||||
GameStats,
|
||||
LibraryGame,
|
||||
ShopDetails,
|
||||
ShopDetailsWithAssets,
|
||||
UserAchievement,
|
||||
} from "@types";
|
||||
|
||||
@@ -69,7 +69,9 @@ export function GameDetailsContextProvider({
|
||||
gameTitle,
|
||||
shop,
|
||||
}: Readonly<GameDetailsContextProps>) {
|
||||
const [shopDetails, setShopDetails] = useState<ShopDetails | null>(null);
|
||||
const [shopDetails, setShopDetails] = useState<ShopDetailsWithAssets | null>(
|
||||
null
|
||||
);
|
||||
const [achievements, setAchievements] = useState<UserAchievement[] | null>(
|
||||
null
|
||||
);
|
||||
@@ -135,19 +137,42 @@ export function GameDetailsContextProvider({
|
||||
) {
|
||||
setHasNSFWContentBlocked(true);
|
||||
}
|
||||
|
||||
if (result?.assets) {
|
||||
setIsLoading(false);
|
||||
}
|
||||
});
|
||||
|
||||
const statsPromise = window.electron
|
||||
.getGameStats(objectId, shop)
|
||||
.then((result) => {
|
||||
if (abortController.signal.aborted) return;
|
||||
if (abortController.signal.aborted) return null;
|
||||
setStats(result);
|
||||
return result;
|
||||
});
|
||||
|
||||
Promise.all([shopDetailsPromise, statsPromise]).finally(() => {
|
||||
if (abortController.signal.aborted) return;
|
||||
setIsLoading(false);
|
||||
});
|
||||
Promise.all([shopDetailsPromise, statsPromise])
|
||||
.then(([_, stats]) => {
|
||||
if (stats) {
|
||||
const assets = stats.assets;
|
||||
if (assets) {
|
||||
window.electron.saveGameShopAssets(objectId, shop, assets);
|
||||
|
||||
setShopDetails((prev) => {
|
||||
if (!prev) return null;
|
||||
console.log("assets", assets);
|
||||
return {
|
||||
...prev,
|
||||
assets,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
if (abortController.signal.aborted) return;
|
||||
setIsLoading(false);
|
||||
});
|
||||
|
||||
if (userDetails) {
|
||||
window.electron
|
||||
|
||||
@@ -137,10 +137,13 @@ export function AchievementsContent({
|
||||
}, [dispatch, gameTitle]);
|
||||
|
||||
const handleHeroLoad = async () => {
|
||||
const output = await average(shopDetails?.libraryHeroImageUrl ?? "", {
|
||||
amount: 1,
|
||||
format: "hex",
|
||||
});
|
||||
const output = await average(
|
||||
shopDetails?.assets?.libraryHeroImageUrl ?? "",
|
||||
{
|
||||
amount: 1,
|
||||
format: "hex",
|
||||
}
|
||||
);
|
||||
|
||||
const backgroundColor = output
|
||||
? (new Color(output).darken(0.7).toString() as string)
|
||||
@@ -185,7 +188,7 @@ export function AchievementsContent({
|
||||
return (
|
||||
<div className="achievements-content__achievements-list">
|
||||
<img
|
||||
src={shopDetails?.libraryHeroImageUrl ?? ""}
|
||||
src={shopDetails?.assets?.libraryHeroImageUrl ?? ""}
|
||||
className="achievements-content__achievements-list__image"
|
||||
alt={gameTitle}
|
||||
onLoad={handleHeroLoad}
|
||||
@@ -211,7 +214,7 @@ export function AchievementsContent({
|
||||
to={buildGameDetailsPath({ shop, objectId, title: gameTitle })}
|
||||
>
|
||||
<img
|
||||
src={shopDetails?.logoImageUrl ?? ""}
|
||||
src={shopDetails?.assets?.logoImageUrl ?? ""}
|
||||
className="achievements-content__achievements-list__section__container__hero__content__game-logo"
|
||||
alt={gameTitle}
|
||||
/>
|
||||
|
||||
@@ -43,19 +43,11 @@ export function GameItem({ game }: GameItemProps) {
|
||||
});
|
||||
}, [game.genres, language, steamGenres]);
|
||||
|
||||
const handleNavigateToGameDetails = async () => {
|
||||
await window.electron.saveGameShopAssets(game.objectId, game.shop, {
|
||||
...game,
|
||||
});
|
||||
|
||||
navigate(buildGameDetailsPath(game));
|
||||
};
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className="game-item"
|
||||
onClick={handleNavigateToGameDetails}
|
||||
onClick={() => navigate(buildGameDetailsPath(game))}
|
||||
>
|
||||
<img
|
||||
className="game-item__cover"
|
||||
|
||||
@@ -24,7 +24,6 @@ export function GameDetailsContent() {
|
||||
const {
|
||||
objectId,
|
||||
shopDetails,
|
||||
stats,
|
||||
game,
|
||||
gameColor,
|
||||
setGameColor,
|
||||
@@ -60,10 +59,13 @@ export function GameDetailsContent() {
|
||||
const [backdropOpacity, setBackdropOpacity] = useState(1);
|
||||
|
||||
const handleHeroLoad = async () => {
|
||||
const output = await average(stats?.assets?.libraryHeroImageUrl ?? "", {
|
||||
amount: 1,
|
||||
format: "hex",
|
||||
});
|
||||
const output = await average(
|
||||
shopDetails?.assets?.libraryHeroImageUrl ?? "",
|
||||
{
|
||||
amount: 1,
|
||||
format: "hex",
|
||||
}
|
||||
);
|
||||
|
||||
const backgroundColor = output
|
||||
? new Color(output).darken(0.7).toString()
|
||||
@@ -101,7 +103,7 @@ export function GameDetailsContent() {
|
||||
<section className="game-details__container">
|
||||
<div ref={heroRef} className="game-details__hero">
|
||||
<img
|
||||
src={stats?.assets?.libraryHeroImageUrl ?? ""}
|
||||
src={shopDetails?.assets?.libraryHeroImageUrl ?? ""}
|
||||
className="game-details__hero-image"
|
||||
alt={game?.title}
|
||||
onLoad={handleHeroLoad}
|
||||
@@ -120,7 +122,7 @@ export function GameDetailsContent() {
|
||||
>
|
||||
<div className="game-details__hero-content">
|
||||
<img
|
||||
src={stats?.assets?.logoImageUrl ?? ""}
|
||||
src={shopDetails?.assets?.logoImageUrl ?? ""}
|
||||
className="game-details__game-logo"
|
||||
alt={game?.title}
|
||||
/>
|
||||
|
||||
@@ -94,12 +94,6 @@ export default function Home() {
|
||||
}
|
||||
};
|
||||
|
||||
const handleClickGameCard = async (game: ShopAssets) => {
|
||||
await window.electron.saveGameShopAssets(game.objectId, game.shop, game);
|
||||
|
||||
navigate(buildGameDetailsPath(game));
|
||||
};
|
||||
|
||||
return (
|
||||
<SkeletonTheme baseColor="#1c1c1c" highlightColor="#444">
|
||||
<section className="home__content">
|
||||
@@ -183,7 +177,7 @@ export default function Home() {
|
||||
<GameCard
|
||||
key={result.objectId}
|
||||
game={result}
|
||||
onClick={() => handleClickGameCard(result)}
|
||||
onClick={() => navigate(buildGameDetailsPath(result))}
|
||||
/>
|
||||
))}
|
||||
</section>
|
||||
|
||||
@@ -52,7 +52,9 @@ export type ShopDetails = SteamAppDetails & {
|
||||
objectId: string;
|
||||
};
|
||||
|
||||
export type ShopDetailsWithAssets = ShopDetails & Partial<ShopAssets>;
|
||||
export type ShopDetailsWithAssets = ShopDetails & {
|
||||
assets: ShopAssets | null;
|
||||
};
|
||||
|
||||
export interface TorrentFile {
|
||||
path: string;
|
||||
|
||||
Reference in New Issue
Block a user