Merge pull request #156 from RobotsAndPencils/matt/OpenIdenticalBuilds

Better handling of duplicate builds and buttons not working
This commit is contained in:
Matt Kiazyk 2021-10-08 16:27:32 -05:00 committed by GitHub
commit 04c79c36ad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 44 additions and 28 deletions

View file

@ -378,13 +378,13 @@ class AppState: ObservableObject {
} }
// MARK: - Uninstall // MARK: - Uninstall
func uninstall(id: Xcode.ID) { func uninstall(xcode: Xcode) {
guard guard
let installedXcode = Current.files.installedXcodes(Path.root/"Applications").first(where: { $0.version == id }), let installedXcodePath = xcode.installedPath,
uninstallPublisher == nil uninstallPublisher == nil
else { return } else { return }
uninstallPublisher = uninstallXcode(path: installedXcode.path) uninstallPublisher = uninstallXcode(path: installedXcodePath)
.flatMap { [unowned self] _ in .flatMap { [unowned self] _ in
self.updateSelectedXcodePath() self.updateSelectedXcodePath()
} }
@ -400,10 +400,10 @@ class AppState: ObservableObject {
) )
} }
func reveal(id: Xcode.ID) { func reveal(xcode: Xcode) {
// TODO: show error if not // TODO: show error if not
guard let installedXcode = Current.files.installedXcodes(Path.root/"Applications").first(where: { $0.version == id }) else { return } guard let installedXcodePath = xcode.installedPath else { return }
NSWorkspace.shared.activateFileViewerSelecting([installedXcode.path.url]) NSWorkspace.shared.activateFileViewerSelecting([installedXcodePath.url])
} }
func reveal(path: String) { func reveal(path: String) {
@ -421,26 +421,26 @@ class AppState: ObservableObject {
/// If they consent to installing the helper then this method will be invoked again with `shouldPrepareUserForHelperInstallation` set to false. /// If they consent to installing the helper then this method will be invoked again with `shouldPrepareUserForHelperInstallation` set to false.
/// This will install the helper and make the Xcode active. /// This will install the helper and make the Xcode active.
/// ///
/// - Parameter id: The identifier of the Xcode to make active. /// - Parameter xcode: The Xcode to make active.
/// - Parameter shouldPrepareUserForHelperInstallation: Whether the user should be presented with an alert preparing them for helper installation before making the Xcode version active. /// - Parameter shouldPrepareUserForHelperInstallation: Whether the user should be presented with an alert preparing them for helper installation before making the Xcode version active.
func select(id: Xcode.ID, shouldPrepareUserForHelperInstallation: Bool = true) { func select(xcode: Xcode, shouldPrepareUserForHelperInstallation: Bool = true) {
guard helperInstallState == .installed || shouldPrepareUserForHelperInstallation == false else { guard helperInstallState == .installed || shouldPrepareUserForHelperInstallation == false else {
isPreparingUserForActionRequiringHelper = { [unowned self] userConsented in isPreparingUserForActionRequiringHelper = { [unowned self] userConsented in
guard userConsented else { return } guard userConsented else { return }
self.select(id: id, shouldPrepareUserForHelperInstallation: false) self.select(xcode: xcode, shouldPrepareUserForHelperInstallation: false)
} }
presentedAlert = .privilegedHelper presentedAlert = .privilegedHelper
return return
} }
guard guard
let installedXcode = Current.files.installedXcodes(Path.root/"Applications").first(where: { $0.version == id }), let installedXcodePath = xcode.installedPath,
selectPublisher == nil selectPublisher == nil
else { return } else { return }
selectPublisher = installHelperIfNecessary() selectPublisher = installHelperIfNecessary()
.flatMap { .flatMap {
Current.helper.switchXcodePath(installedXcode.path.string) Current.helper.switchXcodePath(installedXcodePath.string)
} }
.flatMap { [unowned self] _ in .flatMap { [unowned self] _ in
self.updateSelectedXcodePath() self.updateSelectedXcodePath()
@ -457,16 +457,22 @@ class AppState: ObservableObject {
) )
} }
func open(id: Xcode.ID) { func open(xcode: Xcode) {
guard let installedXcode = Current.files.installedXcodes(Path.root/"Applications").first(where: { $0.version == id }) else { return } switch xcode.installState {
NSWorkspace.shared.openApplication(at: installedXcode.path.url, configuration: .init()) case let .installed(path):
NSWorkspace.shared.openApplication(at: path.url, configuration: .init())
default:
Logger.appState.error("\(xcode.id) is not installed")
return
}
} }
func copyPath(id: Xcode.ID) { func copyPath(xcode: Xcode) {
guard let installedXcode = Current.files.installedXcodes(Path.root/"Applications").first(where: { $0.version == id }) else { return } guard let installedXcodePath = xcode.installedPath else { return }
NSPasteboard.general.declareTypes([.URL, .string], owner: nil) NSPasteboard.general.declareTypes([.URL, .string], owner: nil)
NSPasteboard.general.writeObjects([installedXcode.path.url as NSURL]) NSPasteboard.general.writeObjects([installedXcodePath.url as NSURL])
NSPasteboard.general.setString(installedXcode.path.string, forType: .string) NSPasteboard.general.setString(installedXcodePath.string, forType: .string)
} }
func updateAllXcodes(availableXcodes: [AvailableXcode], installedXcodes: [InstalledXcode], selectedXcodePath: String?) { func updateAllXcodes(availableXcodes: [AvailableXcode], installedXcodes: [InstalledXcode], selectedXcodePath: String?) {

View file

@ -3,6 +3,7 @@ import Foundation
import Version import Version
import struct XCModel.SDKs import struct XCModel.SDKs
import struct XCModel.Compilers import struct XCModel.Compilers
import Path
struct Xcode: Identifiable, CustomStringConvertible { struct Xcode: Identifiable, CustomStringConvertible {
let version: Version let version: Version
@ -57,4 +58,13 @@ struct Xcode: Identifiable, CustomStringConvertible {
return nil return nil
} }
} }
var installedPath: Path? {
switch installState {
case .installed(let path):
return path
default:
return nil
}
}
} }

View file

@ -83,7 +83,7 @@ struct SelectButton: View {
private func select() { private func select() {
guard let xcode = xcode else { return } guard let xcode = xcode else { return }
appState.select(id: xcode.id) appState.select(xcode: xcode)
} }
} }
@ -100,7 +100,7 @@ struct OpenButton: View {
private func open() { private func open() {
guard let xcode = xcode else { return } guard let xcode = xcode else { return }
appState.open(id: xcode.id) appState.open(xcode: xcode)
} }
} }
@ -132,7 +132,7 @@ struct RevealButton: View {
private func reveal() { private func reveal() {
guard let xcode = xcode else { return } guard let xcode = xcode else { return }
appState.reveal(id: xcode.id) appState.reveal(xcode: xcode)
} }
} }
@ -149,7 +149,7 @@ struct CopyPathButton: View {
private func copyPath() { private func copyPath() {
guard let xcode = xcode else { return } guard let xcode = xcode else { return }
appState.copyPath(id: xcode.id) appState.copyPath(xcode: xcode)
} }
} }

View file

@ -31,7 +31,7 @@ struct InfoPane: View {
case let .installed(path): case let .installed(path):
HStack { HStack {
Text(path.string) Text(path.string)
Button(action: { appState.reveal(id: xcode.id) }) { Button(action: { appState.reveal(xcode: xcode) }) {
Image(systemName: "arrow.right.circle.fill") Image(systemName: "arrow.right.circle.fill")
} }
.buttonStyle(PlainButtonStyle()) .buttonStyle(PlainButtonStyle())

View file

@ -22,7 +22,7 @@ struct MainWindow: View {
.alert(item: $appState.xcodeBeingConfirmedForUninstallation) { xcode in .alert(item: $appState.xcodeBeingConfirmedForUninstallation) { xcode in
Alert(title: Text("Uninstall Xcode \(xcode.description)?"), Alert(title: Text("Uninstall Xcode \(xcode.description)?"),
message: Text("It will be moved to the Trash, but won't be emptied."), message: Text("It will be moved to the Trash, but won't be emptied."),
primaryButton: .destructive(Text("Uninstall"), action: { self.appState.uninstall(id: xcode.id) }), primaryButton: .destructive(Text("Uninstall"), action: { self.appState.uninstall(xcode: xcode) }),
secondaryButton: .cancel(Text("Cancel"))) secondaryButton: .cancel(Text("Cancel")))
} }

View file

@ -85,7 +85,7 @@ struct XcodeListViewRow: View {
.foregroundColor(.green) .foregroundColor(.green)
.help("This is the active version") .help("This is the active version")
} else { } else {
Button(action: { appState.select(id: xcode.id) }) { Button(action: { appState.select(xcode: xcode) }) {
Image(systemName: "checkmark.circle") Image(systemName: "checkmark.circle")
.foregroundColor(.secondary) .foregroundColor(.secondary)
} }
@ -101,7 +101,7 @@ struct XcodeListViewRow: View {
private func installControl(for xcode: Xcode) -> some View { private func installControl(for xcode: Xcode) -> some View {
switch xcode.installState { switch xcode.installState {
case .installed: case .installed:
Button("OPEN") { appState.open(id: xcode.id) } Button("OPEN") { appState.open(xcode: xcode) }
.buttonStyle(AppStoreButtonStyle(primary: true, highlighted: selected)) .buttonStyle(AppStoreButtonStyle(primary: true, highlighted: selected))
.help("Open this version") .help("Open this version")
case .notInstalled: case .notInstalled: