Skip to content

Commit

Permalink
Allow WKWebView to be inspectable
Browse files Browse the repository at this point in the history
  • Loading branch information
louischan-oursky committed Apr 3, 2024
2 parents 8888ed0 + 2dce012 commit 85a422c
Show file tree
Hide file tree
Showing 12 changed files with 52 additions and 6 deletions.
1 change: 1 addition & 0 deletions example/capacitor/src/pages/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ function AuthgearDemo() {
? new WebKitWebViewUIImplementation({
ios: {
modalPresentationStyle: "fullScreen",
isInspectable: true,
},
})
: undefined,
Expand Down
1 change: 1 addition & 0 deletions example/reactnative/src/screens/MainScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ const HomeScreen: React.FC = () => {
? new WebKitWebViewUIImplementation({
ios: {
modalPresentationStyle: 'fullScreen',
isInspectable: true,
},
})
: undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class AGWKWebViewController: UIViewController, WKNavigationDelegate {
private var completionHandler: CompletionHandler?
private let webView: WKWebView
private var result: URL?
private let isInspectable: Bool

private var defaultBackgroundColor: UIColor {
get {
Expand All @@ -41,10 +42,11 @@ class AGWKWebViewController: UIViewController, WKNavigationDelegate {
document.documentElement.style.userSelect = 'none';
"""

init(url: URL, redirectURI: URL, completionHandler: @escaping CompletionHandler) {
init(url: URL, redirectURI: URL, isInspectable: Bool, completionHandler: @escaping CompletionHandler) {
self.url = url
self.redirectURI = redirectURI
self.completionHandler = completionHandler
self.isInspectable = isInspectable

let configuration = WKWebViewConfiguration()

Expand All @@ -59,6 +61,12 @@ class AGWKWebViewController: UIViewController, WKNavigationDelegate {
self.webView = WKWebView(frame: .zero, configuration: configuration)
self.webView.translatesAutoresizingMaskIntoConstraints = false
self.webView.allowsBackForwardNavigationGestures = true
if #available(iOS 16.4, *) {
self.webView.isInspectable = isInspectable
} else {
// isInspectable is not available under ios 16.4
// The webview is always inspectable
}

super.init(nibName: nil, bundle: nil)

Expand Down
4 changes: 3 additions & 1 deletion packages/authgear-capacitor/ios/Plugin/AuthgearPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ public class AuthgearPlugin: CAPPlugin {
let modalPresentationStyle = call.getString("modalPresentationStyle")
let navigationBarBackgroundColor = call.getString("navigationBarBackgroundColor")
let navigationBarButtonTintColor = call.getString("navigationBarButtonTintColor")
let isInspectable = call.getBool("iosIsInspectable")

DispatchQueue.main.async {
self.impl.openAuthorizeURLWithWebView(
Expand All @@ -117,7 +118,8 @@ public class AuthgearPlugin: CAPPlugin {
redirectURI: redirectURI,
modalPresentationStyleString: modalPresentationStyle,
navigationBarBackgroundColorString: navigationBarBackgroundColor,
navigationBarButtonTintColorString: navigationBarButtonTintColor
navigationBarButtonTintColorString: navigationBarButtonTintColor,
isInspectable: isInspectable
) { (redirectURI, error) in
if let error = error {
error.reject(call)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,10 +224,11 @@ import Capacitor
modalPresentationStyleString: String?,
navigationBarBackgroundColorString: String?,
navigationBarButtonTintColorString: String?,
isInspectable: Bool?,
completion: @escaping (String?, Error?) -> Void
) {
var controller: AGWKWebViewController?
controller = AGWKWebViewController(url: url, redirectURI: redirectURI) { result, error in
controller = AGWKWebViewController(url: url, redirectURI: redirectURI, isInspectable: isInspectable ?? false) { result, error in
self.agWKWebViewControllerHandles.removeValue(forKey: controller!)
if let error = error {
let nsError = error as NSError
Expand Down
2 changes: 2 additions & 0 deletions packages/authgear-capacitor/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export interface AuthgearPlugin {
navigationBarButtonTintColor?: string;
actionBarBackgroundColor?: string;
actionBarButtonTintColor?: string;
iosIsInspectable?: boolean;
}): Promise<{ redirectURI: string }>;
openURL(options: { url: string }): Promise<void>;
checkBiometricSupported(options: BiometricOptions): Promise<void>;
Expand Down Expand Up @@ -122,6 +123,7 @@ export async function openAuthorizeURLWithWebView(options: {
navigationBarButtonTintColor?: string;
actionBarBackgroundColor?: string;
actionBarButtonTintColor?: string;
iosIsInspectable?: boolean;
}): Promise<string> {
try {
const { redirectURI } = await Authgear.openAuthorizeURLWithWebView(options);
Expand Down
2 changes: 2 additions & 0 deletions packages/authgear-capacitor/src/ui_implementation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export interface WebKitWebViewUIImplementationOptionsIOS {
navigationBarBackgroundColor?: number;
navigationBarButtonTintColor?: number;
modalPresentationStyle?: "automatic" | "fullScreen" | "pageSheet";
isInspectable?: boolean;
}

/**
Expand Down Expand Up @@ -112,6 +113,7 @@ export class WebKitWebViewUIImplementation implements UIImplementation {
this.options?.android?.actionBarBackgroundColor?.toString(16),
actionBarButtonTintColor:
this.options?.android?.actionBarButtonTintColor?.toString(16),
iosIsInspectable: this.options?.ios?.isInspectable,
});
}
}
15 changes: 14 additions & 1 deletion packages/authgear-react-native/ios/AGAuthgearReactNative.m
Original file line number Diff line number Diff line change
Expand Up @@ -284,9 +284,11 @@ + (BOOL)application:(UIApplication *)application
UIModalPresentationStyle modalPresentationStyle = [self modalPresentationStyleFromString:options[@"modalPresentationStyle"]];
UIColor *navigationBarBackgroundColor = [self uiColorFromNSString:options[@"navigationBarBackgroundColor"]];
UIColor *navigationBarButtonTintColor = [self uiColorFromNSString:options[@"navigationBarButtonTintColor"]];
BOOL isInspectable = [self boolFromNSString:options[@"iosIsInspectable"]];

AGWKWebViewController *controller = [[AGWKWebViewController alloc] initWithURL:[[NSURL alloc] initWithString:url]
redirectURI:[[NSURL alloc] initWithString:redirectURI] completionHandler:^(NSURL *url, NSError *error) {
redirectURI:[[NSURL alloc] initWithString:redirectURI]
isInspectable:isInspectable completionHandler:^(NSURL *url, NSError *error) {
if (error) {
BOOL isUserCancelled = [error.domain isEqualToString:AGWKWebViewControllerErrorDomain] && error.code == AGWKWebViewControllerErrorCodeCanceledLogin;
if (isUserCancelled) {
Expand Down Expand Up @@ -946,4 +948,15 @@ -(UIColor *)uiColorFromNSString:(NSString *)inHex
return [UIColor colorWithRed:r green:g blue:b alpha:a];
}

-(BOOL)boolFromNSString:(NSString *)str
{
if (str != nil) {
if ([str isEqualToString:@"true"]) {
return true;
}
return false;
}
return false;
}

@end
2 changes: 1 addition & 1 deletion packages/authgear-react-native/ios/AGWKWebViewController.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ typedef void(^AGWKWebViewControllerCompletionHandler)(NSURL *url, NSError *error

@interface AGWKWebViewController : UIViewController <WKNavigationDelegate>

- (instancetype)initWithURL:(NSURL *)url redirectURI:(NSURL *)redirectURI completionHandler:(AGWKWebViewControllerCompletionHandler) completionHandler;
- (instancetype)initWithURL:(NSURL *)url redirectURI:(NSURL *)redirectURI isInspectable:(BOOL)isInspectable completionHandler:(AGWKWebViewControllerCompletionHandler) completionHandler;

@property (nonatomic, weak) id<AGWKWebViewControllerPresentationContextProviding> presentationContextProvider;
@property (nonatomic, copy) UIColor *navigationBarBackgroundColor;
Expand Down
11 changes: 10 additions & 1 deletion packages/authgear-react-native/ios/AGWKWebViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,19 @@ @interface AGWKWebViewController ()
@property (nonatomic, copy) AGWKWebViewControllerCompletionHandler completionHandler;
@property (nonatomic) WKWebView *webView;
@property (nonatomic, copy) NSURL* result;
@property (nonatomic) BOOL isInspectable;

@end

@implementation AGWKWebViewController

- (instancetype)initWithURL:(NSURL *)url redirectURI:(NSURL *)redirectURI completionHandler:(void (^)(NSURL *url, NSError *error))completionHandler
- (instancetype)initWithURL:(NSURL *)url redirectURI:(NSURL *)redirectURI isInspectable:(BOOL)isInspectable completionHandler:(void (^)(NSURL *url, NSError *error))completionHandler
{
self = [super initWithNibName:nil bundle:nil];
self.url = url;
self.redirectURI = redirectURI;
self.completionHandler = completionHandler;
self.isInspectable = isInspectable;

WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];

Expand All @@ -36,6 +38,13 @@ - (instancetype)initWithURL:(NSURL *)url redirectURI:(NSURL *)redirectURI comple
self.webView.allowsBackForwardNavigationGestures = YES;
self.webView.navigationDelegate = self;

if (@available(iOS 16.4, *)) {
self.webView.inspectable = isInspectable;
} else {
// inspectable is not available under ios 16.4
// The webview is always inspectable
}

return self;
}

Expand Down
5 changes: 5 additions & 0 deletions packages/authgear-react-native/src/nativemodule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import { NativeModules } from "react-native";
import { BiometricPrivateKeyOptions, BiometricOptions } from "./types";
import { _wrapError } from "./error";

// In ios objc code, reading a BOOL from a NSDictionary always got true
// So encode the boolean as string before passing to native
type BooleanString = "false" | "true";

const { AuthgearReactNative } = NativeModules;

async function _wrapPromise<T>(p: Promise<T>): Promise<T> {
Expand Down Expand Up @@ -79,6 +83,7 @@ export async function openAuthorizeURLWithWebView(options: {
navigationBarBackgroundColor?: string;
navigationBarButtonTintColor?: string;
modalPresentationStyle?: string;
iosIsInspectable?: BooleanString;

actionBarBackgroundColor?: string;
actionBarButtonTintColor?: string;
Expand Down
2 changes: 2 additions & 0 deletions packages/authgear-react-native/src/ui_implementation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export interface WebKitWebViewUIImplementationOptionsIOS {
navigationBarBackgroundColor?: number;
navigationBarButtonTintColor?: number;
modalPresentationStyle?: "automatic" | "fullScreen" | "pageSheet";
isInspectable?: boolean;
}

/**
Expand Down Expand Up @@ -108,6 +109,7 @@ export class WebKitWebViewUIImplementation implements UIImplementation {
navigationBarButtonTintColor:
this.options?.ios?.navigationBarButtonTintColor?.toString(16),
modalPresentationStyle: this.options?.ios?.modalPresentationStyle,
iosIsInspectable: this.options?.ios?.isInspectable ? "true" : "false",
actionBarBackgroundColor:
this.options?.android?.actionBarBackgroundColor?.toString(16),
actionBarButtonTintColor:
Expand Down

0 comments on commit 85a422c

Please sign in to comment.