Spaces:
Running
Running
| import SwiftUI | |
| struct DownloadButton: View { | |
| private var model: Model | |
| private var status: String | |
| private var downloadTask: URLSessionDownloadTask? | |
| private var progress = 0.0 | |
| private var observation: NSKeyValueObservation? | |
| private var onLoad: ((_ model: Model) -> Void)? | |
| init(model: Model) { | |
| self.model = model | |
| status = model.fileExists() ? "downloaded" : "download" | |
| } | |
| func onLoad(perform action: @escaping (_ model: Model) -> Void) -> DownloadButton { | |
| var button = self | |
| button.onLoad = action | |
| return button | |
| } | |
| private func download() { | |
| status = "downloading" | |
| print("Downloading model \(model.name) from \(model.url)") | |
| guard let url = URL(string: model.url) else { return } | |
| downloadTask = URLSession.shared.downloadTask(with: url) { temporaryURL, response, error in | |
| if let error = error { | |
| print("Error: \(error.localizedDescription)") | |
| return | |
| } | |
| guard let response = response as? HTTPURLResponse, (200...299).contains(response.statusCode) else { | |
| print("Server error!") | |
| return | |
| } | |
| do { | |
| if let temporaryURL = temporaryURL { | |
| try FileManager.default.copyItem(at: temporaryURL, to: model.fileURL) | |
| print("Writing to \(model.filename) completed") | |
| status = "downloaded" | |
| } | |
| } catch let err { | |
| print("Error: \(err.localizedDescription)") | |
| } | |
| } | |
| observation = downloadTask?.progress.observe(\.fractionCompleted) { progress, _ in | |
| self.progress = progress.fractionCompleted | |
| } | |
| downloadTask?.resume() | |
| } | |
| var body: some View { | |
| VStack { | |
| Button(action: { | |
| if (status == "download") { | |
| download() | |
| } else if (status == "downloading") { | |
| downloadTask?.cancel() | |
| status = "download" | |
| } else if (status == "downloaded") { | |
| if !model.fileExists() { | |
| download() | |
| } | |
| onLoad?(model) | |
| } | |
| }) { | |
| let title = "\(model.name) \(model.info)" | |
| if (status == "download") { | |
| Text("Download \(title)") | |
| } else if (status == "downloading") { | |
| Text("\(title) (Downloading \(Int(progress * 100))%)") | |
| } else if (status == "downloaded") { | |
| Text("Load \(title)") | |
| } else { | |
| Text("Unknown status") | |
| } | |
| }.swipeActions { | |
| if (status == "downloaded") { | |
| Button("Delete") { | |
| do { | |
| try FileManager.default.removeItem(at: model.fileURL) | |
| } catch { | |
| print("Error deleting file: \(error)") | |
| } | |
| status = "download" | |
| } | |
| .tint(.red) | |
| } | |
| } | |
| } | |
| .onDisappear() { | |
| downloadTask?.cancel() | |
| } | |
| } | |
| } | |