From d4bb64c1e659b6e8aa806721b847fa35114ab9b9 Mon Sep 17 00:00:00 2001 From: Hailey <153161762+haileyok@users.noreply.github.com> Date: Tue, 2 Jan 2024 22:36:43 -0800 Subject: [PATCH] Fix various issues with screen dimension detection in external player (#2349) * various dimension fixes * use reactive hook for dimensions * remove debug * accurate dismissing of player --- .../util/post-embeds/ExternalPlayerEmbed.tsx | 64 +++++++++++++------ 1 file changed, 45 insertions(+), 19 deletions(-) diff --git a/src/view/com/util/post-embeds/ExternalPlayerEmbed.tsx b/src/view/com/util/post-embeds/ExternalPlayerEmbed.tsx index 580cf363..ff3dc1ca 100644 --- a/src/view/com/util/post-embeds/ExternalPlayerEmbed.tsx +++ b/src/view/com/util/post-embeds/ExternalPlayerEmbed.tsx @@ -1,14 +1,21 @@ import React from 'react' import { ActivityIndicator, - Dimensions, GestureResponderEvent, Pressable, StyleSheet, + useWindowDimensions, View, } from 'react-native' +import Animated, { + measure, + runOnJS, + useAnimatedRef, + useFrameCallback, +} from 'react-native-reanimated' import {Image} from 'expo-image' import {WebView} from 'react-native-webview' +import {useSafeAreaInsets} from 'react-native-safe-area-context' import YoutubePlayer from 'react-native-youtube-iframe' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {EmbedPlayerParams, getPlayerHeight} from 'lib/strings/embed-player' @@ -116,6 +123,8 @@ export function ExternalPlayer({ params: EmbedPlayerParams }) { const navigation = useNavigation() + const insets = useSafeAreaInsets() + const windowDims = useWindowDimensions() const [isPlayerActive, setPlayerActive] = React.useState(false) const [isLoading, setIsLoading] = React.useState(true) @@ -124,34 +133,51 @@ export function ExternalPlayer({ height: 0, }) - const viewRef = React.useRef(null) + const viewRef = useAnimatedRef() + + const frameCallback = useFrameCallback(() => { + const measurement = measure(viewRef) + if (!measurement) return + + const {height: winHeight, width: winWidth} = windowDims + + // Get the proper screen height depending on what is going on + const realWinHeight = isNative // If it is native, we always want the larger number + ? winHeight > winWidth + ? winHeight + : winWidth + : winHeight // On web, we always want the actual screen height + + const top = measurement.pageY + const bot = measurement.pageY + measurement.height + + // We can use the same logic on all platforms against the screenHeight that we get above + const isVisible = top <= realWinHeight - insets.bottom && bot >= insets.top + + if (!isVisible) { + runOnJS(setPlayerActive)(false) + } + }, false) // False here disables autostarting the callback // watch for leaving the viewport due to scrolling React.useEffect(() => { + // We don't want to do anything if the player isn't active + if (!isPlayerActive) return + // Interval for scrolling works in most cases, However, for twitch embeds, if we navigate away from the screen the webview will // continue playing. We need to watch for the blur event const unsubscribe = navigation.addListener('blur', () => { setPlayerActive(false) }) - const interval = setInterval(() => { - viewRef.current?.measure((x, y, w, h, pageX, pageY) => { - const window = Dimensions.get('window') - const top = pageY - const bot = pageY + h - const isVisible = isNative - ? top >= 0 && bot <= window.height - : !(top >= window.height || bot <= 0) - if (!isVisible) { - setPlayerActive(false) - } - }) - }, 1e3) + // Start watching for changes + frameCallback.setActive(true) + return () => { unsubscribe() - clearInterval(interval) + frameCallback.setActive(false) } - }, [viewRef, navigation]) + }, [navigation, isPlayerActive, frameCallback]) // calculate height for the player and the screen size const height = React.useMemo( @@ -187,7 +213,7 @@ export function ExternalPlayer({ ) return ( - - + ) }