This commit is contained in:
Fredrik Burmester
2025-02-18 13:25:48 +01:00
parent 0db798c9af
commit 59725bd57d
64 changed files with 79 additions and 57 deletions

View File

@@ -41,16 +41,18 @@ class HlsDownloaderModule : Module() {
OnCreate {
android.util.Log.d(TAG, "Creating HLS Downloader module")
val context = appContext.reactContext as Context
val cacheDir = File(context.getExternalFilesDir(null), "downloads")
val cacheDir = File(context.filesDir, "downloads")
if (!cacheDir.exists()) {
cacheDir.mkdirs()
android.util.Log.d(TAG, "Created base downloads directory: ${cacheDir.absolutePath}")
}
val databaseProvider = StandaloneDatabaseProvider(context)
downloadCache = SimpleCache(cacheDir, NoOpCacheEvictor(), databaseProvider)
val dataSourceFactory = DefaultHttpDataSource.Factory()
.setUserAgent("MyApp/1.0")
.setUserAgent("Streamyfin/1.0")
.setAllowCrossProtocolRedirects(true)
downloadManager = DownloadManager(
@@ -161,23 +163,15 @@ class HlsDownloaderModule : Module() {
}
Function("downloadHLSAsset") { providedId: String, url: String, metadata: Map<String, Any>? ->
android.util.Log.d(TAG, "Starting download for $providedId from $url")
android.util.Log.d(TAG, "Starting download for $providedId from $url")
val startTime = System.currentTimeMillis()
val context = appContext.reactContext as Context
val downloadDir = File(context.getExternalFilesDir(null), "downloads/$providedId")
if (downloadDir.exists() && downloadDir.listFiles()?.any { file -> file.name.endsWith(".m3u8") } == true) {
sendEvent(
"onComplete",
mapOf(
"id" to providedId,
"location" to downloadDir.absolutePath,
"state" to "DONE",
"metadata" to (metadata ?: emptyMap()),
"startTime" to startTime
)
)
return@Function
// Create the directory for this download
val downloadDir = File(context.filesDir, "downloads/$providedId")
if (!downloadDir.exists()) {
downloadDir.mkdirs()
android.util.Log.d(TAG, "Created directory: ${downloadDir.absolutePath}")
}
try {
@@ -191,6 +185,12 @@ class HlsDownloaderModule : Module() {
downloadManager.addDownload(downloadRequest)
android.util.Log.d(TAG, "Download request added for $providedId")
saveMetadataFile(DownloadMetadata(
providedId = providedId,
metadata = metadata ?: emptyMap(),
startTime = startTime
))
activeDownloads[providedId] = DownloadMetadata(
providedId = providedId,
metadata = metadata ?: emptyMap(),
@@ -244,12 +244,19 @@ class HlsDownloaderModule : Module() {
private fun saveMetadataFile(metadata: DownloadMetadata) {
try {
val context = appContext.reactContext as Context
// Create metadata file in internal storage
val metadataFile = File(
context.getExternalFilesDir(null),
"downloads/${metadata.providedId}.json"
context.filesDir,
"downloads/${metadata.providedId}/${metadata.providedId}.json"
)
// Ensure the parent directory exists
metadataFile.parentFile?.mkdirs()
android.util.Log.d(TAG, "Saving metadata to: ${metadataFile.absolutePath}")
metadataFile.writeText(JSONObject(metadata.metadata).toString())
} catch (e: Exception) {
android.util.Log.e(TAG, "Error saving metadata file", e)
e.printStackTrace()
}
}

View File

@@ -1,5 +1,6 @@
import useImageStorage from "@/hooks/useImageStorage";
import {
addCompleteListener,
addErrorListener,
addProgressListener,
cancelDownload,
@@ -69,55 +70,48 @@ export type DownloadedFileInfo = {
};
const getDownloadedFiles = async (): Promise<DownloadedFileInfo[]> => {
console.log("getDownloadedFiles ~");
const downloaded: DownloadedFileInfo[] = [];
const files = await FileSystem.readDirectoryAsync(
FileSystem.documentDirectory!
);
console.log(files);
const downloadsDir = Platform.select({
ios: FileSystem.documentDirectory + "downloads/",
android: FileSystem.documentDirectory + "downloads/",
});
return [];
console.log("downloadsDir ~", downloadsDir);
// const downloaded: DownloadedFileInfo[] = [];
if (!downloadsDir) throw new Error("Downloads directory not found");
// const downloadsDir = Platform.select({
// ios: FileSystem.documentDirectory + "downloads/",
// android: FileSystem.cacheDirectory + "../files/downloads/",
// });
const dirInfo = await FileSystem.getInfoAsync(downloadsDir);
// if (!downloadsDir) throw new Error("Downloads directory not found");
if (!dirInfo.exists) {
console.warn("Downloads directory does not exist");
return [];
}
// const dirInfo = await FileSystem.getInfoAsync(downloadsDir);
const files = await FileSystem.readDirectoryAsync(downloadsDir);
// if (!dirInfo.exists) {
// console.warn("Downloads directory does not exist");
// return [];
// }
console.log("getDownloadedFiles ~", files.length);
// const files = await FileSystem.readDirectoryAsync(downloadsDir);
for (let file of files) {
console.log(file);
const fileInfo = await FileSystem.getInfoAsync(downloadsDir + file);
if (fileInfo.isDirectory) continue;
if (!file.endsWith(".json")) continue;
// console.log("getDownloadedFiles ~", files.length);
const fileContent = await FileSystem.readAsStringAsync(downloadsDir + file);
// for (let file of files) {
// console.log(file);
// const fileInfo = await FileSystem.getInfoAsync(downloadsDir + file);
// if (fileInfo.isDirectory) continue;
// if (!file.endsWith(".json")) continue;
// Check that fileContent is actually DownloadMetadata
if (!fileContent) continue;
if (!fileContent.includes("mediaSource")) continue;
if (!fileContent.includes("item")) continue;
// const fileContent = await FileSystem.readAsStringAsync(downloadsDir + file);
// // Check that fileContent is actually DownloadMetadata
// if (!fileContent) continue;
// if (!fileContent.includes("mediaSource")) continue;
// if (!fileContent.includes("item")) continue;
// downloaded.push({
// id: file.replace(".json", ""),
// path: downloadsDir + file.replace(".json", ""),
// metadata: JSON.parse(fileContent) as DownloadMetadata,
// });
// }
// return downloaded;
downloaded.push({
id: file.replace(".json", ""),
path: downloadsDir + file.replace(".json", ""),
metadata: JSON.parse(fileContent) as DownloadMetadata,
});
}
return downloaded;
};
const getDownloadedFile = async (id: string) => {
@@ -220,6 +214,21 @@ export const NativeDownloadProvider: React.FC<{
}
});
const completeListener = addCompleteListener((download) => {
console.log("c ~", {
id: download.id,
state: download.state,
});
// Remove the active download from the state
setDownloads((prev) => {
const newDownloads = { ...prev };
delete newDownloads[download.id];
return newDownloads;
});
refetchDownloadedFiles();
});
const errorListener = addErrorListener((error) => {
setDownloads((prev) => {
const newDownloads = { ...prev };
@@ -239,6 +248,7 @@ export const NativeDownloadProvider: React.FC<{
return () => {
progressListener.remove();
errorListener.remove();
completeListener.remove();
};
}, []);