Skip to content

Commit

Permalink
In App Safari View Controller Support.
Browse files Browse the repository at this point in the history
1- Added SafariViewController support

2- Added dismiss method to close safari.

3- Modified header search path

Signed-off-by: Abhishek Singh <[email protected]>
  • Loading branch information
avkuma authored and IntelliJAbhishek committed Aug 24, 2020
1 parent f3368bf commit e100210
Show file tree
Hide file tree
Showing 8 changed files with 1,131 additions and 924 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Custom Tabs is supported only for Android, so the behavior on each platform is b
If Chrome is installed, open the URL in Chrome that you have customized some of the look & feel. If it is not installed, open in other browser.

* iOS
If Chrome is installed, open the URL in it. If it is not installed, open in Safari.
Presents SafariViewController by default for iOS >9.0. Else opens in Safari.

Customization and detailed behavior refer to the [Usage](#Usage).

Expand Down
11 changes: 11 additions & 0 deletions ios/ReactNativeCustomTabs.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
BBADAF32239FC95A00E94359 /* SafariViewManager.m in Sources */ = {isa = PBXBuildFile; fileRef = BBADAF31239FC95A00E94359 /* SafariViewManager.m */; };
DA7118851CC916080087DF95 /* DBChromeManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DA7118551CC90B700087DF95 /* DBChromeManager.m */; };
/* End PBXBuildFile section */

Expand All @@ -23,6 +24,8 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
BBADAF30239FC95A00E94359 /* SafariViewManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SafariViewManager.h; path = ReactNativeCustomTabs/SafariViewManager.h; sourceTree = "<group>"; };
BBADAF31239FC95A00E94359 /* SafariViewManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SafariViewManager.m; path = ReactNativeCustomTabs/SafariViewManager.m; sourceTree = "<group>"; };
DA7118541CC90B700087DF95 /* DBChromeManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DBChromeManager.h; path = ReactNativeCustomTabs/DBChromeManager.h; sourceTree = "<group>"; };
DA7118551CC90B700087DF95 /* DBChromeManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DBChromeManager.m; path = ReactNativeCustomTabs/DBChromeManager.m; sourceTree = "<group>"; };
DA7118681CC9158A0087DF95 /* libDBCustomTabs.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libDBCustomTabs.a; sourceTree = BUILT_PRODUCTS_DIR; };
Expand All @@ -42,6 +45,8 @@
13B07FAE1A68108700A75B9A /* ReactNativeCustomTabs */ = {
isa = PBXGroup;
children = (
BBADAF30239FC95A00E94359 /* SafariViewManager.h */,
BBADAF31239FC95A00E94359 /* SafariViewManager.m */,
DA7118541CC90B700087DF95 /* DBChromeManager.h */,
DA7118551CC90B700087DF95 /* DBChromeManager.m */,
);
Expand Down Expand Up @@ -106,6 +111,7 @@
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
English,
en,
);
mainGroup = 83CBB9F61A601CBA00E9B192;
Expand All @@ -123,6 +129,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
BBADAF32239FC95A00E94359 /* SafariViewManager.m in Sources */,
DA7118851CC916080087DF95 /* DBChromeManager.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -226,6 +233,8 @@
HEADER_SEARCH_PATHS = (
"$(inherited)",
"$(SRCROOT)/../../react-native/React/**/**",
"$(SRCROOT)/../../react-native/React/**",
"${SRCROOT}/../../../ios/Pods/Headers/Public/**",
);
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
Expand All @@ -242,6 +251,8 @@
HEADER_SEARCH_PATHS = (
"$(inherited)",
"$(SRCROOT)/../../react-native/React/**/**",
"$(SRCROOT)/../../react-native/React/**",
"${SRCROOT}/../../../ios/Pods/Headers/Public/**",
);
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
Expand Down
20 changes: 20 additions & 0 deletions ios/ReactNativeCustomTabs/SafariViewManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// SafariViewManager.h
// DBCustomTabs
//
// Created by Avinash on 10/12/2019.
// Copyright © 2019 Facebook. All rights reserved.
//

#import "RCTEventEmitter.h"
#import <React/RCTBridgeModule.h>

@import SafariServices;

NS_ASSUME_NONNULL_BEGIN

@interface SafariViewManager : RCTEventEmitter<RCTBridgeModule, SFSafariViewControllerDelegate>

@end

NS_ASSUME_NONNULL_END
119 changes: 119 additions & 0 deletions ios/ReactNativeCustomTabs/SafariViewManager.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
//
// SafariViewManager.m
// DBCustomTabs
//
// Created by Avinash on 10/12/2019.
// Copyright © 2019 Facebook. All rights reserved.
//

#import "SafariViewManager.h"
#import <React/RCTUtils.h>
#import <React/RCTLog.h>
#import <React/RCTConvert.h>

@implementation SafariViewManager
{
bool hasListeners;
SFSafariViewController *_safariView;
}

RCT_EXPORT_MODULE()

- (dispatch_queue_t)methodQueue
{
return dispatch_get_main_queue();
}

- (void)startObserving
{
hasListeners = YES;
}

- (void)stopObserving
{
hasListeners = NO;
}

- (NSArray<NSString *> *)supportedEvents
{
return @[@"SafariViewOnShow", @"SafariViewOnDismiss"];
}

RCT_EXPORT_METHOD(show:(NSDictionary *)args resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
// Error if no url is passed
if (!args[@"url"]) {
reject(@"E_SAFARI_VIEW_NO_URL", @"You must specify a url.", nil);
return;
}

NSURL *url = [RCTConvert NSURL:args[@"url"]];
BOOL readerMode = [args[@"readerMode"] boolValue];
UIColor *tintColorString = args[@"tintColor"];
UIColor *barTintColorString = args[@"barTintColor"];
BOOL fromBottom = [args[@"fromBottom"] boolValue];

// Initialize the Safari View
_safariView = [[SFSafariViewController alloc] initWithURL:url entersReaderIfAvailable:readerMode];
_safariView.delegate = self;

// Set tintColor if available
if (tintColorString) {
UIColor *tintColor = [RCTConvert UIColor:tintColorString];
if ([_safariView respondsToSelector:@selector(setPreferredControlTintColor:)]) {
[_safariView setPreferredControlTintColor:tintColor];
} else {
[_safariView.view setTintColor:tintColor];
}
}

// Set barTintColor if available
if (barTintColorString) {
UIColor *barTintColor = [RCTConvert UIColor:barTintColorString];
if ([_safariView respondsToSelector:@selector(setPreferredBarTintColor:)]) {
[_safariView setPreferredBarTintColor:barTintColor];
}
}

// Set modal transition style
if (fromBottom) {
_safariView.modalPresentationStyle = UIModalPresentationOverFullScreen;
}

// get the view controller closest to the foreground
UIViewController *ctrl = RCTPresentedViewController();

// Display the Safari View
[ctrl presentViewController:_safariView animated:YES completion:nil];

if (hasListeners) {
[self sendEventWithName:@"SafariViewOnShow" body:nil];
}

resolve(@YES);
}

RCT_EXPORT_METHOD(isAvailable:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
if (@available(iOS 9.0, *)) {
// SafariView is available
resolve(@YES);
} else {
reject(@"E_SAFARI_VIEW_UNAVAILABLE", @"SafariView is unavailable", nil);
}
}

RCT_EXPORT_METHOD(dismiss)
{
[_safariView dismissViewControllerAnimated:true completion:nil];
}

-(void)safariViewControllerDidFinish:(nonnull SFSafariViewController *)controller
{
_safariView = nil;
NSLog(@"[SafariView] SafariView dismissed.");
if (hasListeners) {
[self sendEventWithName:@"SafariViewOnDismiss" body:nil];
}
}
@end
Loading

0 comments on commit e100210

Please sign in to comment.