mirror of
https://github.com/ninxsoft/Mist.git
synced 2025-05-31 15:28:23 -04:00
180 lines
6 KiB
Swift
180 lines
6 KiB
Swift
//
|
|
// ListRowFirmware.swift
|
|
// Mist
|
|
//
|
|
// Created by Nindi Gill on 13/6/2022.
|
|
//
|
|
|
|
import Blessed
|
|
import SwiftUI
|
|
|
|
struct ListRowFirmware: View {
|
|
@AppStorage("firmwareFilename")
|
|
private var firmwareFilename: String = .firmwareFilenameTemplate
|
|
@AppStorage("retries")
|
|
private var retries: Int = 10
|
|
@AppStorage("retryDelay")
|
|
private var retryDelay: Int = 30
|
|
var firmware: Firmware
|
|
@Binding var savePanel: NSSavePanel
|
|
@Binding var copiedToClipboard: Bool
|
|
@Binding var tasksInProgress: Bool
|
|
@ObservedObject var taskManager: TaskManager
|
|
@State private var alertType: FirmwareAlertType = .compatibility
|
|
@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
|
|
private var compatibilityMessage: String {
|
|
guard let architecture: Architecture = Hardware.architecture else {
|
|
return "Invalid architecture!"
|
|
}
|
|
|
|
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 {
|
|
ListRowDetail(
|
|
imageName: firmware.imageName,
|
|
beta: firmware.beta,
|
|
version: firmware.version,
|
|
build: firmware.build,
|
|
date: firmware.formattedDate,
|
|
size: firmware.size.bytesString(),
|
|
tooltip: firmware.tooltip
|
|
)
|
|
HStack(spacing: 1) {
|
|
Button {
|
|
firmware.compatible ? validate() : showCompatibilityWarning()
|
|
} label: {
|
|
Image(systemName: "arrow.down.circle")
|
|
.padding(.vertical, 1.5)
|
|
}
|
|
.help("Download macOS Firmware")
|
|
.buttonStyle(.mistAction)
|
|
Button {
|
|
copyToClipboard()
|
|
} label: {
|
|
Image(systemName: "list.bullet.clipboard")
|
|
}
|
|
.help("Copy macOS Firmware URL to Clipboard")
|
|
.buttonStyle(.mistAction)
|
|
}
|
|
.clipShape(Capsule())
|
|
}
|
|
.alert(isPresented: $showAlert) {
|
|
switch alertType {
|
|
case .compatibility:
|
|
Alert(
|
|
title: Text("macOS Firmware not compatible!"),
|
|
message: Text(compatibilityMessage),
|
|
primaryButton: .default(Text("Cancel")),
|
|
secondaryButton: .default(Text("Continue")) { Task { validate() } }
|
|
)
|
|
case .helperTool:
|
|
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...")) { Task { installPrivilegedHelperTool() } },
|
|
secondaryButton: .default(Text("Cancel"))
|
|
)
|
|
case .error:
|
|
Alert(
|
|
title: Text("An error has occured!"),
|
|
message: Text(errorMessage),
|
|
dismissButton: .default(Text("OK"))
|
|
)
|
|
}
|
|
}
|
|
.onChange(of: showSavePanel) { boolean in
|
|
|
|
if boolean {
|
|
save()
|
|
}
|
|
}
|
|
.sheet(isPresented: $downloading) {
|
|
ActivityView(
|
|
downloadType: .firmware,
|
|
imageName: firmware.imageName,
|
|
name: firmware.name,
|
|
version: firmware.version,
|
|
build: firmware.build,
|
|
beta: firmware.beta,
|
|
destinationURL: savePanel.url,
|
|
taskManager: taskManager
|
|
)
|
|
}
|
|
}
|
|
|
|
private func copyToClipboard() {
|
|
NSPasteboard.general.declareTypes([.string], owner: nil)
|
|
NSPasteboard.general.setString(firmware.url, forType: .string)
|
|
withAnimation(.easeIn) {
|
|
copiedToClipboard = true
|
|
}
|
|
}
|
|
|
|
private func save() {
|
|
showSavePanel = false
|
|
savePanel.title = "Download Firmware"
|
|
savePanel.nameFieldStringValue = firmwareFilename.stringWithSubstitutions(name: firmware.name, version: firmware.version, build: firmware.build)
|
|
savePanel.canCreateDirectories = true
|
|
savePanel.canSelectHiddenExtension = true
|
|
savePanel.isExtensionHidden = false
|
|
|
|
Task {
|
|
let response: NSApplication.ModalResponse = savePanel.runModal()
|
|
|
|
guard response == .OK else {
|
|
return
|
|
}
|
|
|
|
taskManager.taskGroups = try TaskManager.taskGroups(for: firmware, destination: savePanel.url, retries: retries, delay: retryDelay)
|
|
downloading = true
|
|
tasksInProgress = true
|
|
}
|
|
}
|
|
|
|
private func showCompatibilityWarning() {
|
|
alertType = .compatibility
|
|
showAlert = true
|
|
}
|
|
|
|
private func validate() {
|
|
guard PrivilegedHelperTool.isInstalled() else {
|
|
alertType = .helperTool
|
|
showAlert = true
|
|
return
|
|
}
|
|
|
|
showSavePanel = true
|
|
}
|
|
|
|
private func installPrivilegedHelperTool() {
|
|
do {
|
|
try PrivilegedHelperManager.shared.authorizeAndBless()
|
|
} catch {
|
|
self.error = error
|
|
alertType = .error
|
|
showAlert = true
|
|
}
|
|
}
|
|
}
|
|
|
|
struct ListRowFirmware_Previews: PreviewProvider {
|
|
static var previews: some View {
|
|
ListRowFirmware(firmware: .example, savePanel: .constant(NSSavePanel()), copiedToClipboard: .constant(false), tasksInProgress: .constant(false), taskManager: .shared)
|
|
}
|
|
}
|