mirror of
https://github.com/ninxsoft/Mist.git
synced 2025-05-12 22:26:15 -04:00
Feature custom clear cache (#64)
* Add support for manual cache removal * Format sorting closure
This commit is contained in:
parent
706049becc
commit
f215031df1
5 changed files with 234 additions and 28 deletions
|
@ -138,6 +138,8 @@
|
||||||
575812C22A380B5E00425BAF /* InstallerVolume.swift in Sources */ = {isa = PBXBuildFile; fileRef = 575812C12A380B5E00425BAF /* InstallerVolume.swift */; };
|
575812C22A380B5E00425BAF /* InstallerVolume.swift in Sources */ = {isa = PBXBuildFile; fileRef = 575812C12A380B5E00425BAF /* InstallerVolume.swift */; };
|
||||||
575812C42A3821A900425BAF /* InstallerVolumeSelectionInformationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 575812C32A3821A900425BAF /* InstallerVolumeSelectionInformationView.swift */; };
|
575812C42A3821A900425BAF /* InstallerVolumeSelectionInformationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 575812C32A3821A900425BAF /* InstallerVolumeSelectionInformationView.swift */; };
|
||||||
575812C62A38296A00425BAF /* InstallerVolumeSelectionPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 575812C52A38296A00425BAF /* InstallerVolumeSelectionPickerView.swift */; };
|
575812C62A38296A00425BAF /* InstallerVolumeSelectionPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 575812C52A38296A00425BAF /* InstallerVolumeSelectionPickerView.swift */; };
|
||||||
|
577267AC2A4568CD00434B2C /* SettingsInstallerCacheAlertType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 577267AB2A4568CD00434B2C /* SettingsInstallerCacheAlertType.swift */; };
|
||||||
|
577267AE2A45734700434B2C /* SettingsInstallersCacheTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 577267AD2A45734700434B2C /* SettingsInstallersCacheTableView.swift */; };
|
||||||
5795700B2A31B06F004C7051 /* ButtonStyle+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5795700A2A31B06F004C7051 /* ButtonStyle+Extension.swift */; };
|
5795700B2A31B06F004C7051 /* ButtonStyle+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5795700A2A31B06F004C7051 /* ButtonStyle+Extension.swift */; };
|
||||||
5795700D2A31B081004C7051 /* MistActionButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5795700C2A31B081004C7051 /* MistActionButtonStyle.swift */; };
|
5795700D2A31B081004C7051 /* MistActionButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5795700C2A31B081004C7051 /* MistActionButtonStyle.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
@ -288,6 +290,8 @@
|
||||||
575812C12A380B5E00425BAF /* InstallerVolume.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstallerVolume.swift; sourceTree = "<group>"; };
|
575812C12A380B5E00425BAF /* InstallerVolume.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstallerVolume.swift; sourceTree = "<group>"; };
|
||||||
575812C32A3821A900425BAF /* InstallerVolumeSelectionInformationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstallerVolumeSelectionInformationView.swift; sourceTree = "<group>"; };
|
575812C32A3821A900425BAF /* InstallerVolumeSelectionInformationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstallerVolumeSelectionInformationView.swift; sourceTree = "<group>"; };
|
||||||
575812C52A38296A00425BAF /* InstallerVolumeSelectionPickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstallerVolumeSelectionPickerView.swift; sourceTree = "<group>"; };
|
575812C52A38296A00425BAF /* InstallerVolumeSelectionPickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstallerVolumeSelectionPickerView.swift; sourceTree = "<group>"; };
|
||||||
|
577267AB2A4568CD00434B2C /* SettingsInstallerCacheAlertType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsInstallerCacheAlertType.swift; sourceTree = "<group>"; };
|
||||||
|
577267AD2A45734700434B2C /* SettingsInstallersCacheTableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsInstallersCacheTableView.swift; sourceTree = "<group>"; };
|
||||||
5795700A2A31B06F004C7051 /* ButtonStyle+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ButtonStyle+Extension.swift"; sourceTree = "<group>"; };
|
5795700A2A31B06F004C7051 /* ButtonStyle+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ButtonStyle+Extension.swift"; sourceTree = "<group>"; };
|
||||||
5795700C2A31B081004C7051 /* MistActionButtonStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MistActionButtonStyle.swift; sourceTree = "<group>"; };
|
5795700C2A31B081004C7051 /* MistActionButtonStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MistActionButtonStyle.swift; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
@ -436,6 +440,7 @@
|
||||||
390451D32856F74B00E0B563 /* Package.swift */,
|
390451D32856F74B00E0B563 /* Package.swift */,
|
||||||
3935F48F286976D000760AB0 /* ProgressAlertType.swift */,
|
3935F48F286976D000760AB0 /* ProgressAlertType.swift */,
|
||||||
393F35BB28641181005B7165 /* RefreshState.swift */,
|
393F35BB28641181005B7165 /* RefreshState.swift */,
|
||||||
|
577267AB2A4568CD00434B2C /* SettingsInstallerCacheAlertType.swift */,
|
||||||
);
|
);
|
||||||
path = Model;
|
path = Model;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -556,6 +561,7 @@
|
||||||
39FF05F52859850F00A86670 /* SettingsFirmwaresView.swift */,
|
39FF05F52859850F00A86670 /* SettingsFirmwaresView.swift */,
|
||||||
39252A78285A85AF00956C74 /* SettingsInstallersView.swift */,
|
39252A78285A85AF00956C74 /* SettingsInstallersView.swift */,
|
||||||
39252AB8285C7BC700956C74 /* SettingsInstallersCacheView.swift */,
|
39252AB8285C7BC700956C74 /* SettingsInstallersCacheView.swift */,
|
||||||
|
577267AD2A45734700434B2C /* SettingsInstallersCacheTableView.swift */,
|
||||||
39252ABA285C7D3800956C74 /* SettingsInstallersCatalogsView.swift */,
|
39252ABA285C7D3800956C74 /* SettingsInstallersCatalogsView.swift */,
|
||||||
39FF05F72859851800A86670 /* SettingsApplicationsView.swift */,
|
39FF05F72859851800A86670 /* SettingsApplicationsView.swift */,
|
||||||
39252A7A285AC50400956C74 /* SettingsDiskImagesView.swift */,
|
39252A7A285AC50400956C74 /* SettingsDiskImagesView.swift */,
|
||||||
|
@ -766,6 +772,7 @@
|
||||||
files = (
|
files = (
|
||||||
39FF05F02859848500A86670 /* SettingsView.swift in Sources */,
|
39FF05F02859848500A86670 /* SettingsView.swift in Sources */,
|
||||||
39CF562A2861E1CB006FB5D2 /* DirectoryRemover.swift in Sources */,
|
39CF562A2861E1CB006FB5D2 /* DirectoryRemover.swift in Sources */,
|
||||||
|
577267AE2A45734700434B2C /* SettingsInstallersCacheTableView.swift in Sources */,
|
||||||
575812C62A38296A00425BAF /* InstallerVolumeSelectionPickerView.swift in Sources */,
|
575812C62A38296A00425BAF /* InstallerVolumeSelectionPickerView.swift in Sources */,
|
||||||
398734C828601FFC00B4C357 /* FileMover.swift in Sources */,
|
398734C828601FFC00B4C357 /* FileMover.swift in Sources */,
|
||||||
39CF55AF2861582F006FB5D2 /* AuthorizationError+Extension.swift in Sources */,
|
39CF55AF2861582F006FB5D2 /* AuthorizationError+Extension.swift in Sources */,
|
||||||
|
@ -790,6 +797,7 @@
|
||||||
39252AC3285CA5FE00956C74 /* InstallerExportView.swift in Sources */,
|
39252AC3285CA5FE00956C74 /* InstallerExportView.swift in Sources */,
|
||||||
398734D228603DE700B4C357 /* Array+Extension.swift in Sources */,
|
398734D228603DE700B4C357 /* Array+Extension.swift in Sources */,
|
||||||
39FF05F82859851800A86670 /* SettingsApplicationsView.swift in Sources */,
|
39FF05F82859851800A86670 /* SettingsApplicationsView.swift in Sources */,
|
||||||
|
577267AC2A4568CD00434B2C /* SettingsInstallerCacheAlertType.swift in Sources */,
|
||||||
39CF561D2861C3F5006FB5D2 /* DiskImageCreator.swift in Sources */,
|
39CF561D2861C3F5006FB5D2 /* DiskImageCreator.swift in Sources */,
|
||||||
575812BA2A373A4F00425BAF /* FirmwareAlertType.swift in Sources */,
|
575812BA2A373A4F00425BAF /* FirmwareAlertType.swift in Sources */,
|
||||||
39CF55AD28615530006FB5D2 /* SettingsGeneralHelperView.swift in Sources */,
|
39CF55AD28615530006FB5D2 /* SettingsGeneralHelperView.swift in Sources */,
|
||||||
|
|
11
Mist/Model/SettingsInstallerCacheAlertType.swift
Normal file
11
Mist/Model/SettingsInstallerCacheAlertType.swift
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
//
|
||||||
|
// SettingsInstallerCacheAlertType.swift
|
||||||
|
// Mist
|
||||||
|
//
|
||||||
|
// Created by Nindi Gill on 23/6/2023.
|
||||||
|
//
|
||||||
|
|
||||||
|
enum SettingsInstallerCacheAlertType: String {
|
||||||
|
case confirmation = "Confirmation"
|
||||||
|
case error = "Error"
|
||||||
|
}
|
|
@ -119,7 +119,11 @@ struct RefreshView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
firmwares.sort { $0.version == $1.version ? ($0.build.count == $1.build.count ? $0.build > $1.build : $0.build.count > $1.build.count) : $0.version > $1.version }
|
firmwares.sort {
|
||||||
|
$0.version == $1.version ?
|
||||||
|
($0.build.count == $1.build.count ? $0.build > $1.build : $0.build.count > $1.build.count) :
|
||||||
|
$0.version > $1.version
|
||||||
|
}
|
||||||
return firmwares
|
return firmwares
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
49
Mist/Views/Settings/SettingsInstallersCacheTableView.swift
Normal file
49
Mist/Views/Settings/SettingsInstallersCacheTableView.swift
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
//
|
||||||
|
// SettingsInstallersCacheTableView.swift
|
||||||
|
// Mist
|
||||||
|
//
|
||||||
|
// Created by Nindi Gill on 23/6/2023.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct SettingsInstallersCacheTableView: View {
|
||||||
|
var installers: [Installer]
|
||||||
|
@Binding var selectedInstallerId: String?
|
||||||
|
var cacheDownloads: Bool
|
||||||
|
private let height: CGFloat = 126
|
||||||
|
private let width: CGFloat = 150
|
||||||
|
private let length: CGFloat = 16
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
Table(installers, selection: $selectedInstallerId) {
|
||||||
|
TableColumn("") { installer in
|
||||||
|
ScaledImage(name: "Application - \(installer.version.isEmpty ? "macOS" : installer.imageName)", length: length)
|
||||||
|
}
|
||||||
|
.width(length)
|
||||||
|
TableColumn("Release") { installer in
|
||||||
|
Text(installer.version.isEmpty ? installer.id : installer.name)
|
||||||
|
}
|
||||||
|
.width(width)
|
||||||
|
TableColumn("Version") { installer in
|
||||||
|
Text(installer.version.isEmpty ? "Unknown" : installer.version)
|
||||||
|
}
|
||||||
|
TableColumn("Build") { installer in
|
||||||
|
Text(installer.build.isEmpty ? "Unknown" : installer.build)
|
||||||
|
}
|
||||||
|
TableColumn("Size") { installer in
|
||||||
|
Text(installer.size.bytesString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.tableStyle(.bordered)
|
||||||
|
.frame(minHeight: height, maxHeight: height)
|
||||||
|
.disabled(!cacheDownloads)
|
||||||
|
.opacity(cacheDownloads ? 1 : 0.5)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SettingsInstallersCacheTableView_Previews: PreviewProvider {
|
||||||
|
static var previews: some View {
|
||||||
|
SettingsInstallersCacheTableView(installers: [.example], selectedInstallerId: .constant(nil), cacheDownloads: true)
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,48 +11,78 @@ struct SettingsInstallersCacheView: View {
|
||||||
@Binding var cacheDownloads: Bool
|
@Binding var cacheDownloads: Bool
|
||||||
@Binding var cacheDirectory: String
|
@Binding var cacheDirectory: String
|
||||||
@State private var cacheSize: UInt64 = 0
|
@State private var cacheSize: UInt64 = 0
|
||||||
@State private var buttonClicked: Bool = false
|
|
||||||
@State private var openPanel: NSOpenPanel = NSOpenPanel()
|
@State private var openPanel: NSOpenPanel = NSOpenPanel()
|
||||||
|
@State private var installers: [Installer] = []
|
||||||
|
@State private var selectedInstallerId: String?
|
||||||
|
@State private var showAlert: Bool = false
|
||||||
|
@State private var alertType: SettingsInstallerCacheAlertType = .confirmation
|
||||||
|
private let padding: CGFloat = 5
|
||||||
|
private var removalMessage: String {
|
||||||
|
guard let installer: Installer = installers.first(where: { $0.id == selectedInstallerId }) else {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Removing '\(installer.version.isEmpty ? installer.id : "\(installer.name) \(installer.version) (\(installer.build))")' will free up \(installer.size.bytesString())."
|
||||||
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
HStack(alignment: .firstTextBaseline) {
|
HStack(alignment: .firstTextBaseline) {
|
||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
Toggle(isOn: $cacheDownloads) {
|
Toggle(isOn: $cacheDownloads) { Text("Cache downloads") }
|
||||||
Text("Cache downloads")
|
|
||||||
}
|
|
||||||
FooterText("Speed up future operations by caching a local copy of macOS Installer files.")
|
FooterText("Speed up future operations by caching a local copy of macOS Installer files.")
|
||||||
}
|
}
|
||||||
Spacer()
|
Spacer()
|
||||||
Button("Select...") {
|
Button("Select...") { selectCacheDirectory() }
|
||||||
selectCacheDirectory()
|
|
||||||
}
|
|
||||||
.disabled(!cacheDownloads)
|
.disabled(!cacheDownloads)
|
||||||
}
|
}
|
||||||
PathControl(path: $cacheDirectory)
|
PathControl(path: $cacheDirectory)
|
||||||
.disabled(true)
|
.disabled(true)
|
||||||
|
.opacity(cacheDownloads ? 1 : 0.5)
|
||||||
|
SettingsInstallersCacheTableView(installers: installers, selectedInstallerId: $selectedInstallerId, cacheDownloads: cacheDownloads)
|
||||||
|
.padding(.bottom, padding)
|
||||||
HStack(alignment: .firstTextBaseline) {
|
HStack(alignment: .firstTextBaseline) {
|
||||||
FooterText("Cache directory currently contains \(cacheSize.bytesString()) of data.")
|
FooterText("Cache directory currently contains \(cacheSize.bytesString()) of data.")
|
||||||
Spacer()
|
Spacer()
|
||||||
Button("Empty Cache...") {
|
Button("Show in Finder") {
|
||||||
buttonClicked.toggle()
|
showInFinder()
|
||||||
}
|
}
|
||||||
.disabled(cacheSize == 0)
|
.disabled(!cacheDownloads || selectedInstallerId == nil)
|
||||||
|
Button("Remove...") {
|
||||||
|
alertType = .confirmation
|
||||||
|
showAlert = true
|
||||||
|
}
|
||||||
|
.disabled(!cacheDownloads || selectedInstallerId == nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onAppear {
|
.onAppear {
|
||||||
retrieveCacheSize()
|
retrieveCache()
|
||||||
}
|
}
|
||||||
.onChange(of: cacheDirectory) { _ in
|
.onChange(of: cacheDirectory) { _ in
|
||||||
retrieveCacheSize()
|
retrieveCache()
|
||||||
}
|
}
|
||||||
.alert(isPresented: $buttonClicked) {
|
.alert(isPresented: $showAlert) {
|
||||||
Alert(
|
switch alertType {
|
||||||
title: Text("Empty Cache Directory?"),
|
case .confirmation:
|
||||||
message: Text("Emptying the cache directory will free up \(cacheSize.bytesString())."),
|
return Alert(
|
||||||
|
title: Text("Remove Cached Installer?"),
|
||||||
|
message: Text(removalMessage),
|
||||||
primaryButton: .cancel(),
|
primaryButton: .cancel(),
|
||||||
secondaryButton: .destructive(Text("Empty")) { emptyCache() ; retrieveCacheSize() }
|
secondaryButton: .destructive(Text("Remove")) {
|
||||||
|
Task {
|
||||||
|
await emptyCache(for: selectedInstallerId)
|
||||||
|
retrieveCache()
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
case .error:
|
||||||
|
return Alert(
|
||||||
|
title: Text("An error has occured!"),
|
||||||
|
message: Text("There was an error removing the cached Installer directory. Show in Finder to remove manually."),
|
||||||
|
primaryButton: .default(Text("OK")) { },
|
||||||
|
secondaryButton: .default(Text("Show in Finder")) { showInFinder() }
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,7 +105,7 @@ struct SettingsInstallersCacheView: View {
|
||||||
cacheDirectory = url.path
|
cacheDirectory = url.path
|
||||||
}
|
}
|
||||||
|
|
||||||
private func retrieveCacheSize() {
|
private func retrieveCache() {
|
||||||
|
|
||||||
let url: URL = URL(fileURLWithPath: cacheDirectory)
|
let url: URL = URL(fileURLWithPath: cacheDirectory)
|
||||||
var isDirectory: ObjCBool = false
|
var isDirectory: ObjCBool = false
|
||||||
|
@ -86,22 +116,126 @@ struct SettingsInstallersCacheView: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
cacheSize = try FileManager.default.sizeOfDirectory(at: url)
|
cacheSize = try FileManager.default.sizeOfDirectory(at: url)
|
||||||
|
let ids: [String] = try FileManager.default.contentsOfDirectory(atPath: url.path)
|
||||||
|
var installers: [Installer] = []
|
||||||
|
|
||||||
|
for id in ids {
|
||||||
|
let url: URL = url.appendingPathComponent(id)
|
||||||
|
|
||||||
|
guard FileManager.default.fileExists(atPath: url.path, isDirectory: &isDirectory),
|
||||||
|
isDirectory.boolValue,
|
||||||
|
let installer: Installer = installer(for: url) else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
installers.append(installer)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.installers = installers.sorted {
|
||||||
|
$0.version == $1.version ?
|
||||||
|
($0.build.count == $1.build.count ? $0.build > $1.build : $0.build.count > $1.build.count) :
|
||||||
|
$0.version.compare($1.version, options: .numeric) == .orderedDescending
|
||||||
|
}
|
||||||
|
selectedInstallerId = nil
|
||||||
} catch {
|
} catch {
|
||||||
print(error.localizedDescription)
|
print(error.localizedDescription)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func emptyCache() {
|
private func installer(for url: URL) -> Installer? {
|
||||||
|
|
||||||
|
let id: String = url.lastPathComponent
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let paths: [String] = try FileManager.default.contentsOfDirectory(atPath: cacheDirectory)
|
if let installer: Installer = Installer.legacyInstallers.first(where: { $0.id == id }) {
|
||||||
|
return installer
|
||||||
|
} else {
|
||||||
|
let distributionURL: URL = url.appendingPathComponent("\(id).English.dist")
|
||||||
|
let string: String = try String(contentsOf: distributionURL)
|
||||||
|
|
||||||
for path in paths {
|
if let version: String = versionFromDistribution(string),
|
||||||
let url: URL = URL(fileURLWithPath: cacheDirectory + "/" + path)
|
let build: String = buildFromDistribution(string) {
|
||||||
try FileManager.default.removeItem(at: url)
|
let size: UInt64 = try FileManager.default.sizeOfDirectory(at: url)
|
||||||
|
return Installer(
|
||||||
|
id: id,
|
||||||
|
version: version,
|
||||||
|
build: build,
|
||||||
|
date: "",
|
||||||
|
distributionURL: "",
|
||||||
|
distributionSize: 0,
|
||||||
|
packages: [Package(url: "", size: Int(size), integrityDataURL: nil, integrityDataSize: nil)],
|
||||||
|
boardIDs: [],
|
||||||
|
deviceIDs: [],
|
||||||
|
unsupportedModelIdentifiers: []
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
print(error.localizedDescription)
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
let size: UInt64 = try FileManager.default.sizeOfDirectory(at: url)
|
||||||
|
return Installer(
|
||||||
|
id: id,
|
||||||
|
version: "",
|
||||||
|
build: "",
|
||||||
|
date: "",
|
||||||
|
distributionURL: "",
|
||||||
|
distributionSize: 0,
|
||||||
|
packages: [Package(url: "", size: Int(size), integrityDataURL: nil, integrityDataSize: nil)],
|
||||||
|
boardIDs: [],
|
||||||
|
deviceIDs: [],
|
||||||
|
unsupportedModelIdentifiers: []
|
||||||
|
)
|
||||||
|
} catch {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func versionFromDistribution(_ string: String) -> String? {
|
||||||
|
|
||||||
|
guard string.contains("<key>VERSION</key>") else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.replacingOccurrences(of: "^[\\s\\S]*<key>VERSION<\\/key>\\s*<string>", with: "", options: .regularExpression)
|
||||||
|
.replacingOccurrences(of: "<\\/string>[\\s\\S]*$", with: "", options: .regularExpression)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func buildFromDistribution(_ string: String) -> String? {
|
||||||
|
|
||||||
|
guard string.contains("<key>BUILD</key>") else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.replacingOccurrences(of: "^[\\s\\S]*<key>BUILD<\\/key>\\s*<string>", with: "", options: .regularExpression)
|
||||||
|
.replacingOccurrences(of: "<\\/string>[\\s\\S]*$", with: "", options: .regularExpression)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func showInFinder() {
|
||||||
|
|
||||||
|
guard let id: String = selectedInstallerId else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let url: URL = URL(fileURLWithPath: "\(cacheDirectory)/\(id)")
|
||||||
|
NSWorkspace.shared.open(url)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func emptyCache(for id: String?) async {
|
||||||
|
|
||||||
|
guard let id: String = id else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let url: URL = URL(fileURLWithPath: "\(cacheDirectory)/\(id)")
|
||||||
|
|
||||||
|
do {
|
||||||
|
try await DirectoryRemover.remove(url)
|
||||||
|
} catch {
|
||||||
|
alertType = .error
|
||||||
|
showAlert = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue