diff --git a/Xcodes/Frontend/InfoPane/InfoPane.swift b/Xcodes/Frontend/InfoPane/InfoPane.swift index a1c6716..6b038a4 100644 --- a/Xcodes/Frontend/InfoPane/InfoPane.swift +++ b/Xcodes/Frontend/InfoPane/InfoPane.swift @@ -6,178 +6,153 @@ import struct XCModel.Compilers import struct XCModel.SDKs struct InfoPane: View { - @EnvironmentObject var appState: AppState - let selectedXcodeID: Xcode.ID? + let xcode: Xcode var body: some View { - if let xcode = appState.allXcodes.first(where: { $0.id == selectedXcodeID }) { - ScrollView { - VStack(alignment: .leading, spacing: 16) { - IconView(installState: xcode.installState) - .frame(maxWidth: .infinity, alignment: .center) + ScrollView { + VStack(alignment: .leading, spacing: 16) { + IconView(installState: xcode.installState) + .frame(maxWidth: .infinity, alignment: .center) - Text(verbatim: "Xcode \(xcode.description) \(xcode.version.buildMetadataIdentifiersDisplay)") - .font(.title) + Text(verbatim: "Xcode \(xcode.description) \(xcode.version.buildMetadataIdentifiersDisplay)") + .font(.title) - switch xcode.installState { - case .notInstalled: - NotInstalledStateButtons( - downloadFileSizeString: xcode.downloadFileSizeString, - id: xcode.id - ) - case let .installing(installationStep): - InstallationStepDetailView(installationStep: installationStep) - CancelInstallButton(xcode: xcode) - case .installed: - InstalledStateButtons(xcode: xcode) - } - - Divider() - - Group { - ReleaseNotesView(url: xcode.releaseNotesURL) - ReleaseDateView(date: xcode.releaseDate) - IdenticalBuildsView(builds: xcode.identicalBuilds) - CompatibilityView(requiredMacOSVersion: xcode.requiredMacOSVersion) - SDKsView(sdks: xcode.sdks) - CompilersView(compilers: xcode.compilers) - } - - Spacer() + switch xcode.installState { + case .notInstalled: + NotInstalledStateButtons( + downloadFileSizeString: xcode.downloadFileSizeString, + id: xcode.id + ) + case let .installing(installationStep): + InstallationStepDetailView(installationStep: installationStep) + CancelInstallButton(xcode: xcode) + case .installed: + InstalledStateButtons(xcode: xcode) } - .padding() + + Divider() + + Group { + ReleaseNotesView(url: xcode.releaseNotesURL) + ReleaseDateView(date: xcode.releaseDate) + IdenticalBuildsView(builds: xcode.identicalBuilds) + CompatibilityView(requiredMacOSVersion: xcode.requiredMacOSVersion) + SDKsView(sdks: xcode.sdks) + CompilersView(compilers: xcode.compilers) + } + + Spacer() } - .frame(minWidth: 200, maxWidth: .infinity) - } else { - UnselectedView() } } } struct InfoPane_Previews: PreviewProvider { static var previews: some View { - Group { - InfoPane(selectedXcodeID: Version(major: 12, minor: 3, patch: 0)) - .environmentObject(configure(AppState()) { - $0.allXcodes = [ - .init( - version: Version(major: 12, minor: 3, patch: 0), - installState: .installed(Path("/Applications/Xcode-12.3.0.app")!), - selected: true, - icon: NSWorkspace.shared.icon(forFile: "/Applications/Xcode-12.3.0.app"), - requiredMacOSVersion: "10.15.4", - releaseNotesURL: URL(string: "https://developer.apple.com/documentation/xcode-release-notes/xcode-12_3-release-notes/")!, - releaseDate: Date(), - sdks: SDKs( - macOS: .init(number: "11.1"), - iOS: .init(number: "14.3"), - watchOS: .init(number: "7.3"), - tvOS: .init(number: "14.3") - ), - compilers: Compilers( - gcc: .init(number: "4"), - llvm_gcc: .init(number: "213"), - llvm: .init(number: "2.3"), - clang: .init(number: "7.3"), - swift: .init(number: "5.3.2") - ), - downloadFileSize: 242_342_424 - ), - ] - }) - .previewDisplayName("Populated, Installed, Selected") - - InfoPane(selectedXcodeID: Version(major: 12, minor: 3, patch: 0)) - .environmentObject(configure(AppState()) { - $0.allXcodes = [ - .init( - version: Version(major: 12, minor: 3, patch: 0), - installState: .installed(Path("/Applications/Xcode-12.3.0.app")!), - selected: false, - icon: NSWorkspace.shared.icon(forFile: "/Applications/Xcode-12.3.0.app"), - sdks: SDKs( - macOS: .init(number: "11.1"), - iOS: .init(number: "14.3"), - watchOS: .init(number: "7.3"), - tvOS: .init(number: "14.3") - ), - compilers: Compilers( - gcc: .init(number: "4"), - llvm_gcc: .init(number: "213"), - llvm: .init(number: "2.3"), - clang: .init(number: "7.3"), - swift: .init(number: "5.3.2") - ), - downloadFileSize: 242_342_424 - ), - ] - }) - .previewDisplayName("Populated, Installed, Unselected") - - InfoPane(selectedXcodeID: Version(major: 12, minor: 3, patch: 0)) - .environmentObject(configure(AppState()) { - $0.allXcodes = [ - .init( - version: Version(major: 12, minor: 3, patch: 0), - installState: .notInstalled, - selected: false, - icon: nil, - sdks: SDKs( - macOS: .init(number: "11.1"), - iOS: .init(number: "14.3"), - watchOS: .init(number: "7.3"), - tvOS: .init(number: "14.3") - ), - compilers: Compilers( - gcc: .init(number: "4"), - llvm_gcc: .init(number: "213"), - llvm: .init(number: "2.3"), - clang: .init(number: "7.3"), - swift: .init(number: "5.3.2") - ), - downloadFileSize: 242_342_424 - ), - ] - }) - .previewDisplayName("Populated, Uninstalled") - - InfoPane(selectedXcodeID: Version(major: 12, minor: 3, patch: 1, buildMetadataIdentifiers: ["1234A"])) - .environmentObject(configure(AppState()) { - $0.allXcodes = [ - .init( - version: Version(major: 12, minor: 3, patch: 1, buildMetadataIdentifiers: ["1234A"]), - installState: .installed(Path("/Applications/Xcode-12.3.0.app")!), - selected: false, - icon: nil, - sdks: nil, - compilers: nil - ), - ] - }) - .previewDisplayName("Basic, installed") - - InfoPane(selectedXcodeID: Version(major: 12, minor: 3, patch: 1, buildMetadataIdentifiers: ["1234A"])) - .environmentObject(configure(AppState()) { - $0.allXcodes = [ - .init( - version: Version(major: 12, minor: 3, patch: 1, buildMetadataIdentifiers: ["1234A"]), - installState: .installing(.downloading(progress: configure(Progress(totalUnitCount: 100)) { $0.completedUnitCount = 40; $0.throughput = 232_323_232; $0.fileCompletedCount = 2_323_004; $0.fileTotalCount = 1_193_939_393 })), - selected: false, - icon: nil, - sdks: nil, - compilers: nil - ), - ] - }) - .previewDisplayName("Basic, installing") - - InfoPane(selectedXcodeID: nil) - .environmentObject(configure(AppState()) { - $0.allXcodes = [ - ] - }) - .previewDisplayName("Empty") - } - .frame(maxWidth: 300) + WrapperView() } } + +private struct WrapperView: View { + @State var name: PreviewName = .Populated_Installed_Selected + + var body: some View { + VStack { + InfoPane(xcode: xcode) + .environmentObject(configure(AppState()) { + $0.allXcodes = [xcode] + }) + .border(.red) + .frame(width: 300, height: 400) + Spacer() + Picker("Preview Name", selection: $name) { + ForEach(PreviewName.allCases) { + Text($0.rawValue).tag($0) + } + } + .pickerStyle(.inline) + } + .frame(maxWidth: .infinity) + .padding() + } + + var xcode: Xcode { xcodeDict[name]! } +} + +private enum PreviewName: String, CaseIterable, Identifiable { + case Populated_Installed_Selected + case Populated_Installed_Unselected + case Populated_Uninstalled + case Basic_Installed + case Basic_Installing + + var id: PreviewName { self } +} + +private var xcodeDict: [PreviewName: Xcode] = [ + .Populated_Installed_Selected: .init( + version: _versionNoMeta, + installState: .installed(Path(_path)!), + selected: true, + icon: NSWorkspace.shared.icon(forFile: _path), + requiredMacOSVersion: _requiredMacOSVersion, + releaseNotesURL: URL(string: "https://developer.apple.com/documentation/xcode-release-notes/xcode-12_3-release-notes/")!, + releaseDate: Date(), + sdks: _sdks, + compilers: _compilers, + downloadFileSize: _downloadFileSize + ), + .Populated_Installed_Unselected: .init( + version: _versionNoMeta, + installState: .installed(Path(_path)!), + selected: false, + icon: NSWorkspace.shared.icon(forFile: _path), + sdks: _sdks, + compilers: _compilers, + downloadFileSize: _downloadFileSize + ), + .Populated_Uninstalled: .init( + version: Version(major: 12, minor: 3, patch: 0), + installState: .notInstalled, + selected: false, + icon: nil, + sdks: _sdks, + compilers: _compilers, + downloadFileSize: _downloadFileSize + ), + .Basic_Installed: .init( + version: _versionWithMeta, + installState: .installed(Path(_path)!), + selected: false, + icon: nil, + sdks: nil, + compilers: nil + ), + .Basic_Installing: .init( + version: _versionWithMeta, + installState: .installing(.downloading(progress: configure(Progress(totalUnitCount: 100)) { $0.completedUnitCount = 40; $0.throughput = 232_323_232; $0.fileCompletedCount = 2_323_004; $0.fileTotalCount = 1_193_939_393 })), + selected: false, + icon: nil, + sdks: nil, + compilers: nil + ), +] + +private let _versionNoMeta = Version(major: 12, minor: 3, patch: 0) +private let _versionWithMeta = Version(major: 12, minor: 3, patch: 1, buildMetadataIdentifiers: ["1234A"]) +private let _path = "/Applications/Xcode-12.3.0.app" +private let _requiredMacOSVersion = "10.15.4" +private let _sdks = SDKs( + macOS: .init(number: "11.1"), + iOS: .init(number: "14.3"), + watchOS: .init(number: "7.3"), + tvOS: .init(number: "14.3") +) +private let _compilers = Compilers( + gcc: .init(number: "4"), + llvm_gcc: .init(number: "213"), + llvm: .init(number: "2.3"), + clang: .init(number: "7.3"), + swift: .init(number: "5.3.2") +) +private let _downloadFileSize: Int64 = 242_342_424 diff --git a/Xcodes/Frontend/MainWindow.swift b/Xcodes/Frontend/MainWindow.swift index fcde005..5c74ea4 100644 --- a/Xcodes/Frontend/MainWindow.swift +++ b/Xcodes/Frontend/MainWindow.swift @@ -27,8 +27,15 @@ struct MainWindow: View { } if isShowingInfoPane { - InfoPane(selectedXcodeID: selectedXcodeID) - .frame(minWidth: 300, maxWidth: .infinity) + Group { + if let xcode = xcode { + InfoPane(xcode: xcode) + } else { + UnselectedView() + } + } + .padding() + .frame(minWidth: 300, maxWidth: .infinity) } } .mainToolbar( @@ -59,7 +66,11 @@ struct MainWindow: View { // FB8954571 focusedValue(_:_:) on List row doesn't propagate value to @FocusedValue .focusedValue(\.selectedXcode, SelectedXcode(appState.allXcodes.first { $0.id == selectedXcodeID })) } - + + private var xcode: Xcode? { + appState.allXcodes.first(where: { $0.id == selectedXcodeID }) + } + private var subtitleText: Text { if let lastUpdated = lastUpdated.map(Date.init(timeIntervalSince1970:)) { return Text("\(localizeString("UpdatedAt")) \(lastUpdated, style: .date) \(lastUpdated, style: .time)")