diff --git a/Platform/Shared/ContentView.swift b/Platform/Shared/ContentView.swift index 62c20ca6d..9781ca586 100644 --- a/Platform/Shared/ContentView.swift +++ b/Platform/Shared/ContentView.swift @@ -35,6 +35,7 @@ struct ContentView: View { @StateObject private var releaseHelper = UTMReleaseHelper() @State private var newPopupPresented = false @State private var openSheetPresented = false + @State private var alertItem: AlertItem? @Environment(\.openURL) var openURL @AppStorage("ServerAutostart") private var isServerAutostart: Bool = false @@ -50,6 +51,14 @@ struct ContentView: View { }, content: { VMReleaseNotesView(helper: releaseHelper).padding() }) + .alert(item: $alertItem) { item in + switch item { + case .downloadUrl(let url): + return Alert(title: Text("Download VM"), message: Text("Do you want to download '\(url)'?"), primaryButton: .cancel(), secondaryButton: .default(Text("Download")) { + data.downloadUTMZip(from: url) + }) + } + } .onReceive(NSNotification.ShowReleaseNotes) { _ in Task { await releaseHelper.fetchReleaseNotes(force: true) @@ -115,13 +124,17 @@ struct ContentView: View { } private func handleURL(url: URL) { - data.busyWorkAsync { - if url.isFileURL { + if let components = URLComponents(url: url, resolvingAgainstBaseURL: false), + components.scheme?.lowercased() == "utm", + components.host == "downloadVM", + let urlParameter = components.queryItems?.first(where: { $0.name == "url" })?.value, + let url = URL(string: urlParameter) { + if alertItem == nil { + alertItem = .downloadUrl(url) + } + } else if url.isFileURL { + data.busyWorkAsync { try await importUTM(url: url) - } else if let components = URLComponents(url: url, resolvingAgainstBaseURL: false), - let scheme = components.scheme, - scheme.lowercased() == "utm" { - try await handleUTMURL(with: components) } } } @@ -197,9 +210,6 @@ struct ContentView: View { data.automationSendMouse(to: vm, urlComponents: components) } break - case "downloadVM": - await data.downloadUTMZip(from: components) - break default: return } @@ -246,6 +256,19 @@ extension ContentView: DropDelegate { } } +extension ContentView { + private enum AlertItem: Identifiable { + case downloadUrl(URL) + + var id: Int { + switch self { + case .downloadUrl(let url): + return url.hashValue + } + } + } +} + struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() diff --git a/Platform/UTMData.swift b/Platform/UTMData.swift index 0a69c3cf3..b1367b03a 100644 --- a/Platform/UTMData.swift +++ b/Platform/UTMData.swift @@ -699,12 +699,7 @@ struct AlertMessage: Identifiable { /// Create a new VM by downloading a .zip and extracting it /// - Parameter components: Download URL components - func downloadUTMZip(from components: URLComponents) async { - guard let urlParameter = components.queryItems?.first(where: { $0.name == "url" })?.value, - let url = URL(string: urlParameter) else { - showErrorAlert(message: NSLocalizedString("Failed to parse download URL.", comment: "UTMData")) - return - } + func downloadUTMZip(from url: URL) { let task = UTMDownloadVMTask(for: url) listAdd(pendingVM: task.pendingVM) Task {