Skip to content

Commit ede9bd1

Browse files
committed
redesigned infoPane
1 parent 7070575 commit ede9bd1

19 files changed

Lines changed: 485 additions & 68 deletions

Xcodes.xcodeproj/project.pbxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,9 @@
115115
E81D7EA02805250100A205FC /* Collection+.swift in Sources */ = {isa = PBXBuildFile; fileRef = E81D7E9F2805250100A205FC /* Collection+.swift */; };
116116
E832EAF82B0FBCF4001B570D /* RuntimeInstallationStepDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E832EAF72B0FBCF4001B570D /* RuntimeInstallationStepDetailView.swift */; };
117117
E84B7D0D2B296A8900DBDA2B /* NavigationSplitViewWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = E84B7D0C2B296A8900DBDA2B /* NavigationSplitViewWrapper.swift */; };
118+
E84B7D0F2B30986700DBDA2B /* InfoPane2.swift in Sources */ = {isa = PBXBuildFile; fileRef = E84B7D0E2B30986700DBDA2B /* InfoPane2.swift */; };
118119
E84CF8C12B0FEB8300ECA259 /* RuntimesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E84CF8C02B0FEB8300ECA259 /* RuntimesView.swift */; };
120+
E86671272B309D2F0048559A /* PlatformsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E86671262B309D2F0048559A /* PlatformsView.swift */; };
119121
E87AB3C52939B65E00D72F43 /* Hardware.swift in Sources */ = {isa = PBXBuildFile; fileRef = E87AB3C42939B65E00D72F43 /* Hardware.swift */; };
120122
E87DD6EB25D053FA00D86808 /* Progress+.swift in Sources */ = {isa = PBXBuildFile; fileRef = E87DD6EA25D053FA00D86808 /* Progress+.swift */; };
121123
E89342FA25EDCC17007CF557 /* NotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E89342F925EDCC17007CF557 /* NotificationManager.swift */; };
@@ -311,8 +313,10 @@
311313
E81D7E9F2805250100A205FC /* Collection+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Collection+.swift"; sourceTree = "<group>"; };
312314
E832EAF72B0FBCF4001B570D /* RuntimeInstallationStepDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuntimeInstallationStepDetailView.swift; sourceTree = "<group>"; };
313315
E84B7D0C2B296A8900DBDA2B /* NavigationSplitViewWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationSplitViewWrapper.swift; sourceTree = "<group>"; };
316+
E84B7D0E2B30986700DBDA2B /* InfoPane2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoPane2.swift; sourceTree = "<group>"; };
314317
E84CF8C02B0FEB8300ECA259 /* RuntimesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuntimesView.swift; sourceTree = "<group>"; };
315318
E856BB73291EDD3D00DC438B /* XcodesKit */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = XcodesKit; path = Xcodes/XcodesKit; sourceTree = "<group>"; };
319+
E86671262B309D2F0048559A /* PlatformsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlatformsView.swift; sourceTree = "<group>"; };
316320
E87AB3C42939B65E00D72F43 /* Hardware.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Hardware.swift; sourceTree = "<group>"; };
317321
E87DD6EA25D053FA00D86808 /* Progress+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Progress+.swift"; sourceTree = "<group>"; };
318322
E89342F925EDCC17007CF557 /* NotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManager.swift; sourceTree = "<group>"; };
@@ -648,6 +652,8 @@
648652
B0C6AD0C2AD91D7900E64698 /* IconView.swift */,
649653
E832EAF72B0FBCF4001B570D /* RuntimeInstallationStepDetailView.swift */,
650654
E84CF8C02B0FEB8300ECA259 /* RuntimesView.swift */,
655+
E84B7D0E2B30986700DBDA2B /* InfoPane2.swift */,
656+
E86671262B309D2F0048559A /* PlatformsView.swift */,
651657
);
652658
path = InfoPane;
653659
sourceTree = "<group>";
@@ -911,6 +917,7 @@
911917
CABFA9C12592EEEA00380FEE /* Version+.swift in Sources */,
912918
E8D655C0288DD04700A139C2 /* SelectedActionType.swift in Sources */,
913919
36741BFD291E4FDB00A85AAE /* DownloadPreferencePane.swift in Sources */,
920+
E86671272B309D2F0048559A /* PlatformsView.swift in Sources */,
914921
CA9FF8522595080100E47BAF /* AcknowledgementsView.swift in Sources */,
915922
CABFA9CE2592EEEA00380FEE /* Version+Xcode.swift in Sources */,
916923
CAFBDB912598FE80003DCC5A /* SelectedXcode.swift in Sources */,
@@ -922,6 +929,7 @@
922929
E8B20CBF2A2EDEC20057D816 /* SDKs+Xcode.swift in Sources */,
923930
CA9FF877259528CC00E47BAF /* Version+XcodeReleases.swift in Sources */,
924931
CABFAA2D2592FBFC00380FEE /* Configure.swift in Sources */,
932+
E84B7D0F2B30986700DBDA2B /* InfoPane2.swift in Sources */,
925933
E84B7D0D2B296A8900DBDA2B /* NavigationSplitViewWrapper.swift in Sources */,
926934
CA73510D257BFCEF00EA9CF8 /* NSAttributedString+.swift in Sources */,
927935
CAFBDB952598FE96003DCC5A /* FocusedValues.swift in Sources */,

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

Xcodes/Frontend/InfoPane/CompatibilityView.swift

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,30 @@
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+
.frame(maxWidth: .infinity, alignment: .leading)
33+
.padding()
34+
.background(.background)
35+
.clipShape(RoundedRectangle(cornerRadius: 5, style: .continuous))
2236
} else {
2337
EmptyView()
2438
}
@@ -28,4 +42,5 @@ struct CompatibilityView: View {
2842
#Preview {
2943
CompatibilityView(requiredMacOSVersion: "10.15.4")
3044
.padding()
45+
.environmentObject(AppState())
3146
}

Xcodes/Frontend/InfoPane/IdenticalBuildView.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ struct IdenticalBuildsView: View {
3333
.font(.subheadline)
3434
}
3535
}
36+
.frame(maxWidth: .infinity, alignment: .leading)
37+
.padding()
38+
.background(.background)
39+
.clipShape(RoundedRectangle(cornerRadius: 5, style: .continuous))
3640
.accessibilityElement()
3741
.accessibility(label: Text("IdenticalBuilds"))
3842
.accessibility(value: Text(accessibilityDescription))

Xcodes/Frontend/InfoPane/InfoPane.swift

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import AppKit
2+
import XcodesKit
23
import Path
34
import SwiftUI
45
import Version
@@ -23,7 +24,7 @@ struct InfoPane: View {
2324

2425
Group {
2526
RuntimesView(xcode: xcode)
26-
ReleaseDateView(date: xcode.releaseDate)
27+
ReleaseDateView(date: xcode.releaseDate, url: xcode.releaseNotesURL)
2728
ReleaseNotesView(url: xcode.releaseNotesURL)
2829
IdenticalBuildsView(builds: xcode.identicalBuilds)
2930
CompatibilityView(requiredMacOSVersion: xcode.requiredMacOSVersion)
@@ -37,14 +38,14 @@ struct InfoPane: View {
3738
}
3839
}
3940

40-
#Preview(PreviewName.allCases[0].rawValue) { makePreviewContent(for: 0) }
41-
#Preview(PreviewName.allCases[1].rawValue) { makePreviewContent(for: 1) }
42-
#Preview(PreviewName.allCases[2].rawValue) { makePreviewContent(for: 2) }
43-
#Preview(PreviewName.allCases[3].rawValue) { makePreviewContent(for: 3) }
44-
#Preview(PreviewName.allCases[4].rawValue) { makePreviewContent(for: 4) }
41+
#Preview(XcodePreviewName.allCases[0].rawValue) { makePreviewContent(for: 0) }
42+
#Preview(XcodePreviewName.allCases[1].rawValue) { makePreviewContent(for: 1) }
43+
#Preview(XcodePreviewName.allCases[2].rawValue) { makePreviewContent(for: 2) }
44+
#Preview(XcodePreviewName.allCases[3].rawValue) { makePreviewContent(for: 3) }
45+
#Preview(XcodePreviewName.allCases[4].rawValue) { makePreviewContent(for: 4) }
4546

4647
private func makePreviewContent(for index: Int) -> some View {
47-
let name = PreviewName.allCases[index]
48+
let name = XcodePreviewName.allCases[index]
4849
return InfoPane(xcode: xcodeDict[name]!)
4950
.environmentObject(configure(AppState()) {
5051
$0.allXcodes = [xcodeDict[name]!]
@@ -53,17 +54,17 @@ private func makePreviewContent(for index: Int) -> some View {
5354
.padding()
5455
}
5556

56-
enum PreviewName: String, CaseIterable, Identifiable {
57+
enum XcodePreviewName: String, CaseIterable, Identifiable {
5758
case Populated_Installed_Selected
5859
case Populated_Installed_Unselected
5960
case Populated_Uninstalled
6061
case Basic_Installed
6162
case Basic_Installing
6263

63-
var id: PreviewName { self }
64+
var id: XcodePreviewName { self }
6465
}
6566

66-
var xcodeDict: [PreviewName: Xcode] = [
67+
var xcodeDict: [XcodePreviewName: Xcode] = [
6768
.Populated_Installed_Selected: .init(
6869
version: _versionNoMeta,
6970
installState: .installed(Path(_path)!),
@@ -121,15 +122,48 @@ var xcodeDict: [PreviewName: Xcode] = [
121122
),
122123
]
123124

125+
var downloadableRuntimes: [DownloadableRuntime] = {
126+
var runtimes = try! JSONDecoder().decode([DownloadableRuntime].self, from: Current.files.contents(atPath: Path.runtimeCacheFile.string)!)
127+
// set iOS to installed
128+
let iOSIndex = runtimes.firstIndex { $0.sdkBuildUpdate == "19E239" }!
129+
var iOSRuntime = runtimes[iOSIndex]
130+
iOSRuntime.installState = .installed
131+
runtimes[iOSIndex] = iOSRuntime
132+
133+
let watchOSIndex = runtimes.firstIndex { $0.sdkBuildUpdate == "20R362" }!
134+
var runtime = runtimes[watchOSIndex]
135+
runtime.installState = .installing(
136+
RuntimeInstallationStep.downloading(
137+
progress:configure(Progress()) {
138+
$0.kind = .file
139+
$0.fileOperationKind = .downloading
140+
$0.estimatedTimeRemaining = 123
141+
$0.totalUnitCount = 11_944_848_484
142+
$0.completedUnitCount = 848_444_920
143+
$0.throughput = 9_211_681
144+
}
145+
)
146+
)
147+
runtimes[watchOSIndex] = runtime
148+
149+
return runtimes
150+
}()
151+
152+
var installedRuntimes: [CoreSimulatorImage] = {
153+
[CoreSimulatorImage(uuid: "85B22F5B-048B-4331-B6E2-F4196D8B7475", path: ["relative" : "file:///Library/Developer/CoreSimulator/Images/85B22F5B-048B-4331-B6E2-F4196D8B7475.dmg"], runtimeInfo: CoreSimulatorRuntimeInfo(build: "19E240"))] // same as iOS in _SDK's
154+
}()
155+
156+
124157
private let _versionNoMeta = Version(major: 12, minor: 3, patch: 0)
125158
private let _versionWithMeta = Version(major: 12, minor: 3, patch: 1, buildMetadataIdentifiers: ["1234A"])
126159
private let _path = "/Applications/Xcode-12.3.0.app"
127160
private let _requiredMacOSVersion = "10.15.4"
128161
private let _sdks = SDKs(
129162
macOS: .init(number: "11.1"),
130-
iOS: .init(number: "14.3"),
131-
watchOS: .init(number: "7.3"),
132-
tvOS: .init(number: "14.3")
163+
iOS: .init(number: "15.4", "19E239"),
164+
watchOS: .init(number: "7.3", "20R362"),
165+
tvOS: .init(number: "14.3", "20K67"),
166+
visionOS: .init(number: "1.0", "21N5233e")
133167
)
134168
private let _compilers = Compilers(
135169
gcc: .init(number: "4"),

0 commit comments

Comments
 (0)