import { apiAtom, userAtom } from "@/providers/JellyfinProvider"; import { runningProcesses } from "@/utils/atoms/downloads"; import Ionicons from "@expo/vector-icons/Ionicons"; import { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models"; import AsyncStorage from "@react-native-async-storage/async-storage"; import { useQuery } from "@tanstack/react-query"; import { router } from "expo-router"; import { useAtom } from "jotai"; import { useCallback, useEffect, useState } from "react"; import { ActivityIndicator, TouchableOpacity, View } from "react-native"; import ProgressCircle from "./ProgressCircle"; import { Text } from "./common/Text"; import { useDownloadMedia } from "@/hooks/useDownloadMedia"; import { useRemuxHlsToMp4 } from "@/hooks/useRemuxHlsToMp4"; import { getPlaybackInfo } from "@/utils/jellyfin/media/getPlaybackInfo"; type DownloadProps = { item: BaseItemDto; playbackURL: string; }; export const DownloadItem: React.FC = ({ item, playbackURL, }) => { const [api] = useAtom(apiAtom); const [user] = useAtom(userAtom); const [process] = useAtom(runningProcesses); const { downloadMedia, isDownloading, error, cancelDownload } = useDownloadMedia(api, user?.Id); const { startRemuxing, cancelRemuxing } = useRemuxHlsToMp4(playbackURL, item); const { data: playbackInfo, isLoading } = useQuery({ queryKey: ["playbackInfo", item.Id], queryFn: async () => getPlaybackInfo(api, item.Id, user?.Id), }); const downloadFile = useCallback(async () => { if (!playbackInfo) return; const source = playbackInfo.MediaSources?.[0]; if (source?.SupportsDirectPlay && item.CanDownload) { downloadMedia(item); } else { throw new Error( "Direct play not supported thus the file cannot be downloaded", ); } }, [item, user, playbackInfo]); const [downloaded, setDownloaded] = useState(false); useEffect(() => { (async () => { const data: BaseItemDto[] = JSON.parse( (await AsyncStorage.getItem("downloaded_files")) || "[]", ); if (data.find((d) => d.Id === item.Id)) setDownloaded(true); })(); }, [process]); if (isLoading) { return ; } if (playbackInfo?.MediaSources?.[0].SupportsDirectPlay === false) { return ( ); } if (process && process.item.Id !== item.Id!) { return ( {}} style={{ opacity: 0.5 }}> ); } return ( {process ? ( { cancelRemuxing(); }} className="flex flex-row items-center" > {process.progress === 0 ? ( ) : ( {process.progress.toFixed(0)}% )} {process?.speed && process.speed > 0 ? ( {process.speed.toFixed(2)}x ) : null} ) : downloaded ? ( { router.push( `/(auth)/player/offline/page?url=${item.Id}.mp4&itemId=${item.Id}`, ); }} > ) : ( { // downloadFile(); startRemuxing(); }} > )} ); };