From c6abcdeb2f52d618ee54e4f6f4b9ee0fb03ba6ce Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sun, 30 Jun 2024 10:21:34 +0000 Subject: [PATCH] Create ref handling and basics stollen from Kyoo --- src/Video.web.tsx | 159 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 src/Video.web.tsx diff --git a/src/Video.web.tsx b/src/Video.web.tsx new file mode 100644 index 00000000..ca932569 --- /dev/null +++ b/src/Video.web.tsx @@ -0,0 +1,159 @@ +import React, { + forwardRef, + useCallback, + useEffect, + useImperativeHandle, + useRef, +} from 'react'; +import type {VideoRef, ReactVideoProps} from './types'; + +const Video = forwardRef( + ( + { + source, + paused, + muted, + volume, + onBuffer, + onLoad, + onProgress, + onError, + onEnd, + onPlaybackStateChanged, + }, + ref, + ) => { + const nativeRef = useRef(null); + const errorHandler = useRef(onError); + errorHandler.current = onError; + + const seek = useCallback(async (time: number, _tolerance?: number) => { + if (isNaN(time)) { + throw new Error('Specified time is not a number'); + } + if (!nativeRef.current) { + console.warn('Video Component is not mounted'); + return; + } + nativeRef.current.currentTime = time; + }, []); + + const pause = useCallback(() => { + if (!nativeRef.current) { + return; + } + nativeRef.current.pause(); + }, []); + + const resume = useCallback(() => { + if (!nativeRef.current) { + return; + } + nativeRef.current.play(); + }, []); + + const unsupported = useCallback(() => { + throw new Error('This is unsupported on the web'); + }, []); + + useImperativeHandle( + ref, + () => ({ + seek, + pause, + resume, + // making the video fullscreen does not work with some subtitles polyfils + // so I decided to not include it. + presentFullscreenPlayer: unsupported, + dismissFullscreenPlayer: unsupported, + save: unsupported, + restoreUserInterfaceForPictureInPictureStopCompleted: unsupported, + }), + [seek, pause, resume, unsupported], + ); + + useEffect(() => { + if (paused) { + pause(); + } else { + resume(); + } + }, [paused, pause, resume]); + useEffect(() => { + if (!nativeRef.current || !volume) { + return; + } + nativeRef.current.volume = Math.max(0, Math.min(volume, 100)) / 100; + }, [volume]); + + const setPlay = useSetAtom(playAtom); + useEffect(() => { + if (!nativeRef.current) return; + // Set play state to the player's value (if autoplay is denied) + setPlay(!nativeRef.current.paused); + }, [setPlay]); + + const setProgress = useSetAtom(progressAtom); + + return ( + <> + +