mirror of
https://github.com/advplyr/audiobookshelf-app.git
synced 2025-08-29 14:28:34 +02:00
More improvements to progress status
This commit is contained in:
parent
e9961f64a9
commit
e275aa1699
1 changed files with 38 additions and 40 deletions
|
@ -21,8 +21,8 @@ public class AbsDownloader: CAPPlugin, URLSessionDownloadDelegate {
|
||||||
return URLSession(configuration: .default, delegate: self, delegateQueue: queue)
|
return URLSession(configuration: .default, delegate: self, delegateQueue: queue)
|
||||||
}()
|
}()
|
||||||
private let progressStatusQueue = DispatchQueue(label: "progress-status-queue", attributes: .concurrent)
|
private let progressStatusQueue = DispatchQueue(label: "progress-status-queue", attributes: .concurrent)
|
||||||
private var progressStatusWorkItem: DispatchWorkItem?
|
|
||||||
private var downloadItemProgress = [String: DownloadItem]()
|
private var downloadItemProgress = [String: DownloadItem]()
|
||||||
|
private var isMonitoringProgress = false
|
||||||
|
|
||||||
public func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
|
public func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
|
||||||
handleDownloadTaskUpdate(downloadTask: downloadTask) { downloadItem, downloadItemPart in
|
handleDownloadTaskUpdate(downloadTask: downloadTask) { downloadItem, downloadItemPart in
|
||||||
|
@ -59,7 +59,7 @@ public class AbsDownloader: CAPPlugin, URLSessionDownloadDelegate {
|
||||||
// Calculate the download percentage
|
// Calculate the download percentage
|
||||||
let percentDownloaded = (Double(totalBytesWritten) / Double(totalBytesExpectedToWrite)) * 100
|
let percentDownloaded = (Double(totalBytesWritten) / Double(totalBytesExpectedToWrite)) * 100
|
||||||
// Only update the progress if we received accurate progress data
|
// Only update the progress if we received accurate progress data
|
||||||
if percentDownloaded >= 0.0 && percentDownloaded <= 1.0 {
|
if percentDownloaded >= 0.0 && percentDownloaded <= 100.0 {
|
||||||
downloadItemPart.progress = percentDownloaded
|
downloadItemPart.progress = percentDownloaded
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,6 +73,9 @@ public class AbsDownloader: CAPPlugin, URLSessionDownloadDelegate {
|
||||||
// Find the download item
|
// Find the download item
|
||||||
let downloadItem = Database.shared.getDownloadItem(downloadItemPartId: downloadItemPartId)
|
let downloadItem = Database.shared.getDownloadItem(downloadItemPartId: downloadItemPartId)
|
||||||
guard var downloadItem = downloadItem else { throw LibraryItemDownloadError.downloadItemNotFound }
|
guard var downloadItem = downloadItem else { throw LibraryItemDownloadError.downloadItemNotFound }
|
||||||
|
self.progressStatusQueue.sync {
|
||||||
|
downloadItem = self.downloadItemProgress[downloadItem.id!] ?? downloadItem
|
||||||
|
}
|
||||||
|
|
||||||
// Find the download item part
|
// Find the download item part
|
||||||
let partIndex = downloadItem.downloadItemParts.firstIndex(where: { $0.id == downloadItemPartId })
|
let partIndex = downloadItem.downloadItemParts.firstIndex(where: { $0.id == downloadItemPartId })
|
||||||
|
@ -87,11 +90,10 @@ public class AbsDownloader: CAPPlugin, URLSessionDownloadDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the progress
|
// Update the progress
|
||||||
Database.shared.updateDownloadItemPart(downloadItem.downloadItemParts[partIndex])
|
|
||||||
self.progressStatusQueue.async(flags: .barrier) {
|
self.progressStatusQueue.async(flags: .barrier) {
|
||||||
self.downloadItemProgress.updateValue(downloadItem, forKey: downloadItem.id!)
|
self.downloadItemProgress.updateValue(downloadItem, forKey: downloadItem.id!)
|
||||||
self.notifyDownloadProgress()
|
|
||||||
}
|
}
|
||||||
|
self.notifyDownloadProgress()
|
||||||
} catch {
|
} catch {
|
||||||
NSLog("DownloadItemError")
|
NSLog("DownloadItemError")
|
||||||
debugPrint(error)
|
debugPrint(error)
|
||||||
|
@ -100,35 +102,30 @@ public class AbsDownloader: CAPPlugin, URLSessionDownloadDelegate {
|
||||||
|
|
||||||
// We want to handle updating the UI in the background and throttled so we don't overload the UI with progress updates
|
// We want to handle updating the UI in the background and throttled so we don't overload the UI with progress updates
|
||||||
private func notifyDownloadProgress() {
|
private func notifyDownloadProgress() {
|
||||||
// Return if the loop is running
|
if !self.isMonitoringProgress {
|
||||||
guard self.progressStatusWorkItem == nil else { return }
|
self.isMonitoringProgress = true
|
||||||
|
DispatchQueue.global(qos: .userInteractive).async {
|
||||||
// Create a background thread to send the download status
|
NSLog("Starting monitoring download progress...")
|
||||||
self.progressStatusWorkItem = DispatchWorkItem { [weak self] in
|
|
||||||
// Clean up the work item when done
|
|
||||||
defer { self?.progressStatusWorkItem = nil }
|
|
||||||
|
|
||||||
// Fetch active downloads in a thread-safe way
|
// Fetch active downloads in a thread-safe way
|
||||||
func fetchActiveDownloads() -> [String: DownloadItem]? {
|
func fetchActiveDownloads() -> [String: DownloadItem]? {
|
||||||
self?.progressStatusQueue.sync { self?.downloadItemProgress }
|
self.progressStatusQueue.sync { self.downloadItemProgress }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove a completed download item in a thread-safe way
|
// Remove a completed download item in a thread-safe way
|
||||||
func handleDoneDownloadItem(_ item: DownloadItem) {
|
func handleDoneDownloadItem(_ item: DownloadItem) {
|
||||||
self?.progressStatusQueue.async(flags: .barrier) {
|
self.progressStatusQueue.async(flags: .barrier) {
|
||||||
defer {
|
self.downloadItemProgress.removeValue(forKey: item.id!)
|
||||||
|
}
|
||||||
Database.shared.removeDownloadItem(item)
|
Database.shared.removeDownloadItem(item)
|
||||||
self?.downloadItemProgress.removeValue(forKey: item.id!)
|
self.handleDownloadTaskCompleteFromDownloadItem(item)
|
||||||
}
|
|
||||||
self?.handleDownloadTaskCompleteFromDownloadItem(item)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// While there are active download items, emit status updates
|
// While there are active download items, emit status updates
|
||||||
while !(fetchActiveDownloads()?.isEmpty ?? false) {
|
while !(fetchActiveDownloads()?.isEmpty ?? false) {
|
||||||
if let activeDownloads = fetchActiveDownloads() {
|
if let activeDownloads = fetchActiveDownloads() {
|
||||||
for item in activeDownloads.values {
|
for item in activeDownloads.values {
|
||||||
try? self?.notifyListeners("onItemDownloadUpdate", data: item.asDictionary())
|
try? self.notifyListeners("onItemDownloadUpdate", data: item.asDictionary())
|
||||||
if item.isDoneDownloading() { handleDoneDownloadItem(item) }
|
if item.isDoneDownloading() { handleDoneDownloadItem(item) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,10 +133,11 @@ public class AbsDownloader: CAPPlugin, URLSessionDownloadDelegate {
|
||||||
// Wait 200ms before reporting status again
|
// Wait 200ms before reporting status again
|
||||||
Thread.sleep(forTimeInterval: TimeInterval(0.2))
|
Thread.sleep(forTimeInterval: TimeInterval(0.2))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Start the thread
|
NSLog("Finished monitoring download progress...")
|
||||||
DispatchQueue.global(qos: .userInteractive).async(execute: self.progressStatusWorkItem!)
|
self.isMonitoringProgress = false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func handleDownloadTaskCompleteFromDownloadItem(_ downloadItem: DownloadItem) {
|
private func handleDownloadTaskCompleteFromDownloadItem(_ downloadItem: DownloadItem) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue