diff --git a/.gitignore b/.gitignore
index f3485004..156a3967 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,4 +9,5 @@ npm-debug.log*
yarn-error.log*
.vscode
.idea
+cordova-ionic-phonegap-branch-deep-linking-attribution.iml
src/android/.idea
\ No newline at end of file
diff --git a/package.json b/package.json
index 1f898058..245e90de 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "branch-cordova-sdk",
"description": "Branch Metrics Cordova SDK",
"main": "src/index.js",
- "version": "5.1.0",
+ "version": "5.2.0",
"homepage": "https://github.com/BranchMetrics/cordova-ionic-phonegap-branch-deep-linking",
"repository": {
"type": "git",
diff --git a/plugin.xml b/plugin.xml
index 07ca4aca..5d746a60 100644
--- a/plugin.xml
+++ b/plugin.xml
@@ -63,7 +63,7 @@ SOFTWARE.
Sets the cookie based matching for all incoming requests.
*If you want cookie based matching, call this before initUserSession
@@ -1017,7 +1092,7 @@ public void onLinkCreate(String url, BranchError error) { } } - + protected class ShowShareSheetListener implements Branch.BranchLinkShareListener { private CallbackContext _onShareLinkDialogLaunched; @@ -1197,6 +1272,8 @@ public void run() { lastAttributedTouchData(this.callbackContext); } else if (this.action.equals(("generateShortUrl"))) { generateShortUrl(this.args.getInt(0), this.args.getJSONObject(1), this.args.getJSONObject(2), this.callbackContext); + } else if (this.action.equals(("getBranchQRCode"))) { + getBranchQRCode(this.args.getJSONObject(0), this.args.getInt(1), this.args.getJSONObject(2), this.args.getJSONObject(3), this.callbackContext); } else if (this.action.equals("registerView")) { registerView(this.args.getInt(0), this.callbackContext); } else if (this.action.equals("showShareSheet")) { diff --git a/src/index.js b/src/index.js index 05b03757..eae03123 100644 --- a/src/index.js +++ b/src/index.js @@ -39,7 +39,7 @@ var Branch = function Branch() { this.sessionInitialized = false; }; -// JavsSript to SDK wrappers +// JavaScript to SDK wrappers function execute(method, params) { var output = !params ? [] : params; @@ -314,5 +314,29 @@ Branch.prototype.lastAttributedTouchData = function lastAttributedTouchData() { return execute("lastAttributedTouchData"); }; +Branch.prototype.getBranchQRCode = function getBranchQRCode( + qrCodeSettings, + branchUniversalObject, + analytics, + properties +) { + var args = []; + if (qrCodeSettings) { + args.push(qrCodeSettings); + } + if (branchUniversalObject) { + args.push(branchUniversalObject.instanceId); + } + if (analytics) { + args.push(analytics); + } + if (properties) { + args.push(properties); + } + + return execute("getBranchQRCode", args); +}; + + // export Branch object module.exports = new Branch(); diff --git a/src/ios/BranchSDK.m b/src/ios/BranchSDK.m index ca38c9c7..5b971816 100644 --- a/src/ios/BranchSDK.m +++ b/src/ios/BranchSDK.m @@ -648,6 +648,129 @@ - (void)lastAttributedTouchData:(CDVInvokedUrlCommand *)command { }]; } +- (void)getBranchQRCode:(CDVInvokedUrlCommand*)command +{ + int branchUniversalObjectId = [[command.arguments objectAtIndex:1] intValue]; + NSMutableDictionary *branchUniversalObjDict = [self.branchUniversalObjArray objectAtIndex:branchUniversalObjectId]; + BranchUniversalObject *branchUniversalObj = [branchUniversalObjDict objectForKey:@"branchUniversalObj"]; + + BranchLinkProperties *linkProperties = [BranchLinkProperties new]; + + NSDictionary *arg1 = [command.arguments objectAtIndex:2]; + NSDictionary *arg2 = [command.arguments objectAtIndex:3]; + + for (id key in arg1) { + if ([key isEqualToString:@"duration"]) { + linkProperties.matchDuration = (NSUInteger)[((NSNumber *)[arg1 objectForKey:key]) integerValue]; + } + else if ([key isEqualToString:@"feature"]) { + linkProperties.feature = [arg1 objectForKey:key]; + } + else if ([key isEqualToString:@"stage"]) { + linkProperties.stage = [arg1 objectForKey:key]; + } + else if ([key isEqualToString:@"campaign"]) { + linkProperties.campaign = [arg1 objectForKey:key]; + } + else if ([key isEqualToString:@"alias"]) { + linkProperties.alias = [arg1 objectForKey:key]; + } + else if ([key isEqualToString:@"channel"]) { + linkProperties.channel = [arg1 objectForKey:key]; + } + else if ([key isEqualToString:@"tags"] && [[arg1 objectForKey:key] isKindOfClass:[NSArray class]]) { + linkProperties.tags = [arg1 objectForKey:key]; + } + } + if (arg2) { + for (id key in arg2) { + [linkProperties addControlParam:key withValue:[arg2 objectForKey:key]]; + } + } + + NSMutableDictionary *qrCodeSettingsMap = [command.arguments objectAtIndex:0]; + + BranchQRCode *qrCode = [BranchQRCode new]; + + if (qrCodeSettingsMap[@"codeColor"]) { + qrCode.codeColor = [self colorWithHexString:qrCodeSettingsMap[@"codeColor"]]; + } + if (qrCodeSettingsMap[@"backgroundColor"]) { + qrCode.backgroundColor = [self colorWithHexString:qrCodeSettingsMap[@"backgroundColor"]]; + } + if (qrCodeSettingsMap[@"centerLogo"]) { + qrCode.centerLogo = qrCodeSettingsMap[@"centerLogo"]; + } + if (qrCodeSettingsMap[@"width"]) { + qrCode.width = qrCodeSettingsMap[@"width"]; + } + if (qrCodeSettingsMap[@"margin"]) { + qrCode.margin = qrCodeSettingsMap[@"margin"]; + } + if (qrCodeSettingsMap[@"imageFormat"]) { + if ([qrCodeSettingsMap[@"imageFormat"] isEqual:@"JPEG"]) { + qrCode.imageFormat = BranchQRCodeImageFormatJPEG; + } else { + qrCode.imageFormat = BranchQRCodeImageFormatPNG; + } + } + + [qrCode getQRCodeAsData:branchUniversalObj linkProperties:linkProperties completion:^(NSData * _Nonnull qrCodeData, NSError * _Nonnull error) { + CDVPluginResult* pluginResult = nil; + + if (!error) { + NSString* imageString = [qrCodeData base64EncodedStringWithOptions:nil]; + pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:imageString]; + } else { + pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:[error localizedDescription]]; + } + + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; + }]; +} + +- (UIColor *) colorWithHexString: (NSString *) hexString { + NSString *colorString = [[hexString stringByReplacingOccurrencesOfString: @"#" withString: @""] uppercaseString]; + CGFloat alpha, red, blue, green; + switch ([colorString length]) { + case 3: // #RGB + alpha = 1.0f; + red = [self colorComponentFrom: colorString start: 0 length: 1]; + green = [self colorComponentFrom: colorString start: 1 length: 1]; + blue = [self colorComponentFrom: colorString start: 2 length: 1]; + break; + case 4: // #ARGB + alpha = [self colorComponentFrom: colorString start: 0 length: 1]; + red = [self colorComponentFrom: colorString start: 1 length: 1]; + green = [self colorComponentFrom: colorString start: 2 length: 1]; + blue = [self colorComponentFrom: colorString start: 3 length: 1]; + break; + case 6: // #RRGGBB + alpha = 1.0f; + red = [self colorComponentFrom: colorString start: 0 length: 2]; + green = [self colorComponentFrom: colorString start: 2 length: 2]; + blue = [self colorComponentFrom: colorString start: 4 length: 2]; + break; + case 8: // #AARRGGBB + alpha = [self colorComponentFrom: colorString start: 0 length: 2]; + red = [self colorComponentFrom: colorString start: 2 length: 2]; + green = [self colorComponentFrom: colorString start: 4 length: 2]; + blue = [self colorComponentFrom: colorString start: 6 length: 2]; + break; + default: + NSLog(@"Error: Invalid color value. It should be a hex value of the form #RBG, #ARGB, #RRGGBB, or #AARRGGBB"); + break; + } + return [UIColor colorWithRed: red green: green blue: blue alpha: alpha]; +} + +- (CGFloat) colorComponentFrom: (NSString *) string start: (NSUInteger) start length: (NSUInteger) length { + NSString *substring = [string substringWithRange: NSMakeRange(start, length)]; + NSString *fullHex = length == 2 ? substring : [NSString stringWithFormat: @"%@%@", substring, substring]; + unsigned hexComponent; + [[NSScanner scannerWithString: fullHex] scanHexInt: &hexComponent]; + return hexComponent / 255.0; +} #pragma mark - URL Methods (not fully implemented YET!)