mirror of
https://github.com/sussy-code/smov.git
synced 2024-12-21 14:47:41 +01:00
autoplay and fullscreen feature detection
This commit is contained in:
parent
a9cf056276
commit
44149203cb
3 changed files with 31 additions and 7 deletions
|
@ -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>
|
||||||
|
|
|
@ -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";
|
||||||
|
|
||||||
|
|
|
@ -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 />
|
||||||
|
|
Loading…
Reference in a new issue