diff --git a/Mist/Helpers/PropertyListUpdater.swift b/Mist/Helpers/PropertyListUpdater.swift index a3d151b..37563ab 100644 --- a/Mist/Helpers/PropertyListUpdater.swift +++ b/Mist/Helpers/PropertyListUpdater.swift @@ -10,7 +10,7 @@ import Foundation /// Helper struct to update a Property List key-pair value. struct PropertyListUpdater { - /// Edit a key-pair value in a Property List. + /// Update a key-pair value in a Property List. /// /// - Parameters: /// - url: The URL of the property list to be updated. diff --git a/Mist/Model/FirmwareAlertType.swift b/Mist/Model/FirmwareAlertType.swift index 2dff882..643d35d 100644 --- a/Mist/Model/FirmwareAlertType.swift +++ b/Mist/Model/FirmwareAlertType.swift @@ -10,4 +10,5 @@ import SwiftUI enum FirmwareAlertType: String { case compatibility = "Compatiblity" case helperTool = "Helper Tool" + case error = "Error" } diff --git a/Mist/Model/InstallerAlertType.swift b/Mist/Model/InstallerAlertType.swift index 61381a2..7453da5 100644 --- a/Mist/Model/InstallerAlertType.swift +++ b/Mist/Model/InstallerAlertType.swift @@ -10,4 +10,5 @@ enum InstallerAlertType: String { case helperTool = "Helper Tool" case fullDiskAccess = "Full Disk Access" case cacheDirectory = "Cache Directory" + case error = "Error" } diff --git a/Mist/Views/List/ListRowFirmware.swift b/Mist/Views/List/ListRowFirmware.swift index c61651b..102b0cb 100644 --- a/Mist/Views/List/ListRowFirmware.swift +++ b/Mist/Views/List/ListRowFirmware.swift @@ -23,6 +23,7 @@ struct ListRowFirmware: View { @State private var showAlert: Bool = false @State private var showSavePanel: Bool = false @State private var downloading: Bool = false + @State private var error: Error? private let length: CGFloat = 48 private let spacing: CGFloat = 5 private let padding: CGFloat = 3 @@ -34,6 +35,14 @@ struct ListRowFirmware: View { return "This macOS Firmware download cannot be used to restore macOS on this \(architecture.description) Mac.\n\nAre you sure you want to continue?" } + private var errorMessage: String { + + if let error: BlessError = error as? BlessError { + return error.description + } + + return error?.localizedDescription ?? "" + } var body: some View { HStack { @@ -68,10 +77,16 @@ struct ListRowFirmware: View { case .helperTool: return Alert( title: Text("Privileged Helper Tool not installed!"), - message: Text("The Mist Privileged Helper Tool is required to perform Administrator tasks when downloading macOS Firmwares"), - primaryButton: .default(Text("Install...")) { installPrivilegedHelperTool() }, + message: Text("The Mist Privileged Helper Tool is required to perform Administrator tasks when downloading macOS Firmwares."), + primaryButton: .default(Text("Install...")) { Task { installPrivilegedHelperTool() } }, secondaryButton: .default(Text("Cancel")) ) + case .error: + return Alert( + title: Text("An error has occured!"), + message: Text(errorMessage), + dismissButton: .default(Text("OK")) + ) } } .onChange(of: showSavePanel) { boolean in @@ -132,7 +147,13 @@ struct ListRowFirmware: View { } private func installPrivilegedHelperTool() { - try? PrivilegedHelperManager.shared.authorizeAndBless() + do { + try PrivilegedHelperManager.shared.authorizeAndBless() + } catch { + self.error = error + alertType = .error + showAlert = true + } } } diff --git a/Mist/Views/List/ListRowInstaller.swift b/Mist/Views/List/ListRowInstaller.swift index 10dd5d1..9be0694 100644 --- a/Mist/Views/List/ListRowInstaller.swift +++ b/Mist/Views/List/ListRowInstaller.swift @@ -48,6 +48,7 @@ struct ListRowInstaller: View { @State private var showOpenPanel: Bool = false @State private var exports: [InstallerExportType] = [] @State private var volume: InstallerVolume? + @State private var error: Error? private let length: CGFloat = 48 private let spacing: CGFloat = 5 private let padding: CGFloat = 3 @@ -62,6 +63,14 @@ struct ListRowInstaller: View { private var cacheDirectoryMessage: String { "The cache directory has incorrect ownership and/or permissions, which will cause issues caching macOS Installers.\n\nRepair the cache directory ownership and/or permissions and try again." } + private var errorMessage: String { + + if let error: BlessError = error as? BlessError { + return error.description + } + + return error?.localizedDescription ?? "" + } var body: some View { HStack { @@ -97,36 +106,7 @@ struct ListRowInstaller: View { .clipShape(Capsule()) } .alert(isPresented: $showAlert) { - switch alertType { - case .compatibility: - return Alert( - title: Text("macOS Installer not compatible!"), - message: Text(compatibilityMessage), - primaryButton: .default(Text("Cancel")), - secondaryButton: .default(Text("Continue")) { Task { validate() } } - ) - case .helperTool: - return Alert( - title: Text("Privileged Helper Tool not installed!"), - message: Text("The Mist Privileged Helper Tool is required to perform Administrator tasks when creating macOS Installers."), - primaryButton: .default(Text("Install...")) { installPrivilegedHelperTool() }, - secondaryButton: .default(Text("Cancel")) - ) - case .fullDiskAccess: - return Alert( - title: Text("Full Disk Access required!"), - message: Text("Mist requires Full Disk Access to perform Administrator tasks when creating macOS Installers."), - primaryButton: .default(Text("Allow...")) { openFullDiskAccessPreferences() }, - secondaryButton: .default(Text("Cancel")) - ) - case .cacheDirectory: - return Alert( - title: Text("Cache directory settings incorrect!"), - message: Text(cacheDirectoryMessage), - primaryButton: .default(Text("Repair...")) { Task { try await repairCacheDirectoryOwnershipAndPermissions() } }, - secondaryButton: .default(Text("Cancel")) - ) - } + alert(for: alertType) } .onChange(of: showOpenPanel) { boolean in @@ -309,7 +289,13 @@ struct ListRowInstaller: View { } private func installPrivilegedHelperTool() { - try? PrivilegedHelperManager.shared.authorizeAndBless() + do { + try PrivilegedHelperManager.shared.authorizeAndBless() + } catch { + self.error = error + alertType = .error + showAlert = true + } } private func openFullDiskAccessPreferences() { @@ -326,6 +312,45 @@ struct ListRowInstaller: View { let ownerAccountName: String = NSUserName() try await FileAttributesUpdater.update(url: url, ownerAccountName: ownerAccountName) } + + private func alert(for alertType: InstallerAlertType) -> Alert { + switch alertType { + case .compatibility: + return Alert( + title: Text("macOS Installer not compatible!"), + message: Text(compatibilityMessage), + primaryButton: .default(Text("Cancel")), + secondaryButton: .default(Text("Continue")) { Task { validate() } } + ) + case .helperTool: + return Alert( + title: Text("Privileged Helper Tool not installed!"), + message: Text("The Mist Privileged Helper Tool is required to perform Administrator tasks when creating macOS Installers."), + primaryButton: .default(Text("Install...")) { Task { installPrivilegedHelperTool() } }, + secondaryButton: .default(Text("Cancel")) + ) + case .fullDiskAccess: + return Alert( + title: Text("Full Disk Access required!"), + message: Text("Mist requires Full Disk Access to perform Administrator tasks when creating macOS Installers."), + primaryButton: .default(Text("Allow...")) { openFullDiskAccessPreferences() }, + secondaryButton: .default(Text("Cancel")) + ) + case .cacheDirectory: + return Alert( + title: Text("Cache directory settings incorrect!"), + message: Text(cacheDirectoryMessage), + primaryButton: .default(Text("Repair...")) { Task { try await repairCacheDirectoryOwnershipAndPermissions() } }, + secondaryButton: .default(Text("Cancel")) + ) + case .error: + return Alert( + title: Text("An error has occured!"), + message: Text(errorMessage), + dismissButton: .default(Text("OK")) + ) + } + } } struct ListRowInstaller_Previews: PreviewProvider {