Skip to content

Commit efcf650

Browse files
authored
Merge pull request #463 from XcodesOrg/matt/platformsList
Add new Platforms List Window
2 parents 39f3921 + 7167c40 commit efcf650

20 files changed

Lines changed: 543 additions & 73 deletions

File tree

Xcodes.xcodeproj/project.pbxproj

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@
116116
E832EAF82B0FBCF4001B570D /* RuntimeInstallationStepDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E832EAF72B0FBCF4001B570D /* RuntimeInstallationStepDetailView.swift */; };
117117
E84B7D0D2B296A8900DBDA2B /* NavigationSplitViewWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = E84B7D0C2B296A8900DBDA2B /* NavigationSplitViewWrapper.swift */; };
118118
E84E4F522B323A5F003F3959 /* CornerRadiusModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = E84E4F512B323A5F003F3959 /* CornerRadiusModifier.swift */; };
119+
E84E4F542B333864003F3959 /* PlatformsListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E84E4F532B333864003F3959 /* PlatformsListView.swift */; };
120+
E84E4F572B335094003F3959 /* OrderedCollections in Frameworks */ = {isa = PBXBuildFile; productRef = E84E4F562B335094003F3959 /* OrderedCollections */; };
119121
E86671272B309D2F0048559A /* PlatformsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E86671262B309D2F0048559A /* PlatformsView.swift */; };
120122
E87AB3C52939B65E00D72F43 /* Hardware.swift in Sources */ = {isa = PBXBuildFile; fileRef = E87AB3C42939B65E00D72F43 /* Hardware.swift */; };
121123
E87DD6EB25D053FA00D86808 /* Progress+.swift in Sources */ = {isa = PBXBuildFile; fileRef = E87DD6EA25D053FA00D86808 /* Progress+.swift */; };
@@ -313,6 +315,7 @@
313315
E832EAF72B0FBCF4001B570D /* RuntimeInstallationStepDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuntimeInstallationStepDetailView.swift; sourceTree = "<group>"; };
314316
E84B7D0C2B296A8900DBDA2B /* NavigationSplitViewWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationSplitViewWrapper.swift; sourceTree = "<group>"; };
315317
E84E4F512B323A5F003F3959 /* CornerRadiusModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CornerRadiusModifier.swift; sourceTree = "<group>"; };
318+
E84E4F532B333864003F3959 /* PlatformsListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlatformsListView.swift; sourceTree = "<group>"; };
316319
E856BB73291EDD3D00DC438B /* XcodesKit */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = XcodesKit; path = Xcodes/XcodesKit; sourceTree = "<group>"; };
317320
E86671262B309D2F0048559A /* PlatformsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlatformsView.swift; sourceTree = "<group>"; };
318321
E87AB3C42939B65E00D72F43 /* Hardware.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Hardware.swift; sourceTree = "<group>"; };
@@ -352,6 +355,7 @@
352355
E8FD5727291EE4AC001E004C /* AsyncNetworkService in Frameworks */,
353356
CAA1CB2D255A5262003FD669 /* AppleAPI in Frameworks */,
354357
CABFA9EE2592F0CC00380FEE /* SwiftSoup in Frameworks */,
358+
E84E4F572B335094003F3959 /* OrderedCollections in Frameworks */,
355359
E8F44A1E296B4CD7002D6592 /* Path in Frameworks */,
356360
);
357361
runOnlyForDeploymentPostprocessing = 0;
@@ -628,6 +632,7 @@
628632
E8977EA225C11E1500835F80 /* PreferencesView.swift */,
629633
E8DA461025FAF7FB002E85EF /* NotificationsView.swift */,
630634
E8CBDB8A27AE02FF00B22292 /* ExperiementsPreferencePane.swift */,
635+
E84E4F532B333864003F3959 /* PlatformsListView.swift */,
631636
);
632637
path = Preferences;
633638
sourceTree = "<group>";
@@ -705,6 +710,7 @@
705710
E8FD5726291EE4AC001E004C /* AsyncNetworkService */,
706711
E8C0EB19291EF43E0081528A /* XcodesKit */,
707712
E8F44A1D296B4CD7002D6592 /* Path */,
713+
E84E4F562B335094003F3959 /* OrderedCollections */,
708714
);
709715
productName = XcodesMac;
710716
productReference = CAD2E79E2449574E00113D76 /* Xcodes.app */;
@@ -791,6 +797,7 @@
791797
E689540125BE8C64000EBCEA /* XCRemoteSwiftPackageReference "DockProgress" */,
792798
E8FD5725291EE4AC001E004C /* XCRemoteSwiftPackageReference "AsyncHTTPNetworkService" */,
793799
E8F44A1C296B4CD7002D6592 /* XCRemoteSwiftPackageReference "Path" */,
800+
E84E4F552B335094003F3959 /* XCRemoteSwiftPackageReference "swift-collections" */,
794801
);
795802
productRefGroup = CAD2E79F2449574E00113D76 /* Products */;
796803
projectDirPath = "";
@@ -914,6 +921,7 @@
914921
CABFA9C12592EEEA00380FEE /* Version+.swift in Sources */,
915922
E8D655C0288DD04700A139C2 /* SelectedActionType.swift in Sources */,
916923
36741BFD291E4FDB00A85AAE /* DownloadPreferencePane.swift in Sources */,
924+
E84E4F542B333864003F3959 /* PlatformsListView.swift in Sources */,
917925
E86671272B309D2F0048559A /* PlatformsView.swift in Sources */,
918926
CA9FF8522595080100E47BAF /* AcknowledgementsView.swift in Sources */,
919927
CABFA9CE2592EEEA00380FEE /* Version+Xcode.swift in Sources */,
@@ -1075,6 +1083,7 @@
10751083
"$(inherited)",
10761084
"@executable_path/../Frameworks",
10771085
);
1086+
MACOSX_DEPLOYMENT_TARGET = 13.0;
10781087
MARKETING_VERSION = 1.10.0;
10791088
PRODUCT_BUNDLE_IDENTIFIER = com.xcodesorg.xcodesapp;
10801089
PRODUCT_NAME = Xcodes;
@@ -1098,6 +1107,7 @@
10981107
"@executable_path/../Frameworks",
10991108
"@loader_path/../Frameworks",
11001109
);
1110+
MACOSX_DEPLOYMENT_TARGET = 13.0;
11011111
PRODUCT_BUNDLE_IDENTIFIER = com.robotsandpencils.XcodesAppTests;
11021112
PRODUCT_NAME = "$(TARGET_NAME)";
11031113
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -1318,6 +1328,7 @@
13181328
"$(inherited)",
13191329
"@executable_path/../Frameworks",
13201330
);
1331+
MACOSX_DEPLOYMENT_TARGET = 13.0;
13211332
MARKETING_VERSION = 1.10.0;
13221333
PRODUCT_BUNDLE_IDENTIFIER = com.xcodesorg.xcodesapp;
13231334
PRODUCT_NAME = Xcodes;
@@ -1342,6 +1353,7 @@
13421353
"$(inherited)",
13431354
"@executable_path/../Frameworks",
13441355
);
1356+
MACOSX_DEPLOYMENT_TARGET = 13.0;
13451357
MARKETING_VERSION = 1.10.0;
13461358
PRODUCT_BUNDLE_IDENTIFIER = com.xcodesorg.xcodesapp;
13471359
PRODUCT_NAME = Xcodes;
@@ -1363,6 +1375,7 @@
13631375
"@executable_path/../Frameworks",
13641376
"@loader_path/../Frameworks",
13651377
);
1378+
MACOSX_DEPLOYMENT_TARGET = 13.0;
13661379
PRODUCT_BUNDLE_IDENTIFIER = com.robotsandpencils.XcodesAppTests;
13671380
PRODUCT_NAME = "$(TARGET_NAME)";
13681381
SWIFT_VERSION = 5.0;
@@ -1384,6 +1397,7 @@
13841397
"@executable_path/../Frameworks",
13851398
"@loader_path/../Frameworks",
13861399
);
1400+
MACOSX_DEPLOYMENT_TARGET = 13.0;
13871401
PRODUCT_BUNDLE_IDENTIFIER = com.robotsandpencils.XcodesAppTests;
13881402
PRODUCT_NAME = "$(TARGET_NAME)";
13891403
SWIFT_VERSION = 5.0;
@@ -1501,6 +1515,14 @@
15011515
minimumVersion = 3.2.0;
15021516
};
15031517
};
1518+
E84E4F552B335094003F3959 /* XCRemoteSwiftPackageReference "swift-collections" */ = {
1519+
isa = XCRemoteSwiftPackageReference;
1520+
repositoryURL = "https://github.com/apple/swift-collections.git";
1521+
requirement = {
1522+
kind = upToNextMajorVersion;
1523+
minimumVersion = 1.0.5;
1524+
};
1525+
};
15041526
E8F44A1C296B4CD7002D6592 /* XCRemoteSwiftPackageReference "Path" */ = {
15051527
isa = XCRemoteSwiftPackageReference;
15061528
repositoryURL = "https://github.com/mxcl/Path.swift";
@@ -1572,6 +1594,11 @@
15721594
package = E689540125BE8C64000EBCEA /* XCRemoteSwiftPackageReference "DockProgress" */;
15731595
productName = DockProgress;
15741596
};
1597+
E84E4F562B335094003F3959 /* OrderedCollections */ = {
1598+
isa = XCSwiftPackageProductDependency;
1599+
package = E84E4F552B335094003F3959 /* XCRemoteSwiftPackageReference "swift-collections" */;
1600+
productName = OrderedCollections;
1601+
};
15751602
E8C0EB19291EF43E0081528A /* XcodesKit */ = {
15761603
isa = XCSwiftPackageProductDependency;
15771604
productName = XcodesKit;

Xcodes.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Xcodes/Backend/AppState+Install.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -500,12 +500,13 @@ extension AppState {
500500
}
501501
}
502502

503-
func setInstallationStep(of runtime: DownloadableRuntime, to step: RuntimeInstallationStep) {
503+
func setInstallationStep(of runtime: DownloadableRuntime, to step: RuntimeInstallationStep, postNotification: Bool = true) {
504504
DispatchQueue.main.async {
505505
guard let index = self.downloadableRuntimes.firstIndex(where: { $0.identifier == runtime.identifier }) else { return }
506506
self.downloadableRuntimes[index].installState = .installing(step)
507-
508-
Current.notificationManager.scheduleNotification(title: runtime.name, body: step.description, category: .normal)
507+
if postNotification {
508+
Current.notificationManager.scheduleNotification(title: runtime.name, body: step.description, category: .normal)
509+
}
509510
}
510511
}
511512
}

Xcodes/Backend/AppState+Runtimes.swift

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ extension AppState {
3535
func updateInstalledRuntimes() {
3636
Task {
3737
do {
38+
Logger.appState.info("Loading Installed runtimes")
3839
let runtimes = try await self.runtimeService.localInstalledRuntimes()
3940

4041
DispatchQueue.main.async {
@@ -51,7 +52,7 @@ extension AppState {
5152
do {
5253
let downloadedURL = try await downloadRunTimeFull(runtime: runtime)
5354
if !Task.isCancelled {
54-
Logger.appState.debug("Installing rungtime: \(runtime.name)")
55+
Logger.appState.debug("Installing runtime: \(runtime.name)")
5556
DispatchQueue.main.async {
5657
self.setInstallationStep(of: runtime, to: .installing)
5758
}
@@ -110,11 +111,10 @@ extension AppState {
110111
let aria2Path = Path(url: Bundle.main.url(forAuxiliaryExecutable: "aria2c")!)!
111112
for try await progress in downloadRuntimeWithAria2(runtime, to: expectedRuntimePath, aria2Path: aria2Path) {
112113
DispatchQueue.main.async {
113-
Logger.appState.debug("Downloading: \(progress.fractionCompleted)")
114-
self.setInstallationStep(of: runtime, to: .downloading(progress: progress))
114+
self.setInstallationStep(of: runtime, to: .downloading(progress: progress), postNotification: false)
115115
}
116116
}
117-
Logger.appState.debug("Done downloading")
117+
Logger.appState.debug("Done downloading runtime")
118118

119119
case .urlSession:
120120
throw "Downloading runtimes with URLSession is not supported. Please use aria2"
@@ -210,6 +210,35 @@ extension AppState {
210210

211211
updateInstalledRuntimes()
212212
}
213+
214+
func runtimeInstallPath(xcode: Xcode, runtime: DownloadableRuntime) -> Path? {
215+
if let coreSimulatorInfo = coreSimulatorInfo(runtime: runtime) {
216+
let urlString = coreSimulatorInfo.path["relative"]!
217+
// app was not allowed to open up file:// url's so remove
218+
let fileRemovedString = urlString.replacingOccurrences(of: "file://", with: "")
219+
let url = URL(fileURLWithPath: fileRemovedString)
220+
221+
return Path(url: url)!
222+
}
223+
return nil
224+
}
225+
226+
func coreSimulatorInfo(runtime: DownloadableRuntime) -> CoreSimulatorImage? {
227+
return installedRuntimes.filter({ $0.runtimeInfo.build == runtime.simulatorVersion.buildUpdate }).first
228+
}
229+
230+
func deleteRuntime(runtime: DownloadableRuntime) async throws {
231+
if let info = coreSimulatorInfo(runtime: runtime) {
232+
try await runtimeService.deleteRuntime(identifier: info.uuid)
233+
234+
// give it some time to actually finish deleting before updating
235+
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in
236+
self?.updateInstalledRuntimes()
237+
}
238+
} else {
239+
throw "No simulator found with \(runtime.identifier)"
240+
}
241+
}
213242
}
214243

215244
extension AnyPublisher {

Xcodes/Backend/AppState.swift

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class AppState: ObservableObject {
4848
@Published var isProcessingAuthRequest = false
4949
@Published var xcodeBeingConfirmedForUninstallation: Xcode?
5050
@Published var presentedAlert: XcodesAlert?
51+
@Published var presentedPreferenceAlert: XcodesPreferencesAlert?
5152
@Published var helperInstallState: HelperInstallState = .notInstalled
5253
/// Whether the user is being prepared for the helper installation alert with an explanation.
5354
/// This closure will be performed after the user chooses whether or not to proceed.
@@ -824,19 +825,7 @@ class AppState: ObservableObject {
824825

825826
self.allXcodes = newAllXcodes.sorted { $0.version > $1.version }
826827
}
827-
828-
// MARK: Runtimes
829-
func runtimeInstallPath(xcode: Xcode, runtime: DownloadableRuntime) -> Path? {
830-
if let coreSimulatorInfo = installedRuntimes.filter({ $0.runtimeInfo.build == runtime.simulatorVersion.buildUpdate }).first {
831-
let urlString = coreSimulatorInfo.path["relative"]!
832-
// app was not allowed to open up file:// url's so remove
833-
let fileRemovedString = urlString.replacingOccurrences(of: "file://", with: "")
834-
let url = URL(fileURLWithPath: fileRemovedString)
835-
836-
return Path(url: url)!
837-
}
838-
return nil
839-
}
828+
840829

841830
// MARK: - Private
842831

Xcodes/Frontend/Common/XcodesAlert.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,17 @@ enum XcodesAlert: Identifiable {
1818
}
1919
}
2020
}
21+
22+
// Splitting out alerts that are shown on the preference screen as by default we are showing on the MainWindow()
23+
// and users awkwardly switch screens, sometimes losing the preference screen
24+
enum XcodesPreferencesAlert: Identifiable {
25+
case deletePlatform(runtime: DownloadableRuntime)
26+
case generic(title: String, message: String)
27+
28+
var id: Int {
29+
switch self {
30+
case .deletePlatform: return 1
31+
case .generic: return 2
32+
}
33+
}
34+
}

Xcodes/Frontend/InfoPane/InfoPane.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,8 @@ var downloadableRuntimes: [DownloadableRuntime] = {
171171
}()
172172

173173
var installedRuntimes: [CoreSimulatorImage] = {
174-
[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
174+
[CoreSimulatorImage(uuid: "85B22F5B-048B-4331-B6E2-F4196D8B7475", path: ["relative" : "file:///Library/Developer/CoreSimulator/Images/85B22F5B-048B-4331-B6E2-F4196D8B7475.dmg"], runtimeInfo: CoreSimulatorRuntimeInfo(build: "19E240")),
175+
CoreSimulatorImage(uuid: "85B22F5B-048B-4331-B6E2-F4196D8B7473", path: ["relative" : "file:///Library/Developer/CoreSimulator/Images/85B22F5B-048B-4331-B6E2-F4196D8B7475.dmg"], runtimeInfo: CoreSimulatorRuntimeInfo(build: "21N5233f"))]
175176
}()
176177

177178

Xcodes/Frontend/InfoPane/PlatformsView.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ struct PlatformsView: View {
6262
HStack(alignment: .top, spacing: 5){
6363
RuntimeInstallationStepDetailView(installationStep: installationStep)
6464
.fixedSize(horizontal: false, vertical: true)
65+
Spacer()
6566
CancelRuntimeInstallButton(runtime: runtime)
6667
}
6768

Xcodes/Frontend/MainWindow.swift

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -69,32 +69,6 @@ struct MainWindow: View {
6969
}
7070
}
7171
}
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-
9872
.bottomStatusBar()
9973
.padding([.top], 0)
10074
.navigationSubtitle(subtitleText)

0 commit comments

Comments
 (0)