Add slider functionality

This commit is contained in:
Matheus Dantas 2024-05-04 23:37:47 -03:00
parent 40adf3da0e
commit de1d4c347f
4 changed files with 71 additions and 22 deletions

View file

@ -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: hydra: https://steamcdn-a.akamaihd.net https://cdn.cloudflare.steamstatic.com https://cdn2.steamgriddb.com https://cdn.akamai.steamstatic.com; media-src 'self' data: hydra: 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">

View file

@ -1,43 +1,67 @@
import { useState } from "react";
import { ShopDetails } from "@types";
import { ShopDetails, SteamMovies, SteamScreenshot } from "@types";
import { ChevronRightIcon, ChevronLeftIcon } from "@primer/octicons-react";
import * as styles from "./game-details.css";
import { useTranslation } from "react-i18next";
export interface GallerySliderProps {
gameDetails: ShopDetails | null;
}
}
export function GallerySlider({gameDetails}: GallerySliderProps){
const [imageIndex, setImageIndex] = useState<number>(0)
export function GallerySlider({ gameDetails }: GallerySliderProps) {
const [mediaIndex, setMediaIndex] = useState<number>(0);
const [mediaType, setMediaType] = useState<'video' | 'image'>('video');
const { t } = useTranslation("game_details");
const showNextImage = () => {
setImageIndex((index:number) => {
if(gameDetails?.screenshots.length && index === (gameDetails?.screenshots.length - 1)) return 0
setMediaIndex((index: number) => {
if (gameDetails?.movies.length && index === (gameDetails?.movies.length - 1) && mediaType === 'video') {
setMediaType('image')
return 1
}
if (gameDetails?.screenshots.length && index === (gameDetails?.screenshots.length - 1) && mediaType === 'image') {
setMediaType('video')
return 0
}
return index + 1
})
};
const showPrevImage = () => {
setImageIndex((index:number) => {
if(index === 0 && gameDetails?.screenshots) return gameDetails?.screenshots.length - 1
setMediaIndex((index: number) => {
if (gameDetails?.screenshots.length && index === 0 && mediaType === 'video') {
setMediaType('image')
return gameDetails?.screenshots.length - 1
}
if (gameDetails?.movies.length && index === 1 && mediaType === 'image') {
setMediaType('video')
return gameDetails?.movies.length - 1
}
return index - 1
})
};
return (
<>
{gameDetails?.screenshots && (
<div className={styles.gallerySliderContainer}>
<h2 className={styles.gallerySliderTitle}>Gallery</h2>
<img className={styles.gallerySliderImage} src={gameDetails?.screenshots[imageIndex].path_full} />
<button onClick={showPrevImage} className={styles.gallerySliderButton} style={{left: 0}}><ChevronLeftIcon className={styles.gallerySliderIcons}/></button>
<button onClick={showNextImage} className={styles.gallerySliderButton} style={{right: 0}}><ChevronRightIcon className={styles.gallerySliderIcons}/></button>
</div>
)}
{gameDetails?.screenshots && (
<div className={styles.gallerySliderContainer}>
<h2 className={styles.gallerySliderTitle}>{t('Videos and screenshots')}</h2>
<div className={styles.gallerySliderAnimationContainer}>
{gameDetails.movies.map((video: SteamMovies) => (
<video controls className={styles.gallerySliderMedia} poster={video.thumbnail} style={{translate: `${-100 * mediaIndex}%`}}>
<source src={video.webm.max.replace('http', 'https')} />
</video>
))}
{gameDetails.screenshots.map((image: SteamScreenshot) => (
<img className={styles.gallerySliderMedia} src={image.path_full} style={{translate: `${ -100 * mediaIndex}%`}}/>
))}
</div>
<button onClick={showPrevImage} className={styles.gallerySliderButton} style={{ left: 0 }}><ChevronLeftIcon className={styles.gallerySliderIcons} /></button>
<button onClick={showNextImage} className={styles.gallerySliderButton} style={{ right: 0 }}><ChevronRightIcon className={styles.gallerySliderIcons} /></button>
</div>
)}
</>
)

View file

@ -89,12 +89,22 @@ export const gallerySliderTitle = style({
padding: `${SPACING_UNIT}px 0`,
});
export const gallerySliderImage = style({
export const gallerySliderMedia = style({
width: "100%",
height: "100%",
display: "block",
flexShrink: 0,
flexGrow: 0,
transition: "translate 300ms ease-in-out"
});
export const gallerySliderAnimationContainer = style({
width: "100%",
height: "100%",
display: "flex",
overflow: "hidden"
})
export const gallerySliderButton = style({
all: "unset",
display: "block",

View file

@ -12,6 +12,20 @@ export interface SteamScreenshot {
path_full: string;
}
export interface SteamVideoSource {
max: string;
'480': string;
}
export interface SteamMovies {
id: number;
mp4: SteamVideoSource;
webm: SteamVideoSource;
thumbnail: string;
name: string;
highlight: boolean;
}
export interface SteamAppDetails {
name: string;
detailed_description: string;
@ -19,6 +33,7 @@ export interface SteamAppDetails {
short_description: string;
publishers: string[];
genres: SteamGenre[];
movies: SteamMovies[];
screenshots: SteamScreenshot[];
pc_requirements: {
minimum: string;