This commit is contained in:
Fredrik Burmester
2024-10-04 13:29:16 +02:00
parent 097c428d41
commit d9037e72f0
6 changed files with 55 additions and 24 deletions

View File

@@ -1,12 +1,14 @@
import { Chromecast } from "@/components/Chromecast"; import { Chromecast } from "@/components/Chromecast";
import { HeaderBackButton } from "@/components/common/HeaderBackButton"; import { HeaderBackButton } from "@/components/common/HeaderBackButton";
import { nestedTabPageScreenOptions } from "@/components/stacks/NestedTabPageStack"; import { nestedTabPageScreenOptions } from "@/components/stacks/NestedTabPageStack";
import { useDownload } from "@/providers/DownloadProvider";
import { Feather } from "@expo/vector-icons"; import { Feather } from "@expo/vector-icons";
import { Stack, useRouter } from "expo-router"; import { Stack, useRouter } from "expo-router";
import { Platform, TouchableOpacity, View } from "react-native"; import { Platform, TouchableOpacity, View } from "react-native";
export default function IndexLayout() { export default function IndexLayout() {
const router = useRouter(); const router = useRouter();
return ( return (
<Stack> <Stack>
<Stack.Screen <Stack.Screen

View File

@@ -4,9 +4,11 @@ import { LargeMovieCarousel } from "@/components/home/LargeMovieCarousel";
import { ScrollingCollectionList } from "@/components/home/ScrollingCollectionList"; import { ScrollingCollectionList } from "@/components/home/ScrollingCollectionList";
import { Loader } from "@/components/Loader"; import { Loader } from "@/components/Loader";
import { MediaListSection } from "@/components/medialists/MediaListSection"; import { MediaListSection } from "@/components/medialists/MediaListSection";
import { Colors } from "@/constants/Colors";
import { useDownload } from "@/providers/DownloadProvider";
import { apiAtom, userAtom } from "@/providers/JellyfinProvider"; import { apiAtom, userAtom } from "@/providers/JellyfinProvider";
import { useSettings } from "@/utils/atoms/settings"; import { useSettings } from "@/utils/atoms/settings";
import { Ionicons } from "@expo/vector-icons"; import { Feather, Ionicons } from "@expo/vector-icons";
import { Api } from "@jellyfin/sdk"; import { Api } from "@jellyfin/sdk";
import { import {
BaseItemDto, BaseItemDto,
@@ -21,13 +23,15 @@ import {
} from "@jellyfin/sdk/lib/utils/api"; } from "@jellyfin/sdk/lib/utils/api";
import NetInfo from "@react-native-community/netinfo"; import NetInfo from "@react-native-community/netinfo";
import { QueryFunction, useQuery, useQueryClient } from "@tanstack/react-query"; import { QueryFunction, useQuery, useQueryClient } from "@tanstack/react-query";
import { useRouter } from "expo-router"; import { useNavigation, useRouter } from "expo-router";
import { useAtom } from "jotai"; import { useAtom } from "jotai";
import { useCallback, useEffect, useMemo, useState } from "react"; import { useCallback, useEffect, useMemo, useState } from "react";
import { import {
ActivityIndicator, ActivityIndicator,
Platform,
RefreshControl, RefreshControl,
ScrollView, ScrollView,
TouchableOpacity,
View, View,
} from "react-native"; } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context"; import { useSafeAreaInsets } from "react-native-safe-area-context";
@@ -61,6 +65,29 @@ export default function index() {
const [isConnected, setIsConnected] = useState<boolean | null>(null); const [isConnected, setIsConnected] = useState<boolean | null>(null);
const [loadingRetry, setLoadingRetry] = useState(false); const [loadingRetry, setLoadingRetry] = useState(false);
const { downloadedFiles } = useDownload();
const navigation = useNavigation();
useEffect(() => {
const hasDownloads = downloadedFiles && downloadedFiles.length > 0;
navigation.setOptions({
headerLeft: () => (
<TouchableOpacity
onPress={() => {
router.push("/(auth)/downloads");
}}
className="p-2"
>
<Feather
name="download"
color={hasDownloads ? Colors.primary : "white"}
size={22}
/>
</TouchableOpacity>
),
});
}, [downloadedFiles, navigation, router]);
const checkConnection = useCallback(async () => { const checkConnection = useCallback(async () => {
setLoadingRetry(true); setLoadingRetry(true);
const state = await NetInfo.fetch(); const state = await NetInfo.fetch();

BIN
bun.lockb

Binary file not shown.

View File

@@ -32,7 +32,7 @@ import {
useSharedValue, useSharedValue,
} from "react-native-reanimated"; } from "react-native-reanimated";
import { useSafeAreaInsets } from "react-native-safe-area-context"; import { useSafeAreaInsets } from "react-native-safe-area-context";
import Video, { OnProgressData } from "react-native-video"; import Video, { OnProgressData, ReactVideoProps } from "react-native-video";
import { Text } from "./common/Text"; import { Text } from "./common/Text";
import { itemRouter } from "./common/TouchableItemRouter"; import { itemRouter } from "./common/TouchableItemRouter";
import { Loader } from "./Loader"; import { Loader } from "./Loader";
@@ -199,8 +199,8 @@ export const FullScreenVideoPlayer: React.FC = () => {
}); });
}, [currentlyPlaying?.item, api]); }, [currentlyPlaying?.item, api]);
const videoSource = useMemo(() => { const videoSource: ReactVideoProps["source"] = useMemo(() => {
if (!api || !currentlyPlaying || !poster) return null; if (!api || !currentlyPlaying || !poster) return undefined;
const startPosition = currentlyPlaying.item?.UserData?.PlaybackPositionTicks const startPosition = currentlyPlaying.item?.UserData?.PlaybackPositionTicks
? Math.round(currentlyPlaying.item.UserData.PlaybackPositionTicks / 10000) ? Math.round(currentlyPlaying.item.UserData.PlaybackPositionTicks / 10000)
: 0; : 0;
@@ -342,24 +342,25 @@ export const FullScreenVideoPlayer: React.FC = () => {
}, },
]} ]}
> >
{videoSource && ( <Video
<Video ref={videoRef}
ref={videoRef} source={videoSource}
source={videoSource} style={{ width: "100%", height: "100%" }}
style={{ width: "100%", height: "100%" }} resizeMode={ignoreSafeArea ? "cover" : "contain"}
resizeMode={ignoreSafeArea ? "cover" : "contain"} onProgress={handleVideoProgress}
onProgress={handleVideoProgress} onLoad={(data) => (max.value = secondsToTicks(data.duration))}
onLoad={(data) => (max.value = secondsToTicks(data.duration))} onError={handleVideoError}
onError={handleVideoError} playWhenInactive={true}
playWhenInactive={true} allowsExternalPlayback={true}
allowsExternalPlayback={true} playInBackground={true}
playInBackground={true} pictureInPicture={true}
pictureInPicture={true} showNotificationControls={true}
showNotificationControls={true} ignoreSilentSwitch="ignore"
ignoreSilentSwitch="ignore" fullscreen={false}
fullscreen={false} onVideoTracks={(d) => {
/> console.log("onVideoTracks ~", d);
)} }}
/>
</Pressable> </Pressable>
{(showControls || isBuffering) && ( {(showControls || isBuffering) && (

View File

@@ -7,6 +7,7 @@ const tintColorLight = "#0a7ea4";
const tintColorDark = "#fff"; const tintColorDark = "#fff";
export const Colors = { export const Colors = {
primary: "#9334E9",
text: "#ECEDEE", text: "#ECEDEE",
background: "#151718", background: "#151718",
tint: tintColorDark, tint: tintColorDark,

View File

@@ -79,7 +79,7 @@
"react-native-svg": "15.2.0", "react-native-svg": "15.2.0",
"react-native-url-polyfill": "^2.0.0", "react-native-url-polyfill": "^2.0.0",
"react-native-uuid": "^2.0.2", "react-native-uuid": "^2.0.2",
"react-native-video": "^6.6.3", "react-native-video": "^6.6.4",
"react-native-web": "~0.19.10", "react-native-web": "~0.19.10",
"sonner-native": "^0.14.2", "sonner-native": "^0.14.2",
"tailwindcss": "3.3.2", "tailwindcss": "3.3.2",