UNPKG

@nativescript-community/ui-webview

Version:

Advanced WebView plugin for NativeScript

837 lines (835 loc) 36.6 kB
import { File, Trace, alert, confirm, knownFolders, profile, prompt } from '@nativescript/core'; import { isEnabledProperty } from '@nativescript/core/ui/core/view'; import { WebViewExtBase, WebViewTraceCategory, allowsInlineMediaPlaybackProperty, autoInjectJSBridgeProperty, customUserAgentProperty, debugModeProperty, limitsNavigationsToAppBoundDomainsProperty, mediaPlaybackRequiresUserActionProperty, scrollBarIndicatorVisibleProperty, scrollBounceProperty, viewPortProperty } from './index.common'; import { webViewBridge } from './nativescript-webview-bridge-loader'; export * from './index.common'; const messageHandlerName = 'nsBridge'; export class AWebView extends WebViewExtBase { constructor() { super(...arguments); this.wkNamedUserScripts = []; this.supportXLocalScheme = typeof CustomUrlSchemeHandler !== 'undefined'; this.viewPortSize = { initialScale: 1.0 }; this.limitsNavigationsToAppBoundDomains = false; this.allowsInlineMediaPlayback = false; this.mediaTypesRequiringUser = true; } zoomIn() { return false; } zoomOut() { return false; } zoomBy(zoomFactor) { } createNativeView() { const configuration = WKWebViewConfiguration.new(); configuration.dataDetectorTypes = -1 /* WKDataDetectorTypes.All */; this.wkWebViewConfiguration = configuration; const messageHandler = WKScriptMessageHandlerNotaImpl.initWithOwner(new WeakRef(this)); const wkUController = (this.wkUserContentController = WKUserContentController.new()); wkUController.addScriptMessageHandlerName(messageHandler, messageHandlerName); configuration.userContentController = wkUController; configuration.preferences.setValueForKey(true, 'allowFileAccessFromFileURLs'); configuration.setValueForKey(true, 'allowUniversalAccessFromFileURLs'); configuration.limitsNavigationsToAppBoundDomains = this.limitsNavigationsToAppBoundDomains; configuration.mediaTypesRequiringUserActionForPlayback = this.mediaTypesRequiringUser ? -1 /* WKAudiovisualMediaTypes.All */ : 0 /* WKAudiovisualMediaTypes.None */; configuration.allowsInlineMediaPlayback = this.allowsInlineMediaPlayback; if (this.supportXLocalScheme) { this.wkCustomUrlSchemeHandler = new CustomUrlSchemeHandler(); configuration.setURLSchemeHandlerForURLScheme(this.wkCustomUrlSchemeHandler, this.interceptScheme); } return new WKWebView({ frame: CGRectZero, configuration }); } initNativeView() { super.initNativeView(); this.wkNavigationDelegate = WKNavigationDelegateNotaImpl.initWithOwner(new WeakRef(this)); this.wkUIDelegate = WKUIDelegateNotaImpl.initWithOwner(new WeakRef(this)); this.loadWKUserScripts(); } disposeNativeView() { this.wkWebViewConfiguration?.userContentController?.removeScriptMessageHandlerForName(messageHandlerName); this.wkWebViewConfiguration = null; this.wkNavigationDelegate = null; this.wkCustomUrlSchemeHandler = null; this.wkUIDelegate = null; super.disposeNativeView(); } async injectWebViewBridge() { // return this.ensurePolyfills(); } async injectViewPortMeta() { this.resetViewPortCode(); if (this.supportXLocalScheme) { return; } return super.injectViewPortMeta(); } async executeJavaScript(scriptCode, stringifyResult = true) { if (stringifyResult) { scriptCode = ` (function(window) { var result = null; try { result = ${scriptCode.trim()}; } catch (err) { return JSON.stringify({ error: true, message: err.message, stack: err.stack }); } try { return JSON.stringify(result); } catch (err) { return result; } })(window); `; } const nativeView = this.nativeViewProtected; if (!nativeView) { return Promise.reject(new Error('WebView is missing')); } const rawResult = await new Promise((resolve, reject) => { nativeView.evaluateJavaScriptCompletionHandler(scriptCode.trim(), (result, error) => { if (error) { reject(error); return; } resolve(result); }); }); const result = await this.parseWebViewJavascriptResult(rawResult); const r = result; if (r && typeof r === 'object' && r.error) { const error = new Error(r.message); error.webStack = r.stack; throw error; } return result; } onLoaded() { super.onLoaded(); const nativeView = this.nativeViewProtected; if (nativeView) { nativeView.navigationDelegate = this.wkNavigationDelegate; nativeView.UIDelegate = this.wkUIDelegate; } } onUnloaded() { const nativeView = this.nativeViewProtected; if (nativeView) { nativeView.navigationDelegate = null; nativeView.UIDelegate = null; } super.onUnloaded(); } stopLoading() { const nativeView = this.nativeViewProtected; nativeView.stopLoading(); } _loadUrl(src) { const nativeView = this.nativeViewProtected; const nsURL = NSURL.URLWithString(src); if (src.startsWith('file:///')) { const cachePath = src.substring(0, src.lastIndexOf('/')); const nsReadAccessUrl = NSURL.URLWithString(cachePath); if (Trace.isEnabled()) { Trace.write(`WKWebViewWrapper.loadUrl("${src}") -> ios.loadFileURLAllowingReadAccessToURL("${nsURL}", "${nsReadAccessUrl}"`, WebViewTraceCategory, Trace.messageType.info); } nativeView.loadFileURLAllowingReadAccessToURL(nsURL, nsReadAccessUrl); } else { const nsRequestWithUrl = NSURLRequest.requestWithURL(nsURL); if (Trace.isEnabled()) { Trace.write(`WKWebViewWrapper.loadUrl("${src}") -> ios.loadRequest("${nsRequestWithUrl}"`, WebViewTraceCategory, Trace.messageType.info); } nativeView.loadRequest(nsRequestWithUrl); } } _loadData(content) { const nativeView = this.nativeViewProtected; const baseUrl = `file:///${knownFolders.currentApp().path}/`; const nsBaseUrl = NSURL.URLWithString(baseUrl); if (Trace.isEnabled()) { Trace.write(`WKWebViewWrapper.loadUrl(content) -> this.ios.loadHTMLStringBaseURL("${nsBaseUrl}")`, WebViewTraceCategory, Trace.messageType.info); } nativeView.loadHTMLStringBaseURL(content, nsBaseUrl); } get canGoBack() { const nativeView = this.nativeViewProtected; return nativeView && !!nativeView.canGoBack; } get canGoForward() { const nativeView = this.nativeViewProtected; return nativeView && !!nativeView.canGoForward; } goBack() { const nativeView = this.nativeViewProtected; nativeView.goBack(); } goForward() { const nativeView = this.nativeViewProtected; nativeView.goForward(); } reload() { const nativeView = this.nativeViewProtected; nativeView.reload(); } _webAlert(message, callback) { if (!super._webAlert(message, callback)) { alert(message) .then(() => callback()) .catch(() => callback()); } return true; } _webConfirm(message, callback) { if (!super._webConfirm(message, callback)) { confirm(message) .then((res) => callback(res)) .catch(() => callback(null)); } return true; } _webPrompt(message, defaultText, callback) { if (!super._webPrompt(message, defaultText, callback)) { prompt(message, defaultText) .then((res) => { if (res.result) { callback(res.text); } else { callback(null); } }) .catch(() => callback(null)); } return true; } registerLocalResource(resourceName, path) { const cls = `WebViewExt<${this}.ios>.registerLocalResource("${resourceName}", "${path}")`; if (!this.supportXLocalScheme) { if (Trace.isEnabled()) { Trace.write(`${cls} -> custom schema isn't support on iOS <11`, WebViewTraceCategory, Trace.messageType.error); } return; } resourceName = this.fixLocalResourceName(resourceName); const filepath = this.resolveLocalResourceFilePath(path); if (!filepath) { if (Trace.isEnabled()) { Trace.write(`${cls} -> file doesn't exist`, WebViewTraceCategory, Trace.messageType.error); } return; } if (Trace.isEnabled()) { Trace.write(`${cls} -> file: "${filepath}"`, WebViewTraceCategory, Trace.messageType.info); } this.registerLocalResourceForNative(resourceName, filepath); } unregisterLocalResource(resourceName) { const cls = `WebViewExt<${this}.ios>.unregisterLocalResource("${resourceName}")`; if (!this.supportXLocalScheme) { if (Trace.isEnabled()) { Trace.write(`${cls} -> custom schema isn't support on iOS <11`, WebViewTraceCategory, Trace.messageType.error); } return; } if (Trace.isEnabled()) { Trace.write(cls, WebViewTraceCategory, Trace.messageType.info); } resourceName = this.fixLocalResourceName(resourceName); this.unregisterLocalResourceForNative(resourceName); } getRegisteredLocalResource(resourceName) { resourceName = this.fixLocalResourceName(resourceName); const cls = `WebViewExt<${this}.ios>.getRegisteredLocalResource("${resourceName}")`; if (!this.supportXLocalScheme) { if (Trace.isEnabled()) { Trace.write(`${cls} -> custom schema isn't support on iOS <11`, WebViewTraceCategory, Trace.messageType.error); } return null; } const result = this.getRegisteredLocalResourceFromNative(resourceName); if (Trace.isEnabled()) { Trace.write(`${cls} -> "${result}"`, WebViewTraceCategory, Trace.messageType.info); } return result; } getTitle() { return this.executeJavaScript('document.title'); } async autoLoadStyleSheetFile(resourceName, path, insertBefore) { const filepath = this.resolveLocalResourceFilePath(path); if (!filepath) { if (Trace.isEnabled()) { Trace.write(`WKWebViewWrapper.autoLoadStyleSheetFile("${resourceName}", "${path}") - couldn't resolve filepath`, WebViewTraceCategory, Trace.messageType.info); } return; } resourceName = this.fixLocalResourceName(resourceName); const scriptCode = await this.generateLoadCSSFileScriptCode(resourceName, filepath, insertBefore); if (scriptCode) { this.addNamedWKUserScript(`auto-load-css-${resourceName}`, scriptCode); } } removeAutoLoadStyleSheetFile(resourceName) { resourceName = this.fixLocalResourceName(resourceName); this.removeNamedWKUserScript(`auto-load-css-${resourceName}`); } async autoLoadJavaScriptFile(resourceName, path) { const filepath = this.resolveLocalResourceFilePath(path); if (!filepath) { if (Trace.isEnabled()) { Trace.write(`WKWebViewWrapper.autoLoadJavaScriptFile("${resourceName}", "${path}") - couldn't resolve filepath`, WebViewTraceCategory, Trace.messageType.info); } return; } const scriptCode = await File.fromPath(filepath).readText(); this.addNamedWKUserScript(resourceName, scriptCode); } removeAutoLoadJavaScriptFile(resourceName) { const fixedResourceName = this.fixLocalResourceName(resourceName); const href = `${this.interceptScheme}://${fixedResourceName}`; this.removeNamedWKUserScript(href); } [autoInjectJSBridgeProperty.setNative](enabled) { this.loadWKUserScripts(enabled); } [debugModeProperty.getDefault]() { return false; } [debugModeProperty.setNative](enabled) { const nativeView = this.nativeViewProtected; nativeView['inspectable'] = !!enabled; } [scrollBounceProperty.getDefault]() { const nativeView = this.nativeViewProtected; return nativeView.scrollView.bounces; } [scrollBounceProperty.setNative](enabled) { const nativeView = this.nativeViewProtected; nativeView.scrollView.bounces = !!enabled; } [viewPortProperty.setNative](value) { if (this.src) { this.injectViewPortMeta(); } } [limitsNavigationsToAppBoundDomainsProperty.setNative](enabled) { this.limitsNavigationsToAppBoundDomains = enabled; } [limitsNavigationsToAppBoundDomainsProperty.getDefault]() { return false; } [scrollBarIndicatorVisibleProperty.getDefault]() { return true; } [scrollBarIndicatorVisibleProperty.setNative](value) { this.updateScrollBarVisibility(value); } [customUserAgentProperty.setNative](value) { this.nativeViewProtected.customUserAgent = value; } updateScrollBarVisibility(value) { if (!this.nativeViewProtected) { return; } this.nativeViewProtected.scrollView.showsHorizontalScrollIndicator = value; this.nativeViewProtected.scrollView.showsVerticalScrollIndicator = value; } _onOrientationChanged() { this.updateScrollBarVisibility(this.scrollBarIndicatorVisible); } [isEnabledProperty.setNative](enabled) { const nativeView = this.nativeViewProtected; nativeView.userInteractionEnabled = !!enabled; nativeView.scrollView.userInteractionEnabled = !!enabled; } [mediaPlaybackRequiresUserActionProperty.setNative](enabled) { this.nativeViewProtected.configuration.mediaTypesRequiringUserActionForPlayback = enabled ? -1 /* WKAudiovisualMediaTypes.All */ : 0 /* WKAudiovisualMediaTypes.None */; // this.nativeViewProtected.configuration.setValueForKey(enabled ? WKAudiovisualMediaTypes.All : WKAudiovisualMediaTypes.None, 'mediaTypesRequiringUserActionForPlayback'); } [allowsInlineMediaPlaybackProperty.setNative](enabled) { // this.nativeViewProtected.configuration.setValueForKey(enabled, 'allowsInlineMediaPlayback'); this.nativeViewProtected.configuration.allowsInlineMediaPlayback = enabled; } /** * iOS11+ * * Sets up loading WKUserScripts * * @param autoInjectJSBridge If true viewport-code, bridge-code and named scripts will be loaded, if false only viewport-code */ loadWKUserScripts(autoInjectJSBridge = this.autoInjectJSBridge) { if (!this.wkUserScriptViewPortCode) { this.wkUserScriptViewPortCode = this.makeWKUserScriptPromise(this.generateViewPortCode()); } this.wkUserContentController.removeAllUserScripts(); this.addUserScriptFromPromise(this.wkUserScriptViewPortCode); if (!autoInjectJSBridge) { return; } if (!this.wkUserScriptInjectWebViewBridge) { this.wkUserScriptInjectWebViewBridge = this.createWkUserScript(webViewBridge); } this.addUserScript(this.wkUserScriptInjectWebViewBridge); for (const { wkUserScript } of this.wkNamedUserScripts) { this.addUserScript(wkUserScript); } } /** * iOS11+ * * Remove a named WKUserScript */ removeNamedWKUserScript(resourceName) { const idx = this.wkNamedUserScripts.findIndex((val) => val.resourceName === resourceName); if (idx === -1) { return; } this.wkNamedUserScripts.splice(idx, 1); this.loadWKUserScripts(); } async resetViewPortCode() { this.wkUserScriptViewPortCode = null; const viewPortScriptCode = await this.generateViewPortCode(); if (viewPortScriptCode) { this.executeJavaScript(viewPortScriptCode); this.loadWKUserScripts(); } } registerLocalResourceForNative(resourceName, filepath) { if (!this.wkCustomUrlSchemeHandler) { return; } this.wkCustomUrlSchemeHandler.registerLocalResourceForKeyFilepath(resourceName, filepath); } unregisterLocalResourceForNative(resourceName) { if (!this.wkCustomUrlSchemeHandler) { return; } this.wkCustomUrlSchemeHandler.unregisterLocalResourceForKey(resourceName); } getRegisteredLocalResourceFromNative(resourceName) { if (!this.wkCustomUrlSchemeHandler) { return null; } return this.wkCustomUrlSchemeHandler.getRegisteredLocalResourceForKey(resourceName); } async makeWKUserScriptPromise(scriptCodePromise) { const scriptCode = await scriptCodePromise; if (!scriptCode) { return null; } return this.createWkUserScript(scriptCode); } async addUserScriptFromPromise(userScriptPromise) { const userScript = await userScriptPromise; if (!userScript) { return; } return this.addUserScript(userScript); } addUserScript(userScript) { if (!userScript) { return; } this.wkUserContentController.addUserScript(userScript); } /** * iOS11+ * * Add/replace a named WKUserScript. * These scripts will be injected when a new document is loaded. */ addNamedWKUserScript(resourceName, scriptCode) { if (!scriptCode) { return; } this.removeNamedWKUserScript(resourceName); const wkUserScript = this.createWkUserScript(scriptCode); this.wkNamedUserScripts.push({ resourceName, wkUserScript }); this.addUserScript(wkUserScript); } /** * iOS11+ * * Factory function for creating a WKUserScript instance. */ createWkUserScript(source) { return WKUserScript.alloc().initWithSourceInjectionTimeForMainFrameOnly(source, 1 /* WKUserScriptInjectionTime.AtDocumentEnd */, true); } } AWebView.supportXLocalScheme = typeof CustomUrlSchemeHandler !== 'undefined'; __decorate([ profile ], AWebView.prototype, "onLoaded", null); var WKNavigationDelegateNotaImpl = /** @class */ (function (_super) { __extends(WKNavigationDelegateNotaImpl, _super); function WKNavigationDelegateNotaImpl() { return _super !== null && _super.apply(this, arguments) || this; } WKNavigationDelegateNotaImpl.initWithOwner = function (owner) { var handler = WKNavigationDelegateNotaImpl.new(); handler.owner = owner; return handler; }; WKNavigationDelegateNotaImpl.prototype.webViewDecidePolicyForNavigationActionDecisionHandler = function (webView, navigationAction, decisionHandler) { var owner = this.owner.get(); if (!owner) { decisionHandler(WKNavigationActionPolicy.Cancel); return; } var request = navigationAction.request; var httpMethod = request.HTTPMethod; var url = request.URL && request.URL.absoluteString; if (Trace.isEnabled()) { Trace.write("webViewDecidePolicyForNavigationActionDecisionHandler: \"".concat(url, "\""), WebViewTraceCategory, Trace.messageType.info); } if (!url) { return; } var navType = 'other'; switch (navigationAction.navigationType) { case WKNavigationType.LinkActivated: { navType = 'linkClicked'; break; } case WKNavigationType.FormSubmitted: { navType = 'formSubmitted'; break; } case WKNavigationType.BackForward: { navType = 'backForward'; break; } case WKNavigationType.Reload: { navType = 'reload'; break; } case WKNavigationType.FormResubmitted: { navType = 'formResubmitted'; break; } default: { navType = 'other'; break; } } var shouldOverrideUrlLoading = owner._onShouldOverrideUrlLoading(url, httpMethod, navType); if (shouldOverrideUrlLoading === true) { if (Trace.isEnabled()) { Trace.write("WKNavigationDelegateClass.webViewDecidePolicyForNavigationActionDecisionHandler(\"".concat(url, "\", \"").concat(navigationAction.navigationType, "\") -> method:").concat(httpMethod, " \"").concat(navType, "\" -> cancel"), WebViewTraceCategory, Trace.messageType.info); decisionHandler(WKNavigationActionPolicy.Cancel); } return; } decisionHandler(WKNavigationActionPolicy.Allow); if (Trace.isEnabled()) { Trace.write("WKNavigationDelegateClass.webViewDecidePolicyForNavigationActionDecisionHandler(\"".concat(url, "\", \"").concat(navigationAction.navigationType, "\") -> method:").concat(httpMethod, " \"").concat(navType, "\""), WebViewTraceCategory, Trace.messageType.info); } owner._onLoadStarted(url, navType); }; WKNavigationDelegateNotaImpl.prototype.webViewDidStartProvisionalNavigation = function (webView, navigation) { var owner = this.owner.get(); if (!owner) { return; } if (Trace.isEnabled()) { Trace.write("WKNavigationDelegateClass.webViewDidStartProvisionalNavigation(\"".concat(webView.URL, "\")"), WebViewTraceCategory, Trace.messageType.info); } }; WKNavigationDelegateNotaImpl.prototype.webViewDidFinishNavigation = function (webView, navigation) { var owner = this.owner.get(); if (!owner) { return; } if (Trace.isEnabled()) { Trace.write("WKNavigationDelegateClass.webViewDidFinishNavigation(\"".concat(webView.URL, "\")"), WebViewTraceCategory, Trace.messageType.info); } var src = owner.src; if (webView.URL) { src = webView.URL.absoluteString; } owner._onLoadFinished(src); }; WKNavigationDelegateNotaImpl.prototype.webViewDidFailNavigationWithError = function (webView, navigation, error) { var owner = this.owner.get(); if (!owner) { return; } var src = owner.src; if (webView.URL) { src = webView.URL.absoluteString; } if (Trace.isEnabled()) { Trace.write("WKNavigationDelegateClass.webViewDidFailNavigationWithError(\"".concat(error.localizedDescription, "\")"), WebViewTraceCategory, Trace.messageType.info); } owner._onLoadFinished(src, error.localizedDescription); }; WKNavigationDelegateNotaImpl.prototype.webViewDidFailProvisionalNavigationWithError = function (webView, navigation, error) { var owner = this.owner.get(); if (!owner) { return; } var src = owner.src; if (webView.URL && webView.URL.absoluteString) { src = webView.URL.absoluteString; } if (Trace.isEnabled()) { Trace.write("WKNavigationDelegateClass.webViewDidFailProvisionalNavigationWithError(".concat(error.localizedDescription), WebViewTraceCategory, Trace.messageType.info); } owner._onLoadFinished(src, error.localizedDescription); }; WKNavigationDelegateNotaImpl.ObjCProtocols = [WKNavigationDelegate]; return WKNavigationDelegateNotaImpl; }(NSObject)); export { WKNavigationDelegateNotaImpl }; var WKScriptMessageHandlerNotaImpl = /** @class */ (function (_super) { __extends(WKScriptMessageHandlerNotaImpl, _super); function WKScriptMessageHandlerNotaImpl() { return _super !== null && _super.apply(this, arguments) || this; } WKScriptMessageHandlerNotaImpl.initWithOwner = function (owner) { var delegate = WKScriptMessageHandlerNotaImpl.new(); delegate.owner = owner; return delegate; }; WKScriptMessageHandlerNotaImpl.prototype.userContentControllerDidReceiveScriptMessage = function (userContentController, webViewMessage) { var owner = this.owner.get(); if (!owner) { return; } try { var message = JSON.parse(webViewMessage.body); try { owner.onWebViewEvent(message.eventName, JSON.parse(message.data)); } catch (err) { owner.writeTrace("userContentControllerDidReceiveScriptMessage(".concat(userContentController, ", ").concat(webViewMessage, ") - couldn't parse data: ").concat(message.data), Trace.messageType.error); owner.onWebViewEvent(message.eventName, message.data); } } catch (err) { if (Trace.isEnabled()) { Trace.write("userContentControllerDidReceiveScriptMessage(".concat(userContentController, ", ").concat(webViewMessage, ") - bad message: ").concat(webViewMessage.body), WebViewTraceCategory, Trace.messageType.error); } } }; WKScriptMessageHandlerNotaImpl.ObjCProtocols = [WKScriptMessageHandler]; return WKScriptMessageHandlerNotaImpl; }(NSObject)); export { WKScriptMessageHandlerNotaImpl }; var WKUIDelegateNotaImpl = /** @class */ (function (_super) { __extends(WKUIDelegateNotaImpl, _super); function WKUIDelegateNotaImpl() { return _super !== null && _super.apply(this, arguments) || this; } WKUIDelegateNotaImpl.initWithOwner = function (owner) { var delegate = WKUIDelegateNotaImpl.new(); delegate.owner = owner; return delegate; }; /** * Handle alerts from the webview */ WKUIDelegateNotaImpl.prototype.webViewRunJavaScriptAlertPanelWithMessageInitiatedByFrameCompletionHandler = function (webView, message, frame, completionHandler) { var owner = this.owner.get(); if (!owner) { return; } var gotResponse = false; owner._webAlert(message, function () { if (!gotResponse) { completionHandler(); } gotResponse = true; }); }; /** * Handle confirm dialogs from the webview */ WKUIDelegateNotaImpl.prototype.webViewRunJavaScriptConfirmPanelWithMessageInitiatedByFrameCompletionHandler = function (webView, message, frame, completionHandler) { var owner = this.owner.get(); if (!owner) { return; } var gotResponse = false; owner._webConfirm(message, function (confirmed) { if (!gotResponse) { completionHandler(confirmed); } gotResponse = true; }); }; /** * Handle prompt dialogs from the webview */ WKUIDelegateNotaImpl.prototype.webViewRunJavaScriptTextInputPanelWithPromptDefaultTextInitiatedByFrameCompletionHandler = function (webView, message, defaultText, frame, completionHandler) { var owner = this.owner.get(); if (!owner) { return; } var gotResponse = false; owner._webPrompt(message, defaultText, function (response) { if (!gotResponse) { completionHandler(response); } gotResponse = true; }); }; WKUIDelegateNotaImpl.prototype.webViewCreateWebViewWithConfigurationForNavigationActionWindowFeatures = function (webView, configuration, navigationAction, windowFeatures) { var _a; var owner = this.owner.get(); // Handle popup window requests (window.open() or target="_blank") if (navigationAction && navigationAction.request && navigationAction.request.URL && (!navigationAction.targetFrame || !navigationAction.targetFrame.mainFrame)) { var supportPopups = (_a = owner === null || owner === void 0 ? void 0 : owner.supportPopups) !== null && _a !== void 0 ? _a : true; if (supportPopups) { try { var popupConfig = configuration; popupConfig.userContentController.removeAllUserScripts(); var popupWebView_1 = WKWebView.alloc().initWithFrameConfiguration(CGRectZero, popupConfig); if (webView.customUserAgent) { popupWebView_1.customUserAgent = webView.customUserAgent; } var currentVC = UIApplication.sharedApplication.keyWindow.rootViewController; while (currentVC && currentVC.presentedViewController) { currentVC = currentVC.presentedViewController; } if (currentVC) { var popupVC = UIViewController.alloc().init(); popupVC.view.backgroundColor = UIColor.whiteColor; popupVC.view.addSubview(popupWebView_1); popupWebView_1.translatesAutoresizingMaskIntoConstraints = false; NSLayoutConstraint.activateConstraints([ popupWebView_1.topAnchor.constraintEqualToAnchor(popupVC.view.safeAreaLayoutGuide.topAnchor), popupWebView_1.bottomAnchor.constraintEqualToAnchor(popupVC.view.bottomAnchor), popupWebView_1.leadingAnchor.constraintEqualToAnchor(popupVC.view.leadingAnchor), popupWebView_1.trailingAnchor.constraintEqualToAnchor(popupVC.view.trailingAnchor) ]); var navController_1 = UINavigationController.alloc().initWithRootViewController(popupVC); // Create close button handler var CloseHandler = NSObject.extend({ 'onCloseButtonTap:': function (sender) { navController_1.dismissViewControllerAnimatedCompletion(true, null); } }, { name: 'CloseHandler', exposedMethods: { 'onCloseButtonTap:': { returns: interop.types.void, params: [interop.types.id] } } }); var handler = CloseHandler.alloc().init(); var closeButton = UIBarButtonItem.alloc().initWithBarButtonSystemItemTargetAction(UIBarButtonSystemItem.Done, handler, 'onCloseButtonTap:'); popupVC.navigationItem.leftBarButtonItem = closeButton; var simpleUIDelegate_1 = NSObject .extend({ webViewDidClose: function (webView) { navController_1.dismissViewControllerAnimatedCompletion(true, function () { popupWebView_1 = null; navController_1 = null; simpleUIDelegate_1 = null; }); } }, { protocols: [WKUIDelegate] }) .alloc() .init(); popupWebView_1.UIDelegate = simpleUIDelegate_1; currentVC.presentViewControllerAnimatedCompletion(navController_1, true, null); return popupWebView_1; } } catch (error) { console.error('[ui-webview] Error creating popup:', error); } } // Load in main WebView (fallback or when popups disabled) webView.loadRequest(navigationAction.request); } return null; }; WKUIDelegateNotaImpl.prototype.webViewRequestDeviceOrientationAndMotionPermissionForOriginInitiatedByFrameDecisionHandler = function (webView, origin, frame, decisionHandler) { return __awaiter(this, void 0, void 0, function () { var owner, error_1; return __generator(this, function (_a) { switch (_a.label) { case 0: owner = this.owner.get(); if (!owner) { decisionHandler(WKPermissionDecision.Deny); return [2 /*return*/]; } _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); return [4 /*yield*/, owner._onRequestPermissions(['motion'])]; case 2: _a.sent(); decisionHandler(WKPermissionDecision.Grant); return [3 /*break*/, 4]; case 3: error_1 = _a.sent(); decisionHandler(WKPermissionDecision.Deny); owner.notify({ eventName: 'error', error: error_1 }); return [3 /*break*/, 4]; case 4: return [2 /*return*/]; } }); }); }; WKUIDelegateNotaImpl.prototype.webViewRequestMediaCapturePermissionForOriginInitiatedByFrameTypeDecisionHandler = function (webView, origin, frame, type, decisionHandler) { return __awaiter(this, void 0, void 0, function () { var owner, permissions, error_2; return __generator(this, function (_a) { switch (_a.label) { case 0: owner = this.owner.get(); if (!owner) { decisionHandler(WKPermissionDecision.Deny); return [2 /*return*/]; } _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); permissions = []; switch (type) { case WKMediaCaptureType.Camera: permissions.push('camera'); break; case WKMediaCaptureType.Microphone: permissions.push('microphone'); break; case WKMediaCaptureType.CameraAndMicrophone: permissions.push('camera', 'microphone'); break; } return [4 /*yield*/, owner._onRequestPermissions(permissions)]; case 2: _a.sent(); decisionHandler(WKPermissionDecision.Grant); return [3 /*break*/, 4]; case 3: error_2 = _a.sent(); decisionHandler(WKPermissionDecision.Deny); owner.notify({ eventName: 'error', error: error_2 }); return [3 /*break*/, 4]; case 4: return [2 /*return*/]; } }); }); }; WKUIDelegateNotaImpl.ObjCProtocols = [WKUIDelegate]; return WKUIDelegateNotaImpl; }(NSObject)); export { WKUIDelegateNotaImpl }; //# sourceMappingURL=index.ios.js.map