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

Further cleanup

parent 4590164b
Branches main
No related tags found
No related merge requests found
......@@ -5,15 +5,14 @@ import {ContentMeta} from "../../api/models/dto/ContentMeta";
import {Media} from "../../api/models/Media";
import {getLocalizedDescription, getLocalizedName, getLocalizedRating} from "../../api/models/Content";
import {useLocale} from "../../util/locale/LocalizedContext";
import {SeekBar} from "./SeekBar";
import {SeekBarContainer} from "./SeekBarContainer";
import {VideoElement} from "./video/VideoElement";
import {PlayerApi} from "./video/PlayerApi";
import {Subtitle} from "../../api/models/Subtitle";
import {MousePosition} from "../../util/mouse/MousePosition";
import {VideoProvider} from "./video/VideoContext";
import {PlayerProvider} from "./video/VideoContext";
import {SubtitleRenderer} from "./subtitles/SubtitleRenderer";
import {useShowEpisodes} from "../../api/ApiHooks";
import {useDuration} from "../../util/media/useDuration";
import {AudioSelection} from "./video/AudioSelection";
import {SubtitleSelection} from "./video/SubtitleSelection";
import {EpisodeSelection} from "./video/EpisodeSelection";
......@@ -45,10 +44,8 @@ export function Player(
const [playerApi, setPlayerApi] = useState<PlayerApi | null>(null);
const [mousePosition, setMousePosition] = useState<MousePosition | null>(null);
const duration = useDuration(playerApi);
return (
<VideoProvider value={playerApi?.getVideoElement() || null}>
<PlayerProvider value={playerApi}>
<div>
<Link to="/">Back</Link>
<h2>{name?.name}</h2>
......@@ -78,29 +75,26 @@ export function Player(
/>
<SubtitleRenderer
className={classes.subtitleCanvas}
videoElement={playerApi?.getVideoElement() || null}
subtitle={subtitle}
duration={duration}
/>
</div>
</div>
<PlayerControls playerApi={playerApi} />
<PlayerControls/>
<h3>Audio</h3>
<AudioSelection playerApi={playerApi} />
<AudioSelection/>
<h3>Subtitles</h3>
<SubtitleSelection
subtitles={[null, ...content.subtitles]}
subtitle={subtitle}
setSubtitle={setSubtitle}
/>
<SeekBar
videoApi={playerApi}
<SeekBarContainer
previewSrc={content.preview}
mousePosition={mousePosition}
setMousePosition={setMousePosition}
/>
</div>
</VideoProvider>
</PlayerProvider>
);
}
......
......@@ -13,7 +13,6 @@ interface Props {
}
export function PreviewBar({previewSrc, duration, position, hidden}: Props) {
//console.log("Rendering PreviewBar")
const classes = useStyles();
const [previewTrack, setPreviewTrack] = useState<HTMLTrackElement | null>(null);
......
......@@ -12,23 +12,28 @@ interface Props {
}
export function PreviewViewer({previewTrack, position}: Props) {
//console.log("Rendering PreviewViewer#1")
const classes = useStyles();
const cues = useTextTrackCues(previewTrack);
const activeCue = position === null ? null : cues.find(it => it.startTime <= position && it.endTime >= position);
const activeUrl = previewTrack && activeCue ? new URL(activeCue.text, previewTrack.src).toString() : null;
const activeCue = position === null
? null
: cues.find(it => it.startTime <= position && it.endTime >= position);
const activeUrl = previewTrack && activeCue
? new URL(activeCue.text, previewTrack.src).toString()
: null;
const imageSprite = useMemo(() => parseImageSprite(activeUrl), [activeUrl]);
const image = useImage(imageSprite?.src || null);
const sprite = useImageSprite(imageSprite, image);
const sources = useMemo(() => previewTrack === null ? null : Array.from(new Set(cues.map(it => {
const sources = useMemo(() => previewTrack === null
? null
: Array.from(new Set(cues.map(it => {
const url = new URL(it.text, previewTrack.src);
url.hash = "";
return url.toString();
}))), [cues, previewTrack]);
}))),
[cues, previewTrack]
);
return useMemo(() => {
//console.log("Rendering PreviewViewer#2")
return (
<Fragment>
<HeadPortal>
......
import {Fragment, MouseEvent, useCallback, useMemo, useState} from "react";
import {MouseEvent, useCallback, useMemo, useState} from "react";
import {createUseStyles} from "react-jss";
import {getMousePosition} from "../../util/mouse/getMousePosition";
import {MousePosition} from "../../util/mouse/MousePosition";
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 {getMousePosition} from "../../util/mouse/getMousePosition";
import {MousePosition} from "../../util/mouse/MousePosition";
import {usePlayerApi} from "./video/VideoContext";
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,
}
export function SeekBar({videoApi, previewSrc, mousePosition, setMousePosition}: Props) {
export function SeekBar(
{mousePosition, setMousePosition}: Props
) {
const videoApi = usePlayerApi();
const classes = useStyles();
const isVisible = mousePosition !== null;
const position = useCurrentTime(videoApi)
const duration = useDuration(videoApi);
const [seekBarRef, setSeekBarRef] = useState<HTMLDivElement | null>(null);
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);
......@@ -73,7 +72,7 @@ export function SeekBar({videoApi, previewSrc, mousePosition, setMousePosition}:
/>
), [classes.playHead, playHeadOffset]);
const seekBar = useMemo(() => (
return (
<div
ref={setSeekBarRef}
className={classes.seekBar}
......@@ -84,21 +83,6 @@ export function SeekBar({videoApi, previewSrc, mousePosition, setMousePosition}:
{seekHead}
{playHead}
</div>
), [classes.seekBar, onClick, onMouseLeave, onMouseMove, playHead, seekHead]);
return (
<Fragment>
<p style={{fontVariant: "tabular-nums"}}>
{formatDuration(mousePosition ? (mousePosition.relative * duration) : position)} / {formatDuration(duration)}
</p>
<PreviewBar
previewSrc={previewSrc}
duration={duration}
position={mousePosition}
hidden={mousePosition === null}
/>
{seekBar}
</Fragment>
);
}
......
import {Fragment} from "react";
import {MousePosition} from "../../util/mouse/MousePosition";
import {PreviewBar} from "./PreviewBar";
import {formatDuration} from "../../util/formatDuration";
import {useCurrentTime} from "../../util/media/useCurrentTime";
import {useDuration} from "../../util/media/useDuration";
import {usePlayerApi} from "./video/VideoContext";
import {SeekBar} from "./SeekBar";
interface Props {
previewSrc: string | null,
mousePosition: MousePosition | null,
setMousePosition: (position: MousePosition | null) => void,
}
export function SeekBarContainer({previewSrc, mousePosition, setMousePosition}: Props) {
const videoApi = usePlayerApi();
const position = useCurrentTime(videoApi)
const duration = useDuration(videoApi);
return (
<Fragment>
<p style={{fontVariant: "tabular-nums"}}>
{formatDuration(mousePosition
? (mousePosition.relative * duration)
: position)} / {formatDuration(duration)}
</p>
<PreviewBar
previewSrc={previewSrc}
duration={duration}
position={mousePosition}
hidden={mousePosition === null}
/>
<SeekBar
mousePosition={mousePosition}
setMousePosition={setMousePosition}
/>
</Fragment>
);
}
......@@ -2,22 +2,38 @@ import {Subtitle} from "../../../api/models/Subtitle";
import {Fragment} from "react";
import {TtmlRenderer} from "./TtmlRenderer";
import {SsaRenderer} from "./SsaRenderer";
import {usePlayerApi} from "../video/VideoContext";
import {useDuration} from "../../../util/media/useDuration";
interface Props {
videoElement: HTMLVideoElement | null,
subtitle: Subtitle | null,
duration: number,
className?: string,
}
export function SubtitleRenderer(
props: Props
) {
const playerApi = usePlayerApi();
const videoElement = playerApi?.getVideoElement() || null;
const duration = useDuration(playerApi);
switch (props.subtitle?.format) {
case "ttml":
return (<TtmlRenderer {...props} />);
return (
<TtmlRenderer
videoElement={videoElement}
duration={duration}
{...props}
/>
);
case "ass":
return (<SsaRenderer {...props} />);
return (
<SsaRenderer
videoElement={videoElement}
duration={duration}
{...props}
/>
);
default:
return (<Fragment/>);
}
......
import {PlayerApi} from "./PlayerApi";
import {useAudioTracks} from "../../../util/media/useAudioTracks";
import {usePlayerApi} from "./VideoContext";
interface Props {
playerApi: PlayerApi | null
}
export function AudioSelection() {
const playerApi = usePlayerApi();
export function AudioSelection(
{playerApi}: Props
) {
const [audioTracks, currentTrack, setCurrentTrack] = useAudioTracks(playerApi);
return (
......
import {ChangeEvent, Fragment, useCallback, useState} from "react";
import {PlayerApi} from "./PlayerApi";
import {usePaused} from "../../../util/media/usePaused";
import {usePlayerApi} from "./VideoContext";
interface Props {
playerApi: PlayerApi | null,
}
export function PlayerControls() {
const playerApi = usePlayerApi();
export function PlayerControls(
{playerApi}: Props
) {
const [volume, setVolume] = useState<number>(1);
const paused = usePaused(playerApi);
......
import {forwardRef, Fragment, HTMLProps} from "react";
import {createPortal} from "react-dom";
import {useVideo} from "./VideoContext";
import {usePlayerApi} from "./VideoContext";
export const Track = forwardRef<HTMLTrackElement, HTMLProps<HTMLTrackElement>>(function (
props, ref
) {
const video = useVideo();
if (video) {
const playerApi = usePlayerApi();
const videoElement = playerApi?.getVideoElement();
if (videoElement) {
return createPortal(
<track ref={ref} {...props} />,
video
videoElement
);
} else {
return <Fragment/>;
......
import {createContext, useContext} from "react";
import {PlayerApi} from "./PlayerApi";
const videoContext = createContext<HTMLVideoElement | null>(null);
export const VideoProvider = videoContext.Provider;
export const useVideo = () => useContext<HTMLVideoElement | null>(videoContext);
const playerContext = createContext<PlayerApi | null>(null);
export const PlayerProvider = playerContext.Provider;
export const usePlayerApi = () => useContext<PlayerApi | null>(playerContext);
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment