-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Expand file tree
/
Copy pathFeatureFlag.swift
More file actions
169 lines (158 loc) · 5.49 KB
/
FeatureFlag.swift
File metadata and controls
169 lines (158 loc) · 5.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
import BuildSettingsKit
import Foundation
import FoundationModels
/// FeatureFlag exposes a series of features to be conditionally enabled on
/// different builds.
@objc
public enum FeatureFlag: Int, CaseIterable {
case signUp
case domainRegistration
case selfHostedSites
case whatsNew
case qrCodeLogin
case bloggingPrompts
case jetpackDisconnect
case siteIconCreator
case betaSiteDesigns
case commentModerationUpdate
case compliancePopover
case googleDomainsCard
case voiceToContent
case allowApplicationPasswords
case selfHostedSiteUserManagement
case readerGutenbergCommentComposer
case pluginManagementOverhaul
case newStats
case intelligence
case newSupport
case nativeBlockInserter
case statsAds
/// Returns a boolean indicating if the feature is enabled.
///
/// - warning: If the feature is unconditionally enabled, it doesn't mean
/// that the flag can be removed. It provides a capability of conditionally
/// disabling a feature if necessary. Use your best judgmenet.
var enabled: Bool {
if let overriddenValue = FeatureFlagOverrideStore().overriddenValue(for: self) {
return overriddenValue
}
let app = BuildSettings.current.brand
switch self {
case .signUp:
return true
case .domainRegistration:
return app == .jetpack || app == .reader
case .selfHostedSites:
return app != .reader
case .whatsNew:
return true
case .qrCodeLogin:
return app == .jetpack
case .bloggingPrompts:
return app == .jetpack || app == .reader
case .jetpackDisconnect:
return BuildConfiguration.current == .debug
case .siteIconCreator:
return BuildConfiguration.current.isInternal
case .betaSiteDesigns:
return false
case .commentModerationUpdate:
return false
case .compliancePopover:
return true
case .googleDomainsCard:
return false
case .voiceToContent:
return app == .jetpack && BuildConfiguration.current.isInternal
case .allowApplicationPasswords:
return false
case .selfHostedSiteUserManagement:
return false
case .readerGutenbergCommentComposer:
return false
case .pluginManagementOverhaul:
return false
case .newStats:
return false
case .intelligence:
guard #available(iOS 26, *) else {
return false
}
return SystemLanguageModel.default.supportsLocale()
case .newSupport:
return false
case .nativeBlockInserter:
return true
case .statsAds:
return BuildConfiguration.current == .debug
}
}
var disabled: Bool {
return enabled == false
}
}
/// Objective-C bridge for FeatureFlag.
///
/// Since we can't expose properties on Swift enums we use a class instead
public class Feature: NSObject {
/// Returns a boolean indicating if the feature is enabled
@objc public static func enabled(_ feature: FeatureFlag) -> Bool {
return feature.enabled
}
}
extension FeatureFlag {
/// Descriptions used to display the feature flag override menu in debug builds
public var description: String {
return switch self {
case .signUp: "Sign Up"
case .domainRegistration: "Domain Registration"
case .selfHostedSites: "Self-Hosted Sites"
case .whatsNew: "What's New"
case .qrCodeLogin: "QR Code Login"
case .bloggingPrompts: "Blogging Prompts"
case .jetpackDisconnect: "Jetpack disconnect"
case .siteIconCreator: "Site Icon Creator"
case .betaSiteDesigns: "Fetch Beta Site Designs"
case .commentModerationUpdate: "Comments Moderation Update"
case .compliancePopover: "Compliance Popover"
case .googleDomainsCard: "Google Domains Promotional Card"
case .voiceToContent: "Voice to Content"
case .allowApplicationPasswords: "Allow creating Application Passwords"
case .selfHostedSiteUserManagement: "Self-hosted Site User Management"
case .pluginManagementOverhaul: "Plugin Management Overhaul"
case .readerGutenbergCommentComposer: "Gutenberg Comment Composer"
case .newStats: "New Stats"
case .intelligence: "Intelligence"
case .newSupport: "New Support"
case .nativeBlockInserter: "Native Block Inserter"
case .statsAds: "Stats Ads Tab"
}
}
}
extension FeatureFlag: OverridableFlag {
var originalValue: Bool {
return enabled
}
var key: String {
let key: String
switch self {
case .allowApplicationPasswords:
// This feature toggle description is already shipped and used in the production.
// We want to keep using the same key, but change the description.
key = "Application Passwords for self-hosted sites"
default:
key = String(describing: self)
}
return "ff-override-\(key)"
}
}
extension FeatureFlag: RolloutConfigurableFlag {
/// Represents the percentage of users to roll the flag out to.
///
/// To set a percentage rollout, return a value between 0.0 and 1.0.
/// If a percentage rollout isn't applicable for the flag, return nil.
///
var rolloutPercentage: Double? {
return nil
}
}