Skip to content

Commit

Permalink
Add no-side effects version of navigateToAppLink:error: and navigate: (
Browse files Browse the repository at this point in the history
…#245)

- Allows app to know the type of navigation that would result of calling
  BFAppLinkNavigation's navigateToAppLink:error: or navigate: without
  having any side effects
- Also adds a test to ensure same output as navigateToAppLink:error:
  without the side effects.
  • Loading branch information
biasedbit authored and nlutsenko committed Apr 8, 2016
1 parent d293c44 commit a40b65b
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 0 deletions.
20 changes: 20 additions & 0 deletions Bolts/iOS/BFAppLinkNavigation.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ typedef NS_ENUM(NSInteger, BFAppLinkNavigationType) {
extras:(NSDictionary *)extras
appLinkData:(NSDictionary *)appLinkData;

/*!
Creates an NSDictionary with the correct format for iOS callback URLs,
to be used as 'appLinkData' argument in the call to navigationWithAppLink:extras:appLinkData:
*/
+ (NSDictionary *)callbackAppLinkDataForAppWithName:(NSString *)appName url:(NSString *)url;

/*! Performs the navigation */
- (BFAppLinkNavigationType)navigate:(NSError **)error;

Expand All @@ -69,6 +75,20 @@ typedef NS_ENUM(NSInteger, BFAppLinkNavigationType) {
/*! Navigates to a BFAppLink and returns whether it opened in-app or in-browser */
+ (BFAppLinkNavigationType)navigateToAppLink:(BFAppLink *)link error:(NSError **)error;

/*!
Returns a BFAppLinkNavigationType based on a BFAppLink.
It's essentially a no-side-effect version of navigateToAppLink:error:,
allowing apps to determine flow based on the link type (e.g. open an
internal web view instead of going straight to the browser for regular links.)
*/
+ (BFAppLinkNavigationType)navigationTypeForLink:(BFAppLink *)link;

/*!
Return navigation type for current instance.
No-side-effect version of navigate:
*/
- (BFAppLinkNavigationType)navigationType;

/*! Navigates to a URL (an asynchronous action) and returns a BFNavigationType */
+ (BFTask *)navigateToURLInBackground:(NSURL *)destination;

Expand Down
41 changes: 41 additions & 0 deletions Bolts/iOS/BFAppLinkNavigation.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
FOUNDATION_EXPORT NSString *const BFAppLinkUserAgentKeyName;
FOUNDATION_EXPORT NSString *const BFAppLinkExtrasKeyName;
FOUNDATION_EXPORT NSString *const BFAppLinkVersionKeyName;
FOUNDATION_EXPORT NSString *const BFAppLinkRefererAppLink;
FOUNDATION_EXPORT NSString *const BFAppLinkRefererAppName;
FOUNDATION_EXPORT NSString *const BFAppLinkRefererUrl;

static id<BFAppLinkResolving> defaultResolver;

Expand All @@ -43,6 +46,10 @@ + (instancetype)navigationWithAppLink:(BFAppLink *)appLink
return navigation;
}

+ (NSDictionary *)callbackAppLinkDataForAppWithName:(NSString *)appName url:(NSString *)url {
return @{BFAppLinkRefererAppLink: @{BFAppLinkRefererAppName: appName, BFAppLinkRefererUrl: url}};
}

- (NSString *)stringByEscapingQueryString:(NSString *)string {
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_7_0 || __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_9
return [string stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
Expand Down Expand Up @@ -229,6 +236,40 @@ + (BFAppLinkNavigationType)navigateToAppLink:(BFAppLink *)link error:(NSError **
appLinkData:nil] navigate:error];
}

+ (BFAppLinkNavigationType)navigationTypeForLink:(BFAppLink *)link {
return [[self navigationWithAppLink:link extras:nil appLinkData:nil] navigationType];
}

- (BFAppLinkNavigationType)navigationType {
BFAppLinkTarget *eligibleTarget = nil;
for (BFAppLinkTarget *target in self.appLink.targets) {
if ([[UIApplication sharedApplication] canOpenURL:target.URL]) {
eligibleTarget = target;
break;
}
}

if (eligibleTarget != nil) {
NSURL *appLinkURL = [self appLinkURLWithTargetURL:eligibleTarget.URL error:nil];
if (appLinkURL != nil) {
return BFAppLinkNavigationTypeApp;
} else {
return BFAppLinkNavigationTypeFailure;
}
}

if (self.appLink.webURL != nil) {
NSURL *appLinkURL = [self appLinkURLWithTargetURL:eligibleTarget.URL error:nil];
if (appLinkURL != nil) {
return BFAppLinkNavigationTypeBrowser;
} else {
return BFAppLinkNavigationTypeFailure;
}
}

return BFAppLinkNavigationTypeFailure;
}

+ (id<BFAppLinkResolving>)defaultResolver {
if (defaultResolver) {
return defaultResolver;
Expand Down
4 changes: 4 additions & 0 deletions BoltsTestUI/BoltsTestUI-Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@
</array>
</dict>
</array>
<key>LSApplicationQueriesSchemes</key>
<array>
<string>bolts</string>
</array>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>LSRequiresIPhoneOS</key>
Expand Down
13 changes: 13 additions & 0 deletions BoltsTests/AppLinkTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,19 @@ - (void)testPlatformFiltering {

#pragma mark App link navigation

- (void)testSimpleAppLinkNavigationLookup {
BFAppLinkTarget *target = [BFAppLinkTarget appLinkTargetWithURL:[NSURL URLWithString:@"bolts://"]
appStoreId:@"12345"
appName:@"Bolts"];
BFAppLink *appLink = [BFAppLink appLinkWithSourceURL:[NSURL URLWithString:@"http://www.example.com/path"]
targets:@[target]
webURL:[NSURL URLWithString:@"http://www.example.com/path"]];
BFAppLinkNavigationType navigationType = [BFAppLinkNavigation navigationTypeForLink:appLink];

XCTAssertEqual(navigationType, BFAppLinkNavigationTypeApp);
XCTAssertEqual((NSUInteger)0, openedUrls.count); // no side effects
}

- (void)testSimpleAppLinkNavigation {
BFAppLinkTarget *target = [BFAppLinkTarget appLinkTargetWithURL:[NSURL URLWithString:@"bolts://"]
appStoreId:@"12345"
Expand Down

0 comments on commit a40b65b

Please sign in to comment.