fix: offline playback using player component

This commit is contained in:
Fredrik Burmester
2024-11-24 10:36:06 +01:00
parent 55f8af7069
commit 6a50eb9044
13 changed files with 177 additions and 1328 deletions

View File

@@ -2,7 +2,7 @@ import { Text } from "@/components/common/Text";
import { ActiveDownloads } from "@/components/downloads/ActiveDownloads";
import { MovieCard } from "@/components/downloads/MovieCard";
import { SeriesCard } from "@/components/downloads/SeriesCard";
import { useDownload } from "@/providers/DownloadProvider";
import { DownloadedItem, useDownload } from "@/providers/DownloadProvider";
import { queueAtom } from "@/utils/atoms/queue";
import { useSettings } from "@/utils/atoms/settings";
import { Ionicons } from "@expo/vector-icons";
@@ -20,16 +20,16 @@ const downloads: React.FC = () => {
const [settings] = useSettings();
const movies = useMemo(
() => downloadedFiles?.filter((f) => f.Type === "Movie") || [],
() => downloadedFiles?.filter((f) => f.item.Type === "Movie") || [],
[downloadedFiles]
);
const groupedBySeries = useMemo(() => {
const episodes = downloadedFiles?.filter((f) => f.Type === "Episode");
const series: { [key: string]: BaseItemDto[] } = {};
const episodes = downloadedFiles?.filter((f) => f.item.Type === "Episode");
const series: { [key: string]: DownloadedItem[] } = {};
episodes?.forEach((e) => {
if (!series[e.SeriesName!]) series[e.SeriesName!] = [];
series[e.SeriesName!].push(e);
if (!series[e.item.SeriesName!]) series[e.item.SeriesName!] = [];
series[e.item.SeriesName!].push(e);
});
return Object.values(series);
}, [downloadedFiles]);
@@ -98,17 +98,20 @@ const downloads: React.FC = () => {
</View>
<ScrollView horizontal showsHorizontalScrollIndicator={false}>
<View className="px-4 flex flex-row">
{movies?.map((item: BaseItemDto) => (
<View className="mb-2 last:mb-0" key={item.Id}>
<MovieCard item={item} />
{movies?.map((item) => (
<View className="mb-2 last:mb-0" key={item.item.Id}>
<MovieCard item={item.item} />
</View>
))}
</View>
</ScrollView>
</View>
)}
{groupedBySeries?.map((items: BaseItemDto[], index: number) => (
<SeriesCard items={items} key={items[0].SeriesId} />
{groupedBySeries?.map((items, index) => (
<SeriesCard
items={items.map((i) => i.item)}
key={items[0].item.SeriesId}
/>
))}
{downloadedFiles?.length === 0 && (
<View className="flex px-4">

View File

@@ -1,2 +0,0 @@
// @ts-ignore
export { default } from "@/components/video-player/offline-player";

View File

@@ -27,7 +27,7 @@ import {
} from "@jellyfin/sdk/lib/utils/api";
import { useQuery } from "@tanstack/react-query";
import * as Haptics from "expo-haptics";
import { useLocalSearchParams } from "expo-router";
import { useGlobalSearchParams, useLocalSearchParams } from "expo-router";
import { useAtomValue } from "jotai";
import React, { useCallback, useMemo, useRef, useState } from "react";
import { Alert, Pressable, View } from "react-native";
@@ -58,7 +58,7 @@ export default function page() {
mediaSourceId,
bitrateValue: bitrateValueStr,
offline: offlineStr,
} = useLocalSearchParams<{
} = useGlobalSearchParams<{
itemId: string;
audioIndex: string;
subtitleIndex: string;
@@ -82,21 +82,20 @@ export default function page() {
} = useQuery({
queryKey: ["item", itemId],
queryFn: async () => {
if (!api) return;
console.log("Offline:", offline);
if (offline) {
const item = await getDownloadedItem(itemId);
if (item) return item.item;
}
const res = await getUserLibraryApi(api).getItem({
const res = await getUserLibraryApi(api!).getItem({
itemId,
userId: user?.Id,
});
return res.data;
},
enabled: !!itemId && !!api,
enabled: !!itemId,
staleTime: 0,
});
@@ -114,8 +113,7 @@ export default function page() {
bitrateValue,
],
queryFn: async () => {
if (!api) return;
console.log("Offline:", offline);
if (offline) {
const item = await getDownloadedItem(itemId);
if (!item?.mediaSource) return null;
@@ -146,7 +144,10 @@ export default function page() {
const { mediaSource, sessionId, url } = res;
if (!sessionId || !mediaSource || !url) return null;
if (!sessionId || !mediaSource || !url) {
Alert.alert("Error", "Failed to get stream url");
return null;
}
return {
mediaSource,
@@ -154,7 +155,7 @@ export default function page() {
url,
};
},
enabled: !!itemId && !!api && !!item && !offline,
enabled: !!itemId && !!item,
staleTime: 0,
});
@@ -292,7 +293,7 @@ export default function page() {
pauseVideo: pause,
playVideo: play,
stopPlayback: stop,
offline: offline,
offline,
});
const onPlaybackStateChanged = useCallback((e: PlaybackStatePayload) => {
@@ -338,7 +339,13 @@ export default function page() {
</View>
);
if (!stream || !item) return null;
if (!stream || !item)
return (
<View className="w-screen h-screen flex flex-col items-center justify-center bg-black">
<Text className="text-white">No stream or item</Text>
<Text className="text-white">Offline: {offline}</Text>
</View>
);
return (
<View