mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-04-20 15:54:42 +01:00
fix: offline playback using player component
This commit is contained in:
@@ -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">
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
// @ts-ignore
|
||||
export { default } from "@/components/video-player/offline-player";
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user