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
No related branches found
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 {Link} from "react-router-dom";
import {ContentMeta} from "../../api/models/dto/ContentMeta";
import {Media} from "../../api/models/Media";
import {getLocalizedDescription, getLocalizedName, getLocalizedRating} from "../../api/models/Content";
import {formatDuration} from "../../util/formatDuration";
import {useLocale} from "../../util/locale/LocalizedContext";
import {SeekBar} from "./SeekBar";
import {VideoElement} from "./video/VideoElement";
import {PlayerApi} from "./video/PlayerApi";
import {useAudioTracks} from "../../util/media/useAudioTracks";
import {useDebugInfo} from "../../util/media/useDebugInfo";
import {Subtitle} from "../../api/models/Subtitle";
import {MousePosition} from "../../util/mouse/MousePosition";
import {VideoProvider} from "./video/VideoContext";
import {SubtitleRenderer} from "./subtitles/SubtitleRenderer";
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 {AudioSelection} from "./video/AudioSelection";
import {SubtitleSelection} from "./video/SubtitleSelection";
import {EpisodeSelection} from "./video/EpisodeSelection";
import {PlayerControls} from "./video/PlayerControls";
interface Props {
meta: ContentMeta,
......@@ -47,42 +45,7 @@ export function Player(
const [playerApi, setPlayerApi] = useState<PlayerApi | 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 [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 (
<VideoProvider value={playerApi?.getVideoElement() || null}>
......@@ -98,20 +61,15 @@ export function Player(
{relatedEpisodesError ? (
<p>{"" + relatedEpisodesError}</p>
) : (
<ul>
{relatedEpisodes.map(episode =>
<MediaEpisode
key={episode.content.ids.uuid}
item={episode}
disabled={episode.content.ids.uuid === content.ids.uuid}
<EpisodeSelection
content={content}
episodes={relatedEpisodes}
/>
)}
</ul>
)}
</Fragment>
)}
<div className={classes.player}>
<div className={classes.playerCanvas}>
<div className={classes.videoContainer}>
<div className={classes.videoCanvas}>
<VideoElement
className={classes.video}
media={media}
......@@ -126,83 +84,20 @@ export function Player(
/>
</div>
</div>
<p style={{fontVariant: "tabular-nums"}}>
{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>
<PlayerControls playerApi={playerApi} />
<h3>Audio</h3>
<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>
<AudioSelection playerApi={playerApi} />
<h3>Subtitles</h3>
<ul>
{[null, ...content.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>
<SubtitleSelection
subtitles={[null, ...content.subtitles]}
subtitle={subtitle}
setSubtitle={setSubtitle}
/>
<SeekBar
videoApi={playerApi}
previewSrc={content.preview}
mousePosition={mousePosition}
setMousePosition={setMousePosition}
duration={duration}
position={currentTime}
/>
</div>
</VideoProvider>
......@@ -210,7 +105,7 @@ export function Player(
}
const useStyles = createUseStyles({
player: {
videoContainer: {
width: "40rem",
height: "30rem",
background: "#dc5",
......@@ -219,7 +114,7 @@ const useStyles = createUseStyles({
justifyContent: "center",
alignItems: "center",
},
playerCanvas: {
videoCanvas: {
position: "relative",
display: "flex",
},
......
......@@ -6,17 +6,18 @@ import {useOffsetAbsolute} from "../../util/offset/useOffsetAbsolute";
import {useOffsetRelative} from "../../util/offset/useOffsetRelative";
import {PreviewBar} from "./PreviewBar";
import {PlayerApi} from "./video/PlayerApi";
import {formatDuration} from "../../util/formatDuration";
import {useCurrentTime} from "../../util/media/useCurrentTime";
import {useDuration} from "../../util/media/useDuration";
interface Props {
videoApi: PlayerApi | null,
previewSrc: string | null,
mousePosition: MousePosition | null,
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 isVisible = mousePosition !== null;
......@@ -25,6 +26,9 @@ export function SeekBar({videoApi, previewSrc, mousePosition, setMousePosition,
const [seekHeadRef, setSeekHeadRef] = 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 playHeadOffset = useOffsetRelative(seekBarRef, playHeadRef, position / duration);
......@@ -84,6 +88,9 @@ export function SeekBar({videoApi, previewSrc, mousePosition, setMousePosition,
return (
<Fragment>
<p style={{fontVariant: "tabular-nums"}}>
{formatDuration(mousePosition ? (mousePosition.relative * duration) : position)} / {formatDuration(duration)}
</p>
<PreviewBar
previewSrc={previewSrc}
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