mirror of
https://github.com/hydralauncher/hydra.git
synced 2025-03-09 15:40:26 +00:00
refactor: simplify game details hero section layout and scrolling
This commit is contained in:
parent
0b4c3a6cd2
commit
c5206c68ee
2 changed files with 12 additions and 47 deletions
|
@ -16,13 +16,8 @@ import { useUserDetails } from "@renderer/hooks";
|
||||||
import { useSubscription } from "@renderer/hooks/use-subscription";
|
import { useSubscription } from "@renderer/hooks/use-subscription";
|
||||||
import "./game-details.scss";
|
import "./game-details.scss";
|
||||||
|
|
||||||
const HERO_HEIGHT = 300;
|
|
||||||
const HERO_ANIMATION_THRESHOLD = 25;
|
|
||||||
|
|
||||||
export function GameDetailsContent() {
|
export function GameDetailsContent() {
|
||||||
const heroRef = useRef<HTMLDivElement | null>(null);
|
const heroRef = useRef<HTMLDivElement | null>(null);
|
||||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
|
||||||
const [isHeaderStuck, setIsHeaderStuck] = useState(false);
|
|
||||||
|
|
||||||
const { t } = useTranslation("game_details");
|
const { t } = useTranslation("game_details");
|
||||||
|
|
||||||
|
@ -61,7 +56,7 @@ export function GameDetailsContent() {
|
||||||
return t("no_shop_details");
|
return t("no_shop_details");
|
||||||
}, [shopDetails, t]);
|
}, [shopDetails, t]);
|
||||||
|
|
||||||
const [backdropOpactiy, setBackdropOpacity] = useState(1);
|
const [backdropOpacity, setBackdropOpacity] = useState(1);
|
||||||
|
|
||||||
const handleHeroLoad = async () => {
|
const handleHeroLoad = async () => {
|
||||||
const output = await average(steamUrlBuilder.libraryHero(objectId!), {
|
const output = await average(steamUrlBuilder.libraryHero(objectId!), {
|
||||||
|
@ -80,26 +75,6 @@ export function GameDetailsContent() {
|
||||||
setBackdropOpacity(1);
|
setBackdropOpacity(1);
|
||||||
}, [objectId]);
|
}, [objectId]);
|
||||||
|
|
||||||
const onScroll: React.UIEventHandler<HTMLElement> = (event) => {
|
|
||||||
const heroHeight = heroRef.current?.clientHeight ?? HERO_HEIGHT;
|
|
||||||
|
|
||||||
const scrollY = (event.target as HTMLDivElement).scrollTop;
|
|
||||||
const opacity = Math.max(
|
|
||||||
0,
|
|
||||||
1 - scrollY / (heroHeight - HERO_ANIMATION_THRESHOLD)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (scrollY >= heroHeight && !isHeaderStuck) {
|
|
||||||
setIsHeaderStuck(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scrollY <= heroHeight && isHeaderStuck) {
|
|
||||||
setIsHeaderStuck(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
setBackdropOpacity(opacity);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleCloudSaveButtonClick = () => {
|
const handleCloudSaveButtonClick = () => {
|
||||||
if (!userDetails) {
|
if (!userDetails) {
|
||||||
window.electron.openAuthWindow(AuthPage.SignIn);
|
window.electron.openAuthWindow(AuthPage.SignIn);
|
||||||
|
@ -122,31 +97,25 @@ export function GameDetailsContent() {
|
||||||
<div
|
<div
|
||||||
className={`game-details__wrapper ${hasNSFWContentBlocked ? "game-details__wrapper--blurred" : ""}`}
|
className={`game-details__wrapper ${hasNSFWContentBlocked ? "game-details__wrapper--blurred" : ""}`}
|
||||||
>
|
>
|
||||||
|
<section className="game-details__container">
|
||||||
|
<div ref={heroRef} className="game-details__hero">
|
||||||
<img
|
<img
|
||||||
src={steamUrlBuilder.libraryHero(objectId!)}
|
src={steamUrlBuilder.libraryHero(objectId!)}
|
||||||
className="game-details__hero-image"
|
className="game-details__hero-image"
|
||||||
alt={game?.title}
|
alt={game?.title}
|
||||||
onLoad={handleHeroLoad}
|
onLoad={handleHeroLoad}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<section
|
|
||||||
ref={containerRef}
|
|
||||||
onScroll={onScroll}
|
|
||||||
className="game-details__container"
|
|
||||||
>
|
|
||||||
<div ref={heroRef} className="game-details__hero">
|
|
||||||
<div
|
<div
|
||||||
className="game-details__hero-backdrop"
|
className="game-details__hero-backdrop"
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: gameColor,
|
backgroundColor: gameColor,
|
||||||
flex: 1,
|
flex: 1,
|
||||||
opacity: Math.min(1, 1 - backdropOpactiy),
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
className="game-details__hero-logo-backdrop"
|
className="game-details__hero-logo-backdrop"
|
||||||
style={{ opacity: backdropOpactiy }}
|
style={{ opacity: backdropOpacity }}
|
||||||
>
|
>
|
||||||
<div className="game-details__hero-content">
|
<div className="game-details__hero-content">
|
||||||
<img
|
<img
|
||||||
|
@ -173,7 +142,7 @@ export function GameDetailsContent() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<HeroPanel isHeaderStuck={isHeaderStuck} />
|
<HeroPanel />
|
||||||
|
|
||||||
<div className="game-details__description-container">
|
<div className="game-details__description-container">
|
||||||
<div className="game-details__description-content">
|
<div className="game-details__description-content">
|
||||||
|
|
|
@ -9,11 +9,7 @@ import { HeroPanelPlaytime } from "./hero-panel-playtime";
|
||||||
import { gameDetailsContext } from "@renderer/context";
|
import { gameDetailsContext } from "@renderer/context";
|
||||||
import "./hero-panel.scss";
|
import "./hero-panel.scss";
|
||||||
|
|
||||||
export interface HeroPanelProps {
|
export function HeroPanel() {
|
||||||
isHeaderStuck: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function HeroPanel({ isHeaderStuck }: HeroPanelProps) {
|
|
||||||
const { t } = useTranslation("game_details");
|
const { t } = useTranslation("game_details");
|
||||||
|
|
||||||
const { formatDate } = useDate();
|
const { formatDate } = useDate();
|
||||||
|
@ -56,7 +52,7 @@ export function HeroPanel({ isHeaderStuck }: HeroPanelProps) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{ backgroundColor: gameColor }}
|
style={{ backgroundColor: gameColor }}
|
||||||
className={`hero-panel ${isHeaderStuck ? "hero-panel--stuck" : ""}`}
|
className="hero-panel"
|
||||||
>
|
>
|
||||||
<div className="hero-panel__content">{getInfo()}</div>
|
<div className="hero-panel__content">{getInfo()}</div>
|
||||||
<div className="hero-panel__actions">
|
<div className="hero-panel__actions">
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue