From b32687484d5bfb3c4a6985c612fda6d6342b26ab Mon Sep 17 00:00:00 2001 From: Brandon Evans Date: Tue, 29 Dec 2020 13:47:04 -0700 Subject: [PATCH] Move Xcode selection state into window --- Xcodes/Backend/AppState.swift | 4 ---- Xcodes/Frontend/MainWindow.swift | 9 ++++++--- Xcodes/Frontend/XcodeList/InspectorPane.swift | 15 ++++++--------- Xcodes/Frontend/XcodeList/XcodeListView.swift | 8 +++++--- Xcodes/XcodesApp.swift | 3 --- 5 files changed, 17 insertions(+), 22 deletions(-) diff --git a/Xcodes/Backend/AppState.swift b/Xcodes/Backend/AppState.swift index cef6b90..42b91b8 100644 --- a/Xcodes/Backend/AppState.swift +++ b/Xcodes/Backend/AppState.swift @@ -32,10 +32,6 @@ class AppState: ObservableObject { @Published var presentingSignInAlert = false @Published var isProcessingAuthRequest = false @Published var secondFactorData: SecondFactorData? - // Selected in the Xcode list, not in the xcode-select sense - // This probably belongs as private @State in XcodeListView, - // but we need it here instead so that it can be a focusedValue at the top level in XcodesApp instead of in a list row. The latter seems more like how the focusedValue API is supposed to work, but currently doesn't. - @Published var selectedXcodeID: Xcode.ID? @Published var xcodeBeingConfirmedForUninstallation: Xcode? @Published var helperInstallState: HelperInstallState = .notInstalled diff --git a/Xcodes/Frontend/MainWindow.swift b/Xcodes/Frontend/MainWindow.swift index 28eb395..2de7592 100644 --- a/Xcodes/Frontend/MainWindow.swift +++ b/Xcodes/Frontend/MainWindow.swift @@ -2,7 +2,7 @@ import SwiftUI struct MainWindow: View { @EnvironmentObject var appState: AppState - @State private var selection: Xcode.ID? + @State private var selectedXcodeID: Xcode.ID? @State private var searchText: String = "" @AppStorage("lastUpdated") private var lastUpdated: Double? @SceneStorage("isShowingInfoPane") private var isShowingInfoPane = false @@ -10,11 +10,11 @@ struct MainWindow: View { var body: some View { HSplitView { - XcodeListView(searchText: searchText, category: category) + XcodeListView(selectedXcodeID: $selectedXcodeID, searchText: searchText, category: category) .frame(minWidth: 300) .layoutPriority(1) - InspectorPane() + InspectorPane(selectedXcodeID: selectedXcodeID) .frame(minWidth: 300, maxWidth: .infinity) .frame(width: isShowingInfoPane ? nil : 0) .isHidden(!isShowingInfoPane) @@ -44,6 +44,9 @@ struct MainWindow: View { secondFactorView(appState.secondFactorData!) .environmentObject(appState) } + // I'm expecting to be able to use this modifier on a List row, but using it at the top level here is the only way that has made XcodeCommands work so far. + // FB8954571 focusedValue(_:_:) on List row doesn't propagate value to @FocusedValue + .focusedValue(\.selectedXcode, SelectedXcode(appState.allXcodes.first { $0.id == selectedXcodeID })) } private var subtitleText: Text { diff --git a/Xcodes/Frontend/XcodeList/InspectorPane.swift b/Xcodes/Frontend/XcodeList/InspectorPane.swift index 144d734..078675b 100644 --- a/Xcodes/Frontend/XcodeList/InspectorPane.swift +++ b/Xcodes/Frontend/XcodeList/InspectorPane.swift @@ -6,11 +6,12 @@ import struct XCModel.Compilers struct InspectorPane: View { @EnvironmentObject var appState: AppState + let selectedXcodeID: Xcode.ID? @SwiftUI.Environment(\.openURL) var openURL: OpenURLAction var body: some View { Group { - if let xcode = appState.allXcodes.first(where: { $0.id == appState.selectedXcodeID }) { + if let xcode = appState.allXcodes.first(where: { $0.id == selectedXcodeID }) { VStack(spacing: 16) { icon(for: xcode) @@ -169,7 +170,7 @@ struct InspectorPane: View { struct InspectorPane_Previews: PreviewProvider { static var previews: some View { Group { - InspectorPane() + InspectorPane(selectedXcodeID: Version(major: 12, minor: 3, patch: 0)) .environmentObject(configure(AppState()) { $0.allXcodes = [ .init( @@ -194,11 +195,10 @@ struct InspectorPane_Previews: PreviewProvider { swift: .init(number: "5.3.2") )) ] - $0.selectedXcodeID = Version(major: 12, minor: 3, patch: 0) }) .previewDisplayName("Populated, Installed, Selected") - InspectorPane() + InspectorPane(selectedXcodeID: Version(major: 12, minor: 3, patch: 0)) .environmentObject(configure(AppState()) { $0.allXcodes = [ .init( @@ -221,11 +221,10 @@ struct InspectorPane_Previews: PreviewProvider { swift: .init(number: "5.3.2") )) ] - $0.selectedXcodeID = Version(major: 12, minor: 3, patch: 0) }) .previewDisplayName("Populated, Installed, Unselected") - InspectorPane() + InspectorPane(selectedXcodeID: Version(major: 12, minor: 3, patch: 0)) .environmentObject(configure(AppState()) { $0.allXcodes = [ .init( @@ -248,15 +247,13 @@ struct InspectorPane_Previews: PreviewProvider { swift: .init(number: "5.3.2") )) ] - $0.selectedXcodeID = Version(major: 12, minor: 3, patch: 0) }) .previewDisplayName("Populated, Uninstalled") - InspectorPane() + InspectorPane(selectedXcodeID: nil) .environmentObject(configure(AppState()) { $0.allXcodes = [ ] - $0.selectedXcodeID = nil }) .previewDisplayName("Empty") } diff --git a/Xcodes/Frontend/XcodeList/XcodeListView.swift b/Xcodes/Frontend/XcodeList/XcodeListView.swift index a2c5d6c..edafc3c 100644 --- a/Xcodes/Frontend/XcodeList/XcodeListView.swift +++ b/Xcodes/Frontend/XcodeList/XcodeListView.swift @@ -4,10 +4,12 @@ import PromiseKit struct XcodeListView: View { @EnvironmentObject var appState: AppState + @Binding var selectedXcodeID: Xcode.ID? private let searchText: String private let category: XcodeListCategory - init(searchText: String, category: XcodeListCategory) { + init(selectedXcodeID: Binding, searchText: String, category: XcodeListCategory) { + self._selectedXcodeID = selectedXcodeID self.searchText = searchText self.category = category } @@ -29,7 +31,7 @@ struct XcodeListView: View { } var body: some View { - List(visibleXcodes, selection: $appState.selectedXcodeID) { xcode in + List(visibleXcodes, selection: $selectedXcodeID) { xcode in HStack { appIconView(for: xcode) @@ -87,7 +89,7 @@ struct XcodeListView: View { struct XcodeListView_Previews: PreviewProvider { static var previews: some View { Group { - XcodeListView(searchText: "", category: .all) + XcodeListView(selectedXcodeID: .constant(nil), searchText: "", category: .all) .environmentObject({ () -> AppState in let a = AppState() a.allXcodes = [ diff --git a/Xcodes/XcodesApp.swift b/Xcodes/XcodesApp.swift index fae3bb0..bb4398f 100644 --- a/Xcodes/XcodesApp.swift +++ b/Xcodes/XcodesApp.swift @@ -20,9 +20,6 @@ struct XcodesApp: App { appState.updateIfNeeded() } } - // I'm expecting to be able to use this modifier on a List row, but using it at the top level here is the only way that has made XcodeCommands work so far. - // FB8954571 focusedValue(_:_:) on List row doesn't propagate value to @FocusedValue - .focusedValue(\.selectedXcode, SelectedXcode(appState.allXcodes.first { $0.id == appState.selectedXcodeID })) } .commands { CommandGroup(replacing: .appInfo) {