From 669f8d7d1af09027c5f4b3c60a9ddd4c1f969595 Mon Sep 17 00:00:00 2001 From: Fredrik Burmester Date: Wed, 18 Sep 2024 08:41:48 +0200 Subject: [PATCH] fix: design --- components/FullScreenVideoPlayer.tsx | 183 ++++++++++++++++++++------- 1 file changed, 137 insertions(+), 46 deletions(-) diff --git a/components/FullScreenVideoPlayer.tsx b/components/FullScreenVideoPlayer.tsx index f7fddfc8..0010b7d2 100644 --- a/components/FullScreenVideoPlayer.tsx +++ b/components/FullScreenVideoPlayer.tsx @@ -12,7 +12,7 @@ import { runtimeTicksToSeconds } from "@/utils/time"; import { Ionicons } from "@expo/vector-icons"; import { useQuery } from "@tanstack/react-query"; import { Image } from "expo-image"; -import { useRouter, useSegments } from "expo-router"; +import { useNavigation, useRouter, useSegments } from "expo-router"; import * as ScreenOrientation from "expo-screen-orientation"; import { useAtom } from "jotai"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; @@ -20,7 +20,9 @@ import { Alert, AppState, AppStateStatus, + BackHandler, Dimensions, + Platform, TouchableOpacity, View, } from "react-native"; @@ -38,8 +40,13 @@ import Video, { OnProgressData } from "react-native-video"; import { Text } from "./common/Text"; import { itemRouter } from "./common/TouchableItemRouter"; import { Loader } from "./Loader"; +import * as NavigationBar from "expo-navigation-bar"; +import { setStatusBarHidden, StatusBar } from "expo-status-bar"; +import orientationToOrientationLock from "@/utils/OrientationLockConverter"; +import { BlurView } from "expo-blur"; +import { PlatformBlurView } from "./PlatformBlurView"; -async function setOrientation(orientation: ScreenOrientation.OrientationLock) { +async function lockOrientation(orientation: ScreenOrientation.OrientationLock) { await ScreenOrientation.lockAsync(orientation); } @@ -73,6 +80,9 @@ export const FullScreenVideoPlayer: React.FC = () => { const { previousItem, nextItem } = useAdjacentEpisodes({ currentlyPlaying }); const { showControls, hideControls, opacity } = useControlsVisibility(3000); const [isInteractive, setIsInteractive] = useState(true); + const [orientation, setOrientation] = useState( + ScreenOrientation.OrientationLock.UNKNOWN + ); const [ignoreSafeArea, setIgnoreSafeArea] = useState(false); const from = useMemo(() => segments[2], [segments]); @@ -83,6 +93,34 @@ export const FullScreenVideoPlayer: React.FC = () => { const sliding = useRef(false); const localIsBuffering = useSharedValue(false); const cacheProgress = useSharedValue(0); + const [isStatusBarHidden, setIsStatusBarHidden] = useState(false); + + useEffect(() => { + const backAction = () => { + if (currentlyPlaying) { + // Your custom back action here + console.log("onback"); + Alert.alert("Hold on!", "Are you sure you want to exit?", [ + { + text: "Cancel", + onPress: () => null, + style: "cancel", + }, + { text: "Yes", onPress: () => stopPlayback() }, + ]); + + return true; + } + return false; + }; + + const backHandler = BackHandler.addEventListener( + "hardwareBackPress", + backAction + ); + + return () => backHandler.remove(); + }, [currentlyPlaying]); const { width: screenWidth, height: screenHeight } = Dimensions.get("window"); @@ -152,8 +190,12 @@ export const FullScreenVideoPlayer: React.FC = () => { localIsBuffering.value = false; sliding.current = false; hideControls(); + setStatusBarHidden(false); + // NavigationBar.setVisibilityAsync("visible") } else { - setOrientation( + setStatusBarHidden(true); + // NavigationBar.setVisibilityAsync("hidden") + lockOrientation( settings?.defaultVideoOrientation || ScreenOrientation.OrientationLock.DEFAULT ); @@ -164,6 +206,30 @@ export const FullScreenVideoPlayer: React.FC = () => { } }, [currentlyPlaying, settings]); + /** + * Event listener for orientation + */ + useEffect(() => { + const subscription = ScreenOrientation.addOrientationChangeListener( + (event) => { + setOrientation( + orientationToOrientationLock(event.orientationInfo.orientation) + ); + } + ); + + return () => { + subscription.remove(); + }; + }, []); + + const isLandscape = useMemo(() => { + return orientation === ScreenOrientation.OrientationLock.LANDSCAPE_LEFT || + orientation === ScreenOrientation.OrientationLock.LANDSCAPE_RIGHT + ? true + : false; + }, [orientation]); + const animatedStyles = { controls: useAnimatedStyle(() => ({ opacity: withTiming(opacity.value, { duration: 300 }), @@ -219,9 +285,13 @@ export const FullScreenVideoPlayer: React.FC = () => { progress.value > showButtonAt && progress.value < hideButtonAt; return { opacity: withTiming( - localIsBuffering.value === false && opacity.value === 1 && showButton - ? 1 - : 0, + localIsBuffering.value === false && showButton ? 1 : 0, + { + duration: 300, + } + ), + bottom: withTiming( + opacity.value === 0 ? insets.bottom + 8 : isLandscape ? 85 : 140, { duration: 300, } @@ -387,11 +457,9 @@ export const FullScreenVideoPlayer: React.FC = () => { runOnJS(handleSkipForward)(); }); - const skipIntroGesture = Gesture.Tap() - .enabled(opacity.value !== 0) - .onStart(() => { - runOnJS(skipIntro)(); - }); + const skipIntroGesture = Gesture.Tap().onStart(() => { + runOnJS(skipIntro)(); + }); if (!api || !currentlyPlaying) return null; @@ -403,6 +471,7 @@ export const FullScreenVideoPlayer: React.FC = () => { backgroundColor: "black", }} > +