Skip to content

Commit 3c5f860

Browse files
authored
Merge pull request #461 from XcodesOrg/matt/redesign
Redesign the main window to better suit more data
2 parents c85b3c2 + cd69ddc commit 3c5f860

22 files changed

Lines changed: 519 additions & 222 deletions

Xcodes.xcodeproj/project.pbxproj

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,9 @@
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-
E84CF8C12B0FEB8300ECA259 /* RuntimesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E84CF8C02B0FEB8300ECA259 /* RuntimesView.swift */; };
118-
E872EE4E2808D4F100D3DD8B /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = E872EE502808D4F100D3DD8B /* Localizable.strings */; };
117+
E84B7D0D2B296A8900DBDA2B /* NavigationSplitViewWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = E84B7D0C2B296A8900DBDA2B /* NavigationSplitViewWrapper.swift */; };
118+
E84E4F522B323A5F003F3959 /* CornerRadiusModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = E84E4F512B323A5F003F3959 /* CornerRadiusModifier.swift */; };
119+
E86671272B309D2F0048559A /* PlatformsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E86671262B309D2F0048559A /* PlatformsView.swift */; };
119120
E87AB3C52939B65E00D72F43 /* Hardware.swift in Sources */ = {isa = PBXBuildFile; fileRef = E87AB3C42939B65E00D72F43 /* Hardware.swift */; };
120121
E87DD6EB25D053FA00D86808 /* Progress+.swift in Sources */ = {isa = PBXBuildFile; fileRef = E87DD6EA25D053FA00D86808 /* Progress+.swift */; };
121122
E89342FA25EDCC17007CF557 /* NotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E89342F925EDCC17007CF557 /* NotificationManager.swift */; };
@@ -310,9 +311,10 @@
310311
CAFFFEEE259CEAC400903F81 /* RingProgressViewStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RingProgressViewStyle.swift; sourceTree = "<group>"; };
311312
E81D7E9F2805250100A205FC /* Collection+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Collection+.swift"; sourceTree = "<group>"; };
312313
E832EAF72B0FBCF4001B570D /* RuntimeInstallationStepDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuntimeInstallationStepDetailView.swift; sourceTree = "<group>"; };
313-
E84CF8C02B0FEB8300ECA259 /* RuntimesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuntimesView.swift; sourceTree = "<group>"; };
314+
E84B7D0C2B296A8900DBDA2B /* NavigationSplitViewWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationSplitViewWrapper.swift; sourceTree = "<group>"; };
315+
E84E4F512B323A5F003F3959 /* CornerRadiusModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CornerRadiusModifier.swift; sourceTree = "<group>"; };
314316
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>"; };
317+
E86671262B309D2F0048559A /* PlatformsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlatformsView.swift; sourceTree = "<group>"; };
316318
E87AB3C42939B65E00D72F43 /* Hardware.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Hardware.swift; sourceTree = "<group>"; };
317319
E87DD6EA25D053FA00D86808 /* Progress+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Progress+.swift"; sourceTree = "<group>"; };
318320
E89342F925EDCC17007CF557 /* NotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManager.swift; sourceTree = "<group>"; };
@@ -373,6 +375,7 @@
373375
CA452BAF259FD9770072DFA4 /* ProgressIndicator.swift */,
374376
536CFDD3263C9A8000026CE0 /* XcodesSheet.swift */,
375377
53CBAB2B263DCC9100410495 /* XcodesAlert.swift */,
378+
E84B7D0C2B296A8900DBDA2B /* NavigationSplitViewWrapper.swift */,
376379
);
377380
path = Common;
378381
sourceTree = "<group>";
@@ -646,7 +649,8 @@
646649
B0C6AD0A2AD9178E00E64698 /* IdenticalBuildView.swift */,
647650
B0C6AD0C2AD91D7900E64698 /* IconView.swift */,
648651
E832EAF72B0FBCF4001B570D /* RuntimeInstallationStepDetailView.swift */,
649-
E84CF8C02B0FEB8300ECA259 /* RuntimesView.swift */,
652+
E86671262B309D2F0048559A /* PlatformsView.swift */,
653+
E84E4F512B323A5F003F3959 /* CornerRadiusModifier.swift */,
650654
);
651655
path = InfoPane;
652656
sourceTree = "<group>";
@@ -868,7 +872,6 @@
868872
CA9FF8CF25959A9700E47BAF /* HelperXPCShared.swift in Sources */,
869873
CA735109257BF96D00EA9CF8 /* AttributedText.swift in Sources */,
870874
CAFBDC4E2599B33D003DCC5A /* MainToolbar.swift in Sources */,
871-
E84CF8C12B0FEB8300ECA259 /* RuntimesView.swift in Sources */,
872875
CA11E7BA2598476C00D2EE1C /* XcodeCommands.swift in Sources */,
873876
CAA8589B25A2B83000ACF8C0 /* Aria2CError.swift in Sources */,
874877
536CFDD2263C94DE00026CE0 /* SignedInView.swift in Sources */,
@@ -897,6 +900,7 @@
897900
B0403CFC2AD9A6BF00137C09 /* InstalledStateButtons.swift in Sources */,
898901
36741BFF291E50F500A85AAE /* FileError.swift in Sources */,
899902
CA9FF8872595607900E47BAF /* InstalledXcode.swift in Sources */,
903+
E84E4F522B323A5F003F3959 /* CornerRadiusModifier.swift in Sources */,
900904
B0403CF22AD934B600137C09 /* CompatibilityView.swift in Sources */,
901905
B0403CFE2ADA712C00137C09 /* InfoPaneControls.swift in Sources */,
902906
53CBAB2C263DCC9100410495 /* XcodesAlert.swift in Sources */,
@@ -910,6 +914,7 @@
910914
CABFA9C12592EEEA00380FEE /* Version+.swift in Sources */,
911915
E8D655C0288DD04700A139C2 /* SelectedActionType.swift in Sources */,
912916
36741BFD291E4FDB00A85AAE /* DownloadPreferencePane.swift in Sources */,
917+
E86671272B309D2F0048559A /* PlatformsView.swift in Sources */,
913918
CA9FF8522595080100E47BAF /* AcknowledgementsView.swift in Sources */,
914919
CABFA9CE2592EEEA00380FEE /* Version+Xcode.swift in Sources */,
915920
CAFBDB912598FE80003DCC5A /* SelectedXcode.swift in Sources */,
@@ -921,6 +926,7 @@
921926
E8B20CBF2A2EDEC20057D816 /* SDKs+Xcode.swift in Sources */,
922927
CA9FF877259528CC00E47BAF /* Version+XcodeReleases.swift in Sources */,
923928
CABFAA2D2592FBFC00380FEE /* Configure.swift in Sources */,
929+
E84B7D0D2B296A8900DBDA2B /* NavigationSplitViewWrapper.swift in Sources */,
924930
CA73510D257BFCEF00EA9CF8 /* NSAttributedString+.swift in Sources */,
925931
CAFBDB952598FE96003DCC5A /* FocusedValues.swift in Sources */,
926932
B0403CF42AD9381D00137C09 /* SDKsView.swift in Sources */,
@@ -1040,7 +1046,7 @@
10401046
GCC_WARN_UNUSED_FUNCTION = YES;
10411047
GCC_WARN_UNUSED_VARIABLE = YES;
10421048
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
1043-
MACOSX_DEPLOYMENT_TARGET = 11.0;
1049+
MACOSX_DEPLOYMENT_TARGET = 12.0;
10441050
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
10451051
MTL_FAST_MATH = YES;
10461052
ONLY_ACTIVE_ARCH = YES;
@@ -1227,7 +1233,7 @@
12271233
GCC_WARN_UNUSED_FUNCTION = YES;
12281234
GCC_WARN_UNUSED_VARIABLE = YES;
12291235
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
1230-
MACOSX_DEPLOYMENT_TARGET = 11.0;
1236+
MACOSX_DEPLOYMENT_TARGET = 12.0;
12311237
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
12321238
MTL_FAST_MATH = YES;
12331239
ONLY_ACTIVE_ARCH = YES;
@@ -1285,7 +1291,7 @@
12851291
GCC_WARN_UNUSED_FUNCTION = YES;
12861292
GCC_WARN_UNUSED_VARIABLE = YES;
12871293
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
1288-
MACOSX_DEPLOYMENT_TARGET = 11.0;
1294+
MACOSX_DEPLOYMENT_TARGET = 12.0;
12891295
MTL_ENABLE_DEBUG_INFO = NO;
12901296
MTL_FAST_MATH = YES;
12911297
SDKROOT = macosx;

Xcodes/Backend/AppState+Runtimes.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ extension AppState {
3636
Task {
3737
do {
3838
let runtimes = try await self.runtimeService.localInstalledRuntimes()
39+
3940
DispatchQueue.main.async {
4041
self.installedRuntimes = runtimes
4142
}

Xcodes/Backend/AppState.swift

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,6 @@ class AppState: ObservableObject {
163163
checkIfHelperIsInstalled()
164164
setupAutoInstallTimer()
165165
setupDefaults()
166-
updateInstalledRuntimes()
167166
}
168167

169168
func setupDefaults() {
@@ -410,10 +409,7 @@ class AppState: ObservableObject {
410409

411410
// Check to see if users MacOS is supported
412411
if let requiredMacOSVersion = availableXcode.requiredMacOSVersion {
413-
let split = requiredMacOSVersion.components(separatedBy: ".").compactMap { Int($0) }
414-
let xcodeMinimumMacOSVersion = OperatingSystemVersion(majorVersion: split[safe: 0] ?? 0, minorVersion: split[safe: 1] ?? 0, patchVersion: split[safe: 2] ?? 0)
415-
416-
if !ProcessInfo.processInfo.isOperatingSystemAtLeast(xcodeMinimumMacOSVersion) {
412+
if hasMinSupportedOS(requiredMacOSVersion: requiredMacOSVersion) {
417413
// prompt
418414
self.presentedAlert = .checkMinSupportedVersion(xcode: availableXcode, macOS: ProcessInfo.processInfo.operatingSystemVersion.versionString())
419415
return
@@ -428,6 +424,13 @@ class AppState: ObservableObject {
428424
}
429425
}
430426

427+
func hasMinSupportedOS(requiredMacOSVersion: String) -> Bool {
428+
let split = requiredMacOSVersion.components(separatedBy: ".").compactMap { Int($0) }
429+
let xcodeMinimumMacOSVersion = OperatingSystemVersion(majorVersion: split[safe: 0] ?? 0, minorVersion: split[safe: 1] ?? 0, patchVersion: split[safe: 2] ?? 0)
430+
431+
return !ProcessInfo.processInfo.isOperatingSystemAtLeast(xcodeMinimumMacOSVersion)
432+
}
433+
431434
func install(id: Xcode.ID) {
432435
guard let availableXcode = availableXcodes.first(where: { $0.version == id }) else { return }
433436

Xcodes/Backend/SDKs+Xcode.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
import Foundation
1010
import struct XCModel.SDKs
11+
import XcodesKit
12+
import SwiftUI
1113

1214
extension SDKs {
1315
/// Loops through all SDK's and returns an array of buildNumbers (to be used to correlate runtimes)
@@ -33,3 +35,24 @@ extension SDKs {
3335
return buildNumbers
3436
}
3537
}
38+
39+
extension DownloadableRuntime {
40+
func icon() -> Image {
41+
switch self.platform {
42+
case .iOS:
43+
return Image(systemName: "iphone")
44+
case .macOS:
45+
return Image(systemName: "macwindow")
46+
case .watchOS:
47+
return Image(systemName: "applewatch")
48+
case .tvOS:
49+
return Image(systemName: "appletv")
50+
case .visionOS:
51+
if #available(macOS 14, *) {
52+
return Image(systemName: "visionpro")
53+
} else {
54+
return Image(systemName: "eyeglasses")
55+
}
56+
}
57+
}
58+
}

Xcodes/Backend/XcodeCommands.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,10 @@ struct CancelInstallButton: View {
6161

6262
var body: some View {
6363
Button(action: cancelInstall) {
64-
Text("Cancel")
65-
.help(localizeString("StopInstallation"))
64+
Image(systemName: "xmark.circle.fill")
6665
}
66+
.help(localizeString("StopInstallation"))
67+
.buttonStyle(.plain)
6768
}
6869

6970
private func cancelInstall() {
@@ -78,9 +79,9 @@ struct CancelRuntimeInstallButton: View {
7879

7980
var body: some View {
8081
Button(action: cancelInstall) {
81-
Text("Cancel")
82-
.help(localizeString("StopInstallation"))
83-
}
82+
Image(systemName: "xmark.circle.fill")
83+
}.help(localizeString("StopInstallation"))
84+
.buttonStyle(.plain)
8485
}
8586

8687
private func cancelInstall() {
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/InfoPane/CompatibilityView.swift

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,27 @@
99
import SwiftUI
1010

1111
struct CompatibilityView: View {
12+
@EnvironmentObject var appState: AppState
13+
1214
let requiredMacOSVersion: String?
1315

1416
var body: some View {
1517
if let requiredMacOSVersion = requiredMacOSVersion {
16-
VStack(alignment: .leading) {
17-
Text("Compatibility")
18-
.font(.headline)
19-
Text(String(format: localizeString("MacOSRequirement"), requiredMacOSVersion))
20-
.font(.subheadline)
18+
HStack(alignment: .top){
19+
VStack(alignment: .leading) {
20+
Text("Compatibility")
21+
.font(.headline)
22+
Text(String(format: localizeString("MacOSRequirement"), requiredMacOSVersion))
23+
.font(.subheadline)
24+
.foregroundColor(appState.hasMinSupportedOS(requiredMacOSVersion: requiredMacOSVersion) ? .red : .primary)
25+
}
26+
Spacer()
27+
if appState.hasMinSupportedOS(requiredMacOSVersion: requiredMacOSVersion) {
28+
Image(systemName: "exclamationmark.triangle.fill")
29+
.font(.largeTitle)
30+
}
2131
}
32+
.xcodesBackground()
2233
} else {
2334
EmptyView()
2435
}
@@ -28,4 +39,5 @@ struct CompatibilityView: View {
2839
#Preview {
2940
CompatibilityView(requiredMacOSVersion: "10.15.4")
3041
.padding()
42+
.environmentObject(AppState())
3143
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//
2+
// CornerRadiusModifier.swift
3+
// Xcodes
4+
//
5+
// Created by Matt Kiazyk on 2023-12-19.
6+
//
7+
8+
import Foundation
9+
import SwiftUI
10+
11+
struct CornerRadiusModifier: ViewModifier {
12+
func body(content: Content) -> some View {
13+
content
14+
.frame(maxWidth: .infinity, alignment: .leading)
15+
.padding()
16+
.background(.background)
17+
.clipShape(RoundedRectangle(cornerRadius: 5, style: .continuous))
18+
}
19+
}
20+
21+
extension View {
22+
func xcodesBackground() -> some View {
23+
self.modifier(
24+
CornerRadiusModifier()
25+
)
26+
}
27+
}
28+
29+
struct Previews_CornerRadius_Previews: PreviewProvider {
30+
static var previews: some View {
31+
HStack {
32+
Text("XCODES RULES!")
33+
}.xcodesBackground()
34+
}
35+
}

Xcodes/Frontend/InfoPane/IdenticalBuildView.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ struct IdenticalBuildsView: View {
3333
.font(.subheadline)
3434
}
3535
}
36+
.xcodesBackground()
3637
.accessibilityElement()
3738
.accessibility(label: Text("IdenticalBuilds"))
3839
.accessibility(value: Text(accessibilityDescription))

0 commit comments

Comments
 (0)