Skip to content
Snippets Groups Projects
Verified Commit 4590164b authored by Janne Mareike Koschinski's avatar Janne Mareike Koschinski
Browse files

Cleaned up some code

parent 8eb7a305
Branches
No related tags found
No related merge requests found
import {ChangeEvent, Fragment, useCallback, useState} from "react"; import {Fragment, useState} from "react";
import {createUseStyles} from "react-jss"; import {createUseStyles} from "react-jss";
import {Link} from "react-router-dom"; import {Link} from "react-router-dom";
import {ContentMeta} from "../../api/models/dto/ContentMeta"; import {ContentMeta} from "../../api/models/dto/ContentMeta";
import {Media} from "../../api/models/Media"; import {Media} from "../../api/models/Media";
import {getLocalizedDescription, getLocalizedName, getLocalizedRating} from "../../api/models/Content"; import {getLocalizedDescription, getLocalizedName, getLocalizedRating} from "../../api/models/Content";
import {formatDuration} from "../../util/formatDuration";
import {useLocale} from "../../util/locale/LocalizedContext"; import {useLocale} from "../../util/locale/LocalizedContext";
import {SeekBar} from "./SeekBar"; import {SeekBar} from "./SeekBar";
import {VideoElement} from "./video/VideoElement"; import {VideoElement} from "./video/VideoElement";
import {PlayerApi} from "./video/PlayerApi"; import {PlayerApi} from "./video/PlayerApi";
import {useAudioTracks} from "../../util/media/useAudioTracks";
import {useDebugInfo} from "../../util/media/useDebugInfo";
import {Subtitle} from "../../api/models/Subtitle"; import {Subtitle} from "../../api/models/Subtitle";
import {MousePosition} from "../../util/mouse/MousePosition"; import {MousePosition} from "../../util/mouse/MousePosition";
import {VideoProvider} from "./video/VideoContext"; import {VideoProvider} from "./video/VideoContext";
import {SubtitleRenderer} from "./subtitles/SubtitleRenderer"; import {SubtitleRenderer} from "./subtitles/SubtitleRenderer";
import {useShowEpisodes} from "../../api/ApiHooks"; import {useShowEpisodes} from "../../api/ApiHooks";
import {MediaEpisode} from "../main/MediaEpisode";
import {usePaused} from "../../util/media/usePaused";
import {useCurrentTime} from "../../util/media/useCurrentTime";
import {useDuration} from "../../util/media/useDuration"; import {useDuration} from "../../util/media/useDuration";
import {AudioSelection} from "./video/AudioSelection";
import {SubtitleSelection} from "./video/SubtitleSelection";
import {EpisodeSelection} from "./video/EpisodeSelection";
import {PlayerControls} from "./video/PlayerControls";
interface Props { interface Props {
meta: ContentMeta, meta: ContentMeta,
...@@ -47,42 +45,7 @@ export function Player( ...@@ -47,42 +45,7 @@ export function Player(
const [playerApi, setPlayerApi] = useState<PlayerApi | null>(null); const [playerApi, setPlayerApi] = useState<PlayerApi | null>(null);
const [mousePosition, setMousePosition] = useState<MousePosition | null>(null); const [mousePosition, setMousePosition] = useState<MousePosition | null>(null);
const [volume, setVolume] = useState<number>(1);
const paused = usePaused(playerApi);
const currentTime = useCurrentTime(playerApi)
const duration = useDuration(playerApi); const duration = useDuration(playerApi);
const [audioTracks, currentTrack, setCurrentTrack] = useAudioTracks(playerApi);
useDebugInfo("player", playerApi);
useDebugInfo("content", content);
useDebugInfo("subtitle", subtitle);
useDebugInfo("currentTime", currentTime);
useDebugInfo("duration", duration);
useDebugInfo("audioTracks", audioTracks);
const onPause = useCallback(() => {
if (playerApi) {
playerApi.pause()
}
}, [playerApi]);
const onPlay = useCallback(() => {
if (playerApi) {
playerApi.play()
}
}, [playerApi]);
const onFastForward = useCallback(() => {
if (playerApi) {
playerApi.setCurrentTime(playerApi.getCurrentTime() + 10)
}
}, [playerApi]);
const onRewind = useCallback(() => {
if (playerApi) {
playerApi.setCurrentTime(playerApi.getCurrentTime() - 10)
}
}, [playerApi]);
return ( return (
<VideoProvider value={playerApi?.getVideoElement() || null}> <VideoProvider value={playerApi?.getVideoElement() || null}>
...@@ -98,20 +61,15 @@ export function Player( ...@@ -98,20 +61,15 @@ export function Player(
{relatedEpisodesError ? ( {relatedEpisodesError ? (
<p>{"" + relatedEpisodesError}</p> <p>{"" + relatedEpisodesError}</p>
) : ( ) : (
<ul> <EpisodeSelection
{relatedEpisodes.map(episode => content={content}
<MediaEpisode episodes={relatedEpisodes}
key={episode.content.ids.uuid}
item={episode}
disabled={episode.content.ids.uuid === content.ids.uuid}
/> />
)} )}
</ul>
)}
</Fragment> </Fragment>
)} )}
<div className={classes.player}> <div className={classes.videoContainer}>
<div className={classes.playerCanvas}> <div className={classes.videoCanvas}>
<VideoElement <VideoElement
className={classes.video} className={classes.video}
media={media} media={media}
...@@ -126,83 +84,20 @@ export function Player( ...@@ -126,83 +84,20 @@ export function Player(
/> />
</div> </div>
</div> </div>
<p style={{fontVariant: "tabular-nums"}}> <PlayerControls playerApi={playerApi} />
{formatDuration(mousePosition ? (mousePosition.relative * duration) : currentTime)} / {formatDuration(duration)}
</p>
<button
onClick={onPlay}
disabled={!paused}
>
Play
</button>
<button
onClick={onPause}
disabled={paused}
>
Pause
</button>
<button
onClick={onRewind}
>
Rewind
</button>
<button
onClick={onFastForward}
>
Fast Forward
</button>
<p>
<input
type="range"
min="0"
max="100"
value={volume * 100}
onChange={(event: ChangeEvent<HTMLInputElement>) => {
setVolume(event.target.valueAsNumber / 100);
playerApi?.setVolume(event.target.valueAsNumber / 100)
}}
/>
</p>
<h3>Audio</h3> <h3>Audio</h3>
<ul> <AudioSelection playerApi={playerApi} />
{audioTracks.map(track => (
<li key={track.index}>
<strong>{track.lang}</strong>
&nbsp;{track.labels}
&nbsp;
<button
disabled={currentTrack === track}
onClick={() => setCurrentTrack(track)}
>
Choose
</button>
</li>
))}
</ul>
<h3>Subtitles</h3> <h3>Subtitles</h3>
<ul> <SubtitleSelection
{[null, ...content.subtitles].map(track => ( subtitles={[null, ...content.subtitles]}
<li key={track?.src || "none"}> subtitle={subtitle}
<strong>{track?.language || "none"}</strong> setSubtitle={setSubtitle}
&nbsp;{track?.specifier} />
&nbsp;{track?.format}
&nbsp;
<button
disabled={subtitle === track}
onClick={() => setSubtitle(track)}
>
Choose
</button>
</li>
))}
</ul>
<SeekBar <SeekBar
videoApi={playerApi} videoApi={playerApi}
previewSrc={content.preview} previewSrc={content.preview}
mousePosition={mousePosition} mousePosition={mousePosition}
setMousePosition={setMousePosition} setMousePosition={setMousePosition}
duration={duration}
position={currentTime}
/> />
</div> </div>
</VideoProvider> </VideoProvider>
...@@ -210,7 +105,7 @@ export function Player( ...@@ -210,7 +105,7 @@ export function Player(
} }
const useStyles = createUseStyles({ const useStyles = createUseStyles({
player: { videoContainer: {
width: "40rem", width: "40rem",
height: "30rem", height: "30rem",
background: "#dc5", background: "#dc5",
...@@ -219,7 +114,7 @@ const useStyles = createUseStyles({ ...@@ -219,7 +114,7 @@ const useStyles = createUseStyles({
justifyContent: "center", justifyContent: "center",
alignItems: "center", alignItems: "center",
}, },
playerCanvas: { videoCanvas: {
position: "relative", position: "relative",
display: "flex", display: "flex",
}, },
......
...@@ -6,17 +6,18 @@ import {useOffsetAbsolute} from "../../util/offset/useOffsetAbsolute"; ...@@ -6,17 +6,18 @@ import {useOffsetAbsolute} from "../../util/offset/useOffsetAbsolute";
import {useOffsetRelative} from "../../util/offset/useOffsetRelative"; import {useOffsetRelative} from "../../util/offset/useOffsetRelative";
import {PreviewBar} from "./PreviewBar"; import {PreviewBar} from "./PreviewBar";
import {PlayerApi} from "./video/PlayerApi"; import {PlayerApi} from "./video/PlayerApi";
import {formatDuration} from "../../util/formatDuration";
import {useCurrentTime} from "../../util/media/useCurrentTime";
import {useDuration} from "../../util/media/useDuration";
interface Props { interface Props {
videoApi: PlayerApi | null, videoApi: PlayerApi | null,
previewSrc: string | null, previewSrc: string | null,
mousePosition: MousePosition | null, mousePosition: MousePosition | null,
setMousePosition: (position: MousePosition | null) => void, setMousePosition: (position: MousePosition | null) => void,
duration: number,
position: number,
} }
export function SeekBar({videoApi, previewSrc, mousePosition, setMousePosition, duration, position}: Props) { export function SeekBar({videoApi, previewSrc, mousePosition, setMousePosition}: Props) {
const classes = useStyles(); const classes = useStyles();
const isVisible = mousePosition !== null; const isVisible = mousePosition !== null;
...@@ -25,6 +26,9 @@ export function SeekBar({videoApi, previewSrc, mousePosition, setMousePosition, ...@@ -25,6 +26,9 @@ export function SeekBar({videoApi, previewSrc, mousePosition, setMousePosition,
const [seekHeadRef, setSeekHeadRef] = useState<HTMLDivElement | null>(null); const [seekHeadRef, setSeekHeadRef] = useState<HTMLDivElement | null>(null);
const [playHeadRef, setPlayHeadRef] = useState<HTMLDivElement | null>(null); const [playHeadRef, setPlayHeadRef] = useState<HTMLDivElement | null>(null);
const position = useCurrentTime(videoApi)
const duration = useDuration(videoApi);
const seekHeadOffset = useOffsetAbsolute(seekBarRef, seekHeadRef, mousePosition?.absolute || 0); const seekHeadOffset = useOffsetAbsolute(seekBarRef, seekHeadRef, mousePosition?.absolute || 0);
const playHeadOffset = useOffsetRelative(seekBarRef, playHeadRef, position / duration); const playHeadOffset = useOffsetRelative(seekBarRef, playHeadRef, position / duration);
...@@ -84,6 +88,9 @@ export function SeekBar({videoApi, previewSrc, mousePosition, setMousePosition, ...@@ -84,6 +88,9 @@ export function SeekBar({videoApi, previewSrc, mousePosition, setMousePosition,
return ( return (
<Fragment> <Fragment>
<p style={{fontVariant: "tabular-nums"}}>
{formatDuration(mousePosition ? (mousePosition.relative * duration) : position)} / {formatDuration(duration)}
</p>
<PreviewBar <PreviewBar
previewSrc={previewSrc} previewSrc={previewSrc}
duration={duration} duration={duration}
......
import {PlayerApi} from "./PlayerApi";
import {useAudioTracks} from "../../../util/media/useAudioTracks";
interface Props {
playerApi: PlayerApi | null
}
export function AudioSelection(
{playerApi}: Props
) {
const [audioTracks, currentTrack, setCurrentTrack] = useAudioTracks(playerApi);
return (
<ul>
{audioTracks.map(track => (
<li key={track.index}>
<strong>{track.lang}</strong>
&nbsp;{track.labels}
&nbsp;
<button
disabled={currentTrack === track}
onClick={() => setCurrentTrack(track)}
>
Choose
</button>
</li>
))}
</ul>
);
}
import {MediaEpisode} from "../../main/MediaEpisode";
import {Instalment} from "../../../api/models/Instalment";
import {Content} from "../../../api/models/Content";
interface Props {
content: Content,
episodes: Instalment[],
}
export function EpisodeSelection(
{episodes, content}: Props
) {
return (
<ul>
{episodes.map(episode =>
<MediaEpisode
key={episode.content.ids.uuid}
item={episode}
disabled={episode.content.ids.uuid === content.ids.uuid}
/>
)}
</ul>
);
}
import {ChangeEvent, Fragment, useCallback, useState} from "react";
import {PlayerApi} from "./PlayerApi";
import {usePaused} from "../../../util/media/usePaused";
interface Props {
playerApi: PlayerApi | null,
}
export function PlayerControls(
{playerApi}: Props
) {
const [volume, setVolume] = useState<number>(1);
const paused = usePaused(playerApi);
const onPause = useCallback(() => {
if (playerApi) {
playerApi.pause()
}
}, [playerApi]);
const onPlay = useCallback(() => {
if (playerApi) {
playerApi.play()
}
}, [playerApi]);
const onFastForward = useCallback(() => {
if (playerApi) {
playerApi.setCurrentTime(playerApi.getCurrentTime() + 10)
}
}, [playerApi]);
const onRewind = useCallback(() => {
if (playerApi) {
playerApi.setCurrentTime(playerApi.getCurrentTime() - 10)
}
}, [playerApi]);
return (
<Fragment>
<button
onClick={onPlay}
disabled={!paused}
>
Play
</button>
<button
onClick={onPause}
disabled={paused}
>
Pause
</button>
<button
onClick={onRewind}
>
Rewind
</button>
<button
onClick={onFastForward}
>
Fast Forward
</button>
<p>
<input
type="range"
min="0"
max="100"
value={volume * 100}
onChange={(event: ChangeEvent<HTMLInputElement>) => {
setVolume(event.target.valueAsNumber / 100);
playerApi?.setVolume(event.target.valueAsNumber / 100)
}}
/>
</p>
</Fragment>
);
}
import {Subtitle} from "../../../api/models/Subtitle";
interface Props {
subtitles: (Subtitle | null)[],
subtitle: Subtitle | null,
setSubtitle: (subtitle: Subtitle | null) => void,
}
export function SubtitleSelection(
{subtitles, subtitle, setSubtitle}: Props
) {
return (
<ul>
{subtitles.map(track => (
<li key={track?.src || "none"}>
<strong>{track?.language || "none"}</strong>
&nbsp;{track?.specifier}
&nbsp;{track?.format}
&nbsp;
<button
disabled={subtitle === track}
onClick={() => setSubtitle(track)}
>
Choose
</button>
</li>
))}
</ul>
);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment