react-native-mapp-plugin 1.4.1 → 1.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,24 @@
1
+ ## Version 1.4.3
2
+
3
+ ***Bug Fixes***
4
+
5
+ - Android/iOS: `Mapp.engage(...)` is now awaitable, allowing singleton-dependent calls to run only after native engagement completes. Engagement failures reject the promise.
6
+ - iOS: `Mapp.onInitCompletedListener()` now returns a `Promise<boolean>` instead of `null`.
7
+ - iOS: The promise resolves immediately when the SDK is already ready, or waits for the existing `com.mapp.init` event while initialization is in progress.
8
+ - Android: Preserved the existing native `AppoxeeObserver` implementation and behavior.
9
+ - Android/iOS: Preserved the public `Mapp.onInitCompletedListener(): Promise<boolean>` API with consistent initialization-waiting behavior on both platforms.
10
+
11
+ ***Tests***
12
+
13
+ - Added coverage for an already-ready iOS SDK, waiting for the iOS initialization event, and readiness changing while the event listener is being registered.
14
+ - Updated platform-dispatch coverage for the cross-platform implementation.
15
+
16
+ ## Version 1.4.2
17
+
18
+ ***Dependency Updates***
19
+
20
+ - Android: Aligned with Mapp Engage Android SDK 7.1.2.
21
+
1
22
  ## Version 1.4.1
2
23
 
3
24
  ***Dependency Updates***
package/Mapp.js CHANGED
@@ -130,11 +130,7 @@ export class Mapp {
130
130
  server: string,
131
131
  appID: string,
132
132
  tenantID: string
133
- ) {
134
- if (Platform.OS == "ios") {
135
- RNMappPluginModule.autoengage(server);
136
- return RNMappPluginModule.engageInapp(server);
137
- }
133
+ ): Promise<boolean> {
138
134
  return RNMappPluginModule.engage(
139
135
  sdkKey,
140
136
  googleProjectId,
@@ -170,10 +166,38 @@ export class Mapp {
170
166
  * @return {Promise.<boolean>} A promise with the result.
171
167
  */
172
168
  static onInitCompletedListener(): Promise<boolean> {
173
- if (Platform.OS == "android") {
169
+ if (Platform.OS === "android") {
174
170
  return RNMappPluginModule.onInitCompletedListener();
175
171
  }
176
- return null;
172
+
173
+ return RNMappPluginModule.isReady().then((ready) => {
174
+ if (ready) {
175
+ return true;
176
+ }
177
+
178
+ return new Promise((resolve, reject) => {
179
+ let settled = false;
180
+ let subscription;
181
+ const finish = () => {
182
+ if (settled) return;
183
+ settled = true;
184
+ if (subscription) subscription.remove();
185
+ resolve(true);
186
+ };
187
+
188
+ subscription = EventEmitter.addListener(IOS_INIT, finish);
189
+
190
+ // Close the race between the first readiness check and registration.
191
+ RNMappPluginModule.isReady().then((isReady) => {
192
+ if (isReady) finish();
193
+ }, (error) => {
194
+ if (settled) return;
195
+ settled = true;
196
+ if (subscription) subscription.remove();
197
+ reject(error);
198
+ });
199
+ });
200
+ });
177
201
  }
178
202
 
179
203
  /**
package/README.md CHANGED
@@ -87,7 +87,9 @@ cd ios && pod install
87
87
  ```javascript
88
88
  import Mapp from 'react-native-mapp-plugin';
89
89
 
90
- // TODO: What to do with the module?
91
- Mapp;
90
+ await Mapp.engage('SDK_KEY', 'FCM_PROJECT_ID', 'EMC', 'APP_ID', 'TENANT_ID');
91
+ await Mapp.onInitCompletedListener();
92
92
  ```
93
+
94
+ Always await `Mapp.engage(...)` before calling APIs that use the native Mapp singleton. The promise resolves after native engagement and bridge setup complete.
93
95
 
@@ -17,7 +17,7 @@ Pod::Spec.new do |s|
17
17
 
18
18
  s.source_files = "ios/**/*.{h,c,m,swift}"
19
19
  s.exclude_files = "ios/RNMappPluginTests/**/*"
20
- s.vendored_framework = "ios/Frameworks/AppoxeeSDK.xcframework", "ios/Frameworks/AppoxeeLocationServices.xcframework", "ios/Frameworks/AppoxeeInapp.xcframework"
20
+ s.vendored_framework = "ios/Frameworks/AppoxeeLocationServices.xcframework", "ios/Frameworks/AppoxeeInapp.xcframework"
21
21
  s.resources = "ios/Frameworks/AppoxeeSDKResources.bundle", "ios/Frameworks/AppoxeeInappResources.bundle"
22
22
  s.preserve_path = "ios/Frameworks/"
23
23
  s.public_header_files = "ios/Frameworks/AppoxeeSDK.xcframework/ios-arm64/Headers/", "ios/Frameworks/AppoxeeLocationServices.xcframework/ios-arm64/Headers/", "ios/Frameworks/AppoxeeInapp.xcframework/ios-arm64/Headers/"
@@ -53,7 +53,7 @@ dependencies {
53
53
  api('com.google.android.gms:play-services-location:21.3.0')
54
54
  implementation 'androidx.media:media:1.8.0'
55
55
  implementation 'androidx.legacy:legacy-support-v13:1.0.0'
56
- implementation("com.mapp.sdk:engage-android:7.1.1")
56
+ implementation("com.mapp.sdk:engage-android:7.1.2")
57
57
  testImplementation 'junit:junit:4.13.2'
58
58
  testImplementation 'org.mockito:mockito-core:5.23.0'
59
59
  testImplementation 'org.mockito:mockito-inline:5.2.0'
@@ -76,7 +76,7 @@ public abstract class NativeRNMappPluginModuleSpec extends ReactContextBaseJavaM
76
76
 
77
77
  @ReactMethod
78
78
  @DoNotStrip
79
- public abstract void engage(String sdkKey, String googleProjectId, String server, String appID, String tenantID);
79
+ public abstract void engage(String sdkKey, String googleProjectId, String server, String appID, String tenantID, Promise promise);
80
80
 
81
81
  @ReactMethod
82
82
  @DoNotStrip
@@ -322,21 +322,42 @@ public class RNMappPluginModule extends NativeRNMappPluginModuleSpec implements
322
322
  }
323
323
 
324
324
  @ReactMethod
325
- public void engage(String sdkKey, String googleProjectId, String server, String appID, String tenantID) {
326
- AppoxeeOptions opt = createOptions(server, sdkKey, appID, tenantID);
327
- opt.setNotificationMode(NotificationMode.BACKGROUND_AND_FOREGROUND);
325
+ public void engage(String sdkKey, String googleProjectId, String server, String appID,
326
+ String tenantID, Promise promise) {
327
+ final AppoxeeOptions opt;
328
+ try {
329
+ opt = createOptions(server, sdkKey, appID, tenantID);
330
+ opt.setNotificationMode(NotificationMode.BACKGROUND_AND_FOREGROUND);
331
+ } catch (RuntimeException error) {
332
+ promise.reject("MAPP_ENGAGE_INVALID_CONFIGURATION", error.getMessage(), error);
333
+ return;
334
+ }
328
335
 
329
- new Handler(Looper.getMainLooper()).post(() -> {
330
- Appoxee.engage(Objects.requireNonNull(application), opt);
336
+ Runnable operation = () -> {
337
+ try {
338
+ Appoxee.engage(Objects.requireNonNull(application), opt);
331
339
 
332
- Appoxee.instance().subscribe(new AppoxeeObserver() {
333
- @Override
334
- public void onReadyStatusChanged(boolean status, MappResult<DevicePayload> result) {
335
- }
336
- });
340
+ Appoxee.instance().subscribe(new AppoxeeObserver() {
341
+ @Override
342
+ public void onReadyStatusChanged(boolean status, MappResult<DevicePayload> result) {
343
+ }
344
+ });
337
345
 
338
- Appoxee.instance().setPushBroadcast(MyPushBroadcastReceiver.class);
339
- });
346
+ Appoxee.instance().setPushBroadcast(MyPushBroadcastReceiver.class);
347
+ promise.resolve(true);
348
+ } catch (Exception error) {
349
+ promise.reject("MAPP_ENGAGE_FAILED", "Mapp initialization failed", error);
350
+ }
351
+ };
352
+
353
+ if (Looper.myLooper() == Looper.getMainLooper()) {
354
+ operation.run();
355
+ } else if (!new Handler(Looper.getMainLooper()).post(operation)) {
356
+ promise.reject(
357
+ "MAPP_ENGAGE_FAILED",
358
+ "Unable to post Mapp initialization to the main looper"
359
+ );
360
+ }
340
361
  }
341
362
 
342
363
  @ReactMethod
@@ -64,7 +64,7 @@ static facebook::jsi::Value __hostFunction_NativeRNMappPluginModuleSpecJSI_engag
64
64
 
65
65
  static facebook::jsi::Value __hostFunction_NativeRNMappPluginModuleSpecJSI_engage(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
66
66
  static jmethodID cachedMethodId = nullptr;
67
- return static_cast<JavaTurboModule &>(turboModule).invokeJavaMethod(rt, VoidKind, "engage", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", args, count, cachedMethodId);
67
+ return static_cast<JavaTurboModule &>(turboModule).invokeJavaMethod(rt, PromiseKind, "engage", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lcom/facebook/react/bridge/Promise;)V", args, count, cachedMethodId);
68
68
  }
69
69
 
70
70
  static facebook::jsi::Value __hostFunction_NativeRNMappPluginModuleSpecJSI_engageTestServer(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) {
@@ -154,12 +154,12 @@ private:
154
154
  static_assert(
155
155
  bridging::getParameterCount(&T::engage) == 6,
156
156
  "Expected engage(...) to have 6 parameters");
157
- bridging::callFromJs<void>(rt, &T::engage, static_cast<NativeRNMappPluginModuleCxxSpec*>(&turboModule)->jsInvoker_, static_cast<T*>(&turboModule),
157
+ return bridging::callFromJs<jsi::Value>(rt, &T::engage, static_cast<NativeRNMappPluginModuleCxxSpec*>(&turboModule)->jsInvoker_, static_cast<T*>(&turboModule),
158
158
  count <= 0 ? throw jsi::JSError(rt, "Expected argument in position 0 to be passed") : args[0].asString(rt),
159
159
  count <= 1 ? throw jsi::JSError(rt, "Expected argument in position 1 to be passed") : args[1].asString(rt),
160
160
  count <= 2 ? throw jsi::JSError(rt, "Expected argument in position 2 to be passed") : args[2].asString(rt),
161
161
  count <= 3 ? throw jsi::JSError(rt, "Expected argument in position 3 to be passed") : args[3].asString(rt),
162
- count <= 4 ? throw jsi::JSError(rt, "Expected argument in position 4 to be passed") : args[4].asString(rt));return jsi::Value::undefined();
162
+ count <= 4 ? throw jsi::JSError(rt, "Expected argument in position 4 to be passed") : args[4].asString(rt));
163
163
  }
164
164
 
165
165
  static jsi::Value __engageTestServer(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) {
@@ -37,9 +37,23 @@ RCT_EXPORT_METHOD(removeListeners:(NSInteger)count) {
37
37
 
38
38
  #pragma mark Exported methods - Notifications
39
39
 
40
- RCT_EXPORT_METHOD(engage: (NSString *)sdkKey projectId: (NSString *)projectId cepUrl:(NSString *)cepUrl appID:(NSString *)appID tenantID:(NSString *)tenantID) {
41
- SERVER serv = [self getServerKeyFor:cepUrl];
42
- [[Appoxee shared] engageWithLaunchOptions:nil andDelegate:[RNMappEventEmmiter shared] andSDKID:sdkKey with: serv];
40
+ RCT_EXPORT_METHOD(engage:(NSString *)sdkKey
41
+ googleProjectId:(NSString *)projectId
42
+ server:(NSString *)server
43
+ appID:(NSString *)appID
44
+ tenantID:(NSString *)tenantID
45
+ resolve:(RCTPromiseResolveBlock)resolve
46
+ reject:(RCTPromiseRejectBlock)reject) {
47
+ @try {
48
+ SERVER serv = [self getServerKeyFor:server];
49
+ [[Appoxee shared] engageAndAutoIntegrateWithLaunchOptions:nil andDelegate:[RNMappEventEmmiter shared] with:serv];
50
+ [[Appoxee shared] addObserver:[RNMappEventEmmiter shared] forKeyPath:@"isReady" options:NSKeyValueObservingOptionNew context:nil];
51
+ [[AppoxeeInapp shared] engageWithDelegate:[RNMappEventEmmiter shared] with:[self getInappServerKeyFor:server]];
52
+ resolve(@YES);
53
+ } @catch (NSException *exception) {
54
+ NSString *message = exception.reason ?: @"Mapp initialization failed";
55
+ reject(@"MAPP_ENGAGE_FAILED", message, nil);
56
+ }
43
57
  }
44
58
 
45
59
  RCT_REMAP_METHOD(autoengage,engage:(NSString *) server) {
@@ -371,4 +385,3 @@ RCT_EXPORT_METHOD(stopGeoFencing) {
371
385
 
372
386
 
373
387
  @end
374
-
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-mapp-plugin",
3
- "version": "1.4.1",
3
+ "version": "1.4.3",
4
4
  "description": "Mapp SDK for React Native.",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -15,7 +15,7 @@ export interface Spec extends TurboModule {
15
15
  setAliasWithResend(alias: string, resendCustomAttributes: boolean): Promise<boolean>;
16
16
  getAlias(): Promise<string>;
17
17
  engage2(): void;
18
- engage(sdkKey: string, googleProjectId: string, server: string, appID: string, tenantID: string): void;
18
+ engage(sdkKey: string, googleProjectId: string, server: string, appID: string, tenantID: string): Promise<boolean>;
19
19
  engageTestServer(cepURl: string, sdkKey: string, googleProjectId: string, server: string, appID: string, tenantID: string): void;
20
20
  onInitCompletedListener(): Promise<boolean>;
21
21
  isReady(): Promise<boolean>;