From 04deb08bcf980e4aa131249a7a78d6d14d494a63 Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Mon, 4 Sep 2023 23:35:40 -0400 Subject: [PATCH] Add feature flags to advanced preferences --- .../TuskerPreferences/Preferences.swift | 14 ++++++ .../Preferences/AdvancedPrefsView.swift | 45 +++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/Packages/TuskerPreferences/Sources/TuskerPreferences/Preferences.swift b/Packages/TuskerPreferences/Sources/TuskerPreferences/Preferences.swift index 8c9e4865..2f894db8 100644 --- a/Packages/TuskerPreferences/Sources/TuskerPreferences/Preferences.swift +++ b/Packages/TuskerPreferences/Sources/TuskerPreferences/Preferences.swift @@ -97,6 +97,9 @@ public class Preferences: Codable, ObservableObject { self.hideTrends = try container.decodeIfPresent(Bool.self, forKey: .hideTrends) ?? false self.statusContentType = try container.decode(StatusContentType.self, forKey: .statusContentType) + self.reportErrorsAutomatically = try container.decodeIfPresent(Bool.self, forKey: .reportErrorsAutomatically) ?? true + let featureFlagNames = (try? container.decodeIfPresent([String].self, forKey: .enabledFeatureFlags)) ?? [] + self.enabledFeatureFlags = Set(featureFlagNames.compactMap(FeatureFlag.init)) self.hasShownLocalTimelineDescription = try container.decodeIfPresent(Bool.self, forKey: .hasShownLocalTimelineDescription) ?? false self.hasShownFederatedTimelineDescription = try container.decodeIfPresent(Bool.self, forKey: .hasShownFederatedTimelineDescription) ?? false @@ -149,6 +152,8 @@ public class Preferences: Codable, ObservableObject { try container.encode(hideTrends, forKey: .hideTrends) try container.encode(statusContentType, forKey: .statusContentType) + try container.encode(reportErrorsAutomatically, forKey: .reportErrorsAutomatically) + try container.encode(enabledFeatureFlags, forKey: .enabledFeatureFlags) try container.encode(hasShownLocalTimelineDescription, forKey: .hasShownLocalTimelineDescription) try container.encode(hasShownFederatedTimelineDescription, forKey: .hasShownFederatedTimelineDescription) @@ -213,6 +218,7 @@ public class Preferences: Codable, ObservableObject { // MARK: Advanced @Published public var statusContentType: StatusContentType = .plain @Published public var reportErrorsAutomatically = true + @Published public var enabledFeatureFlags: Set = [] // MARK: @Published public var hasShownLocalTimelineDescription = false @@ -264,6 +270,8 @@ public class Preferences: Codable, ObservableObject { case hideTrends = "hideDiscover" case statusContentType + case reportErrorsAutomatically + case enabledFeatureFlags case hasShownLocalTimelineDescription case hasShownFederatedTimelineDescription @@ -414,3 +422,9 @@ extension Preferences { case icloud } } + +extension Preferences { + public enum FeatureFlag: String, Codable { + case test + } +} diff --git a/Tusker/Screens/Preferences/AdvancedPrefsView.swift b/Tusker/Screens/Preferences/AdvancedPrefsView.swift index d698f14c..7e9d68bb 100644 --- a/Tusker/Screens/Preferences/AdvancedPrefsView.swift +++ b/Tusker/Screens/Preferences/AdvancedPrefsView.swift @@ -16,6 +16,8 @@ struct AdvancedPrefsView : View { @State private var imageCacheSize: Int64 = 0 @State private var mastodonCacheSize: Int64 = 0 @State private var cloudKitStatus: CKAccountStatus? + @State private var isShowingFeatureFlagAlert = false + @State private var featureFlagName = "" var body: some View { List { @@ -23,9 +25,27 @@ struct AdvancedPrefsView : View { cloudKitSection errorReportingSection cachingSection + featureFlagSection + } .listStyle(.insetGrouped) .appGroupedListBackground(container: PreferencesNavigationController.self) + .onTapGesture(count: 3) { + featureFlagName = "" + isShowingFeatureFlagAlert = true + } + .alert("Enable Feature Flag", isPresented: $isShowingFeatureFlagAlert) { + TextField("Name", text: $featureFlagName) + .textInputAutocapitalization(.never) + .autocorrectionDisabled() + + Button("Cancel", role: .cancel) {} + Button("Enable") { + if let flag = Preferences.FeatureFlag(rawValue: featureFlagName) { + preferences.enabledFeatureFlags.insert(flag) + } + } + } .navigationBarTitle(Text("Advanced")) } @@ -148,6 +168,31 @@ struct AdvancedPrefsView : View { } } + @ViewBuilder + var featureFlagSection: some View { + if !preferences.enabledFeatureFlags.isEmpty { + Section { + ForEach(preferences.enabledFeatureFlags.map(\.rawValue).sorted(), id: \.self) { name in + Text(verbatim: name) + .contextMenu { + Button(role: .destructive) { + preferences.enabledFeatureFlags.remove(.init(rawValue: name)!) + } label: { + Label("Remove", systemImage: "trash") + } + } + } + .onDelete { indices in + let sortedFlags = preferences.enabledFeatureFlags.sorted(by: { $0.rawValue < $1.rawValue }) + let removed = indices.map { sortedFlags[$0] } + preferences.enabledFeatureFlags.subtract(removed) + } + } header: { + Text("Feature Flags") + } + } + } + private func clearCache() { for account in UserAccountsManager.shared.accounts { let controller = MastodonController.getForAccount(account)