Handle download complete lifecycle

This commit is contained in:
ronaldheft 2022-08-07 10:27:08 -04:00
parent 5495bcb945
commit b549528e23
5 changed files with 62 additions and 9 deletions

View file

@ -83,6 +83,8 @@ public class AbsDownloader: CAPPlugin, URLSessionDownloadDelegate {
// Handle a completed download // Handle a completed download
if ( downloadItem.isDoneDownloading() ) { if ( downloadItem.isDoneDownloading() ) {
// Delete the download item on exit even if handling complete errors
defer { Database.shared.removeDownloadItem(downloadItem) }
handleDownloadTaskCompleteFromDownloadItem(downloadItem) handleDownloadTaskCompleteFromDownloadItem(downloadItem)
} }
} catch { } catch {
@ -92,17 +94,31 @@ public class AbsDownloader: CAPPlugin, URLSessionDownloadDelegate {
} }
private func handleDownloadTaskCompleteFromDownloadItem(_ downloadItem: DownloadItem) { private func handleDownloadTaskCompleteFromDownloadItem(_ downloadItem: DownloadItem) {
var statusNotification = [String: String]()
if ( downloadItem.didDownloadSuccessfully() ) { if ( downloadItem.didDownloadSuccessfully() ) {
ApiClient.getLibraryItemWithProgress(libraryItemId: downloadItem.libraryItemId!, episodeId: downloadItem.episodeId) { libraryItem in ApiClient.getLibraryItemWithProgress(libraryItemId: downloadItem.libraryItemId!, episodeId: downloadItem.episodeId) { libraryItem in
//let localDirectory = documentsDirectory.appendingPathComponent("\(libraryItem.id)") var statusNotification = [String: Any]()
//let localLibraryItem = LocalLibraryItem(libraryItem, localUrl: localDirectory, server: Store.serverConfig!, files: <#T##[LocalFile]#>) statusNotification["libraryItemId"] = libraryItem?.id
guard let libraryItem = libraryItem else { NSLog("LibraryItem not found"); return }
let localDirectory = self.documentsDirectory.appendingPathComponent("\(libraryItem.id)")
let files = downloadItem.downloadItemParts.map { part in LocalFile(libraryItem.id, part.filename!, part.mimeType()!, part.destinationURL()!) }
let localLibraryItem = LocalLibraryItem(libraryItem, localUrl: localDirectory, server: Store.serverConfig!, files: files)
Database.shared.saveLocalLibraryItem(localLibraryItem: localLibraryItem)
statusNotification["localLibraryItem"] = try? localLibraryItem.asDictionary()
if let progress = libraryItem.userMediaProgress {
// TODO: Handle podcast
let localMediaProgress = LocalMediaProgress(localLibraryItem: localLibraryItem, episode: nil, progress: progress)
Database.shared.saveLocalMediaProgress(localMediaProgress)
statusNotification["localMediaProgress"] = try? localMediaProgress.asDictionary()
}
self.notifyListeners("onItemDownloadComplete", data: statusNotification)
} }
} }
notifyListeners("onItemDownloadComplete", data: statusNotification)
} }
@objc func downloadLibraryItem(_ call: CAPPluginCall) { @objc func downloadLibraryItem(_ call: CAPPluginCall) {
@ -203,4 +219,5 @@ enum LibraryItemDownloadError: String, Error {
case downloadItemNotFound = "DownloadItem not found" case downloadItemNotFound = "DownloadItem not found"
case downloadItemPartNotFound = "DownloadItemPart not found" case downloadItemPartNotFound = "DownloadItemPart not found"
case downloadItemPartDestinationUrlNotDefined = "DownloadItemPart destination URL not defined" case downloadItemPartDestinationUrlNotDefined = "DownloadItemPart destination URL not defined"
case libraryItemNotFound = "LibraryItem not found for id"
} }

View file

@ -9,7 +9,7 @@ import Foundation
import Unrealm import Unrealm
struct DownloadItem: Realmable, Codable { struct DownloadItem: Realmable, Codable {
var id: String = UUID().uuidString var id: String?
var libraryItemId: String? var libraryItemId: String?
var episodeId: String? var episodeId: String?
var userMediaProgress: MediaProgress? var userMediaProgress: MediaProgress?
@ -36,6 +36,7 @@ struct DownloadItem: Realmable, Codable {
extension DownloadItem { extension DownloadItem {
init(libraryItem: LibraryItem, server: ServerConnectionConfig) { init(libraryItem: LibraryItem, server: ServerConnectionConfig) {
self.id = libraryItem.id
self.libraryItemId = libraryItem.id self.libraryItemId = libraryItem.id
//self.episodeId // TODO //self.episodeId // TODO
self.userMediaProgress = libraryItem.userMediaProgress self.userMediaProgress = libraryItem.userMediaProgress
@ -52,7 +53,7 @@ extension DownloadItem {
} }
func didDownloadSuccessfully() -> Bool { func didDownloadSuccessfully() -> Bool {
self.downloadItemParts.allSatisfy({ $0.failed = false }) self.downloadItemParts.allSatisfy({ $0.failed == false })
} }
} }
@ -101,6 +102,10 @@ extension DownloadItemPart {
self.destinationUri = destination.path self.destinationUri = destination.path
} }
func mimeType() -> String? {
audioTrack?.mimeType ?? episode?.audioTrack?.mimeType
}
func downloadURL() -> URL? { func downloadURL() -> URL? {
if let uri = self.uri { if let uri = self.uri {
return URL(string: uri) return URL(string: uri)

View file

@ -63,7 +63,7 @@ struct LocalFile: Realmable, Codable {
} }
struct LocalMediaProgress: Realmable, Codable { struct LocalMediaProgress: Realmable, Codable {
var id: String = UUID().uuidString var id: String = ""
var localLibraryItemId: String = "" var localLibraryItemId: String = ""
var localEpisodeId: String? var localEpisodeId: String?
var duration: Double = 0 var duration: Double = 0

View file

@ -75,6 +75,7 @@ extension LocalFile {
self.init() self.init()
self.id = "\(libraryItemId)_\(filename.toBase64())" self.id = "\(libraryItemId)_\(filename.toBase64())"
self.filename = filename self.filename = filename
self.mimeType = mimeType
self.contentUrl = localUrl.absoluteString self.contentUrl = localUrl.absoluteString
self.absolutePath = localUrl.path self.absolutePath = localUrl.path
self.size = Int(localUrl.fileSize) self.size = Int(localUrl.fileSize)
@ -90,3 +91,27 @@ extension LocalFile {
} }
} }
} }
extension LocalMediaProgress {
init(localLibraryItem: LocalLibraryItem, episode: LocalPodcastEpisode?, progress: MediaProgress) {
self.id = localLibraryItem.id
self.localLibraryItemId = localLibraryItem.id
self.libraryItemId = localLibraryItem.libraryItemId
if let episode = episode {
self.id += "-\(episode.id)"
self.episodeId = episode.id
}
self.serverAddress = localLibraryItem.serverAddress
self.serverUserId = localLibraryItem.serverUserId
self.serverConnectionConfigId = localLibraryItem.serverConnectionConfigId
self.duration = progress.duration
self.currentTime = progress.currentTime
self.isFinished = false
self.lastUpdate = progress.lastUpdate
self.startedAt = progress.startedAt
self.finishedAt = progress.finishedAt
}
}

View file

@ -177,6 +177,12 @@ class Database {
} }
} }
public func removeDownloadItem(_ downloadItem: DownloadItem) {
Database.realmQueue.sync {
try! instance.write { instance.delete(downloadItem) }
}
}
public func getDeviceSettings() -> DeviceSettings { public func getDeviceSettings() -> DeviceSettings {
return Database.realmQueue.sync { return Database.realmQueue.sync {
return instance.objects(DeviceSettings.self).first ?? getDefaultDeviceSettings() return instance.objects(DeviceSettings.self).first ?? getDefaultDeviceSettings()