From fc5b2d456307b74cdb67b2d35749da1d9ba80f09 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Wed, 10 Jul 2024 17:18:21 +0700 Subject: [PATCH] Add web support for fullscreen --- docs/pages/component/methods.mdx | 8 ++-- docs/pages/component/props.mdx | 4 +- src/Video.web.tsx | 82 ++++++++++++++++++++++++++++++-- 3 files changed, 83 insertions(+), 11 deletions(-) diff --git a/docs/pages/component/methods.mdx b/docs/pages/component/methods.mdx index bd4067c8..35d5b0c3 100644 --- a/docs/pages/component/methods.mdx +++ b/docs/pages/component/methods.mdx @@ -6,7 +6,7 @@ This page shows the list of available methods ### `dismissFullscreenPlayer` - + `dismissFullscreenPlayer(): Promise` @@ -25,7 +25,7 @@ Pause the video. ### `presentFullscreenPlayer` - + `presentFullscreenPlayer(): Promise` @@ -117,7 +117,7 @@ This function will throw an error if player is not initialized. ### `setFullScreen` - + `setFullScreen(fullscreen): Promise` @@ -178,7 +178,7 @@ Possible values are: ### `isCodecSupported` - + Indicates whether the provided codec is supported level supported by device. diff --git a/docs/pages/component/props.mdx b/docs/pages/component/props.mdx index 103e9a34..cc197c68 100644 --- a/docs/pages/component/props.mdx +++ b/docs/pages/component/props.mdx @@ -270,7 +270,7 @@ Whether this video view should be focusable with a non-touch input device, eg. r ### `fullscreen` - + Controls whether the player enters fullscreen on play. See [presentFullscreenPlayer](#presentfullscreenplayer) for details. @@ -286,7 +286,7 @@ If a preferred [fullscreenOrientation](#fullscreenorientation) is set, causes th ### `fullscreenOrientation` - + - **all (default)** - - **landscape** diff --git a/src/Video.web.tsx b/src/Video.web.tsx index 2220623f..61631252 100644 --- a/src/Video.web.tsx +++ b/src/Video.web.tsx @@ -20,6 +20,9 @@ const Video = forwardRef( controls, showNotificationControls = false, poster, + fullscreen, + fullscreenAutorotate, + fullscreenOrientation, onBuffer, onLoad, onProgress, @@ -83,6 +86,74 @@ const Video = forwardRef( throw new Error('This is unsupported on the web'); }, []); + // Stock this in a ref to not invalidate memoization when those changes. + const fsPrefs = useRef({ + fullscreenAutorotate, + fullscreenOrientation, + }); + fsPrefs.current = { + fullscreenOrientation, + fullscreenAutorotate, + }; + const setFullScreen = useCallback( + ( + newVal: boolean, + orientation?: ReactVideoProps['fullscreenOrientation'], + autorotate?: boolean, + ) => { + orientation ??= fsPrefs.current.fullscreenOrientation; + autorotate ??= fsPrefs.current.fullscreenAutorotate; + + const run = async () => { + try { + if (newVal) { + await nativeRef.current?.requestFullscreen({ + navigationUI: 'hide', + }); + if (orientation === 'all' || !orientation || autorotate) { + screen.orientation.unlock(); + } else { + await screen.orientation.lock(orientation); + } + } else { + if (document.fullscreenElement) { + await document.exitFullscreen(); + } + screen.orientation.unlock(); + } + } catch (e) { + // Changing fullscreen status without a button click is not allowed so it throws. + // Some browsers also used to throw when locking screen orientation was not supported. + console.error('Could not toggle fullscreen/screen lock status', e); + } + }; + run(); + }, + [], + ); + + useEffect(() => { + setFullScreen( + fullscreen || false, + fullscreenOrientation, + fullscreenAutorotate, + ); + }, [ + setFullScreen, + fullscreen, + fullscreenAutorotate, + fullscreenOrientation, + ]); + + const presentFullscreenPlayer = useCallback( + () => setFullScreen(true), + [setFullScreen], + ); + const dismissFullscreenPlayer = useCallback( + () => setFullScreen(false), + [setFullScreen], + ); + useImperativeHandle( ref, () => ({ @@ -91,11 +162,9 @@ const Video = forwardRef( resume, setVolume, getCurrentPosition, - // making the video fullscreen does not work with some subtitles polyfils - // so I decided to not include it. - presentFullscreenPlayer: unsupported, - dismissFullscreenPlayer: unsupported, - setFullScreen: unsupported, + presentFullscreenPlayer, + dismissFullscreenPlayer, + setFullScreen, save: unsupported, restoreUserInterfaceForPictureInPictureStopCompleted: unsupported, nativeHtmlVideoRef: nativeRef, @@ -108,6 +177,9 @@ const Video = forwardRef( setVolume, getCurrentPosition, nativeRef, + presentFullscreenPlayer, + dismissFullscreenPlayer, + setFullScreen, ], );