Merge pull request #33 from RobotsAndPencils/selection-performance-fix

Move Xcode selection state into window, improve performance
This commit is contained in:
Brandon Evans 2020-12-29 15:11:53 -07:00 committed by GitHub
commit cc9afeda97
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 20 additions and 25 deletions

View file

@ -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

View file

@ -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 {

View file

@ -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")
}

View file

@ -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<Xcode.ID?>, 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)
@ -39,7 +41,7 @@ struct XcodeListView: View {
Text(verbatim: xcode.path ?? "")
.font(.caption)
.foregroundColor(appState.selectedXcodeID == xcode.id ? Color(NSColor.selectedMenuItemTextColor) : Color(NSColor.secondaryLabelColor))
.foregroundColor(selectedXcodeID == xcode.id ? Color(NSColor.selectedMenuItemTextColor) : Color(NSColor.secondaryLabelColor))
}
@ -54,8 +56,8 @@ struct XcodeListView: View {
print("Installing...")
}
.buttonStyle(AppStoreButtonStyle(installed: xcode.installed,
highlighted: appState.selectedXcodeID == xcode.id))
.disabled(xcode.installed)
highlighted: selectedXcodeID == xcode.id))
.disabled(xcode.installed)
}
.contextMenu {
InstallButton(xcode: 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 = [

View file

@ -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) {