diff --git a/src/components/mediaViewer/VideoPlayer.tsx b/src/components/mediaViewer/VideoPlayer.tsx index 45ac7f233..21712eb4d 100644 --- a/src/components/mediaViewer/VideoPlayer.tsx +++ b/src/components/mediaViewer/VideoPlayer.tsx @@ -92,6 +92,7 @@ const VideoPlayer: FC = ({ const [ isPictureInPictureSupported, enterPictureInPicture, + isInPictureInPicture, ] = usePictureInPicture(videoRef, handleEnterFullscreen, handleLeaveFullscreen); const handleVideoMove = useCallback(() => { @@ -207,7 +208,7 @@ const VideoPlayer: FC = ({ useEffect(() => { if (!isMediaViewerOpen) return undefined; const togglePayingStateBySpace = (e: KeyboardEvent) => { - if (e.key === 'Enter' || e.key === ' ') { + if ((e.key === 'Enter' || e.key === ' ') && !isInPictureInPicture) { e.preventDefault(); togglePlayState(e); } @@ -218,7 +219,7 @@ const VideoPlayer: FC = ({ return () => { document.removeEventListener('keydown', togglePayingStateBySpace, false); }; - }, [togglePlayState, isMediaViewerOpen]); + }, [togglePlayState, isMediaViewerOpen, isInPictureInPicture]); const wrapperStyle = posterSize && `width: ${posterSize.width}px; height: ${posterSize.height}px`; const videoStyle = `background-image: url(${posterData})`; diff --git a/src/hooks/usePictureInPicture.ts b/src/hooks/usePictureInPicture.ts index 3e303a512..cdb9f4387 100644 --- a/src/hooks/usePictureInPicture.ts +++ b/src/hooks/usePictureInPicture.ts @@ -7,7 +7,7 @@ type RefType = { current: HTMLVideoElement | null; }; -type ReturnType = [boolean, () => void] | [false]; +type ReturnType = [boolean, () => void, boolean] | [false]; type CallbackType = () => void; export default function usePictureInPicture( @@ -16,6 +16,7 @@ export default function usePictureInPicture( onLeave: CallbackType, ): ReturnType { const [isSupported, setIsSupported] = useState(false); + const [isInPictureInPicture, setIsInPictureInPicture] = useState(false); useLayoutEffect(() => { // PIP is not supported in PWA on iOS, despite being detected @@ -28,11 +29,19 @@ export default function usePictureInPicture( // @ts-ignore video.autoPictureInPicture = true; setIsSupported(true); - video.addEventListener('enterpictureinpicture', onEnter); - video.addEventListener('leavepictureinpicture', onLeave); + const onEnterInternal = () => { + onEnter(); + setIsInPictureInPicture(true); + }; + const onLeaveInternal = () => { + onLeave(); + setIsInPictureInPicture(false); + }; + video.addEventListener('enterpictureinpicture', onEnterInternal); + video.addEventListener('leavepictureinpicture', onLeaveInternal); return () => { - video.removeEventListener('enterpictureinpicture', onEnter); - video.removeEventListener('leavepictureinpicture', onLeave); + video.removeEventListener('enterpictureinpicture', onEnterInternal); + video.removeEventListener('leavepictureinpicture', onLeaveInternal); }; }, [elRef, onEnter, onLeave]); @@ -68,7 +77,7 @@ export default function usePictureInPicture( return [false]; } - return [isSupported, enterPictureInPicture]; + return [isSupported, enterPictureInPicture, isInPictureInPicture]; } function getSetPresentationMode(video: HTMLVideoElement) {