2023-01-10 19:53:55 +01:00
|
|
|
import { useCallback, useRef, useState } from "react";
|
|
|
|
import { CSSTransition } from "react-transition-group";
|
2023-01-08 22:29:38 +01:00
|
|
|
import { BackdropControl } from "./controls/BackdropControl";
|
|
|
|
import { FullscreenControl } from "./controls/FullscreenControl";
|
|
|
|
import { LoadingControl } from "./controls/LoadingControl";
|
2023-01-10 19:53:55 +01:00
|
|
|
import { MiddlePauseControl } from "./controls/MiddlePauseControl";
|
2023-01-08 22:29:38 +01:00
|
|
|
import { PauseControl } from "./controls/PauseControl";
|
|
|
|
import { ProgressControl } from "./controls/ProgressControl";
|
|
|
|
import { TimeControl } from "./controls/TimeControl";
|
|
|
|
import { VolumeControl } from "./controls/VolumeControl";
|
2023-01-15 16:51:55 +01:00
|
|
|
import { VideoPlayerError } from "./parts/VideoPlayerError";
|
2023-01-10 00:27:04 +01:00
|
|
|
import { VideoPlayerHeader } from "./parts/VideoPlayerHeader";
|
2023-01-10 19:53:55 +01:00
|
|
|
import { useVideoPlayerState } from "./VideoContext";
|
2023-01-08 22:29:38 +01:00
|
|
|
import { VideoPlayer, VideoPlayerProps } from "./VideoPlayer";
|
|
|
|
|
2023-01-10 21:18:10 +01:00
|
|
|
interface DecoratedVideoPlayerProps {
|
|
|
|
title?: string;
|
|
|
|
onGoBack?: () => void;
|
|
|
|
}
|
|
|
|
|
2023-01-10 19:53:55 +01:00
|
|
|
function LeftSideControls() {
|
|
|
|
const { videoState } = useVideoPlayerState();
|
|
|
|
|
|
|
|
const handleMouseEnter = useCallback(() => {
|
|
|
|
videoState.setLeftControlsHover(true);
|
|
|
|
}, [videoState]);
|
|
|
|
const handleMouseLeave = useCallback(() => {
|
|
|
|
videoState.setLeftControlsHover(false);
|
|
|
|
}, [videoState]);
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div
|
|
|
|
className="flex items-center px-2"
|
|
|
|
onMouseLeave={handleMouseLeave}
|
|
|
|
onMouseEnter={handleMouseEnter}
|
|
|
|
>
|
|
|
|
<PauseControl />
|
|
|
|
<VolumeControl className="mr-2" />
|
|
|
|
<TimeControl />
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
2023-01-10 00:27:04 +01:00
|
|
|
|
2023-01-10 21:18:10 +01:00
|
|
|
export function DecoratedVideoPlayer(
|
|
|
|
props: VideoPlayerProps & DecoratedVideoPlayerProps
|
|
|
|
) {
|
2023-01-10 19:53:55 +01:00
|
|
|
const top = useRef<HTMLDivElement>(null);
|
|
|
|
const bottom = useRef<HTMLDivElement>(null);
|
|
|
|
const [show, setShow] = useState(false);
|
|
|
|
|
|
|
|
const onBackdropChange = useCallback(
|
|
|
|
(showing: boolean) => {
|
|
|
|
setShow(showing);
|
|
|
|
},
|
|
|
|
[setShow]
|
|
|
|
);
|
|
|
|
|
2023-01-08 22:29:38 +01:00
|
|
|
return (
|
|
|
|
<VideoPlayer autoPlay={props.autoPlay}>
|
2023-01-15 16:51:55 +01:00
|
|
|
<VideoPlayerError title={props.title} onGoBack={props.onGoBack}>
|
|
|
|
<BackdropControl onBackdropChange={onBackdropChange}>
|
|
|
|
<div className="absolute inset-0 flex items-center justify-center">
|
|
|
|
<LoadingControl />
|
|
|
|
</div>
|
|
|
|
<div className="absolute inset-0 flex items-center justify-center">
|
|
|
|
<MiddlePauseControl />
|
|
|
|
</div>
|
|
|
|
<CSSTransition
|
|
|
|
nodeRef={bottom}
|
|
|
|
in={show}
|
|
|
|
timeout={200}
|
|
|
|
classNames={{
|
|
|
|
exit: "transition-[transform,opacity] translate-y-0 duration-200 opacity-100",
|
|
|
|
exitActive: "!translate-y-4 !opacity-0",
|
|
|
|
exitDone: "hidden",
|
|
|
|
enter:
|
|
|
|
"transition-[transform,opacity] translate-y-4 duration-200 opacity-0",
|
|
|
|
enterActive: "!translate-y-0 !opacity-100",
|
|
|
|
}}
|
2023-01-10 19:53:55 +01:00
|
|
|
>
|
2023-01-15 16:51:55 +01:00
|
|
|
<div
|
|
|
|
ref={bottom}
|
|
|
|
className="pointer-events-auto absolute inset-x-0 bottom-0 flex flex-col px-4 pb-2"
|
|
|
|
>
|
|
|
|
<ProgressControl />
|
|
|
|
<div className="flex items-center">
|
|
|
|
<LeftSideControls />
|
|
|
|
<div className="flex-1" />
|
|
|
|
<FullscreenControl />
|
|
|
|
</div>
|
2023-01-10 19:53:55 +01:00
|
|
|
</div>
|
2023-01-15 16:51:55 +01:00
|
|
|
</CSSTransition>
|
|
|
|
<CSSTransition
|
|
|
|
nodeRef={top}
|
|
|
|
in={show}
|
|
|
|
timeout={200}
|
|
|
|
classNames={{
|
|
|
|
exit: "transition-[transform,opacity] translate-y-0 duration-200 opacity-100",
|
|
|
|
exitActive: "!-translate-y-4 !opacity-0",
|
|
|
|
exitDone: "hidden",
|
|
|
|
enter:
|
|
|
|
"transition-[transform,opacity] -translate-y-4 duration-200 opacity-0",
|
|
|
|
enterActive: "!translate-y-0 !opacity-100",
|
|
|
|
}}
|
2023-01-10 19:53:55 +01:00
|
|
|
>
|
2023-01-15 16:51:55 +01:00
|
|
|
<div
|
|
|
|
ref={top}
|
|
|
|
className="pointer-events-auto absolute inset-x-0 top-0 flex flex-col py-6 px-8 pb-2"
|
|
|
|
>
|
|
|
|
<VideoPlayerHeader title={props.title} onClick={props.onGoBack} />
|
|
|
|
</div>
|
|
|
|
</CSSTransition>
|
|
|
|
</BackdropControl>
|
|
|
|
{props.children}
|
|
|
|
</VideoPlayerError>
|
2023-01-08 22:29:38 +01:00
|
|
|
</VideoPlayer>
|
|
|
|
);
|
|
|
|
}
|