autoplay and fullscreen feature detection

This commit is contained in:
Jelle van Snik 2023-01-08 20:36:46 +01:00
parent a9cf056276
commit 44149203cb
3 changed files with 31 additions and 7 deletions

View File

@ -2,14 +2,23 @@ import { forwardRef, useContext, useRef } from "react";
import { VideoPlayerContext, VideoPlayerContextProvider } from "./VideoContext"; import { VideoPlayerContext, VideoPlayerContextProvider } from "./VideoContext";
interface VideoPlayerProps { interface VideoPlayerProps {
autoPlay?: boolean;
children?: React.ReactNode; children?: React.ReactNode;
} }
const VideoPlayerInternals = forwardRef<HTMLVideoElement>((_, ref) => { const VideoPlayerInternals = forwardRef<
HTMLVideoElement,
{ autoPlay: boolean }
>((props, ref) => {
const video = useContext(VideoPlayerContext); const video = useContext(VideoPlayerContext);
return ( return (
<video ref={ref} preload="auto" playsInline className="h-full w-full"> <video
ref={ref}
autoPlay={props.autoPlay}
playsInline
className="h-full w-full"
>
{video.source ? <source src={video.source} type="video/mp4" /> : null} {video.source ? <source src={video.source} type="video/mp4" /> : null}
</video> </video>
); );
@ -25,7 +34,10 @@ export function VideoPlayer(props: VideoPlayerProps) {
className="relative aspect-video w-full bg-black" className="relative aspect-video w-full bg-black"
ref={playerWrapperRef} ref={playerWrapperRef}
> >
<VideoPlayerInternals ref={playerRef} /> <VideoPlayerInternals
autoPlay={props.autoPlay ?? false}
ref={playerRef}
/>
<div className="absolute inset-0">{props.children}</div> <div className="absolute inset-0">{props.children}</div>
</div> </div>
</VideoPlayerContextProvider> </VideoPlayerContextProvider>

View File

@ -1,6 +1,8 @@
import { useCallback } from "react"; import { useCallback } from "react";
import { useVideoPlayerState } from "../VideoContext"; import { useVideoPlayerState } from "../VideoContext";
const canFullscreen = document.fullscreenEnabled;
export function FullscreenControl() { export function FullscreenControl() {
const { videoState } = useVideoPlayerState(); const { videoState } = useVideoPlayerState();
@ -9,6 +11,8 @@ export function FullscreenControl() {
else videoState.enterFullscreen(); else videoState.enterFullscreen();
}, [videoState]); }, [videoState]);
if (!canFullscreen) return null;
let text = "not fullscreen"; let text = "not fullscreen";
if (videoState.isFullscreen) text = "in fullscreen"; if (videoState.isFullscreen) text = "in fullscreen";

View File

@ -4,19 +4,18 @@ import { ProgressControl } from "@/components/video/controls/ProgressControl";
import { SourceControl } from "@/components/video/controls/SourceControl"; import { SourceControl } from "@/components/video/controls/SourceControl";
import { VolumeControl } from "@/components/video/controls/VolumeControl"; import { VolumeControl } from "@/components/video/controls/VolumeControl";
import { VideoPlayer } from "@/components/video/VideoPlayer"; import { VideoPlayer } from "@/components/video/VideoPlayer";
import { useCallback, useState } from "react";
// test videos: https://gist.github.com/jsturgis/3b19447b304616f18657 // test videos: https://gist.github.com/jsturgis/3b19447b304616f18657
// TODO video todos: // TODO video todos:
// - captions // - captions
// - make pretty // - make pretty
// - show fullscreen button depending on is available (document.fullscreenEnabled)
// - better seeking // - better seeking
// - improve seekables // - improve seekables
// - buffering // - buffering
// - error handling // - error handling
// - auto-play prop option // - middle pause button + click to pause
// - middle pause button
// - improve pausing while seeking/buffering // - improve pausing while seeking/buffering
// - captions // - captions
// - show formatted time // - show formatted time
@ -24,9 +23,18 @@ import { VideoPlayer } from "@/components/video/VideoPlayer";
// - IpadOS support: (fullscreen video wrapper should work, see (lookmovie.io) ) // - IpadOS support: (fullscreen video wrapper should work, see (lookmovie.io) )
// - HLS support: feature detection otherwise use HLS.js // - HLS support: feature detection otherwise use HLS.js
export function TestView() { export function TestView() {
const [show, setShow] = useState(false);
const handleClick = useCallback(() => {
setShow((v) => !v);
}, [setShow]);
if (!show) {
return <p onClick={handleClick}>Click me to show</p>;
}
return ( return (
<div className="w-[40rem] max-w-full"> <div className="w-[40rem] max-w-full">
<VideoPlayer> <VideoPlayer autoPlay>
<PauseControl /> <PauseControl />
<FullscreenControl /> <FullscreenControl />
<ProgressControl /> <ProgressControl />