Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP release 16.1.0 #526

Merged
merged 9 commits into from
Sep 11, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
# React Native Module Changelog

## Version 16.1.0 - September 06, 2023
Minor release that updates the iOS SDK to 17.2.2 and Android SDK to 17.2.0. Also adds support for Airship Feature Flag feature and for Channel Tag Editor.

### Changes
- Updated iOS SDK to 17.2.2
- Updated Android SDK to 17.2.0
- Added support for Airship Feature Flag feature
- Added a new method `Airship.channel.editTags()`

## Version 16.0.1 - July 21, 2023
Patch release that updates the iOS and Android Airship SDK to 17.0.3.
Expand Down
4 changes: 2 additions & 2 deletions android/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ Airship_targetSdkVersion=31
Airship_compileSdkVersion=31
Airship_ndkversion=21.4.7075529

Airship_airshipProxyVersion=3.0.2
Airship_airshipProxyVersion=4.1.0

# workaround for now, used for HMS
Airship_airshipVersion=17.0.3
Airship_airshipVersion=17.2.0

Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,8 @@ import com.urbanairship.android.framework.proxy.proxies.SuspendingPredicate
import com.urbanairship.json.JsonMap
import com.urbanairship.json.JsonSerializable
import com.urbanairship.json.JsonValue
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.launch
import java.util.UUID

class AirshipModule internal constructor(val context: ReactApplicationContext) : AirshipSpec(context) {
Expand All @@ -27,6 +25,8 @@ class AirshipModule internal constructor(val context: ReactApplicationContext) :
private var isOverrideForegroundDisplayEnabled: Boolean = false
private val foregroundDisplayRequestMap = mutableMapOf<String, CompletableDeferred<Boolean>>()

private val scope: CoroutineScope = CoroutineScope(Dispatchers.Main) + SupervisorJob()
rlepinski marked this conversation as resolved.
Show resolved Hide resolved

private val foregroundDisplayPredicate = object : SuspendingPredicate<Map<String, Any>> {
override suspend fun apply(value: Map<String, Any>): Boolean {
val deferred = CompletableDeferred<Boolean>()
Expand All @@ -53,11 +53,11 @@ class AirshipModule internal constructor(val context: ReactApplicationContext) :
override fun initialize() {
super.initialize()

MainScope().launch {
scope.launch {
// Background events will create a headless JS task in ReactAutopilot since
// initialized wont be called until we have a JS task.
EventEmitter.shared().pendingEventListener
.filter { it.isForeground() }
.filter { it.type.isForeground() }
.collect {
notifyPending()
}
Expand Down Expand Up @@ -621,6 +621,20 @@ class AirshipModule internal constructor(val context: ReactApplicationContext) :
}
}

override fun featureFlagManagerFlag(flagName: String?, promise: Promise) {
promise.resolveDeferred { callback ->
scope.launch {
try {
requireNotNull(flagName)
val flag = proxy.featureFlagManager.flag(flagName)
callback(flag, null)
} catch (e: Exception) {
callback(null, e)
}
}
}
}

private fun notifyPending() {
if (context.hasActiveReactInstance()) {
val appEventEmitter = context.getJSModule(RCTNativeAppEventEmitter::class.java)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class ReactAutopilot : BaseAutopilot() {

MainScope().launch {
EventEmitter.shared().pendingEventListener
.filter { !it.isForeground() }
.filter { !it.type.isForeground() }
.collect {
AirshipHeadlessEventService.startService(context)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,10 @@ abstract class AirshipSpec internal constructor(context: ReactApplicationContext
@ReactMethod
@com.facebook.proguard.annotations.DoNotStrip
abstract fun pushIosGetAuthorizedNotificationStatus(promise: Promise)

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


53 changes: 30 additions & 23 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
PODS:
- Airship (17.0.3):
- Airship/Automation (= 17.0.3)
- Airship/Basement (= 17.0.3)
- Airship/Core (= 17.0.3)
- Airship/MessageCenter (= 17.0.3)
- Airship/PreferenceCenter (= 17.0.3)
- Airship/Automation (17.0.3):
- Airship (17.2.2):
- Airship/Automation (= 17.2.2)
- Airship/Basement (= 17.2.2)
- Airship/Core (= 17.2.2)
- Airship/FeatureFlags (= 17.2.2)
- Airship/MessageCenter (= 17.2.2)
- Airship/PreferenceCenter (= 17.2.2)
- Airship/Automation (17.2.2):
- Airship/Core
- Airship/Basement (17.0.3)
- Airship/Core (17.0.3):
- Airship/Basement (17.2.2)
- Airship/Core (17.2.2):
- Airship/Basement
- Airship/MessageCenter (17.0.3):
- Airship/FeatureFlags (17.2.2):
- Airship/Core
- Airship/PreferenceCenter (17.0.3):
- Airship/MessageCenter (17.2.2):
- Airship/Core
- AirshipFrameworkProxy (3.0.2):
- Airship (= 17.0.3)
- Airship/PreferenceCenter (17.2.2):
- Airship/Core
- AirshipFrameworkProxy (4.1.0):
- Airship (= 17.2.2)
- boost (1.76.0)
- CocoaAsyncSocket (7.6.5)
- DoubleConversion (1.1.6)
Expand Down Expand Up @@ -315,10 +318,14 @@ PODS:
- React-logger (0.71.1):
- glog
- react-native-airship (16.0.1):
- AirshipFrameworkProxy (= 3.0.2)
- AirshipFrameworkProxy (= 4.1.0)
- React-Core
- react-native-safe-area-context (4.7.1):
- react-native-safe-area-context (4.5.0):
- RCT-Folly
- RCTRequired
- RCTTypeSafety
- React-Core
- ReactCommon/turbomodule/core
- React-perflogger (0.71.1)
- React-RCTActionSheet (0.71.1):
- React-Core/RCTActionSheetHeaders (= 0.71.1)
Expand Down Expand Up @@ -400,9 +407,9 @@ PODS:
- React-jsi (= 0.71.1)
- React-logger (= 0.71.1)
- React-perflogger (= 0.71.1)
- RNGestureHandler (2.12.0):
- RNGestureHandler (2.9.0):
- React-Core
- RNScreens (3.22.1):
- RNScreens (3.19.0):
- React-Core
- React-RCTImage
- SocketRocket (0.6.1)
Expand Down Expand Up @@ -574,8 +581,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/yoga"

SPEC CHECKSUMS:
Airship: 9fdd1ccc3a78c42544f34b7de043d39491951023
AirshipFrameworkProxy: 9a0a26b1b117fe3ccbe1b2d4a9053875e2c0d6d2
Airship: f5a106a6daa01ba46ae2f519b1b3d4595e7e0972
AirshipFrameworkProxy: b9822473fef17241cf54508770fdf198f1af9405
boost: 57d2868c099736d80fcd648bf211b4431e51a558
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
Expand Down Expand Up @@ -609,8 +616,8 @@ SPEC CHECKSUMS:
React-jsiexecutor: 60cf272aababc5212410e4249d17cea14fc36caa
React-jsinspector: ff56004b0c974b688a6548c156d5830ad751ae07
React-logger: 60a0b5f8bed667ecf9e24fecca1f30d125de6d75
react-native-airship: 68a842b1002cabb9e8f12a13cbf7c38260eae868
react-native-safe-area-context: 9697629f7b2cda43cf52169bb7e0767d330648c2
react-native-airship: cb708f7d12b3fcea474119f2eb694d686aac54f6
react-native-safe-area-context: 39c2d8be3328df5d437ac1700f4f3a4f75716acc
React-perflogger: ec8eef2a8f03ecfa6361c2c5fb9197ef4a29cc85
React-RCTActionSheet: a0c023b86cf4c862fa9c4eb0f6f91fbe878fb2de
React-RCTAnimation: 168d53718c74153947c0109f55900faa64d79439
Expand All @@ -624,8 +631,8 @@ SPEC CHECKSUMS:
React-RCTVibration: 49d531ec8498e0afa2c9b22c2205784372e3d4f3
React-runtimeexecutor: 311feb67600774723fe10eb8801d3138cae9ad67
ReactCommon: 03be76588338a27a88d103b35c3c44a3fd43d136
RNGestureHandler: dec4645026e7401a0899f2846d864403478ff6a5
RNScreens: 50ffe2fa2342eabb2d0afbe19f7c1af286bc7fb3
RNGestureHandler: 071d7a9ad81e8b83fe7663b303d132406a7d8f39
RNScreens: ea4cd3a853063cda19a4e3c28d2e52180c80f4eb
SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17
Yoga: 921eb014669cf9c718ada68b08d362517d564e0c
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
Expand Down
8 changes: 4 additions & 4 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ Airship.addListener(EventType.ChannelCreated, (event) => {
console.log('ChannelCreated:', JSON.stringify(event));
});

Airship.addListener(EventType.NotificationStatusChangedStatus, (event) => {
console.log('NotificationStatusChangedStatus:', JSON.stringify(event));
Airship.addListener(EventType.PushNotificationStatusChangedStatus, (event) => {
console.log('PushNotificationStatusChangedStatus:', JSON.stringify(event));
});

Airship.addListener(EventType.iOSAuthorizedNotificationSettingsChanged, (event) => {
console.log('iOSAuthorizedNotificationSettingsChanged:', JSON.stringify(event));
Airship.addListener(EventType.IOSAuthorizedNotificationSettingsChanged, (event) => {
console.log('IOSAuthorizedNotificationSettingsChanged:', JSON.stringify(event));
});


Expand Down
15 changes: 13 additions & 2 deletions ios/AirshipReactNative.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public class AirshipReactNative: NSObject {
AirshipProxy.shared
}

public static let version: String = "16.0.1"
public static let version: String = "16.1.0"

private let eventNotifier = EventNotifier()

Expand Down Expand Up @@ -106,7 +106,7 @@ public class AirshipReactNative: NSObject {
try? AirshipProxy.shared.attemptTakeOff(launchOptions: launchOptions)

Task {
let stream = await AirshipProxyEventEmitter.shared.pendingEventTypeAdded
let stream = await AirshipProxyEventEmitter.shared.pendingEventAdded
for await _ in stream {
await self.eventNotifier.notifyPendingEvents()
}
Expand Down Expand Up @@ -540,6 +540,17 @@ public extension AirshipReactNative {
}



// Feature Flag Manager
@objc
public extension AirshipReactNative {
@objc
func featureFlagManagerFlag(flagName: String) async throws -> Any {
let result = try await AirshipProxy.shared.featureFlagManager.flag(name: flagName)
return try AirshipJSON.wrap(result).unWrap() as Any
}
}

extension AirshipReactNative: AirshipProxyDelegate {
public func migrateData(store: ProxyStore) {
ProxyDataMigrator().migrateData(store: store)
Expand Down
11 changes: 11 additions & 0 deletions ios/RTNAirship.mm
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,17 @@ + (BOOL)requiresMainQueueSetup {
// Android only
}

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

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


-(void)handleResult:(id)result
error:(NSError *)error
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": "16.0.1",
"version": "16.1.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 @@ -36,6 +36,6 @@ Pod::Spec.new do |s|



s.dependency "AirshipFrameworkProxy", "3.0.2"
s.dependency "AirshipFrameworkProxy", "4.1.0"

end
21 changes: 21 additions & 0 deletions src/AirshipFeatureFlagManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { FeatureFlag } from './types';

/**
* Airship feature flag manager.
*/
export class AirshipFeatureFlagManager {
constructor(private readonly module: any) {}

/**
* 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.
* @throws {Error} when failed to fetch
*/
public flag(
flagName: string
): Promise<FeatureFlag> {
return this.module.featureFlagManagerFlag(flagName);
}
}
4 changes: 4 additions & 0 deletions src/AirshipRoot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { AirshipMessageCenter } from './AirshipMessageCenter';
import { AirshipPreferenceCenter } from './AirshipPreferenceCenter';
import { AirshipPrivacyManager } from './AirshipPrivacyManager';
import { AirshipPush } from './AirshipPush';
import { AirshipFeatureFlagManager } from './AirshipFeatureFlagManager';

import { AirshipConfig, EventTypeMap, EventType } from './types';
import { Subscription, UAEventEmitter } from './UAEventEmitter';

Expand All @@ -25,6 +27,7 @@ export class AirshipRoot {
public readonly preferenceCenter: AirshipPreferenceCenter;
public readonly privacyManager: AirshipPrivacyManager;
public readonly push: AirshipPush;
public readonly featureFlagManager: AirshipFeatureFlagManager;

private readonly eventEmitter: UAEventEmitter;

Expand All @@ -39,6 +42,7 @@ export class AirshipRoot {
this.preferenceCenter = new AirshipPreferenceCenter(module);
this.privacyManager = new AirshipPrivacyManager(module);
this.push = new AirshipPush(module);
this.featureFlagManager = new AirshipFeatureFlagManager(module);
this.eventEmitter = new UAEventEmitter(module);
}

Expand Down
3 changes: 3 additions & 0 deletions src/NativeRTNAirship.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ export interface Spec extends TurboModule {
localeSetLocaleOverride(localeIdentifier: string): Promise<void>;
localeGetLocale(): Promise<string>;
localeClearLocaleOverride(): Promise<void>;

// Feature Flag Manager
featureFlagManagerFlag(flagName: string):Promise<Object>;
}

export default TurboModuleRegistry.getEnforcing<Spec>('RTNAirship');
2 changes: 2 additions & 0 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ export { AirshipLocale } from './AirshipLocale';
export { AirshipMessageCenter } from './AirshipMessageCenter';
export { AirshipPreferenceCenter } from './AirshipPreferenceCenter';
export { AirshipPrivacyManager } from './AirshipPrivacyManager';
export { AirshipFeatureFlagManager } from './AirshipFeatureFlagManager';

export { AirshipPush, AirshipPushAndroid, AirshipPushIOS } from './AirshipPush';
export { CustomEvent } from './CustomEvent';
export { SubscriptionListEditor } from './SubscriptionListEditor';
Expand Down
26 changes: 26 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -710,3 +710,29 @@ export type Item =
| AlertItem;

export type Section = CommonSection | LabeledSectionBreak;


/**
* An interface representing the eligibility status of a flag, and optional
* variables associated with the flag.
*/
export interface FeatureFlag {
/**
* A boolean representing flag eligibility; will be `true` if the current
* contact is eligible for the flag.
*/
readonly isEligible: boolean
/**
* A variables associated with the flag, if any. Will be `null` if no data
* is associated with the flag, or if the flag does not exist.
*/
readonly variables: unknown | null
/**
* A boolean representing if the flag exists or not. For ease of use and
* deployment, asking for a flag by any name will return a `FeatureFlag`
* interface, even if the flag was not found to exist. However this property
* may be checked to determine if the flag was actually resolved to a known
* flag name.
*/
readonly exists: boolean
}
Loading