UNPKG

26.9 kBPlain TextView Raw
1#import "RNBranch.h"
2#import <React/RCTEventDispatcher.h>
3#import <React/RCTLog.h>
4#import "BranchEvent+RNBranch.h"
5#import "BranchLinkProperties+RNBranch.h"
6#import "BranchUniversalObject+RNBranch.h"
7#import "RNBranchAgingDictionary.h"
8#import "RNBranchConfig.h"
9#import "RNBranchEventEmitter.h"
10
11NSString * const RNBranchLinkOpenedNotification = @"RNBranchLinkOpenedNotification";
12NSString * const RNBranchLinkOpenedNotificationErrorKey = @"error";
13NSString * const RNBranchLinkOpenedNotificationParamsKey = @"params";
14NSString * const RNBranchLinkOpenedNotificationUriKey = @"uri";
15NSString * const RNBranchLinkOpenedNotificationBranchUniversalObjectKey = @"branch_universal_object";
16NSString * const RNBranchLinkOpenedNotificationLinkPropertiesKey = @"link_properties";
17
18static NSDictionary *initSessionWithLaunchOptionsResult;
19static BOOL useTestInstance = NO;
20static NSDictionary *savedLaunchOptions;
21static BOOL savedIsReferrable;
22static NSString *branchKey;
23static BOOL deferInitializationForJSLoad = NO;
24
25static NSString * const IdentFieldName = @"ident";
26
27// These are only really exposed to the JS layer, so keep them internal for now.
28static NSString * const RNBranchErrorDomain = @"RNBranchErrorDomain";
29static NSInteger const RNBranchUniversalObjectNotFoundError = 1;
30
31#pragma mark - Private RNBranch declarations
32
33@interface RNBranch()
34@property (nonatomic, readonly) UIViewController *currentViewController;
35@property (nonatomic) RNBranchAgingDictionary<NSString *, BranchUniversalObject *> *universalObjectMap;
36@end
37
38#pragma mark - RNBranch implementation
39
40@implementation RNBranch
41
42RCT_EXPORT_MODULE();
43
44+ (Branch *)branch
45{
46 @synchronized(self) {
47 static Branch *instance;
48 static dispatch_once_t once = 0;
49 dispatch_once(&once, ^{
50 RNBranchConfig *config = RNBranchConfig.instance;
51
52 // YES if either [RNBranch useTestInstance] was called or useTestInstance: true is present in branch.json.
53 BOOL usingTestInstance = useTestInstance || config.useTestInstance;
54 NSString *key = branchKey ?: config.branchKey ?: usingTestInstance ? config.testKey : config.liveKey;
55
56 if (key) {
57 // Override the Info.plist if these are present.
58 instance = [Branch getInstance: key];
59 }
60 else {
61 [Branch setUseTestBranchKey:usingTestInstance];
62 instance = [Branch getInstance];
63 }
64
65 [self setupBranchInstance:instance];
66 });
67 return instance;
68 }
69}
70
71+ (BOOL)requiresMainQueueSetup {
72 return YES;
73}
74
75+ (void)setupBranchInstance:(Branch *)instance
76{
77 RCTLogInfo(@"Initializing Branch SDK v. %@", BNC_SDK_VERSION);
78 RNBranchConfig *config = RNBranchConfig.instance;
79 if (config.debugMode) {
80 [instance setDebug];
81 }
82 if (config.delayInitToCheckForSearchAds) {
83 [instance delayInitToCheckForSearchAds];
84 }
85 if (config.appleSearchAdsDebugMode) {
86 [instance setAppleSearchAdsDebugMode];
87 }
88}
89
90- (NSDictionary<NSString *, NSString *> *)constantsToExport {
91 return @{
92 // RN events transmitted to JS by event emitter
93 @"INIT_SESSION_SUCCESS": kRNBranchInitSessionSuccess,
94 @"INIT_SESSION_ERROR": kRNBranchInitSessionError,
95
96 // constants for use with userCompletedAction
97 @"ADD_TO_CART_EVENT": BNCAddToCartEvent,
98 @"ADD_TO_WISHLIST_EVENT": BNCAddToWishlistEvent,
99 @"PURCHASED_EVENT": BNCPurchasedEvent,
100 @"PURCHASE_INITIATED_EVENT": BNCPurchaseInitiatedEvent,
101 @"REGISTER_VIEW_EVENT": BNCRegisterViewEvent,
102 @"SHARE_COMPLETED_EVENT": BNCShareCompletedEvent,
103 @"SHARE_INITIATED_EVENT": BNCShareInitiatedEvent,
104
105 // constants for use with BranchEvent
106
107 // Commerce events
108 @"STANDARD_EVENT_ADD_TO_CART": BranchStandardEventAddToCart,
109 @"STANDARD_EVENT_ADD_TO_WISHLIST": BranchStandardEventAddToWishlist,
110 @"STANDARD_EVENT_VIEW_CART": BranchStandardEventViewCart,
111 @"STANDARD_EVENT_INITIATE_PURCHASE": BranchStandardEventInitiatePurchase,
112 @"STANDARD_EVENT_ADD_PAYMENT_INFO": BranchStandardEventAddPaymentInfo,
113 @"STANDARD_EVENT_PURCHASE": BranchStandardEventPurchase,
114 @"STANDARD_EVENT_SPEND_CREDITS": BranchStandardEventSpendCredits,
115
116 // Content Events
117 @"STANDARD_EVENT_SEARCH": BranchStandardEventSearch,
118 @"STANDARD_EVENT_VIEW_ITEM": BranchStandardEventViewItem,
119 @"STANDARD_EVENT_VIEW_ITEMS": BranchStandardEventViewItems,
120 @"STANDARD_EVENT_RATE": BranchStandardEventRate,
121 @"STANDARD_EVENT_SHARE": BranchStandardEventShare,
122
123 // User Lifecycle Events
124 @"STANDARD_EVENT_COMPLETE_REGISTRATION": BranchStandardEventCompleteRegistration,
125 @"STANDARD_EVENT_COMPLETE_TUTORIAL": BranchStandardEventCompleteTutorial,
126 @"STANDARD_EVENT_ACHIEVE_LEVEL": BranchStandardEventAchieveLevel,
127 @"STANDARD_EVENT_UNLOCK_ACHIEVEMENT": BranchStandardEventUnlockAchievement
128 };
129}
130
131#pragma mark - Class methods
132
133+ (void)setDebug
134{
135 [self.branch setDebug];
136}
137
138+ (void)delayInitToCheckForSearchAds
139{
140 [self.branch delayInitToCheckForSearchAds];
141}
142
143+ (void)setAppleSearchAdsDebugMode
144{
145 [self.branch setAppleSearchAdsDebugMode];
146}
147
148+ (void)setRequestMetadataKey:(NSString *)key value:(NSObject *)value
149{
150 [self.branch setRequestMetadataKey:key value:value];
151}
152
153+ (void)useTestInstance {
154 useTestInstance = YES;
155}
156
157+ (void)deferInitializationForJSLoad
158{
159 deferInitializationForJSLoad = YES;
160}
161
162//Called by AppDelegate.m -- stores initSession result in static variables and posts RNBranchLinkOpened event that's captured by the RNBranch instance to emit it to React Native
163+ (void)initSessionWithLaunchOptions:(NSDictionary *)launchOptions isReferrable:(BOOL)isReferrable {
164 savedLaunchOptions = launchOptions;
165 savedIsReferrable = isReferrable;
166
167 // Can't currently support this on Android.
168 // if (!deferInitializationForJSLoad && !RNBranchConfig.instance.deferInitializationForJSLoad) [self initializeBranchSDK];
169 [self initializeBranchSDK];
170}
171
172+ (void)initializeBranchSDK
173{
174 [self.branch initSessionWithLaunchOptions:savedLaunchOptions isReferrable:savedIsReferrable andRegisterDeepLinkHandler:^(NSDictionary *params, NSError *error) {
175 NSMutableDictionary *result = [NSMutableDictionary dictionary];
176 if (error) result[RNBranchLinkOpenedNotificationErrorKey] = error;
177 if (params) {
178 result[RNBranchLinkOpenedNotificationParamsKey] = params;
179 BOOL clickedBranchLink = params[@"+clicked_branch_link"];
180
181 if (clickedBranchLink) {
182 BranchUniversalObject *branchUniversalObject = [BranchUniversalObject objectWithDictionary:params];
183 if (branchUniversalObject) result[RNBranchLinkOpenedNotificationBranchUniversalObjectKey] = branchUniversalObject;
184
185 BranchLinkProperties *linkProperties = [BranchLinkProperties getBranchLinkPropertiesFromDictionary:params];
186 if (linkProperties) result[RNBranchLinkOpenedNotificationLinkPropertiesKey] = linkProperties;
187
188 if (params[@"~referring_link"]) {
189 result[RNBranchLinkOpenedNotificationUriKey] = [NSURL URLWithString:params[@"~referring_link"]];
190 }
191 }
192 else if (params[@"+non_branch_link"]) {
193 result[RNBranchLinkOpenedNotificationUriKey] = [NSURL URLWithString:params[@"+non_branch_link"]];
194 }
195 }
196
197 [[NSNotificationCenter defaultCenter] postNotificationName:RNBranchLinkOpenedNotification object:nil userInfo:result];
198 }];
199}
200
201// TODO: Eliminate these now that sourceUrl is gone.
202+ (BOOL)handleDeepLink:(NSURL *)url {
203 BOOL handled = [self.branch handleDeepLink:url];
204 return handled;
205}
206
207#pragma clang diagnostic push
208#pragma clang diagnostic ignored "-Wpartial-availability"
209+ (BOOL)continueUserActivity:(NSUserActivity *)userActivity {
210 return [self.branch continueUserActivity:userActivity];
211}
212#pragma clang diagnostic pop
213
214#pragma mark - Object lifecycle
215
216- (instancetype)init {
217 self = [super init];
218
219 if (self) {
220 _universalObjectMap = [RNBranchAgingDictionary dictionaryWithTtl:3600.0];
221
222 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onInitSessionFinished:) name:RNBranchLinkOpenedNotification object:nil];
223 }
224
225 return self;
226}
227
228- (void) dealloc {
229 [[NSNotificationCenter defaultCenter] removeObserver:self];
230}
231
232#pragma mark - Utility methods
233
234- (UIViewController *)currentViewController
235{
236 UIViewController *current = [UIApplication sharedApplication].keyWindow.rootViewController;
237 while (current.presentedViewController && ![current.presentedViewController isKindOfClass:UIAlertController.class]) {
238 current = current.presentedViewController;
239 }
240 return current;
241}
242
243- (void) onInitSessionFinished:(NSNotification*) notification {
244 NSURL *uri = notification.userInfo[RNBranchLinkOpenedNotificationUriKey];
245 NSError *error = notification.userInfo[RNBranchLinkOpenedNotificationErrorKey];
246 NSDictionary *params = notification.userInfo[RNBranchLinkOpenedNotificationParamsKey];
247
248 initSessionWithLaunchOptionsResult = @{
249 RNBranchLinkOpenedNotificationErrorKey: error.localizedDescription ?: NSNull.null,
250 RNBranchLinkOpenedNotificationParamsKey: params ?: NSNull.null,
251 RNBranchLinkOpenedNotificationUriKey: uri.absoluteString ?: NSNull.null
252 };
253
254 // If there is an error, fire error event
255 if (error) {
256 [RNBranchEventEmitter initSessionDidEncounterErrorWithPayload:initSessionWithLaunchOptionsResult];
257 }
258
259 // otherwise notify the session is finished
260 else {
261 [RNBranchEventEmitter initSessionDidSucceedWithPayload:initSessionWithLaunchOptionsResult];
262 }
263}
264
265- (BranchLinkProperties*) createLinkProperties:(NSDictionary *)linkPropertiesMap withControlParams:(NSDictionary *)controlParamsMap
266{
267 BranchLinkProperties *linkProperties = [[BranchLinkProperties alloc] initWithMap:linkPropertiesMap];
268
269 linkProperties.controlParams = controlParamsMap;
270 return linkProperties;
271}
272
273- (BranchUniversalObject *)findUniversalObjectWithIdent:(NSString *)ident rejecter:(RCTPromiseRejectBlock)reject
274{
275 BranchUniversalObject *universalObject = self.universalObjectMap[ident];
276
277 if (!universalObject) {
278 NSString *errorMessage = [NSString stringWithFormat:@"BranchUniversalObject for ident %@ not found.", ident];
279
280 NSError *error = [NSError errorWithDomain:RNBranchErrorDomain
281 code:RNBranchUniversalObjectNotFoundError
282 userInfo:@{IdentFieldName : ident,
283 NSLocalizedDescriptionKey: errorMessage
284 }];
285
286 reject(@"RNBranch::Error::BUONotFound", errorMessage, error);
287 }
288
289 return universalObject;
290}
291
292#pragma mark - Methods exported to React Native
293
294#pragma mark disableTracking
295RCT_EXPORT_METHOD(
296 disableTracking:(BOOL)disable
297 ) {
298 [Branch setTrackingDisabled: disable];
299}
300
301#pragma mark isTrackingDisabled
302RCT_EXPORT_METHOD(
303 isTrackingDisabled:(RCTPromiseResolveBlock)resolve
304 rejecter:(__unused RCTPromiseRejectBlock)reject
305 ) {
306 resolve([Branch trackingDisabled] ? @YES : @NO);
307}
308
309#pragma mark initializeBranch
310RCT_EXPORT_METHOD(initializeBranch:(NSString *)key
311 resolver:(RCTPromiseResolveBlock)resolve
312 rejecter:(RCTPromiseRejectBlock)reject
313 ) {
314 NSError *error = [NSError errorWithDomain:RNBranchErrorDomain
315 code:-1
316 userInfo:nil];
317
318 reject(@"RNBranch::Error::Unsupported", @"Initializing the Branch SDK from JS will be supported in a future release.", error);
319
320 /*
321 if (!deferInitializationForJSLoad && !RNBranchConfig.instance.deferInitializationForJSLoad) {
322 // This is a no-op from JS unless [RNBranch deferInitializationForJSLoad] is called.
323 resolve(0);
324 return;
325 }
326
327 RCTLogTrace(@"Initializing Branch SDK. Key from JS: %@", key);
328 branchKey = key;
329
330 [self.class initializeBranchSDK];
331 resolve(0);
332 // */
333}
334
335#pragma mark redeemInitSessionResult
336RCT_EXPORT_METHOD(
337 redeemInitSessionResult:(RCTPromiseResolveBlock)resolve
338 rejecter:(__unused RCTPromiseRejectBlock)reject
339 ) {
340 resolve(initSessionWithLaunchOptionsResult ?: [NSNull null]);
341}
342
343#pragma mark getLatestReferringParams
344RCT_EXPORT_METHOD(
345 getLatestReferringParams:(RCTPromiseResolveBlock)resolve
346 rejecter:(__unused RCTPromiseRejectBlock)reject
347 ) {
348 resolve([self.class.branch getLatestReferringParams]);
349}
350
351#pragma mark getFirstReferringParams
352RCT_EXPORT_METHOD(
353 getFirstReferringParams:(RCTPromiseResolveBlock)resolve
354 rejecter:(__unused RCTPromiseRejectBlock)reject
355 ) {
356 resolve([self.class.branch getFirstReferringParams]);
357}
358
359#pragma mark setIdentity
360RCT_EXPORT_METHOD(
361 setIdentity:(NSString *)identity
362 ) {
363 [self.class.branch setIdentity:identity];
364}
365
366#pragma mark logout
367RCT_EXPORT_METHOD(
368 logout
369 ) {
370 [self.class.branch logout];
371}
372
373#pragma mark openURL
374RCT_EXPORT_METHOD(
375 openURL:(NSString *)urlString
376 ) {
377 [self.class.branch handleDeepLinkWithNewSession:[NSURL URLWithString:urlString]];
378}
379
380#pragma mark sendCommerceEvent
381RCT_EXPORT_METHOD(
382 sendCommerceEvent:(NSString *)revenue
383 metadata:(NSDictionary *)metadata
384 resolver:(RCTPromiseResolveBlock)resolve
385 rejecter:(__unused RCTPromiseRejectBlock)reject
386 ) {
387 BNCCommerceEvent *commerceEvent = [BNCCommerceEvent new];
388 commerceEvent.revenue = [NSDecimalNumber decimalNumberWithString:revenue];
389 [self.class.branch sendCommerceEvent:commerceEvent metadata:metadata withCompletion:nil];
390 resolve(NSNull.null);
391}
392
393#pragma mark userCompletedAction
394RCT_EXPORT_METHOD(
395 userCompletedAction:(NSString *)event withState:(NSDictionary *)appState
396 ) {
397 [self.class.branch userCompletedAction:event withState:appState];
398}
399
400#pragma mark userCompletedActionOnUniversalObject
401RCT_EXPORT_METHOD(
402 userCompletedActionOnUniversalObject:(NSString *)identifier
403 event:(NSString *)event
404 resolver:(RCTPromiseResolveBlock)resolve
405 rejecter:(RCTPromiseRejectBlock)reject
406) {
407 BranchUniversalObject *branchUniversalObject = [self findUniversalObjectWithIdent:identifier rejecter:reject];
408 if (!branchUniversalObject) return;
409
410 [branchUniversalObject userCompletedAction:event];
411 resolve(NSNull.null);
412}
413
414#pragma mark userCompletedActionOnUniversalObject
415RCT_EXPORT_METHOD(
416 userCompletedActionOnUniversalObject:(NSString *)identifier
417 event:(NSString *)event
418 state:(NSDictionary *)state
419 resolver:(RCTPromiseResolveBlock)resolve
420 rejecter:(RCTPromiseRejectBlock)reject
421 ) {
422 BranchUniversalObject *branchUniversalObject = [self findUniversalObjectWithIdent:identifier rejecter:reject];
423 if (!branchUniversalObject) return;
424
425 [branchUniversalObject userCompletedAction:event withState:state];
426 resolve(NSNull.null);
427}
428
429#pragma mark logEvent
430RCT_EXPORT_METHOD(
431 logEvent:(NSArray *)identifiers
432 eventName:(NSString *)eventName
433 params:(NSDictionary *)params
434 resolver:(RCTPromiseResolveBlock)resolve
435 rejecter:(RCTPromiseRejectBlock)reject
436 ) {
437 BranchEvent *event = [[BranchEvent alloc] initWithName:eventName map:params];
438
439 NSMutableArray<BranchUniversalObject *> *buos = @[].mutableCopy;
440 for (NSString *identifier in identifiers) {
441 BranchUniversalObject *buo = [self findUniversalObjectWithIdent:identifier rejecter:reject];
442 if (!buo) return;
443
444 [buos addObject:buo];
445 }
446
447 event.contentItems = buos;
448 if ([eventName isEqualToString:BranchStandardEventViewItem] && params.count == 0) {
449 for (BranchUniversalObject *buo in buos) {
450 if (!buo.locallyIndex) continue;
451 // for now at least, pending possible changes to the native SDK
452 [buo listOnSpotlight];
453 }
454 }
455
456 [event logEvent];
457 resolve(NSNull.null);
458}
459
460#pragma mark showShareSheet
461RCT_EXPORT_METHOD(
462 showShareSheet:(NSString *)identifier
463 withShareOptions:(NSDictionary *)shareOptionsMap
464 withLinkProperties:(NSDictionary *)linkPropertiesMap
465 withControlParams:(NSDictionary *)controlParamsMap
466 resolver:(RCTPromiseResolveBlock)resolve
467 rejecter:(RCTPromiseRejectBlock)reject
468 ) {
469 BranchUniversalObject *branchUniversalObject = [self findUniversalObjectWithIdent:identifier rejecter:reject];
470 if (!branchUniversalObject) return;
471
472 dispatch_async(dispatch_get_main_queue(), ^{
473 NSMutableDictionary *mutableControlParams = controlParamsMap.mutableCopy;
474 if (shareOptionsMap && shareOptionsMap[@"emailSubject"]) {
475 mutableControlParams[@"$email_subject"] = shareOptionsMap[@"emailSubject"];
476 }
477
478 BranchLinkProperties *linkProperties = [self createLinkProperties:linkPropertiesMap withControlParams:mutableControlParams];
479
480 [branchUniversalObject showShareSheetWithLinkProperties:linkProperties
481 andShareText:shareOptionsMap[@"messageBody"]
482 fromViewController:self.currentViewController
483 completionWithError:^(NSString * _Nullable activityType, BOOL completed, NSError * _Nullable activityError){
484 if (activityError) {
485 NSString *errorCodeString = [NSString stringWithFormat:@"%ld", (long)activityError.code];
486 reject(errorCodeString, activityError.localizedDescription, activityError);
487 return;
488 }
489
490 NSDictionary *result = @{
491 @"channel" : activityType ?: [NSNull null],
492 @"completed" : @(completed),
493 @"error" : [NSNull null]
494 };
495
496 resolve(result);
497 }];
498 });
499}
500
501#pragma mark registerView
502RCT_EXPORT_METHOD(
503 registerView:(NSString *)identifier
504 resolver:(RCTPromiseResolveBlock)resolve
505 rejecter:(RCTPromiseRejectBlock)reject
506 ) {
507 BranchUniversalObject *branchUniversalObject = [self findUniversalObjectWithIdent:identifier rejecter:reject];
508 if (!branchUniversalObject) return;
509
510 [branchUniversalObject registerViewWithCallback:^(NSDictionary *params, NSError *error) {
511 if (!error) {
512 resolve([NSNull null]);
513 } else {
514 reject([NSString stringWithFormat: @"%lu", (long)error.code], error.localizedDescription, error);
515 }
516 }];
517}
518
519#pragma mark generateShortUrl
520RCT_EXPORT_METHOD(
521 generateShortUrl:(NSString *)identifier
522 withLinkProperties:(NSDictionary *)linkPropertiesMap
523 withControlParams:(NSDictionary *)controlParamsMap
524 resolver:(RCTPromiseResolveBlock)resolve
525 rejecter:(RCTPromiseRejectBlock)reject
526 ) {
527 BranchUniversalObject *branchUniversalObject = [self findUniversalObjectWithIdent:identifier rejecter:reject];
528 if (!branchUniversalObject) return;
529
530 BranchLinkProperties *linkProperties = [self createLinkProperties:linkPropertiesMap withControlParams:controlParamsMap];
531
532 [branchUniversalObject getShortUrlWithLinkProperties:linkProperties andCallback:^(NSString *url, NSError *error) {
533 if (!error) {
534 RCTLogInfo(@"RNBranch Success");
535 resolve(@{ @"url": url });
536 }
537 else if (error.code == BNCDuplicateResourceError) {
538 reject(@"RNBranch::Error::DuplicateResourceError", error.localizedDescription, error);
539 }
540 else {
541 reject(@"RNBranch::Error", error.localizedDescription, error);
542 }
543 }];
544}
545
546#pragma mark listOnSpotlight
547RCT_EXPORT_METHOD(
548 listOnSpotlight:(NSString *)identifier
549 resolver:(RCTPromiseResolveBlock)resolve
550 rejecter:(RCTPromiseRejectBlock)reject
551 ) {
552 BranchUniversalObject *branchUniversalObject = [self findUniversalObjectWithIdent:identifier rejecter:reject];
553 if (!branchUniversalObject) return;
554
555 [branchUniversalObject listOnSpotlightWithCallback:^(NSString *string, NSError *error) {
556 if (!error) {
557 NSDictionary *data = @{@"result":string};
558 resolve(data);
559 } else {
560 reject([NSString stringWithFormat: @"%lu", (long)error.code], error.localizedDescription, error);
561 }
562 }];
563}
564
565// @TODO can this be removed? legacy, short url should be created from BranchUniversalObject
566#pragma mark getShortUrl
567RCT_EXPORT_METHOD(
568 getShortUrl:(NSDictionary *)linkPropertiesMap
569 resolver:(RCTPromiseResolveBlock)resolve
570 rejecter:(RCTPromiseRejectBlock)reject
571 ) {
572 NSString *feature = linkPropertiesMap[@"feature"];
573 NSString *channel = linkPropertiesMap[@"channel"];
574 NSString *stage = linkPropertiesMap[@"stage"];
575 NSArray *tags = linkPropertiesMap[@"tags"];
576
577 [self.class.branch getShortURLWithParams:linkPropertiesMap
578 andTags:tags
579 andChannel:channel
580 andFeature:feature
581 andStage:stage
582 andCallback:^(NSString *url, NSError *error) {
583 if (error) {
584 RCTLogError(@"RNBranch::Error: %@", error.localizedDescription);
585 reject(@"RNBranch::Error", @"getShortURLWithParams", error);
586 }
587 resolve(url);
588 }];
589}
590
591#pragma mark loadRewards
592RCT_EXPORT_METHOD(
593 loadRewards:(NSString *)bucket
594 resolver:(RCTPromiseResolveBlock)resolve
595 rejecter:(RCTPromiseRejectBlock)reject
596 ) {
597 [self.class.branch loadRewardsWithCallback:^(BOOL changed, NSError *error) {
598 if(!error) {
599 int credits = 0;
600 if (bucket) {
601 credits = (int)[self.class.branch getCreditsForBucket:bucket];
602 } else {
603 credits = (int)[self.class.branch getCredits];
604 }
605 resolve(@{@"credits": @(credits)});
606 } else {
607 RCTLogError(@"Load Rewards Error: %@", error.localizedDescription);
608 reject(@"RNBranch::Error::loadRewardsWithCallback", @"loadRewardsWithCallback", error);
609 }
610 }];
611}
612
613#pragma mark redeemRewards
614RCT_EXPORT_METHOD(
615 redeemRewards:(NSInteger)amount
616 inBucket:(NSString *)bucket
617 resolver:(RCTPromiseResolveBlock)resolve
618 rejecter:(RCTPromiseRejectBlock)reject
619 ) {
620 if (bucket) {
621 [self.class.branch redeemRewards:amount forBucket:bucket callback:^(BOOL changed, NSError *error) {
622 if (!error) {
623 resolve(@{@"changed": @(changed)});
624 } else {
625 RCTLogError(@"Redeem Rewards Error: %@", error.localizedDescription);
626 reject(@"RNBranch::Error::redeemRewards", error.localizedDescription, error);
627 }
628 }];
629 } else {
630 [self.class.branch redeemRewards:amount callback:^(BOOL changed, NSError *error) {
631 if (!error) {
632 resolve(@{@"changed": @(changed)});
633 } else {
634 RCTLogError(@"Redeem Rewards Error: %@", error.localizedDescription);
635 reject(@"RNBranch::Error::redeemRewards", error.localizedDescription, error);
636 }
637 }];
638 }
639}
640
641#pragma mark getCreditHistory
642RCT_EXPORT_METHOD(
643 getCreditHistory:(RCTPromiseResolveBlock)resolve
644 rejecter:(RCTPromiseRejectBlock)reject
645 ) {
646 [self.class.branch getCreditHistoryWithCallback:^(NSArray *list, NSError *error) {
647 if (!error) {
648 resolve(list);
649 } else {
650 RCTLogError(@"Credit History Error: %@", error.localizedDescription);
651 reject(@"RNBranch::Error::getCreditHistory", error.localizedDescription, error);
652 }
653 }];
654}
655
656#pragma mark createUniversalObject
657RCT_EXPORT_METHOD(
658 createUniversalObject:(NSDictionary *)universalObjectProperties
659 resolver:(RCTPromiseResolveBlock)resolve
660 rejecter:(__unused RCTPromiseRejectBlock)reject
661 ) {
662 BranchUniversalObject *universalObject = [[BranchUniversalObject alloc] initWithMap:universalObjectProperties];
663 NSString *identifier = [NSUUID UUID].UUIDString;
664 self.universalObjectMap[identifier] = universalObject;
665 NSDictionary *response = @{IdentFieldName: identifier};
666
667 resolve(response);
668}
669
670#pragma mark releaseUniversalObject
671RCT_EXPORT_METHOD(
672 releaseUniversalObject:(NSString *)identifier
673 ) {
674 [self.universalObjectMap removeObjectForKey:identifier];
675}
676
677@end