diff --git a/app/(auth)/(tabs)/_layout.tsx b/app/(auth)/(tabs)/_layout.tsx index e1f6c115..15d8b239 100644 --- a/app/(auth)/(tabs)/_layout.tsx +++ b/app/(auth)/(tabs)/_layout.tsx @@ -3,8 +3,9 @@ import React, { useEffect } from "react"; import * as NavigationBar from "expo-navigation-bar"; import { TabBarIcon } from "@/components/navigation/TabBarIcon"; import { Colors } from "@/constants/Colors"; -import { Platform, TouchableOpacity } from "react-native"; +import { Platform, TouchableOpacity, View } from "react-native"; import { Feather } from "@expo/vector-icons"; +import { Chromecast } from "@/components/Chromecast"; export default function TabLayout() { useEffect(() => { @@ -41,18 +42,23 @@ export default function TabLayout() { router.push("/(auth)/downloads"); }} > - + ), headerRight: () => ( - { - router.push("/(auth)/settings"); - }} - > - - + + + { + router.push("/(auth)/settings"); + }} + > + + + + + ), }} /> diff --git a/app/(auth)/items/[id]/page.tsx b/app/(auth)/items/[id]/page.tsx index 85d2a01c..32a74f3d 100644 --- a/app/(auth)/items/[id]/page.tsx +++ b/app/(auth)/items/[id]/page.tsx @@ -137,35 +137,38 @@ const page: React.FC = () => { const [cp, setCp] = useAtom(currentlyPlayingItemAtom); const client = useRemoteMediaClient(); - const onPressPlay = useCallback(async () => { - if (!playbackUrl || !item) return; + const onPressPlay = useCallback( + async (type: "device" | "cast" = "device") => { + if (!playbackUrl || !item) return; - if (chromecastReady && client) { - await CastContext.getPlayServicesState().then((state) => { - if (state && state !== PlayServicesState.SUCCESS) - CastContext.showPlayServicesErrorDialog(state); - else { - client.loadMedia({ - mediaInfo: { - contentUrl: playbackUrl, - contentType: "video/mp4", - metadata: { - type: item.Type === "Episode" ? "tvShow" : "movie", - title: item.Name || "", - subtitle: item.Overview || "", + if (type === "cast" && client) { + await CastContext.getPlayServicesState().then((state) => { + if (state && state !== PlayServicesState.SUCCESS) + CastContext.showPlayServicesErrorDialog(state); + else { + client.loadMedia({ + mediaInfo: { + contentUrl: playbackUrl, + contentType: "video/mp4", + metadata: { + type: item.Type === "Episode" ? "tvShow" : "movie", + title: item.Name || "", + subtitle: item.Overview || "", + }, }, - }, - startTime: 0, - }); - } - }); - } else { - setCp({ - item, - playbackUrl, - }); - } - }, [playbackUrl, item]); + startTime: 0, + }); + } + }); + } else { + setCp({ + item, + playbackUrl, + }); + } + }, + [playbackUrl, item], + ); if (l1) return ( @@ -262,7 +265,6 @@ const page: React.FC = () => { )} - {item.Overview} @@ -287,7 +289,7 @@ const page: React.FC = () => { diff --git a/app/_layout.tsx b/app/_layout.tsx index 0bcddda6..dde840d1 100644 --- a/app/_layout.tsx +++ b/app/_layout.tsx @@ -9,8 +9,8 @@ import { useEffect, useRef, useState } from "react"; import "react-native-reanimated"; import * as ScreenOrientation from "expo-screen-orientation"; import { StatusBar } from "expo-status-bar"; -import { useSafeAreaInsets } from "react-native-safe-area-context"; import { CurrentlyPlayingBar } from "@/components/CurrentlyPlayingBar"; +import { ActionSheetProvider } from "@expo/react-native-action-sheet"; // Prevent the splash screen from auto-hiding before asset loading is complete. SplashScreen.preventAutoHideAsync(); @@ -75,67 +75,69 @@ export default function RootLayout() { return ( - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + ); diff --git a/components/ParallaxPage.tsx b/components/ParallaxPage.tsx index 90f8bff6..d4aa87ec 100644 --- a/components/ParallaxPage.tsx +++ b/components/ParallaxPage.tsx @@ -9,6 +9,7 @@ import Animated, { useScrollViewOffset, } from "react-native-reanimated"; import { useSafeAreaInsets } from "react-native-safe-area-context"; +import { Chromecast } from "./Chromecast"; const HEADER_HEIGHT = 400; @@ -72,6 +73,15 @@ export const ParallaxScrollView: React.FC = ({ /> + + + + {logo && ( {logo} diff --git a/components/PlayButton.tsx b/components/PlayButton.tsx index 2ebfe94e..4429cd31 100644 --- a/components/PlayButton.tsx +++ b/components/PlayButton.tsx @@ -2,10 +2,12 @@ import { Button } from "./Button"; import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models"; import { Feather, Ionicons } from "@expo/vector-icons"; import { runtimeTicksToMinutes } from "@/utils/time"; +import { useActionSheet } from "@expo/react-native-action-sheet"; +import { View } from "react-native"; interface Props extends React.ComponentProps { item: BaseItemDto; - onPress: () => void; + onPress: (type?: "cast" | "device") => void; chromecastReady: boolean; } @@ -15,15 +17,45 @@ export const PlayButton: React.FC = ({ chromecastReady, ...props }) => { + const { showActionSheetWithOptions } = useActionSheet(); + + const _onPress = () => { + if (!chromecastReady) { + onPress("device"); + return; + } + + const options = ["Chromecast", "Device", "Cancel"]; + const cancelButtonIndex = 2; + + showActionSheetWithOptions( + { + options, + cancelButtonIndex, + }, + (selectedIndex: number | undefined) => { + switch (selectedIndex) { + case 0: + onPress("cast"); + break; + case 1: + onPress("device"); + break; + case cancelButtonIndex: + console.log("calcel"); + } + }, + ); + }; + return (