diff --git a/app/(auth)/play.tsx b/app/(auth)/play.tsx
new file mode 100644
index 00000000..0d3b3891
--- /dev/null
+++ b/app/(auth)/play.tsx
@@ -0,0 +1,48 @@
+import { FullScreenVideoPlayer } from "@/components/FullScreenVideoPlayer";
+import { useSettings } from "@/utils/atoms/settings";
+import * as NavigationBar from "expo-navigation-bar";
+import { StatusBar } from "expo-status-bar";
+import { useEffect, useState } from "react";
+import { Platform, View, ViewProps } from "react-native";
+import * as ScreenOrientation from "expo-screen-orientation";
+
+interface Props extends ViewProps {}
+
+export default function page() {
+ const [settings] = useSettings();
+
+ useEffect(() => {
+ if (settings?.autoRotate) {
+ // Don't need to do anything
+ } else if (settings?.defaultVideoOrientation) {
+ ScreenOrientation.lockAsync(settings.defaultVideoOrientation);
+ }
+
+ if (Platform.OS === "android") {
+ NavigationBar.setVisibilityAsync("hidden");
+ NavigationBar.setBehaviorAsync("overlay-swipe");
+ }
+
+ return () => {
+ if (settings?.autoRotate) {
+ ScreenOrientation.unlockAsync();
+ } else {
+ ScreenOrientation.lockAsync(
+ ScreenOrientation.OrientationLock.PORTRAIT_UP
+ );
+ }
+
+ if (Platform.OS === "android") {
+ NavigationBar.setVisibilityAsync("visible");
+ NavigationBar.setBehaviorAsync("inset-swipe");
+ }
+ };
+ }, [settings]);
+
+ return (
+
+
+
+
+ );
+}
diff --git a/app/_layout.tsx b/app/_layout.tsx
index cac8f2ea..e610f447 100644
--- a/app/_layout.tsx
+++ b/app/_layout.tsx
@@ -120,13 +120,17 @@ function Layout() {
title: "",
}}
/>
+
-
+ {/* */}
diff --git a/components/FullScreenVideoPlayer.tsx b/components/FullScreenVideoPlayer.tsx
index d9faf3f4..c80fdb76 100644
--- a/components/FullScreenVideoPlayer.tsx
+++ b/components/FullScreenVideoPlayer.tsx
@@ -45,6 +45,9 @@ import {
ticksToSeconds,
} from "@/utils/time";
+const windowDimensions = Dimensions.get("window");
+const screenDimensions = Dimensions.get("screen");
+
export const FullScreenVideoPlayer: React.FC = () => {
const {
currentlyPlaying,
@@ -85,7 +88,20 @@ export const FullScreenVideoPlayer: React.FC = () => {
const min = useSharedValue(0);
const max = useSharedValue(currentlyPlaying?.item.RunTimeTicks || 0);
- const { width: screenWidth, height: screenHeight } = Dimensions.get("window");
+ const [dimensions, setDimensions] = useState({
+ window: windowDimensions,
+ screen: screenDimensions,
+ });
+
+ useEffect(() => {
+ const subscription = Dimensions.addEventListener(
+ "change",
+ ({ window, screen }) => {
+ setDimensions({ window, screen });
+ }
+ );
+ return () => subscription?.remove();
+ });
const from = useMemo(() => segments[2], [segments]);
@@ -123,7 +139,13 @@ export const FullScreenVideoPlayer: React.FC = () => {
onPress: () => null,
style: "cancel",
},
- { text: "Yes", onPress: () => stopPlayback() },
+ {
+ text: "Yes",
+ onPress: () => {
+ stopPlayback();
+ router.back();
+ },
+ },
]);
return true;
}
@@ -136,7 +158,7 @@ export const FullScreenVideoPlayer: React.FC = () => {
);
return () => backHandler.remove();
- }, [currentlyPlaying, stopPlayback]);
+ }, [currentlyPlaying, stopPlayback, router]);
const [orientation, setOrientation] = useState(
ScreenOrientation.OrientationLock.UNKNOWN
@@ -154,6 +176,10 @@ export const FullScreenVideoPlayer: React.FC = () => {
}
);
+ ScreenOrientation.getOrientationAsync().then((orientation) => {
+ setOrientation(orientationToOrientationLock(orientation));
+ });
+
return () => {
subscription.remove();
};
@@ -199,25 +225,13 @@ export const FullScreenVideoPlayer: React.FC = () => {
}, [currentlyPlaying, api, poster]);
useEffect(() => {
- if (!currentlyPlaying) {
- ScreenOrientation.unlockAsync();
- progress.value = 0;
- max.value = 0;
- setShowControls(true);
- setIsStatusBarHidden(false);
- isSeeking.value = false;
- } else {
- setIsStatusBarHidden(true);
- ScreenOrientation.lockAsync(
- settings?.defaultVideoOrientation ||
- ScreenOrientation.OrientationLock.DEFAULT
- );
+ if (currentlyPlaying) {
progress.value =
currentlyPlaying.item?.UserData?.PlaybackPositionTicks || 0;
max.value = currentlyPlaying.item.RunTimeTicks || 0;
setShowControls(true);
}
- }, [currentlyPlaying, settings]);
+ }, [currentlyPlaying]);
const toggleControls = () => setShowControls(!showControls);
@@ -243,10 +257,10 @@ export const FullScreenVideoPlayer: React.FC = () => {
[setIsPlaying]
);
- const handlePlayPause = () => {
+ const handlePlayPause = useCallback(() => {
if (isPlaying) pauseVideo();
else playVideo();
- };
+ }, [isPlaying, pauseVideo, playVideo]);
const handleSliderComplete = (value: number) => {
progress.value = value;
@@ -287,25 +301,25 @@ export const FullScreenVideoPlayer: React.FC = () => {
}
}, [settings]);
- const handleGoToPreviousItem = () => {
+ const handleGoToPreviousItem = useCallback(() => {
if (!previousItem || !from) return;
const url = itemRouter(previousItem, from);
stopPlayback();
// @ts-ignore
router.push(url);
- };
+ }, [previousItem, from, stopPlayback, router]);
- const handleGoToNextItem = () => {
+ const handleGoToNextItem = useCallback(() => {
if (!nextItem || !from) return;
const url = itemRouter(nextItem, from);
stopPlayback();
// @ts-ignore
router.push(url);
- };
+ }, [nextItem, from, stopPlayback, router]);
- const toggleIgnoreSafeArea = () => {
- setIgnoreSafeArea(!ignoreSafeArea);
- };
+ const toggleIgnoreSafeArea = useCallback(() => {
+ setIgnoreSafeArea((prev) => !prev);
+ }, []);
const { data: introTimestamps } = useQuery({
queryKey: ["introTimestamps", currentlyPlaying?.item.Id],
@@ -338,27 +352,26 @@ export const FullScreenVideoPlayer: React.FC = () => {
enabled: !!currentlyPlaying?.item.Id,
});
- const skipIntro = async () => {
+ const skipIntro = useCallback(async () => {
if (!introTimestamps || !videoRef.current) return;
try {
videoRef.current.seek(introTimestamps.IntroEnd);
} catch (error) {
writeToLog("ERROR", "Error skipping intro", error);
}
- };
+ }, [introTimestamps]);
if (!currentlyPlaying) return null;
return (
-
- {
left: ignoreSafeArea ? 0 : insets.left,
right: ignoreSafeArea ? 0 : insets.right,
width: ignoreSafeArea
- ? screenWidth
- : screenWidth - (insets.left + insets.right),
+ ? dimensions.window.width
+ : dimensions.window.width - (insets.left + insets.right),
},
]}
>
@@ -388,12 +401,28 @@ export const FullScreenVideoPlayer: React.FC = () => {
fullscreen={false}
/>
)}
-
+
+
+ {(showControls || isBuffering) && (
+
+ )}
{isBuffering && (
@@ -409,10 +438,9 @@ export const FullScreenVideoPlayer: React.FC = () => {
bottom: isLandscape ? insets.bottom + 26 : insets.bottom + 70,
right: isLandscape ? insets.right + 32 : insets.right + 16,
height: 70,
- zIndex: 10,
},
]}
- className=""
+ className="z-10"
>
{
{
position: "absolute",
top: insets.top,
- right: isLandscape ? insets.right + 32 : insets.right + 8,
+ right: isLandscape ? insets.right + 32 : insets.right + 16,
height: 70,
+ zIndex: 10,
},
]}
className="flex flex-row items-center space-x-2 z-10"
@@ -447,7 +476,10 @@ export const FullScreenVideoPlayer: React.FC = () => {
/>
{
+ stopPlayback();
+ router.back();
+ }}
className="aspect-square flex flex-col bg-neutral-800 rounded-xl items-center justify-center p-2"
>
@@ -461,8 +493,8 @@ export const FullScreenVideoPlayer: React.FC = () => {
bottom: insets.bottom + 8,
left: isLandscape ? insets.left + 32 : insets.left + 16,
width: isLandscape
- ? screenWidth - insets.left - insets.right - 64
- : screenWidth - insets.left - insets.right - 32,
+ ? dimensions.window.width - insets.left - insets.right - 64
+ : dimensions.window.width - insets.left - insets.right - 32,
},
]}
>
diff --git a/components/PlayButton.tsx b/components/PlayButton.tsx
index 9428e80f..d36554f3 100644
--- a/components/PlayButton.tsx
+++ b/components/PlayButton.tsx
@@ -27,6 +27,7 @@ import Animated, {
} from "react-native-reanimated";
import { Button } from "./Button";
import { Text } from "./common/Text";
+import { useRouter } from "expo-router";
interface Props extends React.ComponentProps {
item?: BaseItemDto | null;
@@ -45,6 +46,8 @@ export const PlayButton: React.FC = ({ item, url, ...props }) => {
const [colorAtom] = useAtom(itemThemeColorAtom);
const [api] = useAtom(apiAtom);
+ const router = useRouter();
+
const memoizedItem = useMemo(() => item, [item?.Id]); // Memoize the item
const memoizedColor = useMemo(() => colorAtom, [colorAtom]); // Memoize the color
@@ -63,6 +66,7 @@ export const PlayButton: React.FC = ({ item, url, ...props }) => {
if (!url || !item) return;
if (!client) {
setCurrentlyPlayingState({ item, url });
+ router.push("/play");
return;
}
const options = ["Chromecast", "Device", "Cancel"];
@@ -159,7 +163,9 @@ export const PlayButton: React.FC = ({ item, url, ...props }) => {
});
break;
case 1:
+ console.log("Device");
setCurrentlyPlayingState({ item, url });
+ router.push("/play");
break;
case cancelButtonIndex:
break;