fix: load active downloads on app open

This commit is contained in:
Fredrik Burmester
2025-02-17 17:24:11 +01:00
parent f30f53f566
commit ec153ebfc6
3 changed files with 45 additions and 27 deletions

View File

@@ -34,6 +34,14 @@ async function cancelDownload(id: string): Promise<void> {
return HlsDownloaderModule.cancelDownload(id); return HlsDownloaderModule.cancelDownload(id);
} }
/**
*
* @returns A list of active downloads.
*/
async function getActiveDownloads(): Promise<DownloadInfo[]> {
return HlsDownloaderModule.getActiveDownloads();
}
/** /**
* Subscribes to download progress events. * Subscribes to download progress events.
* @param listener A callback invoked with progress updates. * @param listener A callback invoked with progress updates.
@@ -104,4 +112,5 @@ export {
addProgressListener, addProgressListener,
HlsDownloaderModule, HlsDownloaderModule,
cancelDownload, cancelDownload,
getActiveDownloads,
}; };

View File

@@ -73,6 +73,18 @@ public class HlsDownloaderModule: Module {
Events("onProgress", "onError", "onComplete") Events("onProgress", "onError", "onComplete")
Function("getActiveDownloads") { () -> [[String: Any]] in
return activeDownloads.map { (taskId, downloadInfo) in
return [
"id": downloadInfo.delegate.providedId,
"state": "DOWNLOADING",
"metadata": downloadInfo.metadata,
"startTime": downloadInfo.startTime,
"taskId": taskId,
]
}
}
Function("downloadHLSAsset") { Function("downloadHLSAsset") {
(providedId: String, url: String, metadata: [String: Any]?) -> Void in (providedId: String, url: String, metadata: [String: Any]?) -> Void in
let startTime = Date().timeIntervalSince1970 let startTime = Date().timeIntervalSince1970

View File

@@ -1,10 +1,10 @@
import useImageStorage from "@/hooks/useImageStorage"; import useImageStorage from "@/hooks/useImageStorage";
import { import {
addCompleteListener,
addErrorListener, addErrorListener,
addProgressListener, addProgressListener,
downloadHLSAsset,
cancelDownload, cancelDownload,
downloadHLSAsset,
getActiveDownloads,
} from "@/modules/hls-downloader"; } from "@/modules/hls-downloader";
import { import {
DownloadInfo, DownloadInfo,
@@ -12,13 +12,12 @@ import {
} from "@/modules/hls-downloader/src/HlsDownloader.types"; } from "@/modules/hls-downloader/src/HlsDownloader.types";
import { getItemImage } from "@/utils/getItemImage"; import { getItemImage } from "@/utils/getItemImage";
import { getStreamUrl } from "@/utils/jellyfin/media/getStreamUrl"; import { getStreamUrl } from "@/utils/jellyfin/media/getStreamUrl";
import { rewriteM3U8Files } from "@/utils/movpkg-to-vlc/tools";
import download from "@/utils/profiles/download"; import download from "@/utils/profiles/download";
import { import {
BaseItemDto, BaseItemDto,
MediaSourceInfo, MediaSourceInfo,
} from "@jellyfin/sdk/lib/generated-client/models"; } from "@jellyfin/sdk/lib/generated-client/models";
import { useQuery, useQueryClient } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query";
import * as FileSystem from "expo-file-system"; import * as FileSystem from "expo-file-system";
import { useAtomValue } from "jotai"; import { useAtomValue } from "jotai";
import { createContext, useContext, useEffect, useState } from "react"; import { createContext, useContext, useEffect, useState } from "react";
@@ -55,28 +54,6 @@ const DownloadContext = createContext<DownloadContextType | undefined>(
undefined undefined
); );
/**
* Marks a file as done by creating a file with the same name in the downloads directory.
* @param doneFile - The name of the file to mark as done.
*/
const markFileAsDone = async (id: string) => {
await FileSystem.writeAsStringAsync(
`${FileSystem.documentDirectory}downloads/${id}-done`,
"done"
);
};
/**
* Checks if a file is marked as done by checking if a file with the same name exists in the downloads directory.
* @param doneFile - The name of the file to check.
* @returns True if the file is marked as done, false otherwise.
*/
const isFileMarkedAsDone = async (id: string) => {
const fileUri = `${FileSystem.documentDirectory}downloads/${id}-done`;
const fileInfo = await FileSystem.getInfoAsync(fileUri);
return fileInfo.exists;
};
export type DownloadedFileInfo = { export type DownloadedFileInfo = {
id: string; id: string;
path: string; path: string;
@@ -129,7 +106,6 @@ export const NativeDownloadProvider: React.FC<{
}> = ({ children }) => { }> = ({ children }) => {
const [downloads, setDownloads] = useState<Record<string, DownloadInfo>>({}); const [downloads, setDownloads] = useState<Record<string, DownloadInfo>>({});
const { saveImage } = useImageStorage(); const { saveImage } = useImageStorage();
const queryClient = useQueryClient();
const user = useAtomValue(userAtom); const user = useAtomValue(userAtom);
const api = useAtomValue(apiAtom); const api = useAtomValue(apiAtom);
@@ -144,6 +120,27 @@ export const NativeDownloadProvider: React.FC<{
}); });
useEffect(() => { useEffect(() => {
const _getActiveDownloads = async () => {
const activeDownloads = await getActiveDownloads();
setDownloads((prev) => {
const newDownloads = { ...prev };
activeDownloads.forEach((download) => {
newDownloads[download.id] = {
id: download.id,
progress: download.progress,
state: download.state,
secondsDownloaded: download.secondsDownloaded,
secondsTotal: download.secondsTotal,
metadata: download.metadata,
startTime: download.startTime,
};
});
return newDownloads;
});
};
_getActiveDownloads();
const progressListener = addProgressListener((download) => { const progressListener = addProgressListener((download) => {
if (!download.metadata) throw new Error("No metadata found in download"); if (!download.metadata) throw new Error("No metadata found in download");