From e3f996da6e3dd3023131245b006ce4dd1a3e0c66 Mon Sep 17 00:00:00 2001 From: Anand Biligiri Date: Wed, 21 Aug 2024 15:07:00 -0700 Subject: [PATCH] Restrict allowed versions & hide 'Support Xcodes' - Introduced a new preference keys allowedMajorVersions, hideSupportXcodes - allowedMajorVersions defaults to Int.max (ie allow all versions till date) - allowedMajorVersions is used to limit the number of major versions to as many as value set for this key. Eg: A value of 1 would allow the latest GA version and one major version before A value of 0 would allow only the latest GA version A value of 2 would allow the latest GA and previous two major versions - allowedMajorVersions does not have preference UI $ defaults write com.xcodesorg.xcodesapp allowedMajorVersions 2 #to limit to current GA and previous major $ defaults delete com.xcodesorg.xcodesapp allowedMajorVersions #to remove limits - Display buildNumber in bottom status bar --- Xcodes/Backend/AppState.swift | 2 + .../Frontend/XcodeList/BottomStatusBar.swift | 52 +++++++++++++++---- Xcodes/Frontend/XcodeList/XcodeListView.swift | 22 +++++++- 3 files changed, 64 insertions(+), 12 deletions(-) diff --git a/Xcodes/Backend/AppState.swift b/Xcodes/Backend/AppState.swift index b4775496..27343141 100644 --- a/Xcodes/Backend/AppState.swift +++ b/Xcodes/Backend/AppState.swift @@ -24,6 +24,8 @@ enum PreferenceKey: String { case downloader case dataSource case xcodeListCategory + case allowedMajorVersions + case hideSupportXcodes func isManaged() -> Bool { UserDefaults.standard.objectIsForced(forKey: self.rawValue) } } diff --git a/Xcodes/Frontend/XcodeList/BottomStatusBar.swift b/Xcodes/Frontend/XcodeList/BottomStatusBar.swift index 18eaf2dc..ac4b2144 100644 --- a/Xcodes/Frontend/XcodeList/BottomStatusBar.swift +++ b/Xcodes/Frontend/XcodeList/BottomStatusBar.swift @@ -11,6 +11,8 @@ import SwiftUI struct BottomStatusModifier: ViewModifier { @EnvironmentObject var appState: AppState + @AppStorage(PreferenceKey.hideSupportXcodes.rawValue) var hideSupportXcodes = false + @SwiftUI.Environment(\.openURL) var openURL: OpenURLAction func body(content: Content) -> some View { @@ -20,17 +22,19 @@ struct BottomStatusModifier: ViewModifier { Divider() HStack { Text(appState.bottomStatusBarMessage) - .font(.subheadline) + .font(.subheadline) Spacer() - Button(action: { - openURL(URL(string: "https://opencollective.com/xcodesapp")!) - }) { - HStack { - Image(systemName: "heart.circle") - Text("Support.Xcodes") + if !hideSupportXcodes { + Button(action: { + openURL(URL(string: "https://opencollective.com/xcodesapp")!) + }) { + HStack { + Image(systemName: "heart.circle") + Text("Support.Xcodes") + } } } - Text(Bundle.main.shortVersion!) + Text("\(Bundle.main.shortVersion!) (\(Bundle.main.version!))") .font(.subheadline) } .frame(maxWidth: .infinity, maxHeight: 30, alignment: .leading) @@ -51,8 +55,34 @@ extension View { struct Previews_BottomStatusBar_Previews: PreviewProvider { static var previews: some View { - HStack { - - }.bottomStatusBar() + Group { + HStack { + + } + .bottomStatusBar() + .environmentObject({ () -> AppState in + let a = AppState() + return a }() + ) + .defaultAppStorage({ () -> UserDefaults in + let d = UserDefaults(suiteName: "hide_support")! + d.set(true, forKey: PreferenceKey.hideSupportXcodes.rawValue) + return d + }()) + + HStack { + + } + .bottomStatusBar() + .environmentObject({ () -> AppState in + let a = AppState() + return a }() + ) + .defaultAppStorage({ () -> UserDefaults in + let d = UserDefaults(suiteName: "show_support")! + d.set(false, forKey: PreferenceKey.hideSupportXcodes.rawValue) + return d + }()) + } } } diff --git a/Xcodes/Frontend/XcodeList/XcodeListView.swift b/Xcodes/Frontend/XcodeList/XcodeListView.swift index 72aa7d2d..44be5985 100644 --- a/Xcodes/Frontend/XcodeList/XcodeListView.swift +++ b/Xcodes/Frontend/XcodeList/XcodeListView.swift @@ -8,7 +8,8 @@ struct XcodeListView: View { private let searchText: String private let category: XcodeListCategory private let isInstalledOnly: Bool - + @AppStorage(PreferenceKey.allowedMajorVersions.rawValue) private var allowedMajorVersions = Int.max + init(selectedXcodeID: Binding, searchText: String, category: XcodeListCategory, isInstalledOnly: Bool) { self._selectedXcodeID = selectedXcodeID self.searchText = searchText @@ -27,6 +28,22 @@ struct XcodeListView: View { xcodes = appState.allXcodes.filter { $0.version.isPrerelease } } + let latestMajor = xcodes.sorted(\.version) + .filter { $0.version.isNotPrerelease } + .last? + .version + .major + + xcodes = xcodes.filter { + if $0.installState.notInstalled, + let latestMajor = latestMajor, + $0.version.major < (latestMajor - min(latestMajor,allowedMajorVersions)) { + return false + } + + return true + } + if !searchText.isEmpty { xcodes = xcodes.filter { $0.description.contains(searchText) } } @@ -87,6 +104,9 @@ struct XcodeListView_Previews: PreviewProvider { Xcode(version: Version("12.2.0")!, installState: .notInstalled, selected: false, icon: nil), Xcode(version: Version("12.1.0")!, installState: .installing(.downloading(progress: configure(Progress(totalUnitCount: 100)) { $0.completedUnitCount = 40 })), selected: false, icon: nil), Xcode(version: Version("12.0.0")!, installState: .installed(Path("/Applications/Xcode-12.3.0.app")!), selected: false, icon: nil), + Xcode(version: Version("10.1.0")!, installState: .notInstalled, selected: false, icon: nil), + Xcode(version: Version("10.0.0")!, installState: .installed(Path("/Applications/Xcode-10.0.0.app")!), selected: false, icon: nil), + Xcode(version: Version("9.0.0")!, installState: .notInstalled, selected: false, icon: nil), ] return a }())