Skip to content

Commit e0cec20

Browse files
authored
Merge pull request #124 from BranchMetrics/buo-custom-params
Support for custom params in BUO.userCompletedAction
2 parents ca1f45a + 70d0b02 commit e0cec20

File tree

7 files changed

+111
-21
lines changed

7 files changed

+111
-21
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ let branchUniversalObject = branch.createBranchUniversalObject('canonicalIdentif
8282
title: 'Cool Content!',
8383
contentDescription: 'Cool Content Description'})
8484
let actionResult = await branchUniversalObject.userCompletedAction(RegisterViewEvent)
85+
let customActionResult = await branchUniversalObject.userCompletedAction('Custom Action', { key: 'value' })
8586

8687
let shareOptions = { messageHeader: 'Check this out', messageBody: 'No really, check this out!' }
8788
let linkProperties = { feature: 'share', channel: 'RNApp' }

android/src/main/java/io/branch/rnbranch/RNBranchModule.java

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,11 +168,11 @@ public void userCompletedAction(String event, ReadableMap appState) throws JSONE
168168
}
169169

170170
@ReactMethod
171-
public void userCompletedActionOnUniversalObject(String ident, String event, Promise promise) {
171+
public void userCompletedActionOnUniversalObject(String ident, String event, ReadableMap state, Promise promise) {
172172
BranchUniversalObject universalObject = findUniversalObjectOrReject(ident, promise);
173173
if (universalObject == null) return;
174174

175-
universalObject.userCompletedAction(event);
175+
universalObject.userCompletedAction(event, convertMapToParams(state));
176176
promise.resolve(null);
177177
}
178178

@@ -693,4 +693,28 @@ private static WritableArray convertJsonToArray(JSONArray jsonArray) throws JSON
693693
}
694694
return array;
695695
}
696+
697+
// Convert an arbitrary ReadableMap to a string-string hash of custom params for userCompletedAction.
698+
private static HashMap<String, String> convertMapToParams(ReadableMap map) {
699+
if (map == null) return null;
700+
701+
HashMap<String, String> hash = new HashMap<>();
702+
703+
ReadableMapKeySetIterator iterator = map.keySetIterator();
704+
while (iterator.hasNextKey()) {
705+
String key = iterator.nextKey();
706+
switch (map.getType(key)) {
707+
case String:
708+
hash.put(key, map.getString(key));
709+
case Boolean:
710+
hash.put(key, "" + map.getBoolean(key));
711+
case Number:
712+
hash.put(key, "" + map.getDouble(key));
713+
default:
714+
Log.w(REACT_CLASS, "Unsupported data type in params, ignoring");
715+
}
716+
}
717+
718+
return hash;
719+
}
696720
}

ios/BranchUniversalObject+RNBranch.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,6 @@
1616

1717
- (instancetype)initWithMap:(NSDictionary *)map;
1818

19+
- (void)rnbranchUserCompletedAction:(NSString *)action withState:(NSDictionary *)state;
20+
1921
@end

ios/BranchUniversalObject+RNBranch.m

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
#import <React/RCTLog.h>
1010

11+
#import <Branch/BranchConstants.h>
12+
1113
#import "BranchUniversalObject+RNBranch.h"
1214
#import "NSObject+RNBranch.h"
1315
#import "RNBranchProperty.h"
@@ -93,4 +95,67 @@ - (void)setExpirationDateWithString:(NSString *)expirationDate
9395
self.expirationDate = [NSDate dateWithTimeIntervalSince1970:timegm(&expiration)];
9496
}
9597

98+
#pragma mark - Code to support userCompletedAction:withState:
99+
100+
/*
101+
* Until the native SDK supports this, the following is largely lifted from BUO.m.
102+
*/
103+
104+
- (void)rnbranchUserCompletedAction:(NSString *)action withState:(NSDictionary *)state
105+
{
106+
// Anticipate that the native SDK will support this.
107+
SEL sdkMethod = @selector(userCompletedAction:withState:);
108+
if ([self respondsToSelector:sdkMethod]) {
109+
[self performSelector:sdkMethod withObject:action withObject:state];
110+
return;
111+
}
112+
113+
NSMutableDictionary *actionPayload = [[NSMutableDictionary alloc] init];
114+
NSDictionary *linkParams = [self getParamsForServerRequest];
115+
if (self.canonicalIdentifier && linkParams) {
116+
actionPayload[BNCCanonicalIdList] = @[self.canonicalIdentifier];
117+
actionPayload[self.canonicalIdentifier] = linkParams;
118+
119+
// Add in custom params
120+
[actionPayload addEntriesFromDictionary:state];
121+
122+
[[Branch getInstance] userCompletedAction:action withState:actionPayload];
123+
if (self.automaticallyListOnSpotlight && [action isEqualToString:BNCRegisterViewEvent])
124+
[self listOnSpotlight];
125+
}
126+
}
127+
128+
- (NSDictionary *)getParamsForServerRequest {
129+
NSMutableDictionary *temp = [[NSMutableDictionary alloc] init];
130+
[self safeSetValue:self.canonicalIdentifier forKey:BRANCH_LINK_DATA_KEY_CANONICAL_IDENTIFIER onDict:temp];
131+
[self safeSetValue:self.canonicalUrl forKey:BRANCH_LINK_DATA_KEY_CANONICAL_URL onDict:temp];
132+
[self safeSetValue:self.title forKey:BRANCH_LINK_DATA_KEY_OG_TITLE onDict:temp];
133+
[self safeSetValue:self.contentDescription forKey:BRANCH_LINK_DATA_KEY_OG_DESCRIPTION onDict:temp];
134+
[self safeSetValue:self.imageUrl forKey:BRANCH_LINK_DATA_KEY_OG_IMAGE_URL onDict:temp];
135+
if (self.contentIndexMode == ContentIndexModePrivate) {
136+
[self safeSetValue:@(0) forKey:BRANCH_LINK_DATA_KEY_PUBLICLY_INDEXABLE onDict:temp];
137+
}
138+
else {
139+
[self safeSetValue:@(1) forKey:BRANCH_LINK_DATA_KEY_PUBLICLY_INDEXABLE onDict:temp];
140+
}
141+
[self safeSetValue:self.keywords forKey:BRANCH_LINK_DATA_KEY_KEYWORDS onDict:temp];
142+
[self safeSetValue:@(1000 * [self.expirationDate timeIntervalSince1970]) forKey:BRANCH_LINK_DATA_KEY_CONTENT_EXPIRATION_DATE onDict:temp];
143+
[self safeSetValue:self.type forKey:BRANCH_LINK_DATA_KEY_CONTENT_TYPE onDict:temp];
144+
[self safeSetValue:self.currency forKey:BNCPurchaseCurrency onDict:temp];
145+
if (self.price) {
146+
// have to add if statement because safeSetValue only accepts objects so even if self.price is not set
147+
// a valid NSNumber object will be created and the request will have amount:0 in all cases.
148+
[self safeSetValue:[NSNumber numberWithFloat:self.price] forKey:BNCPurchaseAmount onDict:temp];
149+
}
150+
151+
[temp addEntriesFromDictionary:[self.metadata copy]];
152+
return [temp copy];
153+
}
154+
155+
- (void)safeSetValue:(NSObject *)value forKey:(NSString *)key onDict:(NSMutableDictionary *)dict {
156+
if (value) {
157+
dict[key] = value;
158+
}
159+
}
160+
96161
@end

ios/RNBranch.m

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,21 @@ - (BranchUniversalObject *)findUniversalObjectWithIdent:(NSString *)ident reject
210210
resolve(NSNull.null);
211211
}
212212

213+
#pragma mark userCompletedActionOnUniversalObject
214+
RCT_EXPORT_METHOD(
215+
userCompletedActionOnUniversalObject:(NSString *)identifier
216+
event:(NSString *)event
217+
state:(NSDictionary *)state
218+
resolver:(RCTPromiseResolveBlock)resolve
219+
rejecter:(RCTPromiseRejectBlock)reject
220+
) {
221+
BranchUniversalObject *branchUniversalObject = [self findUniversalObjectWithIdent:identifier rejecter:reject];
222+
if (!branchUniversalObject) return;
223+
224+
[branchUniversalObject rnbranchUserCompletedAction:event withState:state];
225+
resolve(NSNull.null);
226+
}
227+
213228
#pragma mark showShareSheet
214229
RCT_EXPORT_METHOD(
215230
showShareSheet:(NSString *)identifier

src/branchUniversalObject.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ export default async function createBranchUniversalObject(identifier, options =
4141
if (Platform.OS !== 'ios') return Promise.resolve()
4242
return this._tryFunction(RNBranch.listOnSpotlight)
4343
},
44-
userCompletedAction(event) {
45-
return this._tryFunction(RNBranch.userCompletedActionOnUniversalObject, event)
44+
userCompletedAction(event, state = {}) {
45+
return this._tryFunction(RNBranch.userCompletedActionOnUniversalObject, event, state)
4646
},
4747
release() {
4848
RNBranch.releaseUniversalObject(this.ident)

testbed/testbed_cocoapods/android/app/app.iml

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -128,22 +128,5 @@
128128
<orderEntry type="library" exported="" name="imagepipeline-okhttp3-0.11.0" level="project" />
129129
<orderEntry type="library" exported="" name="react-native-0.42.0" level="project" />
130130
<orderEntry type="module" module-name="react-native-branch" exported="" />
131-
<orderEntry type="library" exported="" name="okhttp-ws-2.5.0" level="project" />
132-
<orderEntry type="library" exported="" name="okio-1.6.0" level="project" />
133-
<orderEntry type="library" exported="" name="stetho-okhttp-1.2.0" level="project" />
134-
<orderEntry type="library" exported="" name="okhttp-2.5.0" level="project" />
135-
<orderEntry type="library" exported="" name="stetho-1.2.0" level="project" />
136-
<orderEntry type="library" exported="" name="jackson-core-2.2.3" level="project" />
137-
<orderEntry type="library" exported="" name="fbcore-0.8.1" level="project" />
138-
<orderEntry type="library" exported="" name="commons-cli-1.2" level="project" />
139-
<orderEntry type="library" exported="" name="recyclerview-v7-23.0.1" level="project" />
140-
<orderEntry type="library" exported="" name="imagepipeline-0.8.1" level="project" />
141-
<orderEntry type="library" exported="" name="fresco-0.8.1" level="project" />
142-
<orderEntry type="library" exported="" name="imagepipeline-okhttp-0.8.1" level="project" />
143-
<orderEntry type="library" exported="" name="bolts-android-1.1.4" level="project" />
144-
<orderEntry type="library" exported="" name="support-v4-23.0.1" level="project" />
145-
<orderEntry type="library" exported="" name="drawee-0.8.1" level="project" />
146-
<orderEntry type="library" exported="" name="react-native-0.20.1" level="project" />
147-
<orderEntry type="library" exported="" name="support-annotations-23.0.1" level="project" />
148131
</component>
149132
</module>

0 commit comments

Comments
 (0)