From 01cf273b9293fdc5798eec5fff3e73b4e2e3a2f2 Mon Sep 17 00:00:00 2001 From: Alexander Zinchuk Date: Sat, 15 Apr 2023 13:50:32 +0200 Subject: [PATCH] Media Viewer: Properly handle switching to PIP mode --- src/components/mediaViewer/MediaViewer.tsx | 7 ++++--- src/hooks/usePictureInPicture.ts | 18 ++++++++++++++---- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/components/mediaViewer/MediaViewer.tsx b/src/components/mediaViewer/MediaViewer.tsx index 81353909d..da1e45e17 100644 --- a/src/components/mediaViewer/MediaViewer.tsx +++ b/src/components/mediaViewer/MediaViewer.tsx @@ -33,7 +33,7 @@ import useFlag from '../../hooks/useFlag'; import useForceUpdate from '../../hooks/useForceUpdate'; import { dispatchHeavyAnimationEvent } from '../../hooks/useHeavyAnimationCheck'; import { dispatchPriorityPlaybackEvent } from '../../hooks/usePriorityPlaybackCheck'; -import { exitPictureInPictureIfNeeded } from '../../hooks/usePictureInPicture'; +import { exitPictureInPictureIfNeeded, usePictureInPictureSignal } from '../../hooks/usePictureInPicture'; import useLang from '../../hooks/useLang'; import usePrevious from '../../hooks/usePrevious'; import { useMediaProps } from './hooks/useMediaProps'; @@ -144,8 +144,9 @@ const MediaViewer: FC = ({ animationKey.current = selectedMediaIndex; } + const [getIsPictureInPicture] = usePictureInPictureSignal(); useEffect(() => { - if (!isOpen) { + if (!isOpen || getIsPictureInPicture()) { return undefined; } @@ -156,7 +157,7 @@ const MediaViewer: FC = ({ stopPriorityPlayback(); enableDirectTextInput(); }; - }, [isOpen]); + }, [isOpen, getIsPictureInPicture]); useEffect(() => { if (isVisible) { diff --git a/src/hooks/usePictureInPicture.ts b/src/hooks/usePictureInPicture.ts index 2d3cb6c39..d20c24379 100644 --- a/src/hooks/usePictureInPicture.ts +++ b/src/hooks/usePictureInPicture.ts @@ -2,6 +2,7 @@ import { useLayoutEffect, useCallback, useState } from '../lib/teact/teact'; import { DEBUG } from '../config'; import { IS_IOS, IS_PWA } from '../util/windowEnvironment'; import safePlay, { getIsVideoPlaying } from '../util/safePlay'; +import { createSignal } from '../util/signals'; type RefType = { current: HTMLVideoElement | null; @@ -10,13 +11,20 @@ type RefType = { type ReturnType = [boolean, () => void, boolean] | [false]; type CallbackType = () => void; +const signal = createSignal(false); +const setIsPictureInPicture = signal[1]; + +export function usePictureInPictureSignal() { + return signal; +} + export default function usePictureInPicture( elRef: RefType, onEnter: CallbackType, onLeave: CallbackType, ): ReturnType { const [isSupported, setIsSupported] = useState(false); - const [isInPictureInPicture, setIsInPictureInPicture] = useState(false); + const [isActive, setIsActive] = useState(false); useLayoutEffect(() => { // PIP is not supported in PWA on iOS, despite being detected @@ -31,11 +39,13 @@ export default function usePictureInPicture( setIsSupported(true); const onEnterInternal = () => { onEnter(); - setIsInPictureInPicture(true); + setIsActive(true); + setIsPictureInPicture(true); }; const onLeaveInternal = () => { + setIsPictureInPicture(false); + setIsActive(false); onLeave(); - setIsInPictureInPicture(false); }; video.addEventListener('enterpictureinpicture', onEnterInternal); video.addEventListener('leavepictureinpicture', onLeaveInternal); @@ -77,7 +87,7 @@ export default function usePictureInPicture( return [false]; } - return [isSupported, enterPictureInPicture, isInPictureInPicture]; + return [isSupported, enterPictureInPicture, isActive]; } function getSetPresentationMode(video: HTMLVideoElement) {