diff --git a/ios/App/App/plugins/AbsDownloader.swift b/ios/App/App/plugins/AbsDownloader.swift index d80ce193..d2efedcc 100644 --- a/ios/App/App/plugins/AbsDownloader.swift +++ b/ios/App/App/plugins/AbsDownloader.swift @@ -13,11 +13,59 @@ public class AbsDownloader: CAPPlugin { @objc func downloadLibraryItem(_ call: CAPPluginCall) { let libraryItemId = call.getString("libraryItemId") let episodeId = call.getString("episodeId") - let localFolderId = call.getString("localFolderId") - // TODO: Implement download - NSLog("Download library item \(libraryItemId ?? "N/A") episode \(episodeId ?? "") to folder \(localFolderId ?? "N/A")") + NSLog("Download library item \(libraryItemId ?? "N/A") episode \(episodeId ?? "")") - call.resolve() + ApiClient.getLibraryItemWithProgress(libraryItemId: libraryItemId!, episodeId: episodeId) { libraryItem in + if (libraryItem == nil) { + NSLog("Library item not found") + call.resolve() + } else { + NSLog("Got library item \(libraryItem!)") + + // TODO: break out in seperate functions + libraryItem!.media.tracks?.forEach { track in + NSLog("TRACK \(track.contentUrl!)") + // filename needs to be encoded otherwise would just use contentUrl + let filename = track.metadata?.filename ?? "" + let filenameEncoded = filename.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed) + let urlstr = "\(Store.serverConfig!.address)/s/item/\(libraryItemId!)/\(filenameEncoded ?? "")?token=\(Store.serverConfig!.token)" + let url = URL(string: urlstr)! + + + let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] + let itemDirectory = documentsDirectory.appendingPathComponent("\(libraryItemId!)") + NSLog("ITEM DIR \(itemDirectory)") + + // Create library item directory + do { + try FileManager.default.createDirectory(at: itemDirectory, withIntermediateDirectories: false) + } catch { + NSLog("Failed to CREATE LI DIRECTORY \(error)") + } + + // Output filename + let trackFilename = itemDirectory.appendingPathComponent("\(filename)") + + let downloadTask = URLSession.shared.downloadTask(with: url) { urlOrNil, responseOrNil, errorOrNil in + + guard let fileURL = urlOrNil else { return } + + do { + NSLog("Download TMP file URL \(fileURL)") + let imageData = try Data(contentsOf:fileURL) + try imageData.write(to: trackFilename) + NSLog("Download written to \(trackFilename)") + } catch { + NSLog("FILE ERROR: \(error)") + } + } + downloadTask.resume() + } + + + call.resolve() + } + } } } diff --git a/ios/App/Shared/models/DataClasses.swift b/ios/App/Shared/models/DataClasses.swift index f3e0b2f5..4237bc7d 100644 --- a/ios/App/Shared/models/DataClasses.swift +++ b/ios/App/Shared/models/DataClasses.swift @@ -15,6 +15,7 @@ struct LibraryItem: Codable { var folderId: String var path: String var relPath: String + var isFile: Bool var mtimeMs: Int64 var ctimeMs: Int64 var birthtimeMs: Int64 @@ -27,6 +28,7 @@ struct LibraryItem: Codable { var mediaType: String var media: MediaType var libraryFiles: [LibraryFile] + var userMediaProgress:MediaProgress? } struct MediaType: Codable { var libraryItemId: String? @@ -125,3 +127,15 @@ struct LibraryFile: Codable { var ino: String var metadata: FileMetadata } +struct MediaProgress:Codable { + var id:String + var libraryItemId:String + var episodeId:String? + var duration:Double + var progress:Double + var currentTime:Double + var isFinished:Bool + var lastUpdate:Int64 + var startedAt:Int64 + var finishedAt:Int64? +} diff --git a/ios/App/Shared/util/ApiClient.swift b/ios/App/Shared/util/ApiClient.swift index 166ef332..3bb309c9 100644 --- a/ios/App/Shared/util/ApiClient.swift +++ b/ios/App/Shared/util/ApiClient.swift @@ -60,6 +60,27 @@ class ApiClient { } } } + public static func getResource(endpoint: String, decodable: T.Type = T.self, callback: ((_ param: T?) -> Void)?) { + if (Store.serverConfig == nil) { + NSLog("Server config not set") + callback?(nil) + return + } + + let headers: HTTPHeaders = [ + "Authorization": "Bearer \(Store.serverConfig!.token)" + ] + + AF.request("\(Store.serverConfig!.address)/\(endpoint)", method: .get, encoding: JSONEncoding.default, headers: headers).responseDecodable(of: decodable) { response in + switch response.result { + case .success(let obj): + callback?(obj) + case .failure(let error): + NSLog("api request to \(endpoint) failed") + print(error) + } + } + } public static func startPlaybackSession(libraryItemId: String, episodeId: String?, forceTranscode:Bool, callback: @escaping (_ param: PlaybackSession) -> Void) { var endpoint = "api/items/\(libraryItemId)/play" @@ -83,4 +104,14 @@ class ApiClient { public static func reportPlaybackProgress(report: PlaybackReport, sessionId: String) { try? postResource(endpoint: "api/session/\(sessionId)/sync", parameters: report.asDictionary().mapValues({ value in "\(value)" }), callback: nil) } + public static func getLibraryItemWithProgress(libraryItemId:String, episodeId:String?, callback: @escaping (_ param: LibraryItem?) -> Void) { + var endpoint = "api/items/\(libraryItemId)?expanded=1&include=progress" + if episodeId != nil { + endpoint += "&episodeId=\(episodeId!)" + } + + ApiClient.getResource(endpoint: endpoint, decodable: LibraryItem.self) { obj in + callback(obj) + } + } }