diff --git a/docs/pages/component/events.mdx b/docs/pages/component/events.mdx index 47f902042f..f59d35f21e 100644 --- a/docs/pages/component/events.mdx +++ b/docs/pages/component/events.mdx @@ -317,7 +317,7 @@ Example: ### `onPictureInPictureStatusChanged` - + Callback function that is called when picture in picture becomes active or inactive. diff --git a/docs/pages/component/methods.mdx b/docs/pages/component/methods.mdx index 5c1f39a249..223fbd2f3e 100644 --- a/docs/pages/component/methods.mdx +++ b/docs/pages/component/methods.mdx @@ -80,7 +80,7 @@ Future: ### `enterPictureInPicture` - + `enterPictureInPicture()` @@ -114,7 +114,7 @@ NOTE: Video ads cannot start when you are using the PIP on iOS (more info availa ### `exitPictureInPicture` - + `exitPictureInPicture()` diff --git a/src/Video.web.tsx b/src/Video.web.tsx index 920e406521..1dcc6843dd 100644 --- a/src/Video.web.tsx +++ b/src/Video.web.tsx @@ -50,6 +50,7 @@ const Video = forwardRef( onVolumeChange, onEnd, onPlaybackStateChanged, + onPictureInPictureStatusChanged, }, ref, ) => { @@ -180,6 +181,31 @@ const Video = forwardRef( [setFullScreen], ); + const enterPictureInPicture = useCallback(() => { + try { + if (!nativeRef.current) { + console.error('Video Component is not mounted'); + } else { + nativeRef.current.requestPictureInPicture(); + } + } catch (e) { + console.error(e); + } + }, []); + + const exitPictureInPicture = useCallback(() => { + if ( + nativeRef.current && + nativeRef.current === document.pictureInPictureElement + ) { + try { + document.exitPictureInPicture(); + } catch (e) { + console.error(e); + } + } + }, []); + useImperativeHandle( ref, () => ({ @@ -193,8 +219,8 @@ const Video = forwardRef( dismissFullscreenPlayer, setFullScreen, save: unsupported, - enterPictureInPicture: unsupported, - exitPictureInPicture: unsupported, + enterPictureInPicture, + exitPictureInPicture, restoreUserInterfaceForPictureInPictureStopCompleted: unsupported, nativeHtmlVideoRef: nativeRef, }), @@ -210,6 +236,8 @@ const Video = forwardRef( presentFullscreenPlayer, dismissFullscreenPlayer, setFullScreen, + enterPictureInPicture, + exitPictureInPicture, ], ); @@ -254,6 +282,27 @@ const Video = forwardRef( nativeRef.current.playbackRate = rate; }, [rate]); + useEffect(() => { + if ( + typeof onPictureInPictureStatusChanged !== 'function' || + !nativeRef.current + ) { + return; + } + const onEnterPip = () => + onPictureInPictureStatusChanged({isActive: true}); + const onLeavePip = () => + onPictureInPictureStatusChanged({isActive: false}); + + const video = nativeRef.current; + video.addEventListener('enterpictureinpicture', onEnterPip); + video.addEventListener('leavepictureinpicture', onLeavePip); + return () => { + video.removeEventListener('enterpictureinpicture', onEnterPip); + video.removeEventListener('leavepictureinpicture', onLeavePip); + }; + }, [onPictureInPictureStatusChanged]); + useMediaSession(src?.metadata, nativeRef, showNotificationControls); return (