-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Expand file tree
/
Copy pathFeatureFlagNotifier.swift
More file actions
117 lines (106 loc) · 4.67 KB
/
FeatureFlagNotifier.swift
File metadata and controls
117 lines (106 loc) · 4.67 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
import Combine
import SwiftUI
import JSONRPC
public extension Notification.Name {
static let gitHubCopilotFeatureFlagsDidChange = Notification
.Name("com.github.CopilotForXcode.CopilotFeatureFlagsDidChange")
}
public enum ExperimentValue: Hashable, Codable {
case string(String)
case number(Double)
case boolean(Bool)
case stringArray([String])
}
public typealias ActiveExperimentForFeatureFlags = [String: ExperimentValue]
public struct DidChangeFeatureFlagsParams: Hashable, Codable {
let envelope: [String: JSONValue]
let token: [String: String]
let activeExps: ActiveExperimentForFeatureFlags
let byok: Bool?
}
public struct FeatureFlags: Hashable, Codable {
public var restrictedTelemetry: Bool
public var snippy: Bool
public var chat: Bool
public var inlineChat: Bool
public var projectContext: Bool
public var agentMode: Bool
public var mcp: Bool
public var ccr: Bool // Copilot Code Review
public var byok: Bool
public var editorPreviewFeatures: Bool
public var activeExperimentForFeatureFlags: ActiveExperimentForFeatureFlags
public init(
restrictedTelemetry: Bool = true,
snippy: Bool = true,
chat: Bool = true,
inlineChat: Bool = true,
projectContext: Bool = true,
agentMode: Bool = true,
mcp: Bool = true,
ccr: Bool = true,
byok: Bool = true,
editorPreviewFeatures: Bool = true,
activeExperimentForFeatureFlags: ActiveExperimentForFeatureFlags = [:]
) {
self.restrictedTelemetry = restrictedTelemetry
self.snippy = snippy
self.chat = chat
self.inlineChat = inlineChat
self.projectContext = projectContext
self.agentMode = agentMode
self.mcp = mcp
self.ccr = ccr
self.byok = byok
self.editorPreviewFeatures = editorPreviewFeatures
self.activeExperimentForFeatureFlags = activeExperimentForFeatureFlags
}
}
public protocol FeatureFlagNotifier {
var didChangeFeatureFlagsParams: DidChangeFeatureFlagsParams { get }
var featureFlagsDidChange: PassthroughSubject<FeatureFlags, Never> { get }
func handleFeatureFlagNotification(_ didChangeFeatureFlagsParams: DidChangeFeatureFlagsParams)
}
public class FeatureFlagNotifierImpl: FeatureFlagNotifier {
public var didChangeFeatureFlagsParams: DidChangeFeatureFlagsParams
public var featureFlags: FeatureFlags
public static let shared = FeatureFlagNotifierImpl()
public var featureFlagsDidChange: PassthroughSubject<FeatureFlags, Never>
init(
didChangeFeatureFlagsParams: DidChangeFeatureFlagsParams = .init(
envelope: [:],
token: [:],
activeExps: [:],
byok: nil
),
featureFlags: FeatureFlags = FeatureFlags(),
featureFlagsDidChange: PassthroughSubject<FeatureFlags, Never> = PassthroughSubject<FeatureFlags, Never>()
) {
self.didChangeFeatureFlagsParams = didChangeFeatureFlagsParams
self.featureFlags = featureFlags
self.featureFlagsDidChange = featureFlagsDidChange
}
private func updateFeatureFlags() {
let xcodeChat = self.didChangeFeatureFlagsParams.envelope["xcode_chat"]?.boolValue != false
let chatEnabled = self.didChangeFeatureFlagsParams.envelope["chat_enabled"]?.boolValue != false
self.featureFlags.restrictedTelemetry = self.didChangeFeatureFlagsParams.token["rt"] != "0"
self.featureFlags.snippy = self.didChangeFeatureFlagsParams.token["sn"] != "0"
self.featureFlags.chat = xcodeChat && chatEnabled
self.featureFlags.inlineChat = chatEnabled
self.featureFlags.agentMode = self.didChangeFeatureFlagsParams.token["agent_mode"] != "0"
self.featureFlags.mcp = self.didChangeFeatureFlagsParams.token["mcp"] != "0"
self.featureFlags.ccr = self.didChangeFeatureFlagsParams.token["ccr"] != "0"
self.featureFlags.byok = self.didChangeFeatureFlagsParams.byok != false
self.featureFlags.editorPreviewFeatures = self.didChangeFeatureFlagsParams.token["editor_preview_features"] != "0"
self.featureFlags.activeExperimentForFeatureFlags = self.didChangeFeatureFlagsParams.activeExps
}
public func handleFeatureFlagNotification(_ didChangeFeatureFlagsParams: DidChangeFeatureFlagsParams) {
self.didChangeFeatureFlagsParams = didChangeFeatureFlagsParams
updateFeatureFlags()
DispatchQueue.main.async { [weak self] in
guard let self else { return }
self.featureFlagsDidChange.send(self.featureFlags)
DistributedNotificationCenter.default().post(name: .gitHubCopilotFeatureFlagsDidChange, object: nil)
}
}
}