Skip to content

Commit

Permalink
Release 20.2.0 (#616)
Browse files Browse the repository at this point in the history
* Types updates for FF enhancements

* iOS update

* Android update

* Bump version

* Update proxy
  • Loading branch information
rlepinski authored Dec 20, 2024
1 parent 17eaa0e commit 61bd0a7
Show file tree
Hide file tree
Showing 11 changed files with 187 additions and 44 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# React Native Module Changelog

## Version 20.2.0 - December 20, 2024
Minor release that updates to the latest Airship SDKs and adds new Feature Flag APIs.

### Changes
- Updated Android SDK to [18.6.0](https://github.com/urbanairship/android-library/releases/tag/18.6.0).
- Updated iOS SDK to [18.14.1](https://github.com/urbanairship/ios-library/releases/tag/18.14.1).
- Adds `Airship.featureFlagManager.resultCache` to cache a result that can be used when `Airship.featureFlagManager.flag` fails to resolve a result.

## Version 20.1.0 - December 5, 2024
Minor release that updates the Android Airship SDK to 18.5.0 and iOS Airship SDK to 18.13.0

Expand Down
2 changes: 1 addition & 1 deletion android/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ Airship_minSdkVersion=21
Airship_targetSdkVersion=34
Airship_compileSdkVersion=34
Airship_ndkversion=26.1.10909125
Airship_airshipProxyVersion=11.1.0
Airship_airshipProxyVersion=11.2.1
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import com.urbanairship.android.framework.proxy.proxies.SuspendingPredicate
import com.urbanairship.json.JsonMap
import com.urbanairship.json.JsonSerializable
import com.urbanairship.json.JsonValue
import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.filter
import java.util.UUID
Expand Down Expand Up @@ -698,21 +699,42 @@ class AirshipModule internal constructor(val context: ReactApplicationContext) :
}

@ReactMethod
override fun featureFlagManagerFlag(flagName: String?, promise: Promise) {
override fun featureFlagManagerFlag(flagName: String, useResultCache: Boolean, promise: Promise) {
promise.resolveSuspending(scope) {
requireNotNull(flagName)
proxy.featureFlagManager.flag(flagName)
proxy.featureFlagManager.flag(flagName, useResultCache)
}
}

@ReactMethod
override fun featureFlagManagerTrackInteraction(flag: ReadableMap?, promise: Promise) {
override fun featureFlagManagerTrackInteraction(flag: ReadableMap, promise: Promise) {
promise.resolveResult {
val parsedFlag = FeatureFlagProxy(Utils.convertMap(requireNotNull(flag)).toJsonValue())
val parsedFlag = FeatureFlagProxy(Utils.convertMap(flag).toJsonValue())
proxy.featureFlagManager.trackInteraction(parsedFlag)
}
}

@ReactMethod
override fun featureFlagManagerResultCacheGetFlag(flagName: String, promise: Promise) {
promise.resolveSuspending(scope) {
proxy.featureFlagManager.resultCache.flag(flagName)
}
}

@ReactMethod
override fun featureFlagManagerResultCacheSetFlag(flag: ReadableMap, ttl: Double, promise: Promise) {
promise.resolveSuspending(scope) {
val parsedFlag = FeatureFlagProxy(Utils.convertMap(flag).toJsonValue())
proxy.featureFlagManager.resultCache.cache(parsedFlag, ttl.milliseconds)
}
}

@ReactMethod
override fun featureFlagManagerResultCacheRemoveFlag(flagName: String, promise: Promise) {
promise.resolveSuspending(scope) {
proxy.featureFlagManager.resultCache.removeCachedFlag(flagName)
}
}

@ReactMethod
override fun liveActivityListAll(promise: Promise) {
promise.resolveResult {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -407,11 +407,23 @@ abstract class AirshipSpec internal constructor(context: ReactApplicationContext

@ReactMethod
@com.facebook.proguard.annotations.DoNotStrip
abstract fun featureFlagManagerFlag(flagName: String?, promise: Promise)
abstract fun featureFlagManagerFlag(flagName: String, useResultCache: Boolean, promise: Promise)

@ReactMethod
@com.facebook.proguard.annotations.DoNotStrip
abstract fun featureFlagManagerTrackInteraction(flag: ReadableMap?, promise: Promise)
abstract fun featureFlagManagerTrackInteraction(flag: ReadableMap, promise: Promise)

@ReactMethod
@com.facebook.proguard.annotations.DoNotStrip
abstract fun featureFlagManagerResultCacheGetFlag(flagName: String, promise: Promise)

@ReactMethod
@com.facebook.proguard.annotations.DoNotStrip
abstract fun featureFlagManagerResultCacheSetFlag(flag: ReadableMap, ttl: Double, promise: Promise)

@ReactMethod
@com.facebook.proguard.annotations.DoNotStrip
abstract fun featureFlagManagerResultCacheRemoveFlag(flagName: String, promise: Promise)

@ReactMethod
@com.facebook.proguard.annotations.DoNotStrip
Expand Down
46 changes: 23 additions & 23 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
PODS:
- Airship (18.13.0):
- Airship/Automation (= 18.13.0)
- Airship/Basement (= 18.13.0)
- Airship/Core (= 18.13.0)
- Airship/FeatureFlags (= 18.13.0)
- Airship/MessageCenter (= 18.13.0)
- Airship/PreferenceCenter (= 18.13.0)
- Airship/Automation (18.13.0):
- Airship (18.14.1):
- Airship/Automation (= 18.14.1)
- Airship/Basement (= 18.14.1)
- Airship/Core (= 18.14.1)
- Airship/FeatureFlags (= 18.14.1)
- Airship/MessageCenter (= 18.14.1)
- Airship/PreferenceCenter (= 18.14.1)
- Airship/Automation (18.14.1):
- Airship/Core
- Airship/Basement (18.13.0)
- Airship/Core (18.13.0):
- Airship/Basement (18.14.1)
- Airship/Core (18.14.1):
- Airship/Basement
- Airship/FeatureFlags (18.13.0):
- Airship/FeatureFlags (18.14.1):
- Airship/Core
- Airship/MessageCenter (18.13.0):
- Airship/MessageCenter (18.14.1):
- Airship/Core
- Airship/PreferenceCenter (18.13.0):
- Airship/PreferenceCenter (18.14.1):
- Airship/Core
- AirshipFrameworkProxy (11.1.0):
- Airship (= 18.13.0)
- AirshipServiceExtension (18.13.0)
- AirshipFrameworkProxy (11.2.1):
- Airship (= 18.14.1)
- AirshipServiceExtension (18.14.0)
- boost (1.83.0)
- DoubleConversion (1.1.6)
- FBLazyVector (0.73.4)
Expand Down Expand Up @@ -907,8 +907,8 @@ PODS:
- React-Mapbuffer (0.73.4):
- glog
- React-debug
- react-native-airship (20.1.0):
- AirshipFrameworkProxy (= 11.1.0)
- react-native-airship (20.2.0):
- AirshipFrameworkProxy (= 11.2.1)
- glog
- RCT-Folly (= 2022.05.16.00)
- React-Core
Expand Down Expand Up @@ -1279,9 +1279,9 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/yoga"

SPEC CHECKSUMS:
Airship: bfe90d95c2b2bd0ea9ed5248a1337f124fe8abfe
AirshipFrameworkProxy: 15e4589484430c292aadc7e9f9878d83b7c0fd25
AirshipServiceExtension: aefb21acb70a7476279793d6e38be2bd612817d0
Airship: f293470bde4a4cbd23ac73dbda986629d9ad9fdb
AirshipFrameworkProxy: 9332b3f7871f054375653e72428fbcf4a3a9f849
AirshipServiceExtension: 1d6c2443724f6ea541eecb76ddbaab307809d561
boost: d3f49c53809116a5d38da093a8aa78bf551aed09
DoubleConversion: fea03f2699887d960129cc54bba7e52542b6f953
FBLazyVector: 84f6edbe225f38aebd9deaf1540a4160b1f087d7
Expand Down Expand Up @@ -1311,7 +1311,7 @@ SPEC CHECKSUMS:
React-jsinspector: 9ac353eccf6ab54d1e0a33862ba91221d1e88460
React-logger: 0a57b68dd2aec7ff738195f081f0520724b35dab
React-Mapbuffer: 63913773ed7f96b814a2521e13e6d010282096ad
react-native-airship: adf4c86f2971ffe1f5f30b7c150d73e60725e009
react-native-airship: a4111a9d2ecb4b12bc021698917be8eeded34793
react-native-safe-area-context: b97eb6f9e3b7f437806c2ce5983f479f8eb5de4b
React-nativeconfig: d7af5bae6da70fa15ce44f045621cf99ed24087c
React-NativeModulesApple: 0123905d5699853ac68519607555a9a4f5c7b3ac
Expand Down Expand Up @@ -1342,4 +1342,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: 71939b1c0f451ff75f31df2f5e51d1c63f04150d

COCOAPODS: 1.16.2
COCOAPODS: 1.15.2
26 changes: 23 additions & 3 deletions ios/AirshipReactNative.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public class AirshipReactNative: NSObject {
AirshipProxy.shared
}

public static let version: String = "20.1.0"
public static let version: String = "20.2.0"

private let eventNotifier = EventNotifier()

Expand Down Expand Up @@ -599,8 +599,8 @@ public extension AirshipReactNative {
@objc
public extension AirshipReactNative {
@objc
func featureFlagManagerFlag(flagName: String) async throws -> Any {
let result = try await AirshipProxy.shared.featureFlagManager.flag(name: flagName)
func featureFlagManagerFlag(flagName: String, useResultCache: Bool) async throws -> Any {
let result = try await AirshipProxy.shared.featureFlagManager.flag(name: flagName, useResultCache: useResultCache)
return try AirshipJSON.wrap(result).unWrap() as Any
}

Expand All @@ -609,6 +609,26 @@ public extension AirshipReactNative {
let flag: FeatureFlagProxy = try AirshipJSON.wrap(flag).decode()
try AirshipProxy.shared.featureFlagManager.trackInteraction(flag: flag)
}

@objc
func featureFlagManagerResultCacheGetFlag(name: String) async throws -> Any {
let result = try await AirshipProxy.shared.featureFlagManager.resultCache.flag(name: name)
return try AirshipJSON.wrap(result).unWrap() as Any
}

@objc
func featureFlagManagerResultCacheSetFlag(flag: Any, ttl: NSNumber) async throws {
let flag: FeatureFlagProxy = try AirshipJSON.wrap(flag).decode()
try await AirshipProxy.shared.featureFlagManager.resultCache.cache(
flag: flag,
ttl: TimeInterval(ttl.uint64Value/1000)
)
}

@objc
func featureFlagManagerResultCacheRemoveFlag(name: String) async throws {
try await AirshipProxy.shared.featureFlagManager.resultCache.removeCachedFlag(name: name)
}
}


Expand Down
38 changes: 38 additions & 0 deletions ios/RTNAirship.mm
Original file line number Diff line number Diff line change
Expand Up @@ -783,15 +783,53 @@ + (BOOL)requiresMainQueueSetup {

RCT_REMAP_METHOD(featureFlagManagerFlag,
featureFlagManagerFlag:(NSString *)flagName
useResultCache:(BOOL)useResultCache
featureFlagManagerFlag:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject) {

[AirshipReactNative.shared featureFlagManagerFlagWithFlagName:flagName
useResultCache:useResultCache
completionHandler:^(id result, NSError * _Nullable error) {
[self handleResult:result error:error resolve:resolve reject:reject];
}];
}

RCT_REMAP_METHOD(featureFlagManagerResultCacheGetFlag,
featureFlagManagerResultCacheGetFlag:(NSString *)flagName
featureFlagManagerResultCacheGetFlag:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject) {

[AirshipReactNative.shared featureFlagManagerResultCacheGetFlagWithName:flagName
completionHandler:^(id result, NSError * _Nullable error) {
[self handleResult:result error:error resolve:resolve reject:reject];
}];
}

RCT_REMAP_METHOD(featureFlagManagerResultCacheSetFlag,
featureFlagManagerResultCacheSetFlag:(NSDictionary *)flag
ttl:(nonnull NSNumber *)ttl
featureFlagManagerResultCacheGetFlag:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject) {

[AirshipReactNative.shared featureFlagManagerResultCacheSetFlagWithFlag:flag
ttl:ttl
completionHandler:^(NSError * _Nullable error) {
[self handleResult:nil error:error resolve:resolve reject:reject];
}];
}

RCT_REMAP_METHOD(featureFlagManagerResultCacheRemoveFlag,
featureFlagManagerResultCacheRemoveFlag:(NSString *)flagName
featureFlagManagerResultCacheRemoveFlag:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject) {

[AirshipReactNative.shared featureFlagManagerResultCacheRemoveFlagWithName:flagName
completionHandler:^(NSError * _Nullable error) {
[self handleResult:nil error:error resolve:resolve reject:reject];
}];
}


RCT_REMAP_METHOD(liveActivityListAll,
liveActivityListAll:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject) {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ua/react-native-airship",
"version": "20.1.0",
"version": "20.2.0",
"description": "Airship plugin for React Native apps.",
"main": "lib/commonjs/index",
"module": "lib/module/index",
Expand Down
2 changes: 1 addition & 1 deletion react-native-airship.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ Pod::Spec.new do |s|
s.dependency "React-Core"
end

s.dependency "AirshipFrameworkProxy", "11.1.0"
s.dependency "AirshipFrameworkProxy", "11.2.1"

end
54 changes: 47 additions & 7 deletions src/AirshipFeatureFlagManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,30 @@ import { FeatureFlag } from './types';
* Airship feature flag manager.
*/
export class AirshipFeatureFlagManager {
constructor(private readonly module: any) {}
/**
* Feature flag cache.
*/
public readonly resultCache: AirshipFeatureFlagResultCache;

/**
constructor(private readonly module: any) {
this.resultCache = new AirshipFeatureFlagResultCache(module);
}

/**
* Retrieve a given flag's status and associated data by its name.
* @param {string} flagName The flag name
* @return {Promise<FeatureFlag>} A promise resolving to the feature flag
* requested.
* @param {boolean} useResultCache If the response should use result cache or not.
* @return {Promise<FeatureFlag>} A promise resolving to the feature flag requested.
* @throws {Error} when failed to fetch
*/
public flag(
flagName: string
flagName: string,
useResultCache: boolean = true
): Promise<FeatureFlag> {
return this.module.featureFlagManagerFlag(flagName);
return this.module.featureFlagManagerFlag(flagName, useResultCache);
}

/**
/**
* Tracks a feature flag interaction event.
* @param {FeatureFlag} flag The flag
* @return {Promise<Void>} A promise with an empty result.
Expand All @@ -29,3 +37,35 @@ export class AirshipFeatureFlagManager {
return this.module.featureFlagManagerTrackInteraction(flag);
}
}

export class AirshipFeatureFlagResultCache {
constructor(private readonly module: any) {}

/**
* Retrieve a flag from the cache.
* @param {string} flagName The flag name
* @return {Promise<FeatureFlag>} A promise resolving to the feature flag.
*/
public flag(flagName: string): Promise<FeatureFlag> {
return this.module.featureFlagManagerResultCacheGetFlag(flagName);
}

/**
* Caches a feature flag.
* @param {FeatureFlag} flag The flag
* @param {FeatureFlag} ttl Cache TTL in milliseconds.
* @return {Promise<Void>} A promise with an empty result.
*/
public cache(flag: FeatureFlag, ttl: number): Promise<void> {
return this.module.featureFlagManagerResultCacheSetFlag(flag, ttl);
}

/**
* Clears the cache for a given flag.
* @param {FeatureFlag} flagName The flag name
* @return {Promise<Void>} A promise with an empty result.
*/
public removeCachedFlag(flagName: string): Promise<void> {
return this.module.featureFlagManagerResultCacheRemoveFlag(flagName);
}
}
5 changes: 4 additions & 1 deletion src/NativeRTNAirship.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,11 @@ export interface Spec extends TurboModule {
localeClearLocaleOverride(): Promise<void>;

// Feature Flag Manager
featureFlagManagerFlag(flagName: string):Promise<Object>;
featureFlagManagerFlag(flagName: string, userResultCache: boolean):Promise<Object>;
featureFlagManagerTrackInteraction(flag: Object): Promise<void>;
featureFlagManagerResultCacheGetFlag(flagName: string): Promise<Object>;
featureFlagManagerResultCacheSetFlag(flag: Object, ttl: number): Promise<void>;
featureFlagManagerResultCacheRemoveFlag(flagName: string): Promise<void>;

// Live Activity
liveActivityListAll(): Promise<Object>;
Expand Down

0 comments on commit 61bd0a7

Please sign in to comment.