diff --git a/apps/expo/src/hooks/DownloadManagerContext.tsx b/apps/expo/src/hooks/DownloadManagerContext.tsx index de6eabb..a1d3ead 100644 --- a/apps/expo/src/hooks/DownloadManagerContext.tsx +++ b/apps/expo/src/hooks/DownloadManagerContext.tsx @@ -23,12 +23,14 @@ export interface DownloadItem { statusText?: string; asset?: Asset; isHLS?: boolean; + downloadResumable?: FileSystem.DownloadResumable; } interface DownloadManagerContextType { downloads: DownloadItem[]; startDownload: (url: string, type: "mp4" | "hls") => Promise; removeDownload: (id: string) => void; + cancelDownload: (id: string) => Promise; } const DownloadManagerContext = createContext< @@ -66,6 +68,24 @@ export const DownloadManagerProvider: React.FC<{ children: ReactNode }> = ({ useDownloadHistoryStore.setState({ downloads }); }, [downloads]); + const cancellationFlags: Record = {}; + + const setCancellationFlag = (downloadId: string, flag: boolean): void => { + cancellationFlags[downloadId] = flag; + }; + + const getCancellationFlag = (downloadId: string): boolean => { + return cancellationFlags[downloadId] ?? false; + }; + + const cancelDownload = async (downloadId: string): Promise => { + setCancellationFlag(downloadId, true); + const downloadItem = downloads.find((d) => d.id === downloadId); + if (downloadItem?.downloadResumable) { + await downloadItem.downloadResumable.cancelAsync(); + } + }; + const startDownload = async ( url: string, type: "mp4" | "hls", @@ -154,6 +174,7 @@ export const DownloadManagerProvider: React.FC<{ children: ReactNode }> = ({ { headers }, callback, ); + updateDownloadItem(downloadId, { downloadResumable }); try { const result = await downloadResumable.downloadAsync(); @@ -199,6 +220,11 @@ export const DownloadManagerProvider: React.FC<{ children: ReactNode }> = ({ const localSegmentPaths = []; for (const [index, segment] of segments.entries()) { + if (getCancellationFlag(downloadId)) { + await FileSystem.deleteAsync(segmentDir, { idempotent: true }); + break; + } + const segmentFile = `${segmentDir}${index}.ts`; localSegmentPaths.push(segmentFile); const downloadResumable = FileSystem.createDownloadResumable( @@ -213,9 +239,16 @@ export const DownloadManagerProvider: React.FC<{ children: ReactNode }> = ({ updateProgress(); } catch (e) { console.error(e); + if (getCancellationFlag(downloadId)) { + break; + } } } + if (getCancellationFlag(downloadId)) { + return removeDownload(downloadId); + } + updateDownloadItem(downloadId, { statusText: "Merging" }); const uri = await VideoManager.mergeVideos( localSegmentPaths, @@ -278,7 +311,7 @@ export const DownloadManagerProvider: React.FC<{ children: ReactNode }> = ({ return ( {children}