Skip to content

Commit

Permalink
ios: queuing batch dispatched events when module is not ready
Browse files Browse the repository at this point in the history
  • Loading branch information
arnaud-roland committed Oct 11, 2022
1 parent 9044b76 commit 0e2d4de
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 82 deletions.
2 changes: 1 addition & 1 deletion ios/RNBatch.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

#define PluginVersion "ReactNative/8.1.0"

@interface RNBatch : RCTEventEmitter <RCTBridgeModule, BatchEventDispatcherDelegate>
@interface RNBatch : RCTEventEmitter <RCTBridgeModule>

+ (void)start;

Expand Down
110 changes: 29 additions & 81 deletions ios/RNBatch.m
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# import <React/RCTConvert.h>
# import "RNBatch.h"
# import "RNBatchOpenedNotificationObserver.h"
# import "RNBatchEventDispatcher.h"

static RNBatchEventDispatcher* dispatcher = nil;

@implementation RNBatch
{
bool hasListeners;
}

+ (BOOL)requiresMainQueueSetup
{
Expand All @@ -27,7 +27,7 @@ - (instancetype)init
{
self = [super init];
_batchInboxFetcherMap = [NSMutableDictionary new];
[BatchEventDispatcher addDispatcher:self];
[dispatcher setModuleIsReady:true];
return self;
}

Expand All @@ -48,6 +48,31 @@ + (void)start

NSString *batchAPIKey = [info objectForKey:@"BatchAPIKey"];
[Batch startWithAPIKey:batchAPIKey];
dispatcher = [[RNBatchEventDispatcher alloc] init];
[BatchEventDispatcher addDispatcher:dispatcher];
}

-(void)startObserving {
[dispatcher setSendBlock:^(RNBatchEvent* event) {
[self sendEventWithName:event.name body:event.body];
}];
}

-(void)stopObserving {
[dispatcher setSendBlock:nil];
}

- (NSArray<NSString *> *)supportedEvents {
NSMutableArray *events = [NSMutableArray new];

for (int i = BatchEventDispatcherTypeNotificationOpen; i <= BatchEventDispatcherTypeMessagingWebViewClick; i++) {
NSString* eventName = [RNBatchEventDispatcher mapBatchEventDispatcherTypeToRNEvent:i];
if (eventName != nil) {
[events addObject:eventName];
}
}

return events;
}

RCT_EXPORT_METHOD(optIn:(RCTPromiseResolveBlock)resolve
Expand Down Expand Up @@ -82,83 +107,6 @@ + (void)start
});
}

// Event Dispatcher

-(void)startObserving {
hasListeners = YES;
}

-(void)stopObserving {
hasListeners = NO;
}

- (NSArray<NSString *> *)supportedEvents {
NSMutableArray *events = [NSMutableArray new];

for (int i = BatchEventDispatcherTypeNotificationOpen; i <= BatchEventDispatcherTypeMessagingWebViewClick; i++) {
NSString* eventName = [self mapBatchEventDispatcherTypeToRNEvent:i];
if (eventName != nil) {
[events addObject:eventName];
}
}

return events;
}

- (void)dispatchEventWithType:(BatchEventDispatcherType)type
payload:(nonnull id<BatchEventDispatcherPayload>)payload {
if (hasListeners) {
NSString* eventName = [self mapBatchEventDispatcherTypeToRNEvent:type];
if (eventName != nil) {
[self sendEventWithName:eventName body:[self dictionaryWithEventDispatcherPayload:payload]];
}
}
}

- (nullable NSString *) mapBatchEventDispatcherTypeToRNEvent:(BatchEventDispatcherType)type {
switch (type) {
case BatchEventDispatcherTypeNotificationOpen:
return @"notification_open";
case BatchEventDispatcherTypeMessagingShow:
return @"messaging_show";
case BatchEventDispatcherTypeMessagingClose:
return @"messaging_close";
case BatchEventDispatcherTypeMessagingCloseError:
return @"messaging_close_error";
case BatchEventDispatcherTypeMessagingAutoClose:
return @"messaging_auto_close";
case BatchEventDispatcherTypeMessagingClick:
return @"messaging_click";
case BatchEventDispatcherTypeMessagingWebViewClick:
return @"messaging_webview_click";
}
}

- (NSDictionary*) dictionaryWithEventDispatcherPayload:(id<BatchEventDispatcherPayload>)payload
{
NSMutableDictionary *output = [NSMutableDictionary dictionaryWithDictionary:@{
@"isPositiveAction": @(payload.isPositiveAction),
}];

if (payload.deeplink != nil) {
output[@"deeplink"] = payload.deeplink;
}

if (payload.trackingId != nil) {
output[@"trackingId"] = payload.trackingId;
}

if (payload.deeplink != nil) {
output[@"webViewAnalyticsIdentifier"] = payload.webViewAnalyticsIdentifier;
}

if (payload.notificationUserInfo != nil) {
output[@"pushPayload"] = payload.notificationUserInfo;
}

return output;
}

// Push Module

RCT_EXPORT_METHOD(push_registerForRemoteNotifications)
Expand Down
21 changes: 21 additions & 0 deletions ios/RNBatchEventDispatcher.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# import "RNBatch.h"

@interface RNBatchEvent : NSObject

@property (readonly) NSString* _Nonnull name;

@property (readonly) NSDictionary* _Nonnull body;

- (nonnull instancetype)initWithName:(nonnull NSString *)name andBody:(nullable NSDictionary *)body;

@end

@interface RNBatchEventDispatcher : NSObject <BatchEventDispatcherDelegate>

- (void)setSendBlock:(void (^_Nullable)(RNBatchEvent* _Nonnull event))callback;

- (void)setModuleIsReady:(BOOL)ready;

+ (nullable NSString *)mapBatchEventDispatcherTypeToRNEvent:(BatchEventDispatcherType)type;

@end
123 changes: 123 additions & 0 deletions ios/RNBatchEventDispatcher.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# import "RNBatchEventDispatcher.h"

@implementation RNBatchEventDispatcher {

BOOL _moduleIsReady;

NSMutableArray<RNBatchEvent*>* _events;

void (^_sendBlock)(RNBatchEvent *_Nonnull event);
}

-(instancetype)init {
self = [super init];
if (self) {
_events = [NSMutableArray array];
}
return self;
}

-(void)setSendBlock:(void (^)(RNBatchEvent* event))callback {
_sendBlock = callback;
if(_sendBlock != nil) {
[self dequeueEvents];
}
}

- (void)setModuleIsReady:(BOOL)ready {
_moduleIsReady = ready;
}


- (void)dequeueEvents {
if(_sendBlock == nil) {
return;
}
@synchronized(_events) {
NSArray *enqueuedEvents = [_events copy];
[_events removeAllObjects];

for (RNBatchEvent *event in enqueuedEvents) {
_sendBlock(event);
}
}
}

- (void)dispatchEventWithType:(BatchEventDispatcherType)type
payload:(nonnull id<BatchEventDispatcherPayload>)payload {

if (_moduleIsReady && _sendBlock == nil) {
// RN Module is ready but no listener registered
// not queuing up events
return;
}
NSString* eventName = [RNBatchEventDispatcher mapBatchEventDispatcherTypeToRNEvent:type];
if (eventName != nil) {
RNBatchEvent* event = [[RNBatchEvent alloc] initWithName:eventName andBody:[self dictionaryWithEventDispatcherPayload:payload]];
@synchronized(_events) {
[_events addObject:event];
}
if (_sendBlock != nil) {
[self dequeueEvents];
}
}
}

+ (nullable NSString *) mapBatchEventDispatcherTypeToRNEvent:(BatchEventDispatcherType)type {
switch (type) {
case BatchEventDispatcherTypeNotificationOpen:
return @"notification_open";
case BatchEventDispatcherTypeMessagingShow:
return @"messaging_show";
case BatchEventDispatcherTypeMessagingClose:
return @"messaging_close";
case BatchEventDispatcherTypeMessagingCloseError:
return @"messaging_close_error";
case BatchEventDispatcherTypeMessagingAutoClose:
return @"messaging_auto_close";
case BatchEventDispatcherTypeMessagingClick:
return @"messaging_click";
case BatchEventDispatcherTypeMessagingWebViewClick:
return @"messaging_webview_click";
}
}

- (NSDictionary*) dictionaryWithEventDispatcherPayload:(id<BatchEventDispatcherPayload>)payload
{
NSMutableDictionary *output = [NSMutableDictionary dictionaryWithDictionary:@{
@"isPositiveAction": @(payload.isPositiveAction),
}];

if (payload.deeplink != nil) {
output[@"deeplink"] = payload.deeplink;
}

if (payload.trackingId != nil) {
output[@"trackingId"] = payload.trackingId;
}

if (payload.deeplink != nil) {
output[@"webViewAnalyticsIdentifier"] = payload.webViewAnalyticsIdentifier;
}

if (payload.notificationUserInfo != nil) {
output[@"pushPayload"] = payload.notificationUserInfo;
}

return output;
}

@end

@implementation RNBatchEvent

- (nonnull instancetype)initWithName:(nonnull NSString *)name andBody:(nullable NSDictionary *)body {
self = [super init];
if (self) {
_name = name;
_body = body;
}
return self;
}

@end
4 changes: 4 additions & 0 deletions ios/RNBatchPush.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
1E4AD39B28EF23220095227A /* RNBatchEventDispatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E4AD39A28EF23220095227A /* RNBatchEventDispatcher.m */; };
AA04798A214AA8EA0049BDB2 /* RNBatch.m in Sources */ = {isa = PBXBuildFile; fileRef = AA047989214AA8EA0049BDB2 /* RNBatch.m */; };
/* End PBXBuildFile section */

Expand All @@ -24,6 +25,7 @@

/* Begin PBXFileReference section */
134814201AA4EA6300B7C361 /* libRNBatchPush.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNBatchPush.a; sourceTree = BUILT_PRODUCTS_DIR; };
1E4AD39A28EF23220095227A /* RNBatchEventDispatcher.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNBatchEventDispatcher.m; sourceTree = "<group>"; };
AA047989214AA8EA0049BDB2 /* RNBatch.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNBatch.m; sourceTree = "<group>"; };
AA04798B214AA8FF0049BDB2 /* RNBatch.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNBatch.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
Expand All @@ -50,6 +52,7 @@
58B511D21A9E6C8500147676 = {
isa = PBXGroup;
children = (
1E4AD39A28EF23220095227A /* RNBatchEventDispatcher.m */,
AA04798B214AA8FF0049BDB2 /* RNBatch.h */,
AA047989214AA8EA0049BDB2 /* RNBatch.m */,
134814211AA4EA7D00B7C361 /* Products */,
Expand Down Expand Up @@ -113,6 +116,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
1E4AD39B28EF23220095227A /* RNBatchEventDispatcher.m in Sources */,
AA04798A214AA8EA0049BDB2 /* RNBatch.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down

0 comments on commit 0e2d4de

Please sign in to comment.