From 3a67d50f425d71ab9f07da513526d0d20acdadd6 Mon Sep 17 00:00:00 2001 From: Jelle van Snik Date: Sun, 8 Jan 2023 15:37:16 +0100 Subject: [PATCH] video player starter --- src/components/video/VideoContext.tsx | 72 +++++++------------ src/components/video/VideoPlayer.tsx | 42 ++--------- .../video/controls/FullscreenControl.tsx | 41 +++++------ .../video/controls/PauseControl.tsx | 26 ++----- src/components/video/hooks/controlVideo.ts | 20 ++++++ src/components/video/hooks/useVideoPlayer.ts | 55 ++++++++++++++ 6 files changed, 137 insertions(+), 119 deletions(-) create mode 100644 src/components/video/hooks/controlVideo.ts create mode 100644 src/components/video/hooks/useVideoPlayer.ts diff --git a/src/components/video/VideoContext.tsx b/src/components/video/VideoContext.tsx index dd8301d9..bc1bedea 100644 --- a/src/components/video/VideoContext.tsx +++ b/src/components/video/VideoContext.tsx @@ -1,36 +1,30 @@ import React, { createContext, MutableRefObject, + useContext, useEffect, useReducer, } from "react"; +import { + initialPlayerState, + PlayerState, + useVideoPlayer, +} from "./hooks/useVideoPlayer"; interface VideoPlayerContextType { - source: null | string; - playerWrapper: HTMLDivElement | null; - player: HTMLVideoElement | null; - controlState: "paused" | "playing"; - fullscreen: boolean; + source: string | null; + state: PlayerState; } -const initial = ( - player: HTMLVideoElement | null = null, - wrapper: HTMLDivElement | null = null -): VideoPlayerContextType => ({ +const initial: VideoPlayerContextType = { source: null, - playerWrapper: wrapper, - player, - controlState: "paused", - fullscreen: false, -}); + state: initialPlayerState, +}; type VideoPlayerContextAction = | { type: "SET_SOURCE"; url: string } - | { type: "CONTROL"; do: "PAUSE" | "PLAY"; soft?: boolean } - | { type: "FULLSCREEN"; do: "ENTER" | "EXIT"; soft?: boolean } | { type: "UPDATE_PLAYER"; - player: HTMLVideoElement | null; - playerWrapper: HTMLDivElement | null; + state: PlayerState; }; function videoPlayerContextReducer( @@ -42,35 +36,16 @@ function videoPlayerContextReducer( video.source = action.url; return video; } - if (action.type === "CONTROL") { - if (action.do === "PAUSE") video.controlState = "paused"; - else if (action.do === "PLAY") video.controlState = "playing"; - if (action.soft) return video; - - if (action.do === "PAUSE") video.player?.pause(); - else if (action.do === "PLAY") video.player?.play(); - return video; - } if (action.type === "UPDATE_PLAYER") { - video.player = action.player; - video.playerWrapper = action.playerWrapper; - return video; - } - if (action.type === "FULLSCREEN") { - video.fullscreen = action.do === "ENTER"; - if (action.soft) return video; - - if (action.do === "ENTER") video.playerWrapper?.requestFullscreen(); - else document.exitFullscreen(); + video.state = action.state; return video; } return original; } -export const VideoPlayerContext = createContext( - initial() -); +export const VideoPlayerContext = + createContext(initial); export const VideoPlayerDispatchContext = createContext< React.Dispatch >(null as any); @@ -78,20 +53,19 @@ export const VideoPlayerDispatchContext = createContext< export function VideoPlayerContextProvider(props: { children: React.ReactNode; player: MutableRefObject; - playerWrapper: MutableRefObject; }) { + const { playerState } = useVideoPlayer(props.player); const [videoData, dispatch] = useReducer( videoPlayerContextReducer, - initial() + initial ); useEffect(() => { dispatch({ type: "UPDATE_PLAYER", - player: props.player.current, - playerWrapper: props.playerWrapper.current, + state: playerState, }); - }, [props.player, props.playerWrapper]); + }, [playerState]); return ( @@ -101,3 +75,11 @@ export function VideoPlayerContextProvider(props: { ); } + +export function useVideoPlayerState() { + const { state } = useContext(VideoPlayerContext); + + return { + videoState: state, + }; +} diff --git a/src/components/video/VideoPlayer.tsx b/src/components/video/VideoPlayer.tsx index d2395bb7..d1b7f341 100644 --- a/src/components/video/VideoPlayer.tsx +++ b/src/components/video/VideoPlayer.tsx @@ -1,37 +1,15 @@ -import { forwardRef, useCallback, useContext, useEffect, useRef } from "react"; -import { - VideoPlayerContext, - VideoPlayerContextProvider, - VideoPlayerDispatchContext, -} from "./VideoContext"; +import { forwardRef, useContext, useRef } from "react"; +import { VideoPlayerContext, VideoPlayerContextProvider } from "./VideoContext"; interface VideoPlayerProps { children?: React.ReactNode; } -const VideoPlayerInternals = forwardRef((props, ref) => { +const VideoPlayerInternals = forwardRef((_, ref) => { const video = useContext(VideoPlayerContext); - const dispatch = useContext(VideoPlayerDispatchContext); - - const onPlay = useCallback(() => { - dispatch({ - type: "CONTROL", - do: "PLAY", - soft: true, - }); - }, [dispatch]); - const onPause = useCallback(() => { - dispatch({ - type: "CONTROL", - do: "PAUSE", - soft: true, - }); - }, [dispatch]); - - useEffect(() => {}, []); return ( -