mirror of
https://github.com/hydralauncher/hydra.git
synced 2025-03-09 15:40:26 +00:00
fix: moving downloader directly to parser
This commit is contained in:
parent
4d32ff2ac2
commit
866ee7b30d
21 changed files with 1207 additions and 1463 deletions
|
|
@ -6,7 +6,7 @@
|
|||
<title>Hydra</title>
|
||||
<meta
|
||||
http-equiv="Content-Security-Policy"
|
||||
content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: hydra: https://steamcdn-a.akamaihd.net https://cdn.cloudflare.steamstatic.com https://cdn2.steamgriddb.com https://cdn.akamai.steamstatic.com;"
|
||||
content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://steamcdn-a.akamaihd.net https://cdn.cloudflare.steamstatic.com https://cdn2.steamgriddb.com https://cdn.akamai.steamstatic.com;"
|
||||
/>
|
||||
</head>
|
||||
<body style="background-color: #1c1c1c">
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
import { forwardRef, useEffect, useState } from "react";
|
||||
|
||||
export interface AsyncImageProps
|
||||
extends React.DetailedHTMLProps<
|
||||
React.ImgHTMLAttributes<HTMLImageElement>,
|
||||
HTMLImageElement
|
||||
> {
|
||||
onSettled?: (url: string) => void;
|
||||
}
|
||||
|
||||
export const AsyncImage = forwardRef<HTMLImageElement, AsyncImageProps>(
|
||||
({ onSettled, ...props }, ref) => {
|
||||
const [source, setSource] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (props.src && props.src.startsWith("http")) {
|
||||
window.electron.getOrCacheImage(props.src).then((url) => {
|
||||
setSource(url);
|
||||
|
||||
if (onSettled) onSettled(url);
|
||||
});
|
||||
}
|
||||
}, [props.src, onSettled]);
|
||||
|
||||
return <img ref={ref} {...props} src={source ?? props.src} />;
|
||||
}
|
||||
);
|
||||
|
||||
AsyncImage.displayName = "AsyncImage";
|
||||
|
|
@ -4,8 +4,6 @@ import type { CatalogueEntry } from "@types";
|
|||
import SteamLogo from "@renderer/assets/steam-logo.svg?react";
|
||||
import EpicGamesLogo from "@renderer/assets/epic-games-logo.svg?react";
|
||||
|
||||
import { AsyncImage } from "../async-image/async-image";
|
||||
|
||||
import * as styles from "./game-card.css";
|
||||
import { useAppSelector } from "@renderer/hooks";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
|
@ -43,11 +41,7 @@ export function GameCard({ game, disabled, ...props }: GameCardProps) {
|
|||
disabled={disabled}
|
||||
>
|
||||
<div className={styles.backdrop}>
|
||||
<AsyncImage
|
||||
src={game.cover}
|
||||
alt={game.title}
|
||||
className={styles.cover}
|
||||
/>
|
||||
<img src={game.cover} alt={game.title} className={styles.cover} />
|
||||
|
||||
<div className={styles.content}>
|
||||
<div className={styles.titleContainer}>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { useNavigate } from "react-router-dom";
|
||||
import { AsyncImage } from "@renderer/components";
|
||||
import * as styles from "./hero.css";
|
||||
import { useEffect, useState } from "react";
|
||||
import { ShopDetails } from "@types";
|
||||
|
|
@ -35,14 +34,14 @@ export function Hero() {
|
|||
className={styles.hero}
|
||||
>
|
||||
<div className={styles.backdrop}>
|
||||
<AsyncImage
|
||||
<img
|
||||
src="https://cdn2.steamgriddb.com/hero/4ef10445b952a8b3c93a9379d581146a.jpg"
|
||||
alt={featuredGameDetails?.name}
|
||||
className={styles.heroMedia}
|
||||
/>
|
||||
|
||||
<div className={styles.content}>
|
||||
<AsyncImage
|
||||
<img
|
||||
src={steamUrlBuilder.logo(FEATURED_GAME_ID)}
|
||||
width="250px"
|
||||
alt={featuredGameDetails?.name}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,5 @@ export * from "./header/header";
|
|||
export * from "./hero/hero";
|
||||
export * from "./modal/modal";
|
||||
export * from "./sidebar/sidebar";
|
||||
export * from "./async-image/async-image";
|
||||
export * from "./text-field/text-field";
|
||||
export * from "./checkbox-field/checkbox-field";
|
||||
|
|
|
|||
|
|
@ -74,7 +74,6 @@ export const menuItem = recipe({
|
|||
active: {
|
||||
true: {
|
||||
backgroundColor: "rgba(255, 255, 255, 0.1)",
|
||||
fontWeight: "bold",
|
||||
},
|
||||
},
|
||||
muted: {
|
||||
|
|
@ -97,11 +96,6 @@ export const menuItemButton = style({
|
|||
overflow: "hidden",
|
||||
width: "100%",
|
||||
padding: `9px ${SPACING_UNIT}px`,
|
||||
selectors: {
|
||||
[`${menuItem({ active: true }).split(" ")[1]} &`]: {
|
||||
fontWeight: "bold",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const menuItemButtonLabel = style({
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { useLocation, useNavigate } from "react-router-dom";
|
|||
|
||||
import type { Game } from "@types";
|
||||
|
||||
import { AsyncImage, TextField } from "@renderer/components";
|
||||
import { TextField } from "@renderer/components";
|
||||
import { useDownload, useLibrary } from "@renderer/hooks";
|
||||
|
||||
import { routes } from "./routes";
|
||||
|
|
@ -14,7 +14,6 @@ import DiscordLogo from "@renderer/assets/discord-icon.svg?react";
|
|||
import XLogo from "@renderer/assets/x-icon.svg?react";
|
||||
|
||||
import * as styles from "./sidebar.css";
|
||||
import { vars } from "@renderer/theme.css";
|
||||
|
||||
const SIDEBAR_MIN_WIDTH = 200;
|
||||
const SIDEBAR_INITIAL_WIDTH = 250;
|
||||
|
|
@ -217,7 +216,11 @@ export function Sidebar() {
|
|||
)
|
||||
}
|
||||
>
|
||||
<AsyncImage className={styles.gameIcon} src={game.iconUrl} />
|
||||
<img
|
||||
className={styles.gameIcon}
|
||||
src={game.iconUrl}
|
||||
alt={game.title}
|
||||
/>
|
||||
<span className={styles.menuItemButtonLabel}>
|
||||
{getGameTitle(game)}
|
||||
</span>
|
||||
|
|
|
|||
1
src/renderer/src/declaration.d.ts
vendored
1
src/renderer/src/declaration.d.ts
vendored
|
|
@ -79,7 +79,6 @@ declare global {
|
|||
getDiskFreeSpace: (path: string) => Promise<DiskSpace>;
|
||||
|
||||
/* Misc */
|
||||
getOrCacheImage: (url: string) => Promise<string>;
|
||||
openExternal: (src: string) => Promise<void>;
|
||||
getVersion: () => Promise<string>;
|
||||
ping: () => string;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useTranslation } from "react-i18next";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
import { AsyncImage, Button, TextField } from "@renderer/components";
|
||||
import { Button, TextField } from "@renderer/components";
|
||||
import { formatDownloadProgress, steamUrlBuilder } from "@renderer/helpers";
|
||||
import { useDownload, useLibrary } from "@renderer/hooks";
|
||||
import type { Game } from "@types";
|
||||
|
|
@ -235,7 +235,7 @@ export function Downloads() {
|
|||
cancelled: game.status === "cancelled",
|
||||
})}
|
||||
>
|
||||
<AsyncImage
|
||||
<img
|
||||
src={steamUrlBuilder.library(game.objectID)}
|
||||
className={styles.downloadCover}
|
||||
alt={game.title}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import type {
|
|||
SteamAppDetails,
|
||||
} from "@types";
|
||||
|
||||
import { AsyncImage, Button } from "@renderer/components";
|
||||
import { Button } from "@renderer/components";
|
||||
import { setHeaderTitle } from "@renderer/features";
|
||||
import { getSteamLanguage, steamUrlBuilder } from "@renderer/helpers";
|
||||
import { useAppDispatch, useDownload } from "@renderer/hooks";
|
||||
|
|
@ -69,14 +69,16 @@ export function GameDetails() {
|
|||
|
||||
const { game: gameDownloading, startDownload, isDownloading } = useDownload();
|
||||
|
||||
const handleImageSettled = useCallback((url: string) => {
|
||||
average(url, { amount: 1, format: "hex" })
|
||||
const heroImage = steamUrlBuilder.libraryHero(objectID!);
|
||||
|
||||
const handleHeroLoad = () => {
|
||||
average(heroImage, { amount: 1, format: "hex" })
|
||||
.then((color) => {
|
||||
const darkColor = new Color(color).darken(0.6).toString() as string;
|
||||
setColor({ light: color as string, dark: darkColor });
|
||||
})
|
||||
.catch(() => {});
|
||||
}, []);
|
||||
};
|
||||
|
||||
const getGame = useCallback(() => {
|
||||
window.electron
|
||||
|
|
@ -218,15 +220,15 @@ export function GameDetails() {
|
|||
) : (
|
||||
<section className={styles.container}>
|
||||
<div className={styles.hero}>
|
||||
<AsyncImage
|
||||
src={steamUrlBuilder.libraryHero(objectID!)}
|
||||
<img
|
||||
src={heroImage}
|
||||
className={styles.heroImage}
|
||||
alt={game?.title}
|
||||
onSettled={handleImageSettled}
|
||||
onLoad={handleHeroLoad}
|
||||
/>
|
||||
<div className={styles.heroBackdrop}>
|
||||
<div className={styles.heroContent}>
|
||||
<AsyncImage
|
||||
<img
|
||||
src={steamUrlBuilder.logo(objectID!)}
|
||||
style={{ width: 300, alignSelf: "flex-end" }}
|
||||
/>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue