forked from Ninjalama/streamyfin_mirror
wip
This commit is contained in:
@@ -28,7 +28,6 @@ function downloadHLSAsset(
|
||||
/**
|
||||
* Checks for existing downloads.
|
||||
* Returns an array of downloads with additional fields:
|
||||
* id, progress, bytesDownloaded, bytesTotal, and state.
|
||||
*/
|
||||
async function checkForExistingDownloads(): Promise<DownloadInfo[]> {
|
||||
return HlsDownloaderModule.checkForExistingDownloads();
|
||||
@@ -99,91 +98,9 @@ function useDownloadError(): string | null {
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves a file from a temporary URI to a permanent location in the document directory.
|
||||
* @param tempFileUri The temporary file URI returned by the native module.
|
||||
* @param newFilename The desired filename (with extension) for the persisted file.
|
||||
* @returns A promise that resolves with the new file URI.
|
||||
*/
|
||||
async function persistDownloadedFile(
|
||||
tempFileUri: string,
|
||||
newFilename: string
|
||||
): Promise<string> {
|
||||
const newUri = FileSystem.documentDirectory + newFilename;
|
||||
try {
|
||||
await FileSystem.moveAsync({
|
||||
from: tempFileUri,
|
||||
to: newUri,
|
||||
});
|
||||
console.log("File persisted to:", newUri);
|
||||
return newUri;
|
||||
} catch (error) {
|
||||
console.error("Error moving file:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* React hook that returns the completion location of the download.
|
||||
* If a destinationFileName is provided, the hook will move the downloaded file
|
||||
* to the document directory under that name, then return the new URI.
|
||||
*
|
||||
* @param destinationFileName Optional filename (with extension) to persist the file.
|
||||
* @returns The final file URI or null if not completed.
|
||||
*/
|
||||
function useDownloadComplete(destinationFileName?: string): string | null {
|
||||
const [location, setLocation] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
console.log("Setting up download complete listener");
|
||||
|
||||
const subscription = addCompleteListener(
|
||||
async (event: OnCompleteEventPayload) => {
|
||||
console.log("Download complete event received:", event);
|
||||
console.log("Original download location:", event.location);
|
||||
|
||||
if (destinationFileName) {
|
||||
console.log(
|
||||
"Attempting to persist file with name:",
|
||||
destinationFileName
|
||||
);
|
||||
try {
|
||||
const newLocation = await persistDownloadedFile(
|
||||
event.location,
|
||||
destinationFileName
|
||||
);
|
||||
console.log("File successfully persisted to:", newLocation);
|
||||
setLocation(newLocation);
|
||||
} catch (error) {
|
||||
console.error("Failed to persist file:", error);
|
||||
console.error("Error details:", {
|
||||
originalLocation: event.location,
|
||||
destinationFileName,
|
||||
error: error instanceof Error ? error.message : error,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
console.log(
|
||||
"No destination filename provided, using original location"
|
||||
);
|
||||
setLocation(event.location);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return () => {
|
||||
console.log("Cleaning up download complete listener");
|
||||
subscription.remove();
|
||||
};
|
||||
}, [destinationFileName]);
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
export {
|
||||
downloadHLSAsset,
|
||||
checkForExistingDownloads,
|
||||
useDownloadComplete,
|
||||
useDownloadError,
|
||||
useDownloadProgress,
|
||||
addCompleteListener,
|
||||
|
||||
@@ -38,7 +38,7 @@ public class HlsDownloaderModule: Module {
|
||||
url: assetURL,
|
||||
options: [
|
||||
"AVURLAssetOutOfBandMIMETypeKey": "application/x-mpegURL",
|
||||
"AVURLAssetHTTPHeaderFieldsKey": ["User-Agent": "YourAppNameHere/1.0"],
|
||||
"AVURLAssetHTTPHeaderFieldsKey": ["User-Agent": "Streamyfin/1.0"],
|
||||
"AVURLAssetAllowsCellularAccessKey": true,
|
||||
])
|
||||
|
||||
@@ -134,8 +134,8 @@ public class HlsDownloaderModule: Module {
|
||||
downloads.append([
|
||||
"id": delegate.providedId.isEmpty ? String(id) : delegate.providedId,
|
||||
"progress": progress,
|
||||
"bytesDownloaded": downloaded,
|
||||
"bytesTotal": total,
|
||||
"secondsDownloaded": downloaded,
|
||||
"secondsTotal": total,
|
||||
"state": self.mappedState(for: task),
|
||||
"metadata": metadata,
|
||||
"startTime": startTime,
|
||||
@@ -243,8 +243,8 @@ class HLSDownloadDelegate: NSObject, AVAssetDownloadDelegate {
|
||||
[
|
||||
"id": providedId,
|
||||
"progress": progress,
|
||||
"bytesDownloaded": downloaded,
|
||||
"bytesTotal": total,
|
||||
"secondsDownloaded": downloaded,
|
||||
"secondsTotal": total,
|
||||
"state": progress >= 1.0 ? "DONE" : "DOWNLOADING",
|
||||
"metadata": metadata,
|
||||
"startTime": startTime,
|
||||
@@ -263,6 +263,26 @@ class HLSDownloadDelegate: NSObject, AVAssetDownloadDelegate {
|
||||
let newLocation = try module.persistDownloadedFolder(
|
||||
originalLocation: location, folderName: folderName)
|
||||
|
||||
// Calculate download size
|
||||
let fileManager = FileManager.default
|
||||
let enumerator = fileManager.enumerator(
|
||||
at: newLocation,
|
||||
includingPropertiesForKeys: [.totalFileAllocatedSizeKey],
|
||||
options: [.skipsHiddenFiles],
|
||||
errorHandler: nil)!
|
||||
|
||||
var totalSize: Int64 = 0
|
||||
while let filePath = enumerator.nextObject() as? URL {
|
||||
do {
|
||||
let resourceValues = try filePath.resourceValues(forKeys: [.totalFileAllocatedSizeKey])
|
||||
if let size = resourceValues.totalFileAllocatedSize {
|
||||
totalSize += Int64(size)
|
||||
}
|
||||
} catch {
|
||||
print("Error calculating size: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
if !metadata.isEmpty {
|
||||
let metadataLocation = newLocation.deletingLastPathComponent().appendingPathComponent(
|
||||
"\(providedId).json")
|
||||
@@ -278,6 +298,7 @@ class HLSDownloadDelegate: NSObject, AVAssetDownloadDelegate {
|
||||
"state": "DONE",
|
||||
"metadata": metadata,
|
||||
"startTime": startTime,
|
||||
"bytesDownloaded": totalSize,
|
||||
])
|
||||
} catch {
|
||||
module?.sendEvent(
|
||||
|
||||
@@ -21,13 +21,13 @@ export type BaseEventPayload = {
|
||||
id: string;
|
||||
state: DownloadState;
|
||||
metadata: DownloadMetadata;
|
||||
startTime?: number;
|
||||
};
|
||||
|
||||
export type OnProgressEventPayload = BaseEventPayload & {
|
||||
progress: number;
|
||||
bytesDownloaded: number;
|
||||
bytesTotal: number;
|
||||
startTime?: number;
|
||||
secondsDownloaded: number;
|
||||
secondsTotal: number;
|
||||
};
|
||||
|
||||
export type OnErrorEventPayload = BaseEventPayload & {
|
||||
@@ -38,6 +38,7 @@ export type OnErrorEventPayload = BaseEventPayload & {
|
||||
|
||||
export type OnCompleteEventPayload = BaseEventPayload & {
|
||||
location: string;
|
||||
bytesDownloaded?: number;
|
||||
};
|
||||
|
||||
export type HlsDownloaderModuleEvents = {
|
||||
@@ -52,8 +53,8 @@ export interface DownloadInfo {
|
||||
startTime?: number;
|
||||
progress: number;
|
||||
state: DownloadState;
|
||||
bytesDownloaded?: number;
|
||||
bytesTotal?: number;
|
||||
secondsDownloaded?: number;
|
||||
secondsTotal?: number;
|
||||
location?: string;
|
||||
error?: string;
|
||||
metadata: DownloadMetadata;
|
||||
|
||||
Reference in New Issue
Block a user