diff --git a/Xcodes/Backend/AppState+Update.swift b/Xcodes/Backend/AppState+Update.swift index 660d2f0..dd5b7d7 100644 --- a/Xcodes/Backend/AppState+Update.swift +++ b/Xcodes/Backend/AppState+Update.swift @@ -133,7 +133,7 @@ extension AppState { else { return nil } let url = urlPrefix.appendingPathComponent(xcodeFile.remotePath) - return AvailableXcode(version: version, url: url, filename: String(xcodeFile.remotePath.suffix(fromLast: "/")), releaseDate: download.dateModified) + return AvailableXcode(version: version, url: url, filename: String(xcodeFile.remotePath.suffix(fromLast: "/")), releaseDate: download.dateModified, fileSize: xcodeFile.fileSize) } return xcodes } diff --git a/Xcodes/Backend/AppState.swift b/Xcodes/Backend/AppState.swift index 59f3089..ed465f8 100644 --- a/Xcodes/Backend/AppState.swift +++ b/Xcodes/Backend/AppState.swift @@ -459,7 +459,8 @@ class AppState: ObservableObject { requiredMacOSVersion: availableXcode.requiredMacOSVersion, releaseNotesURL: availableXcode.releaseNotesURL, sdks: availableXcode.sdks, - compilers: availableXcode.compilers + compilers: availableXcode.compilers, + downloadFileSize: availableXcode.fileSize ) } diff --git a/Xcodes/Backend/AvailableXcode.swift b/Xcodes/Backend/AvailableXcode.swift index c1810ba..cf3f0e4 100644 --- a/Xcodes/Backend/AvailableXcode.swift +++ b/Xcodes/Backend/AvailableXcode.swift @@ -13,6 +13,7 @@ public struct AvailableXcode: Codable { public let releaseNotesURL: URL? public let sdks: SDKs? public let compilers: Compilers? + public let fileSize: Int64? public init( version: Version, @@ -22,7 +23,8 @@ public struct AvailableXcode: Codable { requiredMacOSVersion: String? = nil, releaseNotesURL: URL? = nil, sdks: SDKs? = nil, - compilers: Compilers? = nil + compilers: Compilers? = nil, + fileSize: Int64? = nil ) { self.version = version self.url = url @@ -32,5 +34,6 @@ public struct AvailableXcode: Codable { self.releaseNotesURL = releaseNotesURL self.sdks = sdks self.compilers = compilers + self.fileSize = fileSize } } diff --git a/Xcodes/Backend/Downloads.swift b/Xcodes/Backend/Downloads.swift index 45e2bb7..55096e4 100644 --- a/Xcodes/Backend/Downloads.swift +++ b/Xcodes/Backend/Downloads.swift @@ -6,6 +6,9 @@ struct Downloads: Codable { let downloads: [Download] } +// Set to Int64 as ByteCountFormatter uses it. +public typealias ByteCount = Int64 + public struct Download: Codable { public let name: String public let files: [File] @@ -13,5 +16,6 @@ public struct Download: Codable { public struct File: Codable { public let remotePath: String + public let fileSize: ByteCount } } diff --git a/Xcodes/Backend/Xcode.swift b/Xcodes/Backend/Xcode.swift index 481eb78..a5da1bc 100644 --- a/Xcodes/Backend/Xcode.swift +++ b/Xcodes/Backend/Xcode.swift @@ -13,6 +13,7 @@ struct Xcode: Identifiable, CustomStringConvertible { let releaseNotesURL: URL? let sdks: SDKs? let compilers: Compilers? + let downloadFileSize: Int64? init( version: Version, @@ -22,7 +23,8 @@ struct Xcode: Identifiable, CustomStringConvertible { requiredMacOSVersion: String? = nil, releaseNotesURL: URL? = nil, sdks: SDKs? = nil, - compilers: Compilers? = nil + compilers: Compilers? = nil, + downloadFileSize: Int64? = nil ) { self.version = version self.installState = installState @@ -32,6 +34,7 @@ struct Xcode: Identifiable, CustomStringConvertible { self.releaseNotesURL = releaseNotesURL self.sdks = sdks self.compilers = compilers + self.downloadFileSize = downloadFileSize } var id: Version { version } @@ -39,4 +42,12 @@ struct Xcode: Identifiable, CustomStringConvertible { var description: String { version.appleDescription } + + var downloadFileSizeString: String? { + if let downloadFileSize = downloadFileSize { + return ByteCountFormatter.string(fromByteCount: downloadFileSize, countStyle: .file) + } else { + return nil + } + } } diff --git a/Xcodes/Frontend/XcodeList/InfoPane.swift b/Xcodes/Frontend/XcodeList/InfoPane.swift index 6e0b6b7..382138b 100644 --- a/Xcodes/Frontend/XcodeList/InfoPane.swift +++ b/Xcodes/Frontend/XcodeList/InfoPane.swift @@ -56,7 +56,8 @@ struct InfoPane: View { compatibility(for: xcode) sdks(for: xcode) compilers(for: xcode) - + downloadFileSize(for: xcode) + Spacer() } } else { @@ -162,6 +163,24 @@ struct InfoPane: View { } } + @ViewBuilder + private func downloadFileSize(for xcode: Xcode) -> some View { + // if we've downloaded it no need to show the download size + if let downloadFileSize = xcode.downloadFileSizeString, case .notInstalled = xcode.installState { + VStack(alignment: .leading) { + Text("Download Size") + .font(.headline) + .frame(maxWidth: .infinity, alignment: .leading) + Text("\(downloadFileSize)") + .font(.subheadline) + .frame(maxWidth: .infinity, alignment: .leading) + } + } else { + EmptyView() + } + } + + @ViewBuilder private var empty: some View { VStack { @@ -199,7 +218,9 @@ struct InfoPane_Previews: PreviewProvider { llvm: .init(number: "2.3"), clang: .init(number: "7.3"), swift: .init(number: "5.3.2") - )) + ), + downloadFileSize: 242342424 + ) ] }) .previewDisplayName("Populated, Installed, Selected") @@ -224,7 +245,8 @@ struct InfoPane_Previews: PreviewProvider { llvm: .init(number: "2.3"), clang: .init(number: "7.3"), swift: .init(number: "5.3.2") - )) + ), + downloadFileSize: 242342424) ] }) .previewDisplayName("Populated, Installed, Unselected") @@ -249,7 +271,8 @@ struct InfoPane_Previews: PreviewProvider { llvm: .init(number: "2.3"), clang: .init(number: "7.3"), swift: .init(number: "5.3.2") - )) + ), + downloadFileSize: 242342424) ] }) .previewDisplayName("Populated, Uninstalled") diff --git a/XcodesTests/AppStateTests.swift b/XcodesTests/AppStateTests.swift index c9fffb2..0c4c165 100644 --- a/XcodesTests/AppStateTests.swift +++ b/XcodesTests/AppStateTests.swift @@ -89,7 +89,7 @@ class AppStateTests: XCTestCase { } // It's an available release version else if urlRequest.url! == URLRequest.downloads.url! { - let downloads = Downloads(downloads: [Download(name: "Xcode 0.0.0", files: [Download.File(remotePath: "https://apple.com/xcode.xip")], dateModified: Date())]) + let downloads = Downloads(downloads: [Download(name: "Xcode 0.0.0", files: [Download.File(remotePath: "https://apple.com/xcode.xip", fileSize: 9484444)], dateModified: Date())]) let encoder = JSONEncoder() encoder.dateEncodingStrategy = .formatted(.downloadsDateModified) let downloadsData = try! encoder.encode(downloads) @@ -199,7 +199,7 @@ class AppStateTests: XCTestCase { } // It's an available release version else if urlRequest.url! == URLRequest.downloads.url! { - let downloads = Downloads(downloads: [Download(name: "Xcode 0.0.0", files: [Download.File(remotePath: "https://apple.com/xcode.xip")], dateModified: Date())]) + let downloads = Downloads(downloads: [Download(name: "Xcode 0.0.0", files: [Download.File(remotePath: "https://apple.com/xcode.xip", fileSize: 9494944)], dateModified: Date())]) let encoder = JSONEncoder() encoder.dateEncodingStrategy = .formatted(.downloadsDateModified) let downloadsData = try! encoder.encode(downloads)