2017-09-04 13:01:00 +00:00
|
|
|
#import "RNFirebaseLinks.h"
|
|
|
|
|
2017-10-14 22:33:30 +00:00
|
|
|
#if __has_include(<FirebaseDynamicLinks/FirebaseDynamicLinks.h>)
|
|
|
|
#import <Firebase.h>
|
2017-09-25 14:34:26 +00:00
|
|
|
#import "RNFirebaseEvents.h"
|
2017-09-26 13:54:21 +00:00
|
|
|
|
|
|
|
|
|
|
|
static void sendDynamicLink(NSURL *url, id sender) {
|
|
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:LINKS_DYNAMIC_LINK_RECEIVED
|
|
|
|
object:sender
|
|
|
|
userInfo:@{@"url": url.absoluteString}];
|
2017-09-30 12:54:11 +00:00
|
|
|
NSLog(@"sendDynamicLink Success: %@", url.absoluteString);
|
2017-09-26 13:54:21 +00:00
|
|
|
}
|
|
|
|
|
2017-09-04 13:01:00 +00:00
|
|
|
@implementation RNFirebaseLinks
|
|
|
|
|
|
|
|
RCT_EXPORT_MODULE();
|
|
|
|
|
2017-09-25 14:34:26 +00:00
|
|
|
- (id)init {
|
|
|
|
self = [super init];
|
|
|
|
if (self != nil) {
|
|
|
|
NSLog(@"Setting up RNFirebaseLinks instance");
|
2017-09-30 12:54:11 +00:00
|
|
|
[self initialiseLinks];
|
2017-09-25 14:34:26 +00:00
|
|
|
}
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2017-09-30 12:54:11 +00:00
|
|
|
- (void)initialiseLinks {
|
2017-09-25 14:34:26 +00:00
|
|
|
// Set up internal listener to send notification over bridge
|
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
2017-09-26 13:54:21 +00:00
|
|
|
selector:@selector(sendDynamicLinkEvent:)
|
2017-09-25 14:34:26 +00:00
|
|
|
name:LINKS_DYNAMIC_LINK_RECEIVED
|
|
|
|
object:nil];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)dealloc {
|
|
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
|
|
}
|
|
|
|
|
2017-09-26 13:54:21 +00:00
|
|
|
+ (BOOL)application:(UIApplication *)app
|
|
|
|
openURL:(NSURL *)url
|
|
|
|
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
|
2017-09-30 16:56:58 +00:00
|
|
|
return [self handleLinkFromCustomSchemeURL:url];
|
2017-09-26 13:54:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
+ (BOOL)application:(UIApplication *)application
|
|
|
|
openURL:(NSURL *)url
|
|
|
|
sourceApplication:(NSString *)sourceApplication
|
2017-09-30 16:56:58 +00:00
|
|
|
annotation:(id)annotation {
|
|
|
|
return [self handleLinkFromCustomSchemeURL:url];
|
|
|
|
}
|
|
|
|
|
2017-10-14 22:33:30 +00:00
|
|
|
+ (BOOL)handleLinkFromCustomSchemeURL:(NSURL *)url {
|
2017-09-30 12:54:11 +00:00
|
|
|
FIRDynamicLink *dynamicLink =
|
|
|
|
[[FIRDynamicLinks dynamicLinks] dynamicLinkFromCustomSchemeURL:url];
|
2017-10-14 22:33:30 +00:00
|
|
|
if (dynamicLink && dynamicLink.url) {
|
|
|
|
NSURL* dynamicLinkUrl = dynamicLink.url;
|
|
|
|
sendDynamicLink(dynamicLinkUrl, self);
|
2017-09-30 12:54:11 +00:00
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
return NO;
|
2017-09-26 13:54:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
+ (BOOL)application:(UIApplication *)application
|
|
|
|
continueUserActivity:(NSUserActivity *)userActivity
|
2017-09-30 16:56:58 +00:00
|
|
|
restorationHandler:(void (^)(NSArray *))restorationHandler {
|
2017-09-30 12:54:11 +00:00
|
|
|
BOOL handled = [[FIRDynamicLinks dynamicLinks]
|
|
|
|
handleUniversalLink:userActivity.webpageURL
|
|
|
|
completion:^(FIRDynamicLink * _Nullable dynamicLink, NSError * _Nullable error) {
|
|
|
|
if (error != nil){
|
|
|
|
NSLog(@"Failed to handle universal link: %@", [error localizedDescription]);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) {
|
|
|
|
NSURL* url = dynamicLink ? dynamicLink.url : userActivity.webpageURL;
|
|
|
|
sendDynamicLink(url, self);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}];
|
|
|
|
return handled;
|
2017-09-26 13:54:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSArray<NSString *> *)supportedEvents {
|
|
|
|
return @[LINKS_DYNAMIC_LINK_RECEIVED];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)sendDynamicLinkEvent:(NSNotification *)notification {
|
|
|
|
[self sendEventWithName:LINKS_DYNAMIC_LINK_RECEIVED body:notification.userInfo[@"url"]];
|
|
|
|
}
|
|
|
|
|
2017-09-30 12:54:11 +00:00
|
|
|
-(void)handleInitialLinkFromCustomSchemeURL:(NSURL*)url resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
|
|
|
|
FIRDynamicLink *dynamicLink =
|
|
|
|
[[FIRDynamicLinks dynamicLinks] dynamicLinkFromCustomSchemeURL:url];
|
|
|
|
NSString* urlString = dynamicLink ? dynamicLink.url.absoluteString : (id)kCFNull;
|
|
|
|
NSLog(@"initial link is: %@", urlString);
|
|
|
|
resolve(urlString);
|
|
|
|
}
|
|
|
|
|
|
|
|
-(void)handleInitialLinkFromUniversalLinkURL:(NSDictionary *)userActivityDictionary resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject {
|
|
|
|
NSUserActivity* userActivity = (NSUserActivity*) userActivityDictionary[@"UIApplicationLaunchOptionsUserActivityKey"];
|
|
|
|
if ([userActivityDictionary[UIApplicationLaunchOptionsUserActivityTypeKey] isEqual:NSUserActivityTypeBrowsingWeb])
|
|
|
|
{
|
|
|
|
[[FIRDynamicLinks dynamicLinks]
|
|
|
|
handleUniversalLink:userActivity.webpageURL
|
|
|
|
completion:^(FIRDynamicLink * _Nullable dynamicLink, NSError * _Nullable error) {
|
|
|
|
if (error != nil){
|
|
|
|
NSLog(@"Failed to handle universal link: %@", [error localizedDescription]);
|
|
|
|
reject(@"links/failure", @"Failed to handle universal link", error);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
NSString* urlString = dynamicLink ? dynamicLink.url.absoluteString : userActivity.webpageURL.absoluteString;
|
|
|
|
NSLog(@"initial link is: %@", urlString);
|
|
|
|
resolve(urlString);
|
|
|
|
}
|
|
|
|
}];
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
NSLog(@"no initial link");
|
|
|
|
resolve((id)kCFNull);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-26 13:54:21 +00:00
|
|
|
RCT_EXPORT_METHOD(getInitialLink:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
|
|
|
|
if (self.bridge.launchOptions[UIApplicationLaunchOptionsURLKey]) {
|
2017-09-30 12:54:11 +00:00
|
|
|
NSURL* url = (NSURL*)self.bridge.launchOptions[UIApplicationLaunchOptionsURLKey];
|
|
|
|
[self handleInitialLinkFromCustomSchemeURL:url resolver:resolve rejecter:reject];
|
2017-10-07 22:00:36 +00:00
|
|
|
|
2017-09-26 13:54:21 +00:00
|
|
|
} else {
|
|
|
|
NSDictionary *userActivityDictionary =
|
|
|
|
self.bridge.launchOptions[UIApplicationLaunchOptionsUserActivityDictionaryKey];
|
2017-09-30 12:54:11 +00:00
|
|
|
[self handleInitialLinkFromUniversalLinkURL:userActivityDictionary resolver:resolve rejecter:reject];
|
2017-09-26 13:54:21 +00:00
|
|
|
}
|
|
|
|
}
|
2017-09-25 14:34:26 +00:00
|
|
|
|
|
|
|
RCT_EXPORT_METHOD(createDynamicLink: (NSDictionary *) metadata resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
|
2017-10-07 22:00:36 +00:00
|
|
|
@try {
|
|
|
|
FIRDynamicLinkComponents *components = [self getDynamicLinkComponentsFromMetadata:metadata];
|
|
|
|
|
|
|
|
if (components == nil) {
|
|
|
|
reject(@"links/failure", @"Failed to create Dynamic Link", nil);
|
|
|
|
} else {
|
|
|
|
NSURL *longLink = components.url;
|
|
|
|
NSLog(@"created long dynamic link: %@", longLink.absoluteString);
|
|
|
|
resolve(longLink.absoluteString);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@catch(NSException * e) {
|
|
|
|
NSLog(@"create dynamic link failure %@", e);
|
|
|
|
reject(@"links/failure",[e reason], nil);
|
2017-09-04 13:01:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RCT_EXPORT_METHOD(createShortDynamicLink: (NSDictionary *) metadata resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
|
2017-10-07 22:00:36 +00:00
|
|
|
@try {
|
|
|
|
FIRDynamicLinkComponents *components = [self getDynamicLinkComponentsFromMetadata:metadata];
|
|
|
|
[self setSuffixParameters:metadata components:components];
|
|
|
|
[components shortenWithCompletion:^(NSURL *_Nullable shortURL,
|
|
|
|
NSArray *_Nullable warnings,
|
|
|
|
NSError *_Nullable error) {
|
|
|
|
if (error) {
|
|
|
|
NSLog(@"create short dynamic link failure %@", [error localizedDescription]);
|
|
|
|
reject(@"links/failure", @"Failed to create Short Dynamic Link", error);
|
|
|
|
}
|
|
|
|
NSURL *shortLink = shortURL;
|
|
|
|
NSLog(@"created short dynamic link: %@", shortLink.absoluteString);
|
|
|
|
resolve(shortLink.absoluteString);
|
|
|
|
}];
|
|
|
|
}
|
|
|
|
@catch(NSException * e) {
|
|
|
|
NSLog(@"create short dynamic link failure %@", e);
|
|
|
|
reject(@"links/failure",[e reason], nil);
|
|
|
|
}
|
2017-09-04 13:01:00 +00:00
|
|
|
}
|
|
|
|
|
2017-09-25 14:34:26 +00:00
|
|
|
- (FIRDynamicLinkComponents *)getDynamicLinkComponentsFromMetadata:(NSDictionary *)metadata {
|
2017-10-07 22:00:36 +00:00
|
|
|
@try {
|
2017-10-10 13:22:03 +00:00
|
|
|
NSURL *link = [NSURL URLWithString:metadata[@"link"]];
|
2017-10-07 22:00:36 +00:00
|
|
|
FIRDynamicLinkComponents *components =
|
2017-10-10 13:22:03 +00:00
|
|
|
[FIRDynamicLinkComponents componentsWithLink:link domain:metadata[@"dynamicLinkDomain"]];
|
2017-10-07 22:00:36 +00:00
|
|
|
|
2017-10-10 13:22:03 +00:00
|
|
|
[self setAndroidParameters:metadata components:components];
|
|
|
|
[self setIosParameters:metadata components:components];
|
|
|
|
[self setSocialMetaTagParameters:metadata components:components];
|
2017-10-07 22:00:36 +00:00
|
|
|
|
|
|
|
return components;
|
|
|
|
}
|
|
|
|
@catch(NSException * e) {
|
|
|
|
NSLog(@"error while building componets from meta data %@", e);
|
|
|
|
@throw;
|
|
|
|
}
|
2017-09-04 13:01:00 +00:00
|
|
|
}
|
|
|
|
|
2017-10-09 01:40:27 +00:00
|
|
|
- (void)setAndroidParameters:(NSDictionary *)metadata
|
2017-09-04 13:01:00 +00:00
|
|
|
components:(FIRDynamicLinkComponents *)components {
|
2017-10-09 01:40:27 +00:00
|
|
|
NSDictionary *androidParametersDict = metadata[@"androidInfo"];
|
2017-10-07 22:00:36 +00:00
|
|
|
if (androidParametersDict) {
|
2017-09-04 13:01:00 +00:00
|
|
|
FIRDynamicLinkAndroidParameters *androidParams = [FIRDynamicLinkAndroidParameters
|
2017-10-01 21:55:08 +00:00
|
|
|
parametersWithPackageName: androidParametersDict[@"androidPackageName"]];
|
2017-10-14 22:33:30 +00:00
|
|
|
|
2017-09-04 13:01:00 +00:00
|
|
|
if (androidParametersDict[@"androidFallbackLink"]) {
|
|
|
|
androidParams.fallbackURL = [NSURL URLWithString:androidParametersDict[@"androidFallbackLink"]];
|
|
|
|
}
|
|
|
|
if (androidParametersDict[@"androidMinPackageVersionCode"]) {
|
|
|
|
androidParams.minimumVersion = [androidParametersDict[@"androidMinPackageVersionCode"] integerValue];
|
2017-10-07 22:00:36 +00:00
|
|
|
}
|
2017-09-04 13:01:00 +00:00
|
|
|
components.androidParameters = androidParams;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-09 01:40:27 +00:00
|
|
|
- (void)setIosParameters:(NSDictionary *)metadata
|
2017-09-04 13:01:00 +00:00
|
|
|
components:(FIRDynamicLinkComponents *)components {
|
2017-10-09 01:40:27 +00:00
|
|
|
NSDictionary *iosParametersDict = metadata[@"iosInfo"];
|
2017-10-07 22:00:36 +00:00
|
|
|
if (iosParametersDict) {
|
2017-09-04 13:01:00 +00:00
|
|
|
FIRDynamicLinkIOSParameters *iOSParams = [FIRDynamicLinkIOSParameters
|
|
|
|
parametersWithBundleID:iosParametersDict[@"iosBundleId"]];
|
|
|
|
if (iosParametersDict[@"iosAppStoreId"]) {
|
|
|
|
iOSParams.appStoreID = iosParametersDict[@"iosAppStoreId"];
|
|
|
|
}
|
|
|
|
if (iosParametersDict[@"iosCustomScheme"]) {
|
|
|
|
iOSParams.customScheme = iosParametersDict[@"iosCustomScheme"];
|
|
|
|
}
|
|
|
|
if (iosParametersDict[@"iosFallbackLink"]) {
|
|
|
|
iOSParams.fallbackURL = [NSURL URLWithString:iosParametersDict[@"iosFallbackLink"]];
|
|
|
|
}
|
|
|
|
if (iosParametersDict[@"iosIpadBundleId"]) {
|
|
|
|
iOSParams.iPadBundleID = iosParametersDict[@"iosIpadBundleId"];
|
|
|
|
}
|
|
|
|
if (iosParametersDict[@"iosIpadFallbackLink"]) {
|
|
|
|
iOSParams.iPadFallbackURL = [NSURL URLWithString:iosParametersDict[@"iosIpadFallbackLink"]];
|
|
|
|
}
|
|
|
|
if (iosParametersDict[@"iosMinPackageVersionCode"]) {
|
|
|
|
iOSParams.minimumAppVersion = iosParametersDict[@"iosMinPackageVersionCode"];
|
|
|
|
}
|
|
|
|
components.iOSParameters = iOSParams;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-09 01:40:27 +00:00
|
|
|
- (void)setSocialMetaTagParameters:(NSDictionary *)metadata
|
2017-09-04 13:01:00 +00:00
|
|
|
components:(FIRDynamicLinkComponents *)components {
|
2017-10-09 01:40:27 +00:00
|
|
|
NSDictionary *socialParamsDict = metadata[@"socialMetaTagInfo"];
|
2017-09-04 13:01:00 +00:00
|
|
|
if (socialParamsDict) {
|
|
|
|
FIRDynamicLinkSocialMetaTagParameters *socialParams = [FIRDynamicLinkSocialMetaTagParameters parameters];
|
|
|
|
if (socialParamsDict[@"socialTitle"]) {
|
|
|
|
socialParams.title = socialParamsDict[@"socialTitle"];
|
|
|
|
}
|
|
|
|
if (socialParamsDict[@"socialDescription"]) {
|
|
|
|
socialParams.descriptionText = socialParamsDict[@"socialDescription"];
|
|
|
|
}
|
|
|
|
if (socialParamsDict[@"socialImageLink"]) {
|
|
|
|
socialParams.imageURL = [NSURL URLWithString:socialParamsDict[@"socialImageLink"]];
|
|
|
|
}
|
|
|
|
components.socialMetaTagParameters = socialParams;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setSuffixParameters:(NSDictionary *)metadata
|
2017-09-30 12:54:11 +00:00
|
|
|
components:(FIRDynamicLinkComponents *)components {
|
2017-09-04 13:01:00 +00:00
|
|
|
NSDictionary *suffixParametersDict = metadata[@"suffix"];
|
|
|
|
if (suffixParametersDict) {
|
|
|
|
FIRDynamicLinkComponentsOptions *options = [FIRDynamicLinkComponentsOptions options];
|
|
|
|
if ([suffixParametersDict[@"option"] isEqual: @"SHORT"]) {
|
|
|
|
options.pathLength = FIRShortDynamicLinkPathLengthShort;
|
|
|
|
}
|
|
|
|
else if ([suffixParametersDict[@"option"] isEqual: @"UNGUESSABLE"]) {
|
|
|
|
options.pathLength = FIRShortDynamicLinkPathLengthUnguessable;
|
|
|
|
}
|
|
|
|
components.options = options;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
#else
|
|
|
|
@implementation RNFirebaseLinks
|
|
|
|
@end
|
|
|
|
#endif
|
2017-10-07 22:00:36 +00:00
|
|
|
|
2017-10-09 01:40:27 +00:00
|
|
|
|