Skip to content

Commit 7070575

Browse files
committed
Switch to NavigationSplitView
1 parent 6385430 commit 7070575

6 files changed

Lines changed: 148 additions & 63 deletions

File tree

Xcodes.xcodeproj/project.pbxproj

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@
114114
E689540325BE8C64000EBCEA /* DockProgress in Frameworks */ = {isa = PBXBuildFile; productRef = E689540225BE8C64000EBCEA /* DockProgress */; };
115115
E81D7EA02805250100A205FC /* Collection+.swift in Sources */ = {isa = PBXBuildFile; fileRef = E81D7E9F2805250100A205FC /* Collection+.swift */; };
116116
E832EAF82B0FBCF4001B570D /* RuntimeInstallationStepDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E832EAF72B0FBCF4001B570D /* RuntimeInstallationStepDetailView.swift */; };
117+
E84B7D0D2B296A8900DBDA2B /* NavigationSplitViewWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = E84B7D0C2B296A8900DBDA2B /* NavigationSplitViewWrapper.swift */; };
117118
E84CF8C12B0FEB8300ECA259 /* RuntimesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E84CF8C02B0FEB8300ECA259 /* RuntimesView.swift */; };
118-
E872EE4E2808D4F100D3DD8B /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = E872EE502808D4F100D3DD8B /* Localizable.strings */; };
119119
E87AB3C52939B65E00D72F43 /* Hardware.swift in Sources */ = {isa = PBXBuildFile; fileRef = E87AB3C42939B65E00D72F43 /* Hardware.swift */; };
120120
E87DD6EB25D053FA00D86808 /* Progress+.swift in Sources */ = {isa = PBXBuildFile; fileRef = E87DD6EA25D053FA00D86808 /* Progress+.swift */; };
121121
E89342FA25EDCC17007CF557 /* NotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E89342F925EDCC17007CF557 /* NotificationManager.swift */; };
@@ -310,9 +310,9 @@
310310
CAFFFEEE259CEAC400903F81 /* RingProgressViewStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RingProgressViewStyle.swift; sourceTree = "<group>"; };
311311
E81D7E9F2805250100A205FC /* Collection+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Collection+.swift"; sourceTree = "<group>"; };
312312
E832EAF72B0FBCF4001B570D /* RuntimeInstallationStepDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuntimeInstallationStepDetailView.swift; sourceTree = "<group>"; };
313+
E84B7D0C2B296A8900DBDA2B /* NavigationSplitViewWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationSplitViewWrapper.swift; sourceTree = "<group>"; };
313314
E84CF8C02B0FEB8300ECA259 /* RuntimesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuntimesView.swift; sourceTree = "<group>"; };
314315
E856BB73291EDD3D00DC438B /* XcodesKit */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = XcodesKit; path = Xcodes/XcodesKit; sourceTree = "<group>"; };
315-
E872EE4F2808D4F100D3DD8B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
316316
E87AB3C42939B65E00D72F43 /* Hardware.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Hardware.swift; sourceTree = "<group>"; };
317317
E87DD6EA25D053FA00D86808 /* Progress+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Progress+.swift"; sourceTree = "<group>"; };
318318
E89342F925EDCC17007CF557 /* NotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManager.swift; sourceTree = "<group>"; };
@@ -373,6 +373,7 @@
373373
CA452BAF259FD9770072DFA4 /* ProgressIndicator.swift */,
374374
536CFDD3263C9A8000026CE0 /* XcodesSheet.swift */,
375375
53CBAB2B263DCC9100410495 /* XcodesAlert.swift */,
376+
E84B7D0C2B296A8900DBDA2B /* NavigationSplitViewWrapper.swift */,
376377
);
377378
path = Common;
378379
sourceTree = "<group>";
@@ -921,6 +922,7 @@
921922
E8B20CBF2A2EDEC20057D816 /* SDKs+Xcode.swift in Sources */,
922923
CA9FF877259528CC00E47BAF /* Version+XcodeReleases.swift in Sources */,
923924
CABFAA2D2592FBFC00380FEE /* Configure.swift in Sources */,
925+
E84B7D0D2B296A8900DBDA2B /* NavigationSplitViewWrapper.swift in Sources */,
924926
CA73510D257BFCEF00EA9CF8 /* NSAttributedString+.swift in Sources */,
925927
CAFBDB952598FE96003DCC5A /* FocusedValues.swift in Sources */,
926928
B0403CF42AD9381D00137C09 /* SDKsView.swift in Sources */,
@@ -1040,7 +1042,7 @@
10401042
GCC_WARN_UNUSED_FUNCTION = YES;
10411043
GCC_WARN_UNUSED_VARIABLE = YES;
10421044
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
1043-
MACOSX_DEPLOYMENT_TARGET = 11.0;
1045+
MACOSX_DEPLOYMENT_TARGET = 12.0;
10441046
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
10451047
MTL_FAST_MATH = YES;
10461048
ONLY_ACTIVE_ARCH = YES;
@@ -1227,7 +1229,7 @@
12271229
GCC_WARN_UNUSED_FUNCTION = YES;
12281230
GCC_WARN_UNUSED_VARIABLE = YES;
12291231
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
1230-
MACOSX_DEPLOYMENT_TARGET = 11.0;
1232+
MACOSX_DEPLOYMENT_TARGET = 12.0;
12311233
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
12321234
MTL_FAST_MATH = YES;
12331235
ONLY_ACTIVE_ARCH = YES;
@@ -1285,7 +1287,7 @@
12851287
GCC_WARN_UNUSED_FUNCTION = YES;
12861288
GCC_WARN_UNUSED_VARIABLE = YES;
12871289
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
1288-
MACOSX_DEPLOYMENT_TARGET = 11.0;
1290+
MACOSX_DEPLOYMENT_TARGET = 12.0;
12891291
MTL_ENABLE_DEBUG_INFO = NO;
12901292
MTL_FAST_MATH = YES;
12911293
SDKROOT = macosx;
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//
2+
// NavigationSplitViewWrapper.swift
3+
// Xcodes
4+
//
5+
// Created by Matt Kiazyk on 2023-12-12.
6+
//
7+
8+
import SwiftUI
9+
10+
struct NavigationSplitViewWrapper<Sidebar, Detail>: View where Sidebar: View, Detail: View {
11+
private var sidebar: Sidebar
12+
private var detail: Detail
13+
14+
init(
15+
@ViewBuilder sidebar: () -> Sidebar,
16+
@ViewBuilder detail: () -> Detail
17+
) {
18+
self.sidebar = sidebar()
19+
self.detail = detail()
20+
}
21+
22+
var body: some View {
23+
if #available(iOS 16, macOS 13, tvOS 16, watchOS 9, visionOS 1, *) {
24+
// Use the latest API available
25+
NavigationSplitView {
26+
27+
if #available(macOS 14, *) {
28+
sidebar
29+
.toolbar(removing: .sidebarToggle)
30+
} else {
31+
sidebar
32+
}
33+
} detail: {
34+
detail
35+
}
36+
} else {
37+
// Alternative code for earlier versions of OS.
38+
NavigationView {
39+
// The first column is the sidebar.
40+
sidebar
41+
detail
42+
}
43+
.navigationViewStyle(.columns)
44+
}
45+
}
46+
}

Xcodes/Frontend/MainWindow.swift

Lines changed: 76 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import ErrorHandling
22
import SwiftUI
33
import XcodesKit
4+
import Path
5+
import Version
46

57
struct MainWindow: View {
68
@EnvironmentObject var appState: AppState
@@ -16,7 +18,7 @@ struct MainWindow: View {
1618
@AppStorage("isInstalledOnly") private var isInstalledOnly = false
1719

1820
var body: some View {
19-
HSplitView {
21+
NavigationSplitViewWrapper {
2022
XcodeListView(selectedXcodeID: $selectedXcodeID, searchText: searchText, category: category, isInstalledOnly: isInstalledOnly)
2123
.frame(minWidth: 300)
2224
.layoutPriority(1)
@@ -26,25 +28,73 @@ struct MainWindow: View {
2628
primaryButton: .destructive(Text("Uninstall"), action: { self.appState.uninstall(xcode: xcode) }),
2729
secondaryButton: .cancel(Text("Cancel")))
2830
}
29-
30-
if isShowingInfoPane {
31-
Group {
32-
if let xcode = xcode {
33-
InfoPane(xcode: xcode)
31+
.searchable(text: $searchText, placement: .sidebar)
32+
.mainToolbar(
33+
category: $category,
34+
isInstalledOnly: $isInstalledOnly,
35+
isShowingInfoPane: $isShowingInfoPane
36+
)
37+
} detail: {
38+
Group {
39+
if let xcode = xcode {
40+
InfoPane(xcode: xcode)
41+
} else {
42+
UnselectedView()
43+
}
44+
}
45+
.padding()
46+
.toolbar {
47+
ToolbarItemGroup {
48+
Button(action: { appState.presentedSheet = .signIn }, label: {
49+
Label("Login", systemImage: "person.circle")
50+
})
51+
.help("LoginDescription")
52+
if #available(macOS 14, *) {
53+
SettingsLink(label: {
54+
Label("Preferences", systemImage: "gearshape")
55+
})
56+
.help("PreferencesDescription")
3457
} else {
35-
UnselectedView()
58+
Button(action: {
59+
if #available(macOS 13, *) {
60+
NSApp.sendAction(Selector(("showSettingsWindow:")), to: nil, from: nil)
61+
} else {
62+
NSApp.sendAction(Selector(("showPreferencesWindow:")), to: nil, from: nil)
63+
}
64+
}, label: {
65+
Label("Preferences", systemImage: "gearshape")
66+
})
67+
.help("PreferencesDescription")
3668
}
3769
}
38-
.padding()
39-
.frame(minWidth: 300, maxWidth: .infinity)
4070
}
4171
}
42-
.mainToolbar(
43-
category: $category,
44-
isInstalledOnly: $isInstalledOnly,
45-
isShowingInfoPane: $isShowingInfoPane,
46-
searchText: $searchText
47-
)
72+
73+
// HSplitView {
74+
// XcodeListView(selectedXcodeID: $selectedXcodeID, searchText: searchText, category: category, isInstalledOnly: isInstalledOnly)
75+
// .frame(minWidth: 300)
76+
// .layoutPriority(1)
77+
// .alert(item: $appState.xcodeBeingConfirmedForUninstallation) { xcode in
78+
// Alert(title: Text(String(format: localizeString("Alert.Uninstall.Title"), xcode.description)),
79+
// message: Text("Alert.Uninstall.Message"),
80+
// primaryButton: .destructive(Text("Uninstall"), action: { self.appState.uninstall(xcode: xcode) }),
81+
// secondaryButton: .cancel(Text("Cancel")))
82+
// }
83+
// .searchable(text: $searchText)
84+
//
85+
// if isShowingInfoPane {
86+
// Group {
87+
// if let xcode = xcode {
88+
// InfoPane(xcode: xcode)
89+
// } else {
90+
// UnselectedView()
91+
// }
92+
// }
93+
// .padding()
94+
// .frame(minWidth: 300, maxWidth: .infinity)
95+
// }
96+
// }
97+
4898
.bottomStatusBar()
4999
.padding([.top], 0)
50100
.navigationSubtitle(subtitleText)
@@ -197,6 +247,16 @@ struct MainWindow: View {
197247

198248
struct MainWindow_Previews: PreviewProvider {
199249
static var previews: some View {
200-
MainWindow()
250+
MainWindow().environmentObject({ () -> AppState in
251+
let a = AppState()
252+
a.allXcodes = [
253+
Xcode(version: Version("12.0.0+1234A")!, identicalBuilds: [Version("12.0.0+1234A")!, Version("12.0.0-RC+1234A")!], installState: .installed(Path("/Applications/Xcode-12.3.0.app")!), selected: false, icon: nil),
254+
Xcode(version: Version("12.3.0")!, installState: .installed(Path("/Applications/Xcode-12.3.0.app")!), selected: true, icon: nil),
255+
Xcode(version: Version("12.2.0")!, installState: .notInstalled, selected: false, icon: nil),
256+
Xcode(version: Version("12.1.0")!, installState: .installing(.downloading(progress: configure(Progress(totalUnitCount: 100)) { $0.completedUnitCount = 40 })), selected: false, icon: nil),
257+
Xcode(version: Version("12.0.0")!, installState: .installed(Path("/Applications/Xcode-12.3.0.app")!), selected: false, icon: nil),
258+
]
259+
return a
260+
}())
201261
}
202262
}

Xcodes/Frontend/XcodeList/MainToolbar.swift

Lines changed: 14 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ struct MainToolbarModifier: ViewModifier {
55
@Binding var category: XcodeListCategory
66
@Binding var isInstalledOnly: Bool
77
@Binding var isShowingInfoPane: Bool
8-
@Binding var searchText: String
98

109
func body(content: Content) -> some View {
1110
content
@@ -14,10 +13,6 @@ struct MainToolbarModifier: ViewModifier {
1413

1514
private var toolbar: some ToolbarContent {
1615
ToolbarItemGroup {
17-
Button(action: { appState.presentedSheet = .signIn }, label: {
18-
Label("Login", systemImage: "person.circle")
19-
})
20-
.help("LoginDescription")
2116

2217
ProgressButton(
2318
isInProgress: appState.isUpdating,
@@ -27,7 +22,7 @@ struct MainToolbarModifier: ViewModifier {
2722
}
2823
.keyboardShortcut(KeyEquivalent("r"))
2924
.help("RefreshDescription")
30-
25+
Spacer()
3126
Button(action: {
3227
switch category {
3328
case .all: category = .release
@@ -75,39 +70,18 @@ struct MainToolbarModifier: ViewModifier {
7570
}
7671
.help("FilterInstalledDescription")
7772

78-
Button(action: { isShowingInfoPane.toggle() }) {
79-
if isShowingInfoPane {
80-
Label("Info", systemImage: "info.circle.fill")
81-
.foregroundColor(.accentColor)
82-
} else {
83-
Label("Info", systemImage: "info.circle")
84-
}
85-
}
86-
.keyboardShortcut(KeyboardShortcut("i", modifiers: [.command, .option]))
87-
.help("InfoDescription")
88-
89-
if #available(macOS 14, *) {
90-
SettingsLink(label: {
91-
Label("Preferences", systemImage: "gearshape")
92-
})
93-
.help("PreferencesDescription")
94-
} else {
95-
Button(action: {
96-
if #available(macOS 13, *) {
97-
NSApp.sendAction(Selector(("showSettingsWindow:")), to: nil, from: nil)
98-
} else {
99-
NSApp.sendAction(Selector(("showPreferencesWindow:")), to: nil, from: nil)
100-
}
101-
}, label: {
102-
Label("Preferences", systemImage: "gearshape")
103-
})
104-
.help("PreferencesDescription")
105-
}
73+
// Button(action: { isShowingInfoPane.toggle() }) {
74+
// if isShowingInfoPane {
75+
// Label("Info", systemImage: "info.circle.fill")
76+
// .foregroundColor(.accentColor)
77+
// } else {
78+
// Label("Info", systemImage: "info.circle")
79+
// }
80+
// }
81+
// .keyboardShortcut(KeyboardShortcut("i", modifiers: [.command, .option]))
82+
// .help("InfoDescription")
10683

107-
TextField("Search", text: $searchText)
108-
.textFieldStyle(RoundedBorderTextFieldStyle())
109-
.frame(width: 200)
110-
.help("SearchDescription")
84+
11185
}
11286
}
11387
}
@@ -116,15 +90,13 @@ extension View {
11690
func mainToolbar(
11791
category: Binding<XcodeListCategory>,
11892
isInstalledOnly: Binding<Bool>,
119-
isShowingInfoPane: Binding<Bool>,
120-
searchText: Binding<String>
93+
isShowingInfoPane: Binding<Bool>
12194
) -> some View {
12295
self.modifier(
12396
MainToolbarModifier(
12497
category: category,
12598
isInstalledOnly: isInstalledOnly,
126-
isShowingInfoPane: isShowingInfoPane,
127-
searchText: searchText
99+
isShowingInfoPane: isShowingInfoPane
128100
)
129101
)
130102
}

Xcodes/Frontend/XcodeList/XcodeListView.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ struct XcodeListView: View {
4242
List(visibleXcodes, selection: $selectedXcodeID) { xcode in
4343
XcodeListViewRow(xcode: xcode, selected: selectedXcodeID == xcode.id, appState: appState)
4444
}
45+
.listStyle(.sidebar)
4546
}
4647
}
4748

Xcodes/Resources/Localizable.xcstrings

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8193,6 +8193,7 @@
81938193
}
81948194
},
81958195
"Info" : {
8196+
"extractionState" : "stale",
81968197
"localizations" : {
81978198
"ca" : {
81988199
"stringUnit" : {
@@ -8299,6 +8300,7 @@
82998300
}
83008301
},
83018302
"InfoDescription" : {
8303+
"extractionState" : "stale",
83028304
"localizations" : {
83038305
"ca" : {
83048306
"stringUnit" : {
@@ -16125,6 +16127,7 @@
1612516127
}
1612616128
},
1612716129
"Search" : {
16130+
"extractionState" : "stale",
1612816131
"localizations" : {
1612916132
"ca" : {
1613016133
"stringUnit" : {
@@ -16237,6 +16240,7 @@
1623716240
}
1623816241
},
1623916242
"SearchDescription" : {
16243+
"extractionState" : "stale",
1624016244
"localizations" : {
1624116245
"ca" : {
1624216246
"stringUnit" : {

0 commit comments

Comments
 (0)