78 lines
2.6 KiB
Swift
78 lines
2.6 KiB
Swift
import Foundation
|
|
import Shared
|
|
import WebKit
|
|
|
|
@MainActor
|
|
final class DownloadManagerViewModel: NSObject, ObservableObject {
|
|
@Published var fileName: String = ""
|
|
@Published var finished: Bool = false
|
|
@Published var failed: Bool = false
|
|
@Published var errorMessage: String = ""
|
|
@Published var progress: String = ""
|
|
@Published var lastURLCreated: URL?
|
|
|
|
private var progressObservation: NSKeyValueObservation?
|
|
private var lastDownload: WKDownload?
|
|
|
|
func deleteFile() {
|
|
if let url = lastURLCreated {
|
|
// Guarantee to delete file before leaving screen
|
|
do {
|
|
try FileManager.default.removeItem(at: url)
|
|
} catch {
|
|
Current.Log.error("Failed to remove file before leaving download manager at \(url), error: \(error)")
|
|
}
|
|
}
|
|
}
|
|
|
|
func cancelDownload() {
|
|
progressObservation?.invalidate()
|
|
lastDownload?.cancel()
|
|
}
|
|
|
|
private func bytesToMBString(_ bytes: Int64) -> String {
|
|
let formatter = ByteCountFormatter()
|
|
formatter.allowedUnits = [.useMB]
|
|
formatter.countStyle = .file
|
|
return formatter.string(fromByteCount: bytes)
|
|
}
|
|
}
|
|
|
|
extension DownloadManagerViewModel: WKDownloadDelegate {
|
|
func download(
|
|
_ download: WKDownload,
|
|
decideDestinationUsing response: URLResponse,
|
|
suggestedFilename: String
|
|
) async -> URL? {
|
|
lastDownload = download
|
|
let name = suggestedFilename.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? "Unknown"
|
|
fileName = name
|
|
if let url = URL(string: name, relativeTo: AppConstants.DownloadsDirectory) {
|
|
lastURLCreated = url
|
|
// Guarantee file does not exist, otherwise download will fail
|
|
do {
|
|
try FileManager.default.removeItem(at: url)
|
|
} catch {
|
|
Current.Log.error("Failed to remove file for download manager at \(url), error: \(error)")
|
|
}
|
|
progressObservation?.invalidate()
|
|
progressObservation = download.progress.observe(\.completedUnitCount) { [weak self] progress, _ in
|
|
guard let self else { return }
|
|
self.progress = bytesToMBString(progress.completedUnitCount)
|
|
}
|
|
return url
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func downloadDidFinish(_ download: WKDownload) {
|
|
finished = true
|
|
}
|
|
|
|
func download(_ download: WKDownload, didFailWithError error: any Error, resumeData: Data?) {
|
|
errorMessage = L10n.DownloadManager.Failed.title(error.localizedDescription)
|
|
failed = true
|
|
}
|
|
}
|