diff --git a/apps/expo/index.js b/apps/expo/index.js index ab16fb5..a561933 100644 --- a/apps/expo/index.js +++ b/apps/expo/index.js @@ -1,2 +1,3 @@ import "expo-router/entry"; +import "react-native-gesture-handler"; import "@react-native-anywhere/polyfill-base64"; diff --git a/apps/expo/src/app/_layout.tsx b/apps/expo/src/app/_layout.tsx index e186aaa..8d95069 100644 --- a/apps/expo/src/app/_layout.tsx +++ b/apps/expo/src/app/_layout.tsx @@ -1,6 +1,7 @@ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ import { useEffect } from "react"; import { useColorScheme } from "react-native"; +import { GestureHandlerRootView } from "react-native-gesture-handler"; import { useFonts } from "expo-font"; import { SplashScreen, Stack } from "expo-router"; import FontAwesome from "@expo/vector-icons/FontAwesome"; @@ -57,7 +58,11 @@ export default function RootLayout() { return null; } - return ; + return ( + + + + ); } function RootLayoutNav() { diff --git a/apps/expo/src/app/videoPlayer/index.tsx b/apps/expo/src/app/videoPlayer/index.tsx index b9309e6..23e607a 100644 --- a/apps/expo/src/app/videoPlayer/index.tsx +++ b/apps/expo/src/app/videoPlayer/index.tsx @@ -1,6 +1,8 @@ import type { AVPlaybackSource } from "expo-av"; import React, { useEffect, useState } from "react"; import { ActivityIndicator, Platform, StyleSheet, View } from "react-native"; +import { Gesture, GestureDetector } from "react-native-gesture-handler"; +import { runOnJS, useSharedValue } from "react-native-reanimated"; import { ResizeMode, Video } from "expo-av"; import * as NavigationBar from "expo-navigation-bar"; import { useLocalSearchParams, useRouter } from "expo-router"; @@ -37,7 +39,9 @@ const VideoPlayer: React.FC = ({ data }) => { const [videoSrc, setVideoSrc] = useState(); const [isLoading, setIsLoading] = useState(true); const [headerData, setHeaderData] = useState(); + const [resizeMode, setResizeMode] = useState(ResizeMode.CONTAIN); const router = useRouter(); + const scale = useSharedValue(1); const setVideoRef = usePlayerStore((state) => state.setVideoRef); const setStatus = usePlayerStore((state) => state.setStatus); const setIsIdle = usePlayerStore((state) => state.setIsIdle); @@ -48,6 +52,19 @@ const VideoPlayer: React.FC = ({ data }) => { (state) => state.dismissFullscreenPlayer, ); + const updateResizeMode = (newMode: ResizeMode) => { + setResizeMode(newMode); + }; + + const pinchGesture = Gesture.Pinch().onUpdate((e) => { + scale.value = e.scale; + if (scale.value > 1 && resizeMode !== ResizeMode.COVER) { + runOnJS(updateResizeMode)(ResizeMode.COVER); + } else if (scale.value <= 1 && resizeMode !== ResizeMode.CONTAIN) { + runOnJS(updateResizeMode)(ResizeMode.CONTAIN); + } + }); + useEffect(() => { const initializePlayer = async () => { StatusBar.setStatusBarHidden(true); @@ -122,22 +139,24 @@ const VideoPlayer: React.FC = ({ data }) => { }; return ( - -