mirror of
https://github.com/hydralauncher/hydra.git
synced 2026-01-18 00:33:59 +00:00
feat: get image assets from api
This commit is contained in:
@@ -6,7 +6,8 @@ export const LUDUSAVI_MANIFEST_URL = "https://cdn.losbroxas.org/manifest.yaml";
|
||||
|
||||
export const defaultDownloadsPath = SystemPath.getPath("downloads");
|
||||
|
||||
export const isStaging = import.meta.env.MAIN_VITE_API_URL.includes("staging");
|
||||
export const isStaging =
|
||||
true || import.meta.env.MAIN_VITE_API_URL.includes("staging");
|
||||
|
||||
export const windowsStartMenuPath = path.join(
|
||||
SystemPath.getPath("appData"),
|
||||
|
||||
@@ -11,12 +11,12 @@ const getTrendingGames = async (_event: Electron.IpcMainInvokeEvent) => {
|
||||
.then((language) => language || "en");
|
||||
|
||||
const trendingGames = await HydraApi.get<TrendingGame[]>(
|
||||
"/games/trending",
|
||||
"/games/featured",
|
||||
{ language },
|
||||
{ needsAuth: false }
|
||||
).catch(() => []);
|
||||
|
||||
return trendingGames;
|
||||
return trendingGames.slice(0, 1);
|
||||
};
|
||||
|
||||
registerEvent("getTrendingGames", getTrendingGames);
|
||||
|
||||
@@ -1,25 +1,6 @@
|
||||
import { registerEvent } from "../register-event";
|
||||
import { HydraApi, logger } from "@main/services";
|
||||
import { steamGamesWorker } from "@main/workers";
|
||||
import { HydraApi } from "@main/services";
|
||||
import type { UserProfile } from "@types";
|
||||
import { steamUrlBuilder } from "@shared";
|
||||
|
||||
const getSteamGame = async (objectId: string) => {
|
||||
try {
|
||||
const steamGame = await steamGamesWorker.run(Number(objectId), {
|
||||
name: "getById",
|
||||
});
|
||||
|
||||
return {
|
||||
title: steamGame.name as string,
|
||||
iconUrl: steamUrlBuilder.icon(objectId, steamGame.clientIcon),
|
||||
};
|
||||
} catch (err) {
|
||||
logger.error("Failed to get Steam game", err);
|
||||
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const getUser = async (
|
||||
_event: Electron.IpcMainInvokeEvent,
|
||||
@@ -30,62 +11,11 @@ const getUser = async (
|
||||
|
||||
if (!profile) return null;
|
||||
|
||||
const recentGames = await Promise.all(
|
||||
profile.recentGames
|
||||
.map(async (game) => {
|
||||
const steamGame = await getSteamGame(game.objectId);
|
||||
|
||||
return {
|
||||
...game,
|
||||
...steamGame,
|
||||
};
|
||||
})
|
||||
.filter((game) => game)
|
||||
);
|
||||
|
||||
const libraryGames = await Promise.all(
|
||||
profile.libraryGames
|
||||
.map(async (game) => {
|
||||
const steamGame = await getSteamGame(game.objectId);
|
||||
|
||||
return {
|
||||
...game,
|
||||
...steamGame,
|
||||
};
|
||||
})
|
||||
.filter((game) => game)
|
||||
);
|
||||
|
||||
if (profile.currentGame) {
|
||||
const steamGame = await getSteamGame(profile.currentGame.objectId);
|
||||
|
||||
if (steamGame) {
|
||||
profile.currentGame = {
|
||||
...profile.currentGame,
|
||||
...steamGame,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const friends = await Promise.all(
|
||||
profile.friends.map(async (friend) => {
|
||||
if (!friend.currentGame) return friend;
|
||||
|
||||
const currentGame = await getSteamGame(friend.currentGame.objectId);
|
||||
|
||||
return {
|
||||
...friend,
|
||||
currentGame: {
|
||||
...friend.currentGame,
|
||||
...currentGame,
|
||||
},
|
||||
};
|
||||
})
|
||||
);
|
||||
const recentGames = profile.recentGames.filter((game) => game);
|
||||
const libraryGames = profile.libraryGames.filter((game) => game);
|
||||
|
||||
return {
|
||||
...profile,
|
||||
friends,
|
||||
libraryGames,
|
||||
recentGames,
|
||||
};
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { HydraApi } from "../hydra-api";
|
||||
import { steamGamesWorker } from "@main/workers";
|
||||
import { steamUrlBuilder } from "@shared";
|
||||
import { gamesSublevel, levelKeys } from "@main/level";
|
||||
|
||||
export const mergeWithRemoteGames = async () => {
|
||||
@@ -31,20 +29,12 @@ export const mergeWithRemoteGames = async () => {
|
||||
playTimeInMilliseconds: updatedPlayTime,
|
||||
});
|
||||
} else {
|
||||
const steamGame = await steamGamesWorker.run(Number(game.objectId), {
|
||||
name: "getById",
|
||||
});
|
||||
|
||||
const iconUrl = steamGame?.clientIcon
|
||||
? steamUrlBuilder.icon(game.objectId, steamGame.clientIcon)
|
||||
: null;
|
||||
|
||||
await gamesSublevel.put(levelKeys.game(game.shop, game.objectId), {
|
||||
objectId: game.objectId,
|
||||
title: steamGame?.name,
|
||||
title: game.title,
|
||||
remoteId: game.id,
|
||||
shop: game.shop,
|
||||
iconUrl,
|
||||
iconUrl: game.iconUrl,
|
||||
lastTimePlayed: game.lastTimePlayed,
|
||||
playTimeInMilliseconds: game.playTimeInMilliseconds,
|
||||
isDeleted: false,
|
||||
|
||||
@@ -9,7 +9,6 @@ import { useTranslation } from "react-i18next";
|
||||
import { Badge } from "../badge/badge";
|
||||
import { useCallback, useState, useMemo } from "react";
|
||||
import { useFormat, useRepacks } from "@renderer/hooks";
|
||||
import { steamUrlBuilder } from "@shared";
|
||||
|
||||
export interface GameCardProps
|
||||
extends React.DetailedHTMLProps<
|
||||
@@ -63,7 +62,7 @@ export function GameCard({ game, ...props }: GameCardProps) {
|
||||
>
|
||||
<div className="game-card__backdrop">
|
||||
<img
|
||||
src={steamUrlBuilder.library(game.objectId)}
|
||||
src={game.libraryImageUrl}
|
||||
alt={game.title}
|
||||
className="game-card__cover"
|
||||
loading="lazy"
|
||||
|
||||
@@ -43,7 +43,7 @@ export function Hero() {
|
||||
<div className="hero__backdrop">
|
||||
<img
|
||||
src={game.background}
|
||||
alt={game.description}
|
||||
alt={game.description ?? ""}
|
||||
className="hero__media"
|
||||
/>
|
||||
|
||||
@@ -52,7 +52,7 @@ export function Hero() {
|
||||
<img
|
||||
src={game.logo}
|
||||
width="250px"
|
||||
alt={game.description}
|
||||
alt={game.description ?? ""}
|
||||
loading="eager"
|
||||
/>
|
||||
)}
|
||||
|
||||
3
src/renderer/src/declaration.d.ts
vendored
3
src/renderer/src/declaration.d.ts
vendored
@@ -33,6 +33,7 @@ import type {
|
||||
Badge,
|
||||
Auth,
|
||||
ShortcutLocation,
|
||||
CatalogueSearchResult,
|
||||
} from "@types";
|
||||
import type { AxiosProgressEvent } from "axios";
|
||||
import type disk from "diskusage";
|
||||
@@ -69,7 +70,7 @@ declare global {
|
||||
payload: CatalogueSearchPayload,
|
||||
take: number,
|
||||
skip: number
|
||||
) => Promise<{ edges: any[]; count: number }>;
|
||||
) => Promise<{ edges: CatalogueSearchResult[]; count: number }>;
|
||||
getCatalogue: (category: CatalogueCategory) => Promise<any[]>;
|
||||
getGameShopDetails: (
|
||||
objectId: string,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { DownloadSource } from "@types";
|
||||
import type { CatalogueSearchResult, DownloadSource } from "@types";
|
||||
|
||||
import {
|
||||
useAppDispatch,
|
||||
@@ -44,7 +44,7 @@ export default function Catalogue() {
|
||||
const [downloadSources, setDownloadSources] = useState<DownloadSource[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
const [results, setResults] = useState<any[]>([]);
|
||||
const [results, setResults] = useState<CatalogueSearchResult[]>([]);
|
||||
|
||||
const [itemsCount, setItemsCount] = useState(0);
|
||||
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { Badge } from "@renderer/components";
|
||||
import { buildGameDetailsPath } from "@renderer/helpers";
|
||||
import { useAppSelector, useRepacks } from "@renderer/hooks";
|
||||
import { steamUrlBuilder } from "@shared";
|
||||
import { useMemo } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
import "./game-item.scss";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { CatalogueSearchResult } from "@types";
|
||||
|
||||
export interface GameItemProps {
|
||||
game: any;
|
||||
game: CatalogueSearchResult;
|
||||
}
|
||||
|
||||
export function GameItem({ game }: GameItemProps) {
|
||||
@@ -51,7 +51,7 @@ export function GameItem({ game }: GameItemProps) {
|
||||
>
|
||||
<img
|
||||
className="game-item__cover"
|
||||
src={steamUrlBuilder.library(game.objectId)}
|
||||
src={game.libraryImageUrl}
|
||||
alt={game.title}
|
||||
loading="lazy"
|
||||
/>
|
||||
|
||||
@@ -12,7 +12,6 @@ import { userProfileContext } from "@renderer/context";
|
||||
import { ClockIcon, TrophyIcon } from "@primer/octicons-react";
|
||||
import { MAX_MINUTES_TO_SHOW_IN_PLAYTIME } from "@renderer/constants";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { steamUrlBuilder } from "@shared";
|
||||
import "./user-library-game-card.scss";
|
||||
|
||||
interface UserLibraryGameCardProps {
|
||||
@@ -150,7 +149,7 @@ export function UserLibraryGameCard({
|
||||
</div>
|
||||
|
||||
<img
|
||||
src={steamUrlBuilder.cover(game.objectId)}
|
||||
src={game.coverImageUrl}
|
||||
alt={game.title}
|
||||
className="user-library-game__game-image"
|
||||
/>
|
||||
|
||||
@@ -50,7 +50,10 @@ export interface UserGame {
|
||||
shop: GameShop;
|
||||
title: string;
|
||||
iconUrl: string | null;
|
||||
cover: string;
|
||||
libraryHeroImageUrl: string;
|
||||
libraryImageUrl: string;
|
||||
logoImageUrl: string;
|
||||
coverImageUrl: string;
|
||||
playTimeInSeconds: number;
|
||||
lastTimePlayed: Date | null;
|
||||
unlockedAchievementCount: number;
|
||||
@@ -103,6 +106,10 @@ export interface UserFriend {
|
||||
currentGame: {
|
||||
title: string;
|
||||
iconUrl: string;
|
||||
libraryHeroImageUrl: string;
|
||||
libraryImageUrl: string;
|
||||
logoImageUrl: string;
|
||||
coverImageUrl: string;
|
||||
objectId: string;
|
||||
shop: GameShop;
|
||||
sessionDurationInSeconds: number;
|
||||
@@ -141,6 +148,10 @@ export interface UserRelation {
|
||||
export interface UserProfileCurrentGame extends Omit<GameRunning, "objectId"> {
|
||||
objectId: string;
|
||||
sessionDurationInSeconds: number;
|
||||
libraryHeroImageUrl: string;
|
||||
libraryImageUrl: string;
|
||||
logoImageUrl: string;
|
||||
coverImageUrl: string;
|
||||
}
|
||||
|
||||
export type ProfileVisibility = "PUBLIC" | "PRIVATE" | "FRIENDS";
|
||||
@@ -218,10 +229,14 @@ export interface GameStats {
|
||||
}
|
||||
|
||||
export interface TrendingGame {
|
||||
uri: string;
|
||||
description: string;
|
||||
objectId: string;
|
||||
shop: GameShop;
|
||||
title: string;
|
||||
description: string | null;
|
||||
background: string;
|
||||
logo: string | null;
|
||||
logo: string;
|
||||
logoPosition: string | null;
|
||||
uri: string;
|
||||
}
|
||||
|
||||
export interface UserStatsPercentile {
|
||||
@@ -302,6 +317,25 @@ export interface CatalogueSearchPayload {
|
||||
developers: string[];
|
||||
}
|
||||
|
||||
export interface CatalogueSearchResult {
|
||||
id: string;
|
||||
tags: string[];
|
||||
genres: string[];
|
||||
objectId: string;
|
||||
shop: GameShop;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
title: string;
|
||||
installCount: number;
|
||||
achievementCount: number;
|
||||
iconUrl: string;
|
||||
libraryHeroImageUrl: string;
|
||||
libraryImageUrl: string;
|
||||
logoImageUrl: string;
|
||||
coverImageUrl: string;
|
||||
shopData: string;
|
||||
}
|
||||
|
||||
export interface LibraryGame extends Game {
|
||||
id: string;
|
||||
download: Download | null;
|
||||
|
||||
Reference in New Issue
Block a user