diff --git a/apps/expo/src/app/hooks/usePlayer.ts b/apps/expo/src/app/hooks/usePlayer.ts new file mode 100644 index 0000000..093268c --- /dev/null +++ b/apps/expo/src/app/hooks/usePlayer.ts @@ -0,0 +1,41 @@ +import type { VideoRef } from "react-native-video"; +import { useCallback, useRef } from "react"; +import * as ScreenOrientation from "expo-screen-orientation"; + +export const usePlayer = () => { + const ref = useRef(null); + + const lockOrientation = useCallback(async () => { + await ScreenOrientation.lockAsync( + ScreenOrientation.OrientationLock.LANDSCAPE, + ); + }, []); + + const unlockOrientation = useCallback(async () => { + await ScreenOrientation.lockAsync( + ScreenOrientation.OrientationLock.PORTRAIT_UP, + ); + }, []); + + const presentFullscreenPlayer = useCallback(async () => { + if (ref.current) { + ref.current.presentFullscreenPlayer(); + await lockOrientation(); + } + }, [lockOrientation]); + + const dismissFullscreenPlayer = useCallback(async () => { + if (ref.current) { + ref.current.dismissFullscreenPlayer(); + await unlockOrientation(); + } + }, [unlockOrientation]); + + return { + videoRef: ref, + lockOrientation, + unlockOrientation, + presentFullscreenPlayer, + dismissFullscreenPlayer, + } as const; +}; diff --git a/apps/expo/src/app/video-player.tsx b/apps/expo/src/app/video-player.tsx index 780abe8..80373e6 100644 --- a/apps/expo/src/app/video-player.tsx +++ b/apps/expo/src/app/video-player.tsx @@ -1,5 +1,5 @@ -import type { VideoRef } from "react-native-video"; -import React, { useEffect, useRef, useState } from "react"; +import type { ReactVideoSource } from "react-native-video"; +import React, { useEffect, useState } from "react"; import { ActivityIndicator, StyleSheet } from "react-native"; import { SafeAreaView } from "react-native-safe-area-context"; import Video from "react-native-video"; @@ -14,6 +14,7 @@ import { import { fetchMediaDetails } from "@movie-web/tmdb"; import type { ItemData } from "./components/item/item"; +import { usePlayer } from "./hooks/usePlayer"; export default function VideoPlayerWrapper() { const params = useLocalSearchParams(); @@ -28,11 +29,15 @@ interface VideoPlayerProps { } const VideoPlayer: React.FC = ({ data }) => { - const [videoUrl, setVideoUrl] = useState(""); - const [headers, setHeaders] = useState({} as Record); + const [videoSrc, setVideoSrc] = useState(); const [isLoading, setIsLoading] = useState(true); - const videoPlayer = useRef(null); const router = useRouter(); + const { + videoRef, + unlockOrientation, + presentFullscreenPlayer, + dismissFullscreenPlayer, + } = usePlayer(); useEffect(() => { const initializePlayer = async () => { @@ -84,13 +89,13 @@ const VideoPlayer: React.FC = ({ data }) => { url = stream.playlist; } - const combinedHeaders = { - ...stream.headers, - ...stream.preferredHeaders, - }; - - setHeaders(combinedHeaders); - setVideoUrl(url); + setVideoSrc({ + uri: url, + headers: { + ...stream.preferredHeaders, + ...stream.headers, + }, + }); setIsLoading(false); } else { await ScreenOrientation.lockAsync( @@ -100,40 +105,21 @@ const VideoPlayer: React.FC = ({ data }) => { } }; - const lockOrientation = async () => { - await ScreenOrientation.lockAsync( - ScreenOrientation.OrientationLock.LANDSCAPE, - ); - }; - - const unlockOrientation = async () => { - await ScreenOrientation.lockAsync( - ScreenOrientation.OrientationLock.PORTRAIT_UP, - ); - }; - - const presentFullscreenPlayer = async () => { - if (videoPlayer.current) { - videoPlayer.current.presentFullscreenPlayer(); - await lockOrientation(); - } - }; - - const dismissFullscreenPlayer = async () => { - if (videoPlayer.current) { - videoPlayer.current.dismissFullscreenPlayer(); - await unlockOrientation(); - } - }; - setIsLoading(true); void presentFullscreenPlayer(); void initializePlayer(); return () => { void dismissFullscreenPlayer(); + void unlockOrientation(); }; - }, [data, router]); + }, [ + data, + dismissFullscreenPlayer, + presentFullscreenPlayer, + router, + unlockOrientation, + ]); const onVideoLoadStart = () => { setIsLoading(true); @@ -146,8 +132,8 @@ const VideoPlayer: React.FC = ({ data }) => { return (