From b30786595431878d7d965c0977454da13c92c64c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ska=C5=82ka?= Date: Fri, 15 Mar 2024 13:49:12 +0100 Subject: [PATCH 01/17] Add window dimensions blocking POC --- src/App.tsx | 2 ++ .../AttachmentCarousel/CarouselItem.js | 1 + .../Attachments/AttachmentCarousel/index.js | 18 +++++++++- src/components/VideoPlayer/BaseVideoPlayer.js | 21 ++++++++---- .../VideoPlayerContexts/FullScreenContext.tsx | 34 +++++++++++++++++++ .../VideoPlayerContexts/PlaybackContext.tsx | 18 ++++++++-- src/hooks/useWindowDimensions/index.ts | 33 ++++++++++++++++-- 7 files changed, 114 insertions(+), 13 deletions(-) create mode 100644 src/components/VideoPlayerContexts/FullScreenContext.tsx diff --git a/src/App.tsx b/src/App.tsx index 0e247d5faa53..db0c22f6481d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -20,6 +20,7 @@ import SafeArea from './components/SafeArea'; import ThemeIllustrationsProvider from './components/ThemeIllustrationsProvider'; import ThemeProvider from './components/ThemeProvider'; import ThemeStylesProvider from './components/ThemeStylesProvider'; +import {FullScreenContextProvider} from './components/VideoPlayerContexts/FullScreenContext'; import {PlaybackContextProvider} from './components/VideoPlayerContexts/PlaybackContext'; import {VideoPopoverMenuContextProvider} from './components/VideoPlayerContexts/VideoPopoverMenuContext'; import {VolumeContextProvider} from './components/VideoPlayerContexts/VolumeContext'; @@ -76,6 +77,7 @@ function App({url}: AppProps) { ActiveElementRoleProvider, ActiveWorkspaceContextProvider, PlaybackContextProvider, + FullScreenContextProvider, VolumeContextProvider, VideoPopoverMenuContextProvider, ]} diff --git a/src/components/Attachments/AttachmentCarousel/CarouselItem.js b/src/components/Attachments/AttachmentCarousel/CarouselItem.js index b2c9fed64467..e924cb8c13e9 100644 --- a/src/components/Attachments/AttachmentCarousel/CarouselItem.js +++ b/src/components/Attachments/AttachmentCarousel/CarouselItem.js @@ -109,6 +109,7 @@ function CarouselItem({item, onPress, isFocused, isModalHovered}) { isHovered={isModalHovered} isFocused={isFocused} optionalVideoDuration={item.duration} + isUsedInCarousel /> diff --git a/src/components/Attachments/AttachmentCarousel/index.js b/src/components/Attachments/AttachmentCarousel/index.js index ef6a11f6e67c..a1c923b94425 100644 --- a/src/components/Attachments/AttachmentCarousel/index.js +++ b/src/components/Attachments/AttachmentCarousel/index.js @@ -4,6 +4,8 @@ import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; import BlockingView from '@components/BlockingViews/BlockingView'; import * as Illustrations from '@components/Icon/Illustrations'; +import {useFullScreenContext} from '@components/VideoPlayerContexts/FullScreenContext'; +import {usePlaybackContext} from '@components/VideoPlayerContexts/PlaybackContext'; import withLocalize from '@components/withLocalize'; import withWindowDimensions from '@components/withWindowDimensions'; import useTheme from '@hooks/useTheme'; @@ -32,6 +34,7 @@ function AttachmentCarousel({report, reportActions, parentReportActions, source, const theme = useTheme(); const styles = useThemeStyles(); const scrollRef = useRef(null); + const {isFullscreen} = useFullScreenContext(); const canUseTouchScreen = DeviceCapabilities.canUseTouchScreen(); @@ -77,6 +80,10 @@ function AttachmentCarousel({report, reportActions, parentReportActions, source, */ const updatePage = useCallback( ({viewableItems}) => { + if (isFullscreen.current) { + return; + } + Keyboard.dismiss(); // Since we can have only one item in view at a time, we can use the first item in the array @@ -101,6 +108,10 @@ function AttachmentCarousel({report, reportActions, parentReportActions, source, */ const cycleThroughAttachments = useCallback( (deltaSlide) => { + if (isFullscreen.current) { + return; + } + console.log('cycleThroughAttachments'); const nextIndex = page + deltaSlide; const nextItem = attachments[nextIndex]; @@ -157,7 +168,12 @@ function AttachmentCarousel({report, reportActions, parentReportActions, source, return ( setContainerWidth(PixelRatio.roundToNearestPixel(nativeEvent.layout.width))} + onLayout={({nativeEvent}) => { + if (isFullscreen.current) { + return; + } + setContainerWidth(PixelRatio.roundToNearestPixel(nativeEvent.layout.width)); + }} onMouseEnter={() => !canUseTouchScreen && setShouldShowArrows(true)} onMouseLeave={() => !canUseTouchScreen && setShouldShowArrows(false)} > diff --git a/src/components/VideoPlayer/BaseVideoPlayer.js b/src/components/VideoPlayer/BaseVideoPlayer.js index 92d829e9d0db..1e7cdf7aab66 100644 --- a/src/components/VideoPlayer/BaseVideoPlayer.js +++ b/src/components/VideoPlayer/BaseVideoPlayer.js @@ -6,6 +6,7 @@ import _ from 'underscore'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import Hoverable from '@components/Hoverable'; import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback'; +import {useFullScreenContext} from '@components/VideoPlayerContexts/FullScreenContext'; import {usePlaybackContext} from '@components/VideoPlayerContexts/PlaybackContext'; import VideoPopoverMenu from '@components/VideoPopoverMenu'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -44,6 +45,7 @@ function BaseVideoPlayer({ const styles = useThemeStyles(); const {pauseVideo, playVideo, currentlyPlayingURL, updateSharedElements, sharedElement, originalParent, shareVideoPlayerElements, currentVideoPlayerRef, updateCurrentlyPlayingURL} = usePlaybackContext(); + const {isFullscreen} = useFullScreenContext(); const [duration, setDuration] = useState(videoDuration * 1000); const [position, setPosition] = useState(0); const [isPlaying, setIsPlaying] = useState(false); @@ -120,11 +122,17 @@ function BaseVideoPlayer({ const handleFullscreenUpdate = useCallback( (e) => { + if (e.fullscreenUpdate === VideoFullscreenUpdate.PLAYER_DID_PRESENT) { + isFullscreen.current = true; + } else if (e.fullscreenUpdate === VideoFullscreenUpdate.PLAYER_DID_DISMISS) { + isFullscreen.current = false; + } + onFullscreenUpdate(e); // fix for iOS native and mWeb: when switching to fullscreen and then exiting // the fullscreen mode while playing, the video pauses - if (!isPlaying || e.fullscreenUpdate !== VideoFullscreenUpdate.PLAYER_DID_DISMISS) { + if (e.fullscreenUpdate !== VideoFullscreenUpdate.PLAYER_DID_DISMISS) { return; } @@ -134,7 +142,7 @@ function BaseVideoPlayer({ playVideo(); videoResumeTryNumber.current = 3; }, - [isPlaying, onFullscreenUpdate, pauseVideo, playVideo], + [isFullscreen, onFullscreenUpdate, pauseVideo, playVideo], ); const bindFunctions = useCallback(() => { @@ -174,17 +182,18 @@ function BaseVideoPlayer({ // update shared video elements useEffect(() => { - if (shouldUseSharedVideoElement || url !== currentlyPlayingURL) { + if (shouldUseSharedVideoElement || url !== currentlyPlayingURL || isFullscreen.current) { return; } shareVideoPlayerElements(videoPlayerRef.current, videoPlayerElementParentRef.current, videoPlayerElementRef.current, isUploading); - }, [currentlyPlayingURL, shouldUseSharedVideoElement, shareVideoPlayerElements, updateSharedElements, url, isUploading]); + }, [currentlyPlayingURL, shouldUseSharedVideoElement, shareVideoPlayerElements, updateSharedElements, url, isUploading, isFullscreen]); // append shared video element to new parent (used for example in attachment modal) useEffect(() => { - if (url !== currentlyPlayingURL || !sharedElement || !shouldUseSharedVideoElement) { + if (url !== currentlyPlayingURL || !sharedElement || !shouldUseSharedVideoElement || isFullscreen.current) { return; } + alert(shouldUseSharedVideoElement); const newParentRef = sharedVideoPlayerParentRef.current; videoPlayerRef.current = currentVideoPlayerRef.current; @@ -198,7 +207,7 @@ function BaseVideoPlayer({ } originalParent.appendChild(sharedElement); }; - }, [bindFunctions, currentVideoPlayerRef, currentlyPlayingURL, originalParent, sharedElement, shouldUseSharedVideoElement, url]); + }, [bindFunctions, currentVideoPlayerRef, currentlyPlayingURL, isFullscreen, originalParent, sharedElement, shouldUseSharedVideoElement, url]); return ( <> diff --git a/src/components/VideoPlayerContexts/FullScreenContext.tsx b/src/components/VideoPlayerContexts/FullScreenContext.tsx new file mode 100644 index 000000000000..34525cf10057 --- /dev/null +++ b/src/components/VideoPlayerContexts/FullScreenContext.tsx @@ -0,0 +1,34 @@ +import {last} from 'lodash'; +import PropTypes from 'prop-types'; +import React, {useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react'; +import useCurrentReportID from '@hooks/useCurrentReportID'; + +const FullScreenContext = React.createContext(null); + +function FullScreenContextProvider({children}) { + const isFullscreen = useRef(false); + const lastWindowDimensions = useRef(null); + + const update = useCallback((obj: any) => { + lastWindowDimensions.current = obj; + }, []); + + const contextValue = useMemo(() => ({isFullscreen, lastWindowDimensions, update}), []); + return {children}; +} + +function useFullScreenContext() { + const context = useContext(FullScreenContext); + if (context === undefined) { + throw new Error('usePlaybackContext must be used within a PlaybackContextProvider'); + } + return context; +} + +FullScreenContextProvider.displayName = 'PlaybackContextProvider'; +FullScreenContextProvider.propTypes = { + /** Actual content wrapped by this component */ + children: PropTypes.node.isRequired, +}; + +export {FullScreenContext, FullScreenContextProvider, useFullScreenContext}; diff --git a/src/components/VideoPlayerContexts/PlaybackContext.tsx b/src/components/VideoPlayerContexts/PlaybackContext.tsx index caad4ce5519b..f83eb77e6454 100644 --- a/src/components/VideoPlayerContexts/PlaybackContext.tsx +++ b/src/components/VideoPlayerContexts/PlaybackContext.tsx @@ -13,6 +13,7 @@ function PlaybackContextProvider({children}: ChildrenProps) { const [originalParent, setOriginalParent] = useState(null); const currentVideoPlayerRef = useRef