Skip to content
This repository was archived by the owner on Oct 29, 2024. It is now read-only.

Commit 171192e

Browse files
prepare 6.1.0 release (#119)
### Added: - Added `privateAttributeNames` configuration option for `LDConfig` allowing the configuration of private attributes for all users. ([#102](#102)) ### Fixed: - Android: Updated Android SDK dependency to [3.1.3](https://github.com/launchdarkly/android-client-sdk/releases/tag/3.1.3). - Android: Added missing native module API stubs to prevent warning on `NativeEventEmitter`. ([#116](#116)) - iOS: Fixed ownership handling of native callbacks to avoid garbage collection of all flags and connection mode listeners that are still in use. ([#106](#106))
1 parent ecc0cfe commit 171192e

File tree

8 files changed

+54
-27
lines changed

8 files changed

+54
-27
lines changed

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ workflows:
138138
name: rn<<matrix.rn-version>>-xc<<matrix.xcode-version>>-build-apps-using-template
139139
matrix:
140140
parameters:
141-
rn-version: ["0.64.3", "0.65.2", "0.66.4", "0.67.2"]
141+
rn-version: ["0.64.3", "0.65.2", "0.66.4", "0.67.3"]
142142
xcode-version: ["12.2.0", "12.5.1", "13.2.1"]
143143
requires:
144144
- test-javascript

ManualTestApp/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
## Manual testing application
22

3-
Add your mobile key in `App.js`, `npx pod-install`, `yarn run <android|ios>`.
3+
Add your mobile key in `App.js`, `npx yarn install`, `npx pod-install`, `npx yarn run <android|ios>`.

ManualTestApp/yarn.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3137,7 +3137,7 @@ kleur@^3.0.3:
31373137
integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
31383138

31393139
"launchdarkly-react-native-client-sdk@file:..":
3140-
version "5.1.1"
3140+
version "6.0.0"
31413141

31423142
leven@^3.1.0:
31433143
version "3.1.0"

android/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ allprojects {
4545

4646
dependencies {
4747
implementation("com.facebook.react:react-native:+")
48-
implementation("com.launchdarkly:launchdarkly-android-client-sdk:3.1.2")
48+
implementation("com.launchdarkly:launchdarkly-android-client-sdk:3.1.3")
4949
implementation("com.jakewharton.timber:timber:5.0.1")
5050
implementation("com.google.code.gson:gson:2.8.9")
5151
}

android/src/main/java/com/launchdarkly/reactnative/LaunchdarklyReactNativeClientModule.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,16 @@ public Map<String, Object> getConstants() {
187187
return constants;
188188
}
189189

190+
@ReactMethod
191+
public void addListener(String eventName) {
192+
// Keep: Required for RN built in Event Emitter Calls.
193+
}
194+
195+
@ReactMethod
196+
public void removeListeners(Integer count) {
197+
// Keep: Required for RN built in Event Emitter Calls.
198+
}
199+
190200
@ReactMethod
191201
public void configure(ReadableMap config, ReadableMap user, final Promise promise) {
192202
internalConfigure(config, user, null, promise);

index.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,14 @@ declare module 'launchdarkly-react-native-client-sdk' {
189189
* that provides the full details for the user.
190190
*/
191191
inlineUsersInEvents?: boolean;
192+
193+
/**
194+
* The names of user attributes that should be marked as private, and not sent to
195+
* LaunchDarkly in analytics events.
196+
*
197+
* You can also specify this on a per-user basis with [[LDUser.privateAttributeNames]].
198+
*/
199+
privateAttributeNames?: string[]
192200
};
193201

194202
/**

ios/LaunchdarklyReactNativeClient.swift

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,17 @@ import LaunchDarkly
33

44
@objc(LaunchdarklyReactNativeClient)
55
class LaunchdarklyReactNativeClient: RCTEventEmitter {
6-
private var listenerKeys: [String:LDObserverOwner] = [:]
7-
86
private let FLAG_PREFIX = "LaunchDarkly-Flag-"
97
private let ALL_FLAGS_PREFIX = "LaunchDarkly-All-Flags-"
108
private let CONNECTION_MODE_PREFIX = "LaunchDarkly-Connection-Mode-"
119
private let ERROR_INIT = "E_INITIALIZE"
1210
private let ERROR_IDENTIFY = "E_IDENTIFY"
1311
private let ERROR_UNKNOWN = "E_UNKNOWN"
14-
12+
13+
private var flagListenerOwners: [String: ObserverOwner] = [:]
14+
private var allFlagsListenerOwners: [String: ObserverOwner] = [:]
15+
private var connectionModeListenerOwners: [String: ObserverOwner] = [:]
16+
1517
override func supportedEvents() -> [String]! {
1618
return [FLAG_PREFIX, ALL_FLAGS_PREFIX, CONNECTION_MODE_PREFIX]
1719
}
@@ -89,6 +91,7 @@ class LaunchdarklyReactNativeClient: RCTEventEmitter {
8991
configField(&ldConfig.allUserAttributesPrivate, config["allUserAttributesPrivate"], id)
9092
configField(&ldConfig.autoAliasingOptOut, config["autoAliasingOptOut"], id)
9193
configField(&ldConfig.inlineUserInEvents, config["inlineUsersInEvents"], id)
94+
configField(&ldConfig.privateUserAttributes, config["privateAttributeNames"], id)
9295

9396
if let val = config["secondaryMobileKeys"] as? [String: String] {
9497
try! ldConfig.setSecondaryMobileKeys(val)
@@ -382,53 +385,56 @@ class LaunchdarklyReactNativeClient: RCTEventEmitter {
382385

383386
@objc func registerFeatureFlagListener(_ flagKey: String, environment: String) -> Void {
384387
let multiListenerId = envConcat(environment: environment, identifier: flagKey)
385-
let flagChangeOwner = multiListenerId as LDObserverOwner
386-
listenerKeys[multiListenerId] = flagChangeOwner
387-
LDClient.get(environment: environment)!.observe(key: flagKey, owner: flagChangeOwner, handler: { changedFlag in
388+
let owner = ObserverOwner()
389+
flagListenerOwners[multiListenerId] = owner
390+
LDClient.get(environment: environment)!.observe(key: flagKey, owner: owner) { changedFlag in
388391
if self.bridge != nil {
389392
self.sendEvent(withName: self.FLAG_PREFIX, body: ["flagKey": changedFlag.key, "listenerId": multiListenerId])
390393
}
391-
})
392-
}
393-
394-
private func unregisterListener(_ key: String, _ environment: String) -> Void {
395-
let multiListenerId = envConcat(environment: environment, identifier: key)
396-
let owner = multiListenerId as LDObserverOwner
397-
if listenerKeys.removeValue(forKey: multiListenerId) != nil {
398-
LDClient.get(environment: environment)!.stopObserving(owner: owner)
399394
}
400395
}
401396

402397
@objc func unregisterFeatureFlagListener(_ flagKey: String, environment: String) -> Void {
403-
unregisterListener(flagKey, environment)
398+
let multiListenerId = envConcat(environment: environment, identifier: flagKey)
399+
if let owner = flagListenerOwners.removeValue(forKey: multiListenerId) {
400+
LDClient.get(environment: environment)!.stopObserving(owner: owner)
401+
}
404402
}
405403

406404
@objc func registerCurrentConnectionModeListener(_ listenerId: String, environment: String) -> Void {
407405
let multiListenerId = envConcat(environment: environment, identifier: listenerId)
408-
let currentConnectionModeOwner = multiListenerId as LDObserverOwner
409-
LDClient.get(environment: environment)!.observeCurrentConnectionMode(owner: currentConnectionModeOwner, handler: { connectionMode in
406+
let owner = ObserverOwner()
407+
connectionModeListenerOwners[multiListenerId] = owner
408+
LDClient.get(environment: environment)!.observeCurrentConnectionMode(owner: owner) { connectionMode in
410409
if self.bridge != nil {
411410
self.sendEvent(withName: self.CONNECTION_MODE_PREFIX, body: ["connectionMode": connectionMode, "listenerId": multiListenerId])
412411
}
413-
})
412+
}
414413
}
415414

416415
@objc func unregisterCurrentConnectionModeListener(_ listenerId: String, environment: String) -> Void {
417-
unregisterListener(listenerId, environment)
416+
let multiListenerId = envConcat(environment: environment, identifier: listenerId)
417+
if let owner = connectionModeListenerOwners.removeValue(forKey: multiListenerId) {
418+
LDClient.get(environment: environment)!.stopObserving(owner: owner)
419+
}
418420
}
419421

420422
@objc func registerAllFlagsListener(_ listenerId: String, environment: String) -> Void {
421423
let multiListenerId = envConcat(environment: environment, identifier: listenerId)
422-
let flagChangeOwner = multiListenerId as LDObserverOwner
423-
LDClient.get(environment: environment)!.observeAll(owner: flagChangeOwner, handler: { changedFlags in
424+
let owner = ObserverOwner()
425+
allFlagsListenerOwners[multiListenerId] = owner
426+
LDClient.get(environment: environment)!.observeAll(owner: owner) { changedFlags in
424427
if self.bridge != nil {
425428
self.sendEvent(withName: self.ALL_FLAGS_PREFIX, body: ["flagKeys": Array(changedFlags.keys), "listenerId": multiListenerId])
426429
}
427-
})
430+
}
428431
}
429432

430433
@objc func unregisterAllFlagsListener(_ listenerId: String, environment: String) -> Void {
431-
unregisterListener(listenerId, environment)
434+
let multiListenerId = envConcat(environment: environment, identifier: listenerId)
435+
if let owner = allFlagsListenerOwners.removeValue(forKey: multiListenerId) {
436+
LDClient.get(environment: environment)!.stopObserving(owner: owner)
437+
}
432438
}
433439

434440
@objc func isInitialized(_ environment: String, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) -> Void {
@@ -442,6 +448,8 @@ class LaunchdarklyReactNativeClient: RCTEventEmitter {
442448
}
443449
}
444450

451+
class ObserverOwner{}
452+
445453
extension NSDictionary {
446454
@objc var swiftDictionary: Dictionary<String, Any> {
447455
var swiftDictionary = Dictionary<String, Any>()

test-types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ async function tests() {
4848
allUserAttributesPrivate: true,
4949
autoAliasingOptOut: true,
5050
inlineUsersInEvents: true,
51+
privateAttributeNames: ['abc', 'def'],
5152
};
5253
const userEmpty: LDUser = {};
5354
const userWithKeyOnly: LDUser = { key: 'user' };

0 commit comments

Comments
 (0)