react-native-mapp-plugin 1.4.1 → 2.0.0-beta.1
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/BREAKING_CHANGES.md +126 -0
- package/CHANGELOG.md +28 -0
- package/MIGRATION_2.0.md +100 -0
- package/Mapp.js +7 -8
- package/README.md +138 -75
- package/RNMappPlugin.podspec +10 -4
- package/android/build.gradle +137 -7
- package/android/gradle.properties +0 -2
- package/android/settings.gradle +5 -6
- package/android/src/main/AndroidManifest.xml +8 -1
- package/android/src/main/java/com/reactlibrary/MappEngagementDispatcher.java +102 -0
- package/android/src/main/java/com/reactlibrary/MappPushHelper.java +126 -0
- package/android/src/main/java/com/reactlibrary/MessageService.java +3 -23
- package/android/src/main/java/com/reactlibrary/RNMappPluginModule.java +94 -28
- package/app.plugin.js +4 -0
- package/ios/RNMappEventEmmiter.m +21 -2
- package/ios/RNMappPluginModule.h +8 -1
- package/ios/{RNMappPluginModule.m → RNMappPluginModule.mm} +123 -39
- package/package.json +31 -8
- package/plugin/build/android.d.ts +4 -0
- package/plugin/build/android.js +53 -0
- package/plugin/build/index.d.ts +8 -0
- package/plugin/build/index.js +24 -0
- package/plugin/build/ios.d.ts +5 -0
- package/plugin/build/ios.js +77 -0
- package/plugin/build/types.d.ts +32 -0
- package/plugin/build/types.js +2 -0
- package/plugin/build/validation.d.ts +3 -0
- package/plugin/build/validation.js +76 -0
- package/specs/NativeRNMappPluginModule.js +3 -0
|
@@ -11,8 +11,6 @@ import android.content.Intent;
|
|
|
11
11
|
import android.content.pm.PackageManager;
|
|
12
12
|
import android.net.Uri;
|
|
13
13
|
import android.os.Build;
|
|
14
|
-
import android.os.Handler;
|
|
15
|
-
import android.os.Looper;
|
|
16
14
|
import android.util.DisplayMetrics;
|
|
17
15
|
import android.provider.Settings;
|
|
18
16
|
|
|
@@ -24,6 +22,7 @@ import androidx.core.content.ContextCompat;
|
|
|
24
22
|
import com.appoxee.Appoxee;
|
|
25
23
|
import com.appoxee.internal.model.response.DevicePayload;
|
|
26
24
|
import com.appoxee.shared.InboxMessage;
|
|
25
|
+
import com.appoxee.shared.MessageStatus;
|
|
27
26
|
import com.appoxee.sdk.BuildConfig;
|
|
28
27
|
import com.appoxee.shared.AppoxeeObserver;
|
|
29
28
|
import com.appoxee.shared.AppoxeeOptions;
|
|
@@ -80,12 +79,15 @@ public class RNMappPluginModule extends NativeRNMappPluginModuleSpec implements
|
|
|
80
79
|
|
|
81
80
|
public static final String NAME = "RNMappPluginModule";
|
|
82
81
|
private static final int POST_NOTIFICATION_PERMISSION_REQUEST_CODE = 1001;
|
|
82
|
+
private static final int GEOFENCE_PERMISSION_REQUEST_CODE = 2001;
|
|
83
83
|
private final ReactApplicationContext reactContext;
|
|
84
84
|
private Map<Callback, String> mFeedSubscriberMap = new ConcurrentHashMap<>();
|
|
85
85
|
private Map<Callback, Boolean> mCallbackWasCalledMap = new ConcurrentHashMap<>();
|
|
86
86
|
private final Map<Integer, Promise> notificationPermissionPromises = new ConcurrentHashMap<>();
|
|
87
|
+
private final Map<Integer, Promise> geofencePermissionPromises = new ConcurrentHashMap<>();
|
|
87
88
|
private Application application = null;
|
|
88
89
|
private int nextNotificationPermissionRequestCode = POST_NOTIFICATION_PERMISSION_REQUEST_CODE;
|
|
90
|
+
private int nextGeofencePermissionRequestCode = GEOFENCE_PERMISSION_REQUEST_CODE;
|
|
89
91
|
|
|
90
92
|
public RNMappPluginModule(ReactApplicationContext reactContext) {
|
|
91
93
|
super(reactContext);
|
|
@@ -128,10 +130,32 @@ public class RNMappPluginModule extends NativeRNMappPluginModuleSpec implements
|
|
|
128
130
|
promise.resolve(true);
|
|
129
131
|
return;
|
|
130
132
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
133
|
+
if (hasFineLocationPermission() && hasBackgroundLocationPermission()) {
|
|
134
|
+
promise.resolve(true);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
Activity activity = getCurrentActivity();
|
|
138
|
+
if (!(activity instanceof PermissionAwareActivity)) {
|
|
139
|
+
promise.resolve(false);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
int requestCode = nextGeofencePermissionRequestCode++;
|
|
143
|
+
geofencePermissionPromises.put(requestCode, promise);
|
|
144
|
+
String[] permissions = hasFineLocationPermission()
|
|
145
|
+
? new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION}
|
|
146
|
+
: new String[]{Manifest.permission.ACCESS_FINE_LOCATION};
|
|
147
|
+
((PermissionAwareActivity) activity).requestPermissions(permissions, requestCode, this);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
private boolean hasFineLocationPermission() {
|
|
151
|
+
return ContextCompat.checkSelfPermission(reactContext, Manifest.permission.ACCESS_FINE_LOCATION)
|
|
152
|
+
== PackageManager.PERMISSION_GRANTED;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
private boolean hasBackgroundLocationPermission() {
|
|
156
|
+
return Build.VERSION.SDK_INT < Build.VERSION_CODES.Q
|
|
157
|
+
|| ContextCompat.checkSelfPermission(reactContext, Manifest.permission.ACCESS_BACKGROUND_LOCATION)
|
|
158
|
+
== PackageManager.PERMISSION_GRANTED;
|
|
135
159
|
}
|
|
136
160
|
|
|
137
161
|
@ReactMethod
|
|
@@ -168,6 +192,31 @@ public class RNMappPluginModule extends NativeRNMappPluginModuleSpec implements
|
|
|
168
192
|
|
|
169
193
|
@Override
|
|
170
194
|
public boolean onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
|
|
195
|
+
Promise geofencePromise = geofencePermissionPromises.remove(requestCode);
|
|
196
|
+
if (geofencePromise != null) {
|
|
197
|
+
boolean granted = grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED;
|
|
198
|
+
if (!granted) {
|
|
199
|
+
geofencePromise.resolve(false);
|
|
200
|
+
return true;
|
|
201
|
+
}
|
|
202
|
+
if (!hasBackgroundLocationPermission()) {
|
|
203
|
+
Activity activity = getCurrentActivity();
|
|
204
|
+
if (!(activity instanceof PermissionAwareActivity)) {
|
|
205
|
+
geofencePromise.resolve(false);
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
int backgroundRequestCode = nextGeofencePermissionRequestCode++;
|
|
209
|
+
geofencePermissionPromises.put(backgroundRequestCode, geofencePromise);
|
|
210
|
+
((PermissionAwareActivity) activity).requestPermissions(
|
|
211
|
+
new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION},
|
|
212
|
+
backgroundRequestCode,
|
|
213
|
+
this
|
|
214
|
+
);
|
|
215
|
+
return true;
|
|
216
|
+
}
|
|
217
|
+
geofencePromise.resolve(hasFineLocationPermission());
|
|
218
|
+
return true;
|
|
219
|
+
}
|
|
171
220
|
Promise promise = notificationPermissionPromises.remove(requestCode);
|
|
172
221
|
if (promise == null) {
|
|
173
222
|
return false;
|
|
@@ -287,11 +336,24 @@ public class RNMappPluginModule extends NativeRNMappPluginModuleSpec implements
|
|
|
287
336
|
FirebaseMessaging.getInstance().getToken().addOnCompleteListener(new OnCompleteListener<String>() {
|
|
288
337
|
@Override
|
|
289
338
|
public void onComplete(@NonNull Task<String> task) {
|
|
290
|
-
|
|
339
|
+
settleTokenTask(task, promise);
|
|
291
340
|
}
|
|
292
341
|
});
|
|
293
342
|
}
|
|
294
343
|
|
|
344
|
+
static void settleTokenTask(@NonNull Task<String> task, @NonNull Promise promise) {
|
|
345
|
+
if (task.isSuccessful()) {
|
|
346
|
+
promise.resolve(task.getResult());
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
Exception exception = task.getException();
|
|
351
|
+
String message = exception != null && exception.getMessage() != null
|
|
352
|
+
? exception.getMessage()
|
|
353
|
+
: "FCM registration failed";
|
|
354
|
+
promise.reject("FCM_REGISTRATION_FAILED", message, exception);
|
|
355
|
+
}
|
|
356
|
+
|
|
295
357
|
// -------------------------------------------------------------------------
|
|
296
358
|
// Alias
|
|
297
359
|
// -------------------------------------------------------------------------
|
|
@@ -318,7 +380,7 @@ public class RNMappPluginModule extends NativeRNMappPluginModuleSpec implements
|
|
|
318
380
|
@ReactMethod
|
|
319
381
|
@Deprecated(forRemoval = true)
|
|
320
382
|
public void engage2() {
|
|
321
|
-
|
|
383
|
+
MappEngagementDispatcher.engageAsync(Objects.requireNonNull(application), null, null);
|
|
322
384
|
}
|
|
323
385
|
|
|
324
386
|
@ReactMethod
|
|
@@ -326,9 +388,7 @@ public class RNMappPluginModule extends NativeRNMappPluginModuleSpec implements
|
|
|
326
388
|
AppoxeeOptions opt = createOptions(server, sdkKey, appID, tenantID);
|
|
327
389
|
opt.setNotificationMode(NotificationMode.BACKGROUND_AND_FOREGROUND);
|
|
328
390
|
|
|
329
|
-
|
|
330
|
-
Appoxee.engage(Objects.requireNonNull(application), opt);
|
|
331
|
-
|
|
391
|
+
MappEngagementDispatcher.engageAsync(Objects.requireNonNull(application), opt, () -> {
|
|
332
392
|
Appoxee.instance().subscribe(new AppoxeeObserver() {
|
|
333
393
|
@Override
|
|
334
394
|
public void onReadyStatusChanged(boolean status, MappResult<DevicePayload> result) {
|
|
@@ -344,9 +404,7 @@ public class RNMappPluginModule extends NativeRNMappPluginModuleSpec implements
|
|
|
344
404
|
String appID, String tenantID) {
|
|
345
405
|
AppoxeeOptions opt = createOptions(server, sdkKey, appID, tenantID);
|
|
346
406
|
|
|
347
|
-
|
|
348
|
-
Appoxee.engage(Objects.requireNonNull(application), opt);
|
|
349
|
-
|
|
407
|
+
MappEngagementDispatcher.engageAsync(Objects.requireNonNull(application), opt, () -> {
|
|
350
408
|
Appoxee.instance().subscribe(new AppoxeeObserver() {
|
|
351
409
|
@Override
|
|
352
410
|
public void onReadyStatusChanged(boolean status, MappResult<DevicePayload> result) {
|
|
@@ -738,33 +796,41 @@ public class RNMappPluginModule extends NativeRNMappPluginModuleSpec implements
|
|
|
738
796
|
});
|
|
739
797
|
}
|
|
740
798
|
|
|
741
|
-
/**
|
|
742
|
-
* Stubbed: InApp statistics internal classes were removed in v7.
|
|
743
|
-
* The @ReactMethod signature is preserved to avoid breaking the JS public API.
|
|
744
|
-
*/
|
|
745
799
|
@ReactMethod
|
|
746
800
|
public void inAppMarkAsRead(double templateId, String eventId) {
|
|
747
|
-
|
|
801
|
+
updateInboxMessageStatus((long) templateId, MessageStatus.READ);
|
|
748
802
|
}
|
|
749
803
|
|
|
750
|
-
/**
|
|
751
|
-
* @see #inAppMarkAsRead
|
|
752
|
-
*/
|
|
753
804
|
@ReactMethod
|
|
754
805
|
public void inAppMarkAsUnRead(double templateId, String eventId) {
|
|
755
|
-
|
|
806
|
+
updateInboxMessageStatus((long) templateId, MessageStatus.UNREAD);
|
|
756
807
|
}
|
|
757
808
|
|
|
758
|
-
/**
|
|
759
|
-
* @see #inAppMarkAsRead
|
|
760
|
-
*/
|
|
761
809
|
@ReactMethod
|
|
762
810
|
public void inAppMarkAsDeleted(double templateId, String eventId) {
|
|
763
|
-
|
|
811
|
+
updateInboxMessageStatus((long) templateId, MessageStatus.DELETED);
|
|
764
812
|
}
|
|
765
813
|
|
|
766
814
|
/**
|
|
767
|
-
*
|
|
815
|
+
* Mapp Engage v7 updates inbox state using the SDK's InboxMessage object,
|
|
816
|
+
* so fetch the message by template ID before sending the status update.
|
|
817
|
+
* The legacy eventId argument is not required by the v7 API.
|
|
818
|
+
*/
|
|
819
|
+
private void updateInboxMessageStatus(long templateId, MessageStatus status) {
|
|
820
|
+
final Appoxee appoxee = Appoxee.instance();
|
|
821
|
+
appoxee.fetchInboxMessage(templateId).enqueue(fetchResult -> {
|
|
822
|
+
if (fetchResult == null || !fetchResult.isSuccess() || fetchResult.getData() == null) {
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
appoxee.updateInboxMessageStatus(fetchResult.getData(), status).enqueue(updateResult -> {
|
|
827
|
+
});
|
|
828
|
+
});
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
/**
|
|
832
|
+
* Stubbed: InApp statistics internal classes were removed in v7.
|
|
833
|
+
* The @ReactMethod signature is preserved to avoid breaking the JS public API.
|
|
768
834
|
*/
|
|
769
835
|
@ReactMethod
|
|
770
836
|
public void triggerStatistic(double templateId, String originalEventId,
|
package/app.plugin.js
ADDED
package/ios/RNMappEventEmmiter.m
CHANGED
|
@@ -43,6 +43,11 @@ NSString *const MappRNInappMessage = @"com.mapp.inapp_message";
|
|
|
43
43
|
|
|
44
44
|
-(void)startObserving {
|
|
45
45
|
hasListeners = YES;
|
|
46
|
+
NSArray *events = [self.pendingEvents copy];
|
|
47
|
+
[self.pendingEvents removeAllObjects];
|
|
48
|
+
for (NSDictionary *event in events) {
|
|
49
|
+
[super sendEventWithName:event[@"name"] body:event[@"body"]];
|
|
50
|
+
}
|
|
46
51
|
}
|
|
47
52
|
|
|
48
53
|
-(void)stopObserving {
|
|
@@ -50,7 +55,22 @@ NSString *const MappRNInappMessage = @"com.mapp.inapp_message";
|
|
|
50
55
|
}
|
|
51
56
|
|
|
52
57
|
- (NSArray<NSString *> *)supportedEvents {
|
|
53
|
-
return @[MappRNInitEvent, MappRNInboxMessageReceived, MappRNInboxMessagesReceived, MappRNLocationEnter, MappRNCustomLinkReceived, MappRNDeepLinkReceived, MappRNRichMessage,MappRNPushMessage, MappErrorMessage,MappRNInappMessage];
|
|
58
|
+
return @[MappRNInitEvent, MappRNInboxMessageReceived, MappRNInboxMessagesReceived, MappRNLocationEnter, MappRNLocationExit, MappRNCustomLinkReceived, MappRNDeepLinkReceived, MappRNRichMessage,MappRNPushMessage, MappErrorMessage,MappRNInappMessage];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
- (void)sendEventWithName:(NSString *)name body:(id)body {
|
|
62
|
+
if (hasListeners) {
|
|
63
|
+
[super sendEventWithName:name body:body];
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (!self.pendingEvents) {
|
|
67
|
+
self.pendingEvents = [NSMutableArray array];
|
|
68
|
+
}
|
|
69
|
+
// Bound the cold-start queue so repeated background callbacks cannot grow it forever.
|
|
70
|
+
if (self.pendingEvents.count >= 50) {
|
|
71
|
+
[self.pendingEvents removeObjectAtIndex:0];
|
|
72
|
+
}
|
|
73
|
+
[self.pendingEvents addObject:@{ @"name": name, @"body": body ?: [NSNull null] }];
|
|
54
74
|
}
|
|
55
75
|
|
|
56
76
|
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
|
|
@@ -224,4 +244,3 @@ NSString *const MappRNInappMessage = @"com.mapp.inapp_message";
|
|
|
224
244
|
}
|
|
225
245
|
@end
|
|
226
246
|
|
|
227
|
-
|
package/ios/RNMappPluginModule.h
CHANGED
|
@@ -4,7 +4,14 @@
|
|
|
4
4
|
#import "AppoxeeInapp.h"
|
|
5
5
|
#import "AppoxeeLocationManager.h"
|
|
6
6
|
#import <UserNotifications/UNUserNotificationCenter.h>
|
|
7
|
+
#if RCT_NEW_ARCH_ENABLED
|
|
8
|
+
#import <RNMappPlugin/RNMappPlugin.h>
|
|
9
|
+
#endif
|
|
7
10
|
|
|
8
|
-
@interface RNMappPluginModule : NSObject <RCTBridgeModule,AppoxeeInappDelegate, AppoxeeNotificationDelegate, AppoxeeLocationManagerDelegate
|
|
11
|
+
@interface RNMappPluginModule : NSObject <RCTBridgeModule,AppoxeeInappDelegate, AppoxeeNotificationDelegate, AppoxeeLocationManagerDelegate
|
|
12
|
+
#if RCT_NEW_ARCH_ENABLED
|
|
13
|
+
, NativeRNMappPluginModuleSpec
|
|
14
|
+
#endif
|
|
15
|
+
>
|
|
9
16
|
|
|
10
17
|
@end
|
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
#import "RNMappPluginModule.h"
|
|
2
2
|
#import "RNMappEventEmmiter.h"
|
|
3
|
+
#if RCT_NEW_ARCH_ENABLED
|
|
4
|
+
#import <ReactCommon/RCTTurboModule.h>
|
|
5
|
+
#endif
|
|
3
6
|
|
|
4
7
|
|
|
5
8
|
@implementation RNMappPluginModule
|
|
6
9
|
|
|
10
|
+
#if RCT_NEW_ARCH_ENABLED
|
|
11
|
+
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
|
12
|
+
(const facebook::react::ObjCTurboModule::InitParams &)params
|
|
13
|
+
{
|
|
14
|
+
return std::make_shared<facebook::react::NativeRNMappPluginModuleSpecJSI>(params);
|
|
15
|
+
}
|
|
16
|
+
#endif
|
|
17
|
+
|
|
7
18
|
|
|
8
19
|
- (void)setBridge:(RCTBridge *)bridge {
|
|
9
20
|
[RNMappEventEmmiter shared].bridge = bridge;
|
|
@@ -35,20 +46,87 @@ RCT_EXPORT_METHOD(removeListeners:(NSInteger)count) {
|
|
|
35
46
|
[[RNMappEventEmmiter shared] removeListeners:count];
|
|
36
47
|
}
|
|
37
48
|
|
|
38
|
-
|
|
49
|
+
// Cross-platform TurboModule methods that need iOS-specific behavior or have no
|
|
50
|
+
// meaningful iOS equivalent. Keeping them here makes the generated spec safe to
|
|
51
|
+
// invoke under the New Architecture instead of relying on legacy interop.
|
|
52
|
+
RCT_EXPORT_METHOD(requestGeofenceLocationPermission:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
|
|
53
|
+
CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
|
|
54
|
+
if (status == kCLAuthorizationStatusNotDetermined) {
|
|
55
|
+
[[[CLLocationManager alloc] init] requestAlwaysAuthorization];
|
|
56
|
+
}
|
|
57
|
+
resolve(@(status == kCLAuthorizationStatusAuthorizedAlways));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
RCT_EXPORT_METHOD(requestPostNotificationPermission:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
|
|
61
|
+
[[UNUserNotificationCenter currentNotificationCenter]
|
|
62
|
+
requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound)
|
|
63
|
+
completionHandler:^(BOOL granted, NSError *error) {
|
|
64
|
+
if (error) reject(@"NOTIFICATION_PERMISSION_ERROR", @"Unable to request notification permission", error);
|
|
65
|
+
else resolve(@(granted));
|
|
66
|
+
}];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
RCT_EXPORT_METHOD(setRemoteMessage:(NSString *)msgJson resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
|
|
70
|
+
// iOS delivery is handled by APNs/Appoxee auto-integration, not FCM RemoteMessage JSON.
|
|
71
|
+
resolve(@NO);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
RCT_EXPORT_METHOD(isPushFromMapp:(NSString *)msgJson resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
|
|
75
|
+
resolve(@NO);
|
|
76
|
+
}
|
|
39
77
|
|
|
40
|
-
RCT_EXPORT_METHOD(
|
|
41
|
-
|
|
42
|
-
[[Appoxee shared] engageWithLaunchOptions:nil andDelegate:[RNMappEventEmmiter shared] andSDKID:sdkKey with: serv];
|
|
78
|
+
RCT_EXPORT_METHOD(getToken:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
|
|
79
|
+
reject(@"APNS_TOKEN_UNAVAILABLE", @"Mapp auto-integration owns the native APNs token on iOS", nil);
|
|
43
80
|
}
|
|
44
81
|
|
|
45
|
-
|
|
82
|
+
RCT_EXPORT_METHOD(engage2) {}
|
|
83
|
+
|
|
84
|
+
RCT_EXPORT_METHOD(engageTestServer:(NSString *)cepUrl sdkKey:(NSString *)sdkKey googleProjectId:(NSString *)projectId server:(NSString *)server appID:(NSString *)appID tenantID:(NSString *)tenantID) {
|
|
85
|
+
[self engage:sdkKey googleProjectId:projectId server:server appID:appID tenantID:tenantID];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
RCT_EXPORT_METHOD(onInitCompletedListener:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
|
|
89
|
+
resolve(@([[Appoxee shared] isReady]));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
RCT_EXPORT_METHOD(setAttributeBoolean:(NSString *)key value:(BOOL)value) {
|
|
93
|
+
[[Appoxee shared] setNumberValue:@(value) forKey:key withCompletionHandler:nil];
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
RCT_EXPORT_METHOD(removeAttribute:(NSString *)attribute) {
|
|
97
|
+
// The vendored iOS SDK has no single-field removal API.
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
RCT_EXPORT_METHOD(getDeviceDmcInfo:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
|
|
101
|
+
[self getDeviceInfo:resolve reject:reject];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
RCT_EXPORT_METHOD(lockScreenOrientation:(NSInteger)orientation) {}
|
|
105
|
+
|
|
106
|
+
RCT_EXPORT_METHOD(startGeofencing:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
|
|
107
|
+
[[AppoxeeLocationManager shared] enableLocationMonitoring];
|
|
108
|
+
resolve(@"started");
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
RCT_EXPORT_METHOD(stopGeofencing:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
|
|
112
|
+
[[AppoxeeLocationManager shared] disableLocationMonitoring];
|
|
113
|
+
resolve(@"stopped");
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
RCT_EXPORT_METHOD(triggerStatistic:(NSInteger)templateId originalEventId:(NSString *)originalEventId trackingKey:(NSString *)trackingKey displayMillis:(NSInteger)displayMillis reason:(NSString *)reason link:(NSString *)link) {}
|
|
117
|
+
RCT_EXPORT_METHOD(addAndroidListener:(NSString *)eventName) {}
|
|
118
|
+
RCT_EXPORT_METHOD(removeAndroidListeners:(NSInteger)count) {}
|
|
119
|
+
|
|
120
|
+
#pragma mark Exported methods - Notifications
|
|
121
|
+
|
|
122
|
+
RCT_EXPORT_METHOD(engage: (NSString *)sdkKey googleProjectId: (NSString *)projectId server:(NSString *)server appID:(NSString *)appID tenantID:(NSString *)tenantID) {
|
|
46
123
|
SERVER serv = [self getServerKeyFor:server];
|
|
47
124
|
[[Appoxee shared] engageAndAutoIntegrateWithLaunchOptions:nil andDelegate:[RNMappEventEmmiter shared] with:serv];
|
|
48
125
|
[[Appoxee shared] addObserver: [RNMappEventEmmiter shared] forKeyPath:@"isReady" options:NSKeyValueObservingOptionNew context:nil];
|
|
126
|
+
[[AppoxeeInapp shared] engageWithDelegate:[RNMappEventEmmiter shared] with:[self getInappServerKeyFor:server]];
|
|
49
127
|
}
|
|
50
128
|
|
|
51
|
-
RCT_EXPORT_METHOD(getAlias:(RCTPromiseResolveBlock)resolve
|
|
129
|
+
RCT_EXPORT_METHOD(getAlias:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
|
|
52
130
|
[[Appoxee shared] getDeviceAliasWithCompletionHandler:^(NSError * _Nullable appoxeeError, id _Nullable data) {
|
|
53
131
|
if (appoxeeError == nil && data != nil) {
|
|
54
132
|
resolve(data);
|
|
@@ -58,24 +136,34 @@ RCT_EXPORT_METHOD(getAlias:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseR
|
|
|
58
136
|
}];
|
|
59
137
|
}
|
|
60
138
|
|
|
61
|
-
RCT_EXPORT_METHOD(setAlias:(NSString *) alias) {
|
|
139
|
+
RCT_EXPORT_METHOD(setAlias:(NSString *) alias resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
|
|
62
140
|
[[Appoxee shared] setDeviceAlias:alias withCompletionHandler:^(NSError * _Nullable appoxeeError, id _Nullable data) {
|
|
63
141
|
if (appoxeeError != nil) {
|
|
64
|
-
|
|
142
|
+
reject(@"SET_ALIAS_ERROR", @"Failed to set alias", appoxeeError);
|
|
143
|
+
} else {
|
|
144
|
+
resolve(@YES);
|
|
65
145
|
}
|
|
66
146
|
}];
|
|
67
147
|
}
|
|
68
148
|
|
|
69
|
-
RCT_EXPORT_METHOD(setAliasWithResend:(NSString *) alias
|
|
149
|
+
RCT_EXPORT_METHOD(setAliasWithResend:(NSString *) alias resendCustomAttributes:(BOOL) resendAttributes resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
|
|
70
150
|
[[Appoxee shared] setDeviceAlias:alias withResendAttributes:resendAttributes withCompletionHandler:^(NSError * _Nullable appoxeeError, id _Nullable data) {
|
|
71
151
|
if (appoxeeError != nil) {
|
|
72
|
-
|
|
152
|
+
reject(@"SET_ALIAS_ERROR", @"Failed to set alias", appoxeeError);
|
|
153
|
+
} else {
|
|
154
|
+
resolve(@YES);
|
|
73
155
|
}
|
|
74
156
|
}];
|
|
75
157
|
}
|
|
76
158
|
|
|
77
|
-
RCT_EXPORT_METHOD(setToken:(NSString *) token) {
|
|
78
|
-
|
|
159
|
+
RCT_EXPORT_METHOD(setToken:(NSString *) token resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
|
|
160
|
+
NSData *deviceToken = [[NSData alloc] initWithBase64EncodedString:token options:0];
|
|
161
|
+
if (!deviceToken) {
|
|
162
|
+
reject(@"INVALID_APNS_TOKEN", @"setToken expects a base64-encoded native APNs device token, not an Expo push token", nil);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
[[Appoxee shared] didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
|
|
166
|
+
resolve(@YES);
|
|
79
167
|
}
|
|
80
168
|
|
|
81
169
|
RCT_EXPORT_METHOD(removeDeviceAlias) {
|
|
@@ -90,11 +178,11 @@ RCT_EXPORT_METHOD(logOut: (BOOL) pushEnabled) {
|
|
|
90
178
|
[[Appoxee shared] logoutWithOptin:pushEnabled];
|
|
91
179
|
}
|
|
92
180
|
|
|
93
|
-
RCT_EXPORT_METHOD(isReady:(RCTPromiseResolveBlock)resolve
|
|
181
|
+
RCT_EXPORT_METHOD(isReady:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
|
|
94
182
|
resolve(@([[Appoxee shared] isReady]));
|
|
95
183
|
}
|
|
96
184
|
|
|
97
|
-
RCT_EXPORT_METHOD(isPushEnabled:(RCTPromiseResolveBlock)resolve
|
|
185
|
+
RCT_EXPORT_METHOD(isPushEnabled:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
|
|
98
186
|
[[Appoxee shared] isPushEnabled:^(NSError * _Nullable appoxeeError, id _Nullable data) {
|
|
99
187
|
if (appoxeeError == nil) {
|
|
100
188
|
resolve(data);
|
|
@@ -132,15 +220,17 @@ RCT_EXPORT_METHOD(incrementNumericKey: (NSString *) key value: (NSNumber *) numb
|
|
|
132
220
|
}];
|
|
133
221
|
}
|
|
134
222
|
|
|
135
|
-
RCT_EXPORT_METHOD(setAttributes: (NSDictionary *)attributes) {
|
|
223
|
+
RCT_EXPORT_METHOD(setAttributes: (NSDictionary *)attributes resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
|
|
136
224
|
[[Appoxee shared] setCustomAttributtes:attributes withCompletionHandler:^(NSError * _Nullable appoxeeError, id _Nullable data) {
|
|
137
225
|
if (appoxeeError) {
|
|
138
|
-
|
|
226
|
+
reject(@"SET_ATTRIBUTES_ERROR", @"Failed to set attributes", appoxeeError);
|
|
227
|
+
} else {
|
|
228
|
+
resolve(@YES);
|
|
139
229
|
}
|
|
140
230
|
}];
|
|
141
231
|
}
|
|
142
232
|
|
|
143
|
-
RCT_EXPORT_METHOD(getAttributes: (NSArray *)attributes
|
|
233
|
+
RCT_EXPORT_METHOD(getAttributes: (NSArray *)attributes resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
|
|
144
234
|
[[Appoxee shared] getCustomAttributes:attributes withCompletionHandler:^(NSError * _Nullable appoxeeError, id _Nullable data) {
|
|
145
235
|
if (appoxeeError) {
|
|
146
236
|
NSLog(@"%@", appoxeeError.debugDescription);
|
|
@@ -157,8 +247,8 @@ RCT_EXPORT_METHOD(setAttribute: (NSString *)key value: (NSString *) value) {
|
|
|
157
247
|
}];
|
|
158
248
|
}
|
|
159
249
|
|
|
160
|
-
RCT_EXPORT_METHOD(setAttributeInt: (NSString *)key value: (
|
|
161
|
-
[[Appoxee shared] setNumberValue
|
|
250
|
+
RCT_EXPORT_METHOD(setAttributeInt: (NSString *)key value: (NSInteger) value) {
|
|
251
|
+
[[Appoxee shared] setNumberValue:@(value) forKey:key withCompletionHandler:^(NSError * _Nullable appoxeeError, id _Nullable data) {
|
|
162
252
|
if(appoxeeError != nil) {
|
|
163
253
|
NSLog(@"%@", appoxeeError.debugDescription);
|
|
164
254
|
}
|
|
@@ -181,7 +271,7 @@ RCT_EXPORT_METHOD(addTag: (NSString *) tag) {
|
|
|
181
271
|
}];
|
|
182
272
|
}
|
|
183
273
|
|
|
184
|
-
RCT_EXPORT_METHOD(getTags:(RCTPromiseResolveBlock)resolve
|
|
274
|
+
RCT_EXPORT_METHOD(getTags:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
|
|
185
275
|
[[Appoxee shared] fetchDeviceTags:^(NSError * _Nullable appoxeeError, id _Nullable data) {
|
|
186
276
|
if (!appoxeeError && [data isKindOfClass:[NSArray class]]) {
|
|
187
277
|
NSArray *deviceTags = (NSArray *)data;
|
|
@@ -192,7 +282,7 @@ RCT_EXPORT_METHOD(getTags:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRe
|
|
|
192
282
|
}];
|
|
193
283
|
}
|
|
194
284
|
|
|
195
|
-
RCT_EXPORT_METHOD(getDeviceInfo:(RCTPromiseResolveBlock)resolve
|
|
285
|
+
RCT_EXPORT_METHOD(getDeviceInfo:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
|
|
196
286
|
[[Appoxee shared] deviceInformationwithCompletionHandler:^(NSError * _Nullable appoxeeError, id _Nullable data) {
|
|
197
287
|
if (!appoxeeError && [data isKindOfClass:[APXClientDevice class]]) {
|
|
198
288
|
APXClientDevice *device = (APXClientDevice *)data;
|
|
@@ -204,7 +294,7 @@ RCT_EXPORT_METHOD(getDeviceInfo:(RCTPromiseResolveBlock)resolve rejecter:(RCTPro
|
|
|
204
294
|
}];
|
|
205
295
|
}
|
|
206
296
|
|
|
207
|
-
RCT_EXPORT_METHOD(getAttributeStringValue: (NSString *) key
|
|
297
|
+
RCT_EXPORT_METHOD(getAttributeStringValue: (NSString *) key resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
|
|
208
298
|
[[Appoxee shared] fetchCustomFieldByKey:key withCompletionHandler:^(NSError * _Nullable appoxeeError, id _Nullable data) {
|
|
209
299
|
NSLog(@"%@", data);
|
|
210
300
|
if (!appoxeeError && [data isKindOfClass:[NSDictionary class]]) {
|
|
@@ -245,23 +335,18 @@ RCT_EXPORT_METHOD(clearNotifications) {
|
|
|
245
335
|
[[UNUserNotificationCenter currentNotificationCenter] removeAllDeliveredNotifications];
|
|
246
336
|
}
|
|
247
337
|
|
|
248
|
-
RCT_EXPORT_METHOD(clearNotification: (
|
|
249
|
-
[[UNUserNotificationCenter currentNotificationCenter] removeDeliveredNotificationsWithIdentifiers: @[[index
|
|
338
|
+
RCT_EXPORT_METHOD(clearNotification: (NSInteger) index ){
|
|
339
|
+
[[UNUserNotificationCenter currentNotificationCenter] removeDeliveredNotificationsWithIdentifiers: @[[NSString stringWithFormat:@"%ld", (long)index]]];
|
|
250
340
|
}
|
|
251
341
|
|
|
252
342
|
#pragma mark Exported methods - Inapp
|
|
253
343
|
|
|
254
|
-
|
|
255
|
-
INAPPSERVER serv = [self getInappServerKeyFor:server];
|
|
256
|
-
[[AppoxeeInapp shared] engageWithDelegate:[RNMappEventEmmiter shared] with:serv];
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
RCT_EXPORT_METHOD(fetchInboxMessage: (RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
|
|
344
|
+
RCT_EXPORT_METHOD(fetchInboxMessage: (RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
|
|
260
345
|
[[AppoxeeInapp shared] fetchAPXInBoxMessages];
|
|
261
346
|
resolve(@"Fetching, set event listener for iOS");
|
|
262
347
|
}
|
|
263
348
|
|
|
264
|
-
RCT_EXPORT_METHOD(fetchLatestInboxMessage: (RCTPromiseResolveBlock)resolve
|
|
349
|
+
RCT_EXPORT_METHOD(fetchLatestInboxMessage: (RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
|
|
265
350
|
[[AppoxeeInapp shared] fetchAPXInBoxMessages];
|
|
266
351
|
resolve(@"Fetching, set event listener for iOS");
|
|
267
352
|
}
|
|
@@ -270,28 +355,28 @@ RCT_EXPORT_METHOD(triggerInApp: (NSString *) event) {
|
|
|
270
355
|
[[AppoxeeInapp shared] reportInteractionEventWithName:event andAttributes:nil];
|
|
271
356
|
}
|
|
272
357
|
|
|
273
|
-
RCT_EXPORT_METHOD(inAppMarkAsRead: (
|
|
274
|
-
APXInBoxMessage *message = [[RNMappEventEmmiter shared] getMessageWith
|
|
358
|
+
RCT_EXPORT_METHOD(inAppMarkAsRead: (NSInteger) templateId eventId: (NSString * _Nonnull) eventId) {
|
|
359
|
+
APXInBoxMessage *message = [[RNMappEventEmmiter shared] getMessageWith:@(templateId) event:eventId];
|
|
275
360
|
if (message) {
|
|
276
361
|
[message markAsRead];
|
|
277
362
|
}
|
|
278
363
|
}
|
|
279
364
|
|
|
280
|
-
RCT_EXPORT_METHOD(inAppMarkAsUnRead: (
|
|
281
|
-
APXInBoxMessage *message = [[RNMappEventEmmiter shared] getMessageWith
|
|
365
|
+
RCT_EXPORT_METHOD(inAppMarkAsUnRead: (NSInteger) templateId eventId: (NSString * _Nonnull) eventId) {
|
|
366
|
+
APXInBoxMessage *message = [[RNMappEventEmmiter shared] getMessageWith:@(templateId) event:eventId];
|
|
282
367
|
if (message) {
|
|
283
368
|
[message markAsUnread];
|
|
284
369
|
}
|
|
285
370
|
}
|
|
286
371
|
|
|
287
|
-
RCT_EXPORT_METHOD(inAppMarkAsDeleted: (
|
|
288
|
-
APXInBoxMessage *message = [[RNMappEventEmmiter shared] getMessageWith
|
|
372
|
+
RCT_EXPORT_METHOD(inAppMarkAsDeleted: (NSInteger) templateId eventId: (NSString * _Nonnull) eventId) {
|
|
373
|
+
APXInBoxMessage *message = [[RNMappEventEmmiter shared] getMessageWith:@(templateId) event:eventId];
|
|
289
374
|
if (message) {
|
|
290
375
|
[message markAsDeleted];
|
|
291
376
|
}
|
|
292
377
|
}
|
|
293
378
|
|
|
294
|
-
RCT_EXPORT_METHOD(isDeviceRegistered:(RCTPromiseResolveBlock)resolve
|
|
379
|
+
RCT_EXPORT_METHOD(isDeviceRegistered:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) {
|
|
295
380
|
resolve(@([[Appoxee shared] isReady]));
|
|
296
381
|
}
|
|
297
382
|
|
|
@@ -371,4 +456,3 @@ RCT_EXPORT_METHOD(stopGeoFencing) {
|
|
|
371
456
|
|
|
372
457
|
|
|
373
458
|
@end
|
|
374
|
-
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-mapp-plugin",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0-beta.1",
|
|
4
4
|
"description": "Mapp SDK for React Native.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"files": [
|
|
@@ -16,10 +16,14 @@
|
|
|
16
16
|
"ios/RNMappEventEmmiter.m",
|
|
17
17
|
"ios/RNMappPlugin.xcodeproj/project.pbxproj",
|
|
18
18
|
"ios/RNMappPluginModule.h",
|
|
19
|
-
"ios/RNMappPluginModule.
|
|
19
|
+
"ios/RNMappPluginModule.mm",
|
|
20
|
+
"app.plugin.js",
|
|
21
|
+
"plugin/build/",
|
|
20
22
|
"android/src/main/jni/",
|
|
21
23
|
"specs/",
|
|
24
|
+
"BREAKING_CHANGES.md",
|
|
22
25
|
"CHANGELOG.md",
|
|
26
|
+
"MIGRATION_2.0.md",
|
|
23
27
|
"CustomEvent.js",
|
|
24
28
|
"Mapp.js",
|
|
25
29
|
"MappEventEmitter.js",
|
|
@@ -42,24 +46,41 @@
|
|
|
42
46
|
"node": ">=20.19.4"
|
|
43
47
|
},
|
|
44
48
|
"peerDependencies": {
|
|
49
|
+
"@expo/config-plugins": ">=56.0.0",
|
|
45
50
|
"react": "^19.2.3",
|
|
46
51
|
"react-native": ">=0.84"
|
|
47
52
|
},
|
|
53
|
+
"peerDependenciesMeta": {
|
|
54
|
+
"@expo/config-plugins": {
|
|
55
|
+
"optional": true
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"dependencies": {
|
|
59
|
+
"@expo/plist": "^0.7.0"
|
|
60
|
+
},
|
|
48
61
|
"devDependencies": {
|
|
49
62
|
"@babel/preset-env": "^7.29.2",
|
|
50
63
|
"@babel/preset-flow": "^7.27.1",
|
|
64
|
+
"@expo/config-plugins": "~56.0.14",
|
|
51
65
|
"@react-native-community/cli": "^20.1.3",
|
|
52
|
-
"@react-native/codegen": "0.
|
|
53
|
-
"@react-native/gradle-plugin": "0.
|
|
66
|
+
"@react-native/codegen": "0.85.3",
|
|
67
|
+
"@react-native/gradle-plugin": "0.85.3",
|
|
68
|
+
"@types/jest": "^30.0.0",
|
|
69
|
+
"@types/node": "^24.13.3",
|
|
54
70
|
"babel-jest": "^30.3.0",
|
|
55
71
|
"jest": "^30.2.0",
|
|
56
72
|
"react": "19.2.4",
|
|
57
|
-
"react-native": "0.
|
|
73
|
+
"react-native": "0.85.3",
|
|
74
|
+
"ts-jest": "^29.4.12",
|
|
75
|
+
"typescript": "^6.0.3"
|
|
58
76
|
},
|
|
59
77
|
"scripts": {
|
|
78
|
+
"build:plugin": "tsc -p plugin/tsconfig.json",
|
|
79
|
+
"test:plugin": "jest --runInBand plugin/__tests__",
|
|
60
80
|
"generate:codegen": "react-native codegen specs",
|
|
61
81
|
"build:android": "cd android && ./gradlew assembleDebug",
|
|
62
|
-
"test": "jest"
|
|
82
|
+
"test": "jest",
|
|
83
|
+
"prepare": "npm run build:plugin"
|
|
63
84
|
},
|
|
64
85
|
"codegenConfig": {
|
|
65
86
|
"name": "RNMappPlugin",
|
|
@@ -73,10 +94,12 @@
|
|
|
73
94
|
"jest": {
|
|
74
95
|
"testEnvironment": "node",
|
|
75
96
|
"testMatch": [
|
|
76
|
-
"**/__tests__/**/*.test.js"
|
|
97
|
+
"**/__tests__/**/*.test.js",
|
|
98
|
+
"**/plugin/__tests__/**/*.test.ts"
|
|
77
99
|
],
|
|
78
100
|
"transform": {
|
|
79
|
-
"^.+\\.js$": "babel-jest"
|
|
101
|
+
"^.+\\.js$": "babel-jest",
|
|
102
|
+
"^.+\\.ts$": ["ts-jest", { "tsconfig": "plugin/tsconfig.json" }]
|
|
80
103
|
},
|
|
81
104
|
"moduleNameMapper": {
|
|
82
105
|
"^react-native$": "<rootDir>/__mocks__/react-native.js"
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ConfigPlugin } from '@expo/config-plugins';
|
|
2
|
+
import type { NormalizedMappExpoPluginProps } from './types';
|
|
3
|
+
export declare function updatePushHandling(androidManifest: any, pushHandling: NormalizedMappExpoPluginProps['android']['pushHandling']): any;
|
|
4
|
+
export declare const withMappEngageAndroid: ConfigPlugin<NormalizedMappExpoPluginProps['android']>;
|