@capgo/capacitor-inappbrowser 8.10.7 → 8.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -0
- package/android/build.gradle +1 -0
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/CapgoInAppBrowserPlugin.java +11 -0
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/Options.java +10 -0
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/WebViewCallbacks.java +4 -0
- package/android/src/main/java/ee/forgr/capacitor_inappbrowser/WebViewDialog.java +44 -0
- package/android/src/main/res/layout/content_browser.xml +2 -2
- package/dist/docs.json +76 -0
- package/dist/esm/definitions.d.ts +32 -0
- package/dist/esm/definitions.js.map +1 -1
- package/ios/Sources/InAppBrowserPlugin/InAppBrowserPlugin.swift +192 -105
- package/ios/Sources/InAppBrowserPlugin/WKWebViewController.swift +54 -14
- package/package.json +1 -1
|
@@ -110,7 +110,6 @@ enum CustomSchemeOpenSupport {
|
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
|
|
114
113
|
protocol ProxyRequestLocating {
|
|
115
114
|
func hasPendingProxyRequest(_ requestId: String) -> Bool
|
|
116
115
|
}
|
|
@@ -149,7 +148,6 @@ enum ProxyResponseRoutingSupport {
|
|
|
149
148
|
}
|
|
150
149
|
}
|
|
151
150
|
|
|
152
|
-
|
|
153
151
|
enum StatusBarBackgroundLayoutSupport {
|
|
154
152
|
enum Placement: Equatable {
|
|
155
153
|
case skip
|
|
@@ -232,7 +230,7 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
232
230
|
case aware = "AWARE"
|
|
233
231
|
case fakeVisible = "FAKE_VISIBLE"
|
|
234
232
|
}
|
|
235
|
-
private let pluginVersion: String = "8.
|
|
233
|
+
private let pluginVersion: String = "8.12.0"
|
|
236
234
|
public let identifier = "CapgoInAppBrowserPlugin"
|
|
237
235
|
public let jsName = "CapgoInAppBrowser"
|
|
238
236
|
public let pluginMethods: [CAPPluginMethod] = [
|
|
@@ -279,6 +277,7 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
279
277
|
private var hiddenWebViewContainers: [ObjectIdentifier: UIView] = [:]
|
|
280
278
|
private var closeModalTitle: String?
|
|
281
279
|
private var layeredWebViewIds = Set<String>()
|
|
280
|
+
private var framedOverlayWebViewIds = Set<String>()
|
|
282
281
|
private var transparentHostWebViewIds = Set<String>()
|
|
283
282
|
private var hasStoredHostWebViewAppearance = false
|
|
284
283
|
private var originalHostWebViewBackgroundColor: UIColor?
|
|
@@ -339,6 +338,7 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
339
338
|
}
|
|
340
339
|
|
|
341
340
|
private func unregisterWebView(id: String) {
|
|
341
|
+
detachFramedOverlayWebView(id: id)
|
|
342
342
|
detachLayeredWebView(id: id)
|
|
343
343
|
if let webView = webViewControllers[id]?.capableWebView {
|
|
344
344
|
cleanupHiddenWebViewContainer(for: webView)
|
|
@@ -606,7 +606,20 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
606
606
|
return true
|
|
607
607
|
}
|
|
608
608
|
|
|
609
|
+
if let resolvedId,
|
|
610
|
+
let webViewController = webViewControllers[resolvedId],
|
|
611
|
+
webViewController.shouldPresentAsFramedOverlay {
|
|
612
|
+
dismissActiveKeyboard()
|
|
613
|
+
if presentNavigationControllerAsFramedOverlay(id: resolvedId) {
|
|
614
|
+
self.currentPluginCall?.resolve()
|
|
615
|
+
return true
|
|
616
|
+
}
|
|
617
|
+
self.currentPluginCall?.reject("Failed to present webview")
|
|
618
|
+
return false
|
|
619
|
+
}
|
|
620
|
+
|
|
609
621
|
if let resolvedId {
|
|
622
|
+
detachFramedOverlayWebView(id: resolvedId)
|
|
610
623
|
detachLayeredWebView(id: resolvedId)
|
|
611
624
|
}
|
|
612
625
|
dismissActiveKeyboard()
|
|
@@ -621,61 +634,6 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
621
634
|
return true
|
|
622
635
|
}
|
|
623
636
|
|
|
624
|
-
private func targetFrame(for webViewController: WKWebViewController, in hostWebView: UIView) -> CGRect {
|
|
625
|
-
return CustomWebViewFrameSupport.resolvedFrame(
|
|
626
|
-
width: webViewController.customWidth,
|
|
627
|
-
height: webViewController.customHeight,
|
|
628
|
-
x: webViewController.customX,
|
|
629
|
-
y: webViewController.customY,
|
|
630
|
-
fallbackSize: hostWebView.bounds.size
|
|
631
|
-
) ?? hostWebView.bounds
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
@discardableResult
|
|
635
|
-
private func sendNavigationControllerToBack(id: String, transparentBackground: Bool) -> Bool {
|
|
636
|
-
guard let navigationController = navigationControllers[id],
|
|
637
|
-
let webViewController = webViewControllers[id],
|
|
638
|
-
let hostWebView = self.bridge?.webView else {
|
|
639
|
-
return false
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
if let webView = webViewController.capableWebView, webView.superview !== webViewController.view {
|
|
643
|
-
cleanupHiddenWebViewContainer(for: webView)
|
|
644
|
-
attachWebViewToController(webViewController, webView: webView)
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
dismissActiveKeyboard()
|
|
648
|
-
navigationController.view.removeFromSuperview()
|
|
649
|
-
if transparentBackground {
|
|
650
|
-
makeHostWebViewTransparent(for: id)
|
|
651
|
-
} else {
|
|
652
|
-
restoreHostWebViewBackgroundIfNeeded(for: id)
|
|
653
|
-
}
|
|
654
|
-
navigationController.view.frame = targetFrame(for: webViewController, in: hostWebView)
|
|
655
|
-
navigationController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
|
656
|
-
navigationController.view.isUserInteractionEnabled = false
|
|
657
|
-
hostWebView.addSubview(navigationController.view)
|
|
658
|
-
hostWebView.sendSubviewToBack(navigationController.view)
|
|
659
|
-
navigationController.view.setNeedsLayout()
|
|
660
|
-
navigationController.view.layoutIfNeeded()
|
|
661
|
-
|
|
662
|
-
layeredWebViewIds.insert(id)
|
|
663
|
-
webViewController.isLayeredBehind = true
|
|
664
|
-
webViewController.transparentHostBackground = transparentBackground
|
|
665
|
-
return true
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
private func detachLayeredWebView(id: String) {
|
|
669
|
-
if let navigationController = navigationControllers[id] {
|
|
670
|
-
if navigationController.view.superview === self.bridge?.webView {
|
|
671
|
-
navigationController.view.removeFromSuperview()
|
|
672
|
-
}
|
|
673
|
-
navigationController.view.isUserInteractionEnabled = true
|
|
674
|
-
}
|
|
675
|
-
layeredWebViewIds.remove(id)
|
|
676
|
-
restoreHostWebViewBackgroundIfNeeded(for: id)
|
|
677
|
-
}
|
|
678
|
-
|
|
679
637
|
private func storeSubviewBackgrounds(from view: UIView) {
|
|
680
638
|
for subview in view.subviews {
|
|
681
639
|
originalHostSubviewBackgrounds.append((subview, subview.backgroundColor, subview.isOpaque))
|
|
@@ -1291,6 +1249,7 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1291
1249
|
|
|
1292
1250
|
// Read disableOverscroll option (iOS only - controls WebView bounce effect)
|
|
1293
1251
|
let disableOverscroll = call.getBool("disableOverscroll", false)
|
|
1252
|
+
let enableReloadGesture = call.getBool("enableReloadGesture", false)
|
|
1294
1253
|
|
|
1295
1254
|
let legacyProxyRequests = ProxySchemeRequestSupport.legacyProxyRequestsConfiguration(from: call.options["proxyRequests"])
|
|
1296
1255
|
let outboundProxyRulesRaw = call.getArray("outboundProxyRules", [])
|
|
@@ -1361,6 +1320,8 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1361
1320
|
authorizedAppLinks: authorizedAppLinks,
|
|
1362
1321
|
openBlankTargetInWebView: openBlankTargetInWebView
|
|
1363
1322
|
)
|
|
1323
|
+
webViewController.enableReloadGesture = enableReloadGesture
|
|
1324
|
+
webViewController.disableOverscroll = disableOverscroll
|
|
1364
1325
|
webViewController.initWebview(isInspectable: isInspectable)
|
|
1365
1326
|
self.webViewController = webViewController
|
|
1366
1327
|
|
|
@@ -1390,8 +1351,6 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1390
1351
|
webViewController.customY = CGFloat(yPos)
|
|
1391
1352
|
}
|
|
1392
1353
|
|
|
1393
|
-
// Set disableOverscroll option
|
|
1394
|
-
webViewController.disableOverscroll = disableOverscroll
|
|
1395
1354
|
webViewController.handleDownloads = handleDownloads
|
|
1396
1355
|
|
|
1397
1356
|
// Set native navigation gestures before view loads
|
|
@@ -1603,42 +1562,9 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1603
1562
|
}
|
|
1604
1563
|
webViewController.updateTitleAppearance()
|
|
1605
1564
|
|
|
1606
|
-
//
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
// Create a pass-through container
|
|
1611
|
-
let containerView = PassThroughView()
|
|
1612
|
-
containerView.backgroundColor = .clear
|
|
1613
|
-
containerView.frame = UIScreen.main.bounds
|
|
1614
|
-
containerView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
|
1615
|
-
containerView.passthroughView = self.bridge?.webView
|
|
1616
|
-
|
|
1617
|
-
let targetFrame = CustomWebViewFrameSupport.resolvedFrame(
|
|
1618
|
-
width: width.map { CGFloat($0) },
|
|
1619
|
-
height: height.map { CGFloat($0) },
|
|
1620
|
-
x: xPos.map { CGFloat($0) },
|
|
1621
|
-
y: yPos.map { CGFloat($0) },
|
|
1622
|
-
fallbackSize: UIScreen.main.bounds.size
|
|
1623
|
-
)
|
|
1624
|
-
containerView.targetFrame = targetFrame
|
|
1625
|
-
|
|
1626
|
-
// Replace the navigation controller's view with our pass-through container
|
|
1627
|
-
if let navController = self.navigationWebViewController,
|
|
1628
|
-
let originalView = navController.view {
|
|
1629
|
-
navController.view = containerView
|
|
1630
|
-
containerView.addSubview(originalView)
|
|
1631
|
-
containerView.framedContentView = originalView
|
|
1632
|
-
originalView.translatesAutoresizingMaskIntoConstraints = true
|
|
1633
|
-
originalView.autoresizingMask = []
|
|
1634
|
-
if let targetFrame {
|
|
1635
|
-
originalView.frame = targetFrame
|
|
1636
|
-
}
|
|
1637
|
-
}
|
|
1638
|
-
} else {
|
|
1639
|
-
self.navigationWebViewController?.modalPresentationStyle = .overCurrentContext
|
|
1640
|
-
}
|
|
1641
|
-
|
|
1565
|
+
// Custom width/height front browsers are attached as framed child overlays in
|
|
1566
|
+
// presentView (matching Android window sizing) so host taps outside the frame work.
|
|
1567
|
+
self.navigationWebViewController?.modalPresentationStyle = .overCurrentContext
|
|
1642
1568
|
self.navigationWebViewController?.modalTransitionStyle = .crossDissolve
|
|
1643
1569
|
if toolbarType == "blank" {
|
|
1644
1570
|
self.navigationWebViewController?.navigationBar.isHidden = true
|
|
@@ -1765,6 +1691,7 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1765
1691
|
|
|
1766
1692
|
if hidden {
|
|
1767
1693
|
if let resolvedId {
|
|
1694
|
+
self.detachFramedOverlayWebView(id: resolvedId)
|
|
1768
1695
|
self.detachLayeredWebView(id: resolvedId)
|
|
1769
1696
|
}
|
|
1770
1697
|
if !self.attachWebViewToWindow(webView) {
|
|
@@ -1793,9 +1720,22 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1793
1720
|
if let navController = navigationController {
|
|
1794
1721
|
if let resolvedId {
|
|
1795
1722
|
self.setActiveWebView(id: resolvedId, webView: webViewController, navigationController: navController)
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1723
|
+
if navController.presentingViewController == nil && !self.framedOverlayWebViewIds.contains(resolvedId) {
|
|
1724
|
+
self.revealNavigationController(
|
|
1725
|
+
id: resolvedId,
|
|
1726
|
+
navigationController: navController,
|
|
1727
|
+
webViewController: webViewController,
|
|
1728
|
+
animated: true
|
|
1729
|
+
) { presented in
|
|
1730
|
+
if presented {
|
|
1731
|
+
call?.resolve()
|
|
1732
|
+
} else {
|
|
1733
|
+
call?.reject("Failed to present webview")
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
return
|
|
1737
|
+
}
|
|
1738
|
+
} else if navController.presentingViewController == nil {
|
|
1799
1739
|
let presenter = self.bridge?.viewController?.presentedViewController ?? self.bridge?.viewController
|
|
1800
1740
|
self.presentNavigationControllerSafely(navController, from: presenter, animated: true) { presented in
|
|
1801
1741
|
if presented {
|
|
@@ -1873,9 +1813,13 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1873
1813
|
self.attachWebViewToController(webViewController, webView: webView)
|
|
1874
1814
|
}
|
|
1875
1815
|
self.setActiveWebView(id: resolvedId, webView: webViewController, navigationController: navigationController)
|
|
1876
|
-
if navigationController.presentingViewController == nil {
|
|
1877
|
-
|
|
1878
|
-
|
|
1816
|
+
if navigationController.presentingViewController == nil && !self.framedOverlayWebViewIds.contains(resolvedId) {
|
|
1817
|
+
self.revealNavigationController(
|
|
1818
|
+
id: resolvedId,
|
|
1819
|
+
navigationController: navigationController,
|
|
1820
|
+
webViewController: webViewController,
|
|
1821
|
+
animated: isAnimated
|
|
1822
|
+
) { presented in
|
|
1879
1823
|
if presented {
|
|
1880
1824
|
call.resolve()
|
|
1881
1825
|
} else {
|
|
@@ -1884,6 +1828,12 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1884
1828
|
}
|
|
1885
1829
|
return
|
|
1886
1830
|
}
|
|
1831
|
+
if webViewController.shouldPresentAsFramedOverlay {
|
|
1832
|
+
guard self.presentNavigationControllerAsFramedOverlay(id: resolvedId) else {
|
|
1833
|
+
call.reject("Failed to present webview")
|
|
1834
|
+
return
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1887
1837
|
call.resolve()
|
|
1888
1838
|
}
|
|
1889
1839
|
}
|
|
@@ -2117,7 +2067,6 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
2117
2067
|
}
|
|
2118
2068
|
}
|
|
2119
2069
|
|
|
2120
|
-
|
|
2121
2070
|
/// Keep PassThroughView clear so custom y-offsets show the host app behind the gap.
|
|
2122
2071
|
private func applyBlankToolbarBackground(_ color: UIColor, to navigationController: UINavigationController?) {
|
|
2123
2072
|
guard let navigationController else { return }
|
|
@@ -2377,9 +2326,12 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
2377
2326
|
let webViewController = self.webViewControllers[targetId],
|
|
2378
2327
|
let navigationController = self.navigationControllers[targetId] {
|
|
2379
2328
|
let currentUrl = webViewController.url?.absoluteString ?? ""
|
|
2329
|
+
let wasPresented = navigationController.presentingViewController != nil
|
|
2380
2330
|
webViewController.cleanupWebView()
|
|
2381
2331
|
self.handleWebViewDidClose(id: targetId, url: currentUrl)
|
|
2382
|
-
|
|
2332
|
+
if wasPresented {
|
|
2333
|
+
navigationController.dismiss(animated: isAnimated, completion: nil)
|
|
2334
|
+
}
|
|
2383
2335
|
call.resolve()
|
|
2384
2336
|
return
|
|
2385
2337
|
}
|
|
@@ -2415,7 +2367,6 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
2415
2367
|
}
|
|
2416
2368
|
}
|
|
2417
2369
|
|
|
2418
|
-
|
|
2419
2370
|
private func showPrivacyScreen() {
|
|
2420
2371
|
if privacyScreen == nil {
|
|
2421
2372
|
let newPrivacyScreen = UIImageView()
|
|
@@ -2617,3 +2568,139 @@ extension CapgoInAppBrowserPlugin: SFSafariViewControllerDelegate {
|
|
|
2617
2568
|
}
|
|
2618
2569
|
}
|
|
2619
2570
|
}
|
|
2571
|
+
|
|
2572
|
+
|
|
2573
|
+
extension CapgoInAppBrowserPlugin {
|
|
2574
|
+
private func targetFrame(for webViewController: WKWebViewController, in hostWebView: UIView) -> CGRect {
|
|
2575
|
+
return CustomWebViewFrameSupport.resolvedFrame(
|
|
2576
|
+
width: webViewController.customWidth,
|
|
2577
|
+
height: webViewController.customHeight,
|
|
2578
|
+
x: webViewController.customX,
|
|
2579
|
+
y: webViewController.customY,
|
|
2580
|
+
fallbackSize: hostWebView.bounds.size
|
|
2581
|
+
) ?? hostWebView.bounds
|
|
2582
|
+
}
|
|
2583
|
+
|
|
2584
|
+
@discardableResult
|
|
2585
|
+
private func sendNavigationControllerToBack(id: String, transparentBackground: Bool) -> Bool {
|
|
2586
|
+
guard let navigationController = navigationControllers[id],
|
|
2587
|
+
let webViewController = webViewControllers[id],
|
|
2588
|
+
let hostWebView = self.bridge?.webView else {
|
|
2589
|
+
return false
|
|
2590
|
+
}
|
|
2591
|
+
|
|
2592
|
+
if let webView = webViewController.capableWebView, webView.superview !== webViewController.view {
|
|
2593
|
+
cleanupHiddenWebViewContainer(for: webView)
|
|
2594
|
+
attachWebViewToController(webViewController, webView: webView)
|
|
2595
|
+
}
|
|
2596
|
+
|
|
2597
|
+
dismissActiveKeyboard()
|
|
2598
|
+
detachFramedOverlayWebView(id: id)
|
|
2599
|
+
navigationController.view.removeFromSuperview()
|
|
2600
|
+
if transparentBackground {
|
|
2601
|
+
makeHostWebViewTransparent(for: id)
|
|
2602
|
+
} else {
|
|
2603
|
+
restoreHostWebViewBackgroundIfNeeded(for: id)
|
|
2604
|
+
}
|
|
2605
|
+
navigationController.view.frame = targetFrame(for: webViewController, in: hostWebView)
|
|
2606
|
+
navigationController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
|
2607
|
+
navigationController.view.isUserInteractionEnabled = false
|
|
2608
|
+
hostWebView.addSubview(navigationController.view)
|
|
2609
|
+
hostWebView.sendSubviewToBack(navigationController.view)
|
|
2610
|
+
navigationController.view.setNeedsLayout()
|
|
2611
|
+
navigationController.view.layoutIfNeeded()
|
|
2612
|
+
|
|
2613
|
+
layeredWebViewIds.insert(id)
|
|
2614
|
+
webViewController.isLayeredBehind = true
|
|
2615
|
+
webViewController.transparentHostBackground = transparentBackground
|
|
2616
|
+
return true
|
|
2617
|
+
}
|
|
2618
|
+
|
|
2619
|
+
private func detachLayeredWebView(id: String) {
|
|
2620
|
+
if let navigationController = navigationControllers[id] {
|
|
2621
|
+
if navigationController.view.superview === self.bridge?.webView {
|
|
2622
|
+
navigationController.view.removeFromSuperview()
|
|
2623
|
+
}
|
|
2624
|
+
navigationController.view.isUserInteractionEnabled = true
|
|
2625
|
+
}
|
|
2626
|
+
layeredWebViewIds.remove(id)
|
|
2627
|
+
restoreHostWebViewBackgroundIfNeeded(for: id)
|
|
2628
|
+
}
|
|
2629
|
+
|
|
2630
|
+
/// Front custom-dimension browsers are child VCs with an exact frame (Android-style).
|
|
2631
|
+
/// Full-screen modal + PassThroughView still leaves UITransitionView eating host taps.
|
|
2632
|
+
@discardableResult
|
|
2633
|
+
private func presentNavigationControllerAsFramedOverlay(id: String) -> Bool {
|
|
2634
|
+
guard let navigationController = navigationControllers[id],
|
|
2635
|
+
let webViewController = webViewControllers[id],
|
|
2636
|
+
let parent = self.bridge?.viewController else {
|
|
2637
|
+
return false
|
|
2638
|
+
}
|
|
2639
|
+
|
|
2640
|
+
dismissNavigationControllerIfPresented(navigationController)
|
|
2641
|
+
detachLayeredWebView(id: id)
|
|
2642
|
+
|
|
2643
|
+
let frame = targetFrame(for: webViewController, in: parent.view)
|
|
2644
|
+
|
|
2645
|
+
if navigationController.parent !== parent {
|
|
2646
|
+
if navigationController.parent != nil {
|
|
2647
|
+
navigationController.willMove(toParent: nil)
|
|
2648
|
+
navigationController.view.removeFromSuperview()
|
|
2649
|
+
navigationController.removeFromParent()
|
|
2650
|
+
}
|
|
2651
|
+
parent.addChild(navigationController)
|
|
2652
|
+
parent.view.addSubview(navigationController.view)
|
|
2653
|
+
navigationController.didMove(toParent: parent)
|
|
2654
|
+
} else if navigationController.view.superview !== parent.view {
|
|
2655
|
+
parent.view.addSubview(navigationController.view)
|
|
2656
|
+
}
|
|
2657
|
+
|
|
2658
|
+
navigationController.view.frame = frame
|
|
2659
|
+
navigationController.view.autoresizingMask = []
|
|
2660
|
+
navigationController.view.isUserInteractionEnabled = true
|
|
2661
|
+
parent.view.bringSubviewToFront(navigationController.view)
|
|
2662
|
+
navigationController.view.setNeedsLayout()
|
|
2663
|
+
navigationController.view.layoutIfNeeded()
|
|
2664
|
+
webViewController.applyCustomDimensions()
|
|
2665
|
+
|
|
2666
|
+
framedOverlayWebViewIds.insert(id)
|
|
2667
|
+
webViewController.isLayeredBehind = false
|
|
2668
|
+
return true
|
|
2669
|
+
}
|
|
2670
|
+
|
|
2671
|
+
private func detachFramedOverlayWebView(id: String) {
|
|
2672
|
+
guard let navigationController = navigationControllers[id] else {
|
|
2673
|
+
framedOverlayWebViewIds.remove(id)
|
|
2674
|
+
return
|
|
2675
|
+
}
|
|
2676
|
+
|
|
2677
|
+
if navigationController.parent != nil {
|
|
2678
|
+
navigationController.willMove(toParent: nil)
|
|
2679
|
+
navigationController.view.removeFromSuperview()
|
|
2680
|
+
navigationController.removeFromParent()
|
|
2681
|
+
} else if framedOverlayWebViewIds.contains(id) {
|
|
2682
|
+
navigationController.view.removeFromSuperview()
|
|
2683
|
+
}
|
|
2684
|
+
|
|
2685
|
+
framedOverlayWebViewIds.remove(id)
|
|
2686
|
+
}
|
|
2687
|
+
|
|
2688
|
+
private func revealNavigationController(
|
|
2689
|
+
id: String,
|
|
2690
|
+
navigationController: UINavigationController,
|
|
2691
|
+
webViewController: WKWebViewController,
|
|
2692
|
+
animated: Bool,
|
|
2693
|
+
completion: ((Bool) -> Void)? = nil
|
|
2694
|
+
) {
|
|
2695
|
+
if webViewController.shouldPresentAsFramedOverlay {
|
|
2696
|
+
completion?(presentNavigationControllerAsFramedOverlay(id: id))
|
|
2697
|
+
return
|
|
2698
|
+
}
|
|
2699
|
+
|
|
2700
|
+
detachFramedOverlayWebView(id: id)
|
|
2701
|
+
let presenter = self.bridge?.viewController?.presentedViewController ?? self.bridge?.viewController
|
|
2702
|
+
presentNavigationControllerSafely(navigationController, from: presenter, animated: animated, completion: completion)
|
|
2703
|
+
}
|
|
2704
|
+
|
|
2705
|
+
}
|
|
2706
|
+
|
|
@@ -471,6 +471,7 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
|
|
|
471
471
|
var blockedHosts: [String] = []
|
|
472
472
|
var authorizedAppLinks: [String] = []
|
|
473
473
|
var activeNativeNavigationForWebview: Bool = true
|
|
474
|
+
var enableReloadGesture: Bool = false
|
|
474
475
|
var disableOverscroll: Bool = false
|
|
475
476
|
var proxyRequests: Bool = false
|
|
476
477
|
var proxySchemeHandler: ProxySchemeHandler?
|
|
@@ -490,6 +491,11 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
|
|
|
490
491
|
var customX: CGFloat?
|
|
491
492
|
var customY: CGFloat?
|
|
492
493
|
|
|
494
|
+
/// Front (non-toBack) browsers with a custom height use a framed child overlay.
|
|
495
|
+
var shouldPresentAsFramedOverlay: Bool {
|
|
496
|
+
!isLayeredBehind && customHeight != nil
|
|
497
|
+
}
|
|
498
|
+
|
|
493
499
|
internal var preShowSemaphore: DispatchSemaphore?
|
|
494
500
|
internal var preShowError: String?
|
|
495
501
|
private var isWebViewInitialized = false
|
|
@@ -2207,6 +2213,7 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
|
|
|
2207
2213
|
|
|
2208
2214
|
// Disable bounce effect by setting scrollView.bounces to false when disableOverscroll is true
|
|
2209
2215
|
webView.scrollView.bounces = !self.disableOverscroll
|
|
2216
|
+
configureReloadGesture(for: webView)
|
|
2210
2217
|
configureWebViewScrollViewSafeArea(webView)
|
|
2211
2218
|
|
|
2212
2219
|
webView.addObserver(self, forKeyPath: estimatedProgressKeyPath, options: .new, context: nil)
|
|
@@ -2289,6 +2296,7 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
|
|
|
2289
2296
|
configuration.userContentController = WKUserContentController()
|
|
2290
2297
|
self.initialWebConfiguration = configuration
|
|
2291
2298
|
self.persistWebViewData = parent.persistWebViewData
|
|
2299
|
+
self.enableReloadGesture = parent.enableReloadGesture
|
|
2292
2300
|
self.disableOverscroll = parent.disableOverscroll
|
|
2293
2301
|
self.proxyRequests = parent.proxyRequests
|
|
2294
2302
|
self.proxySchemeHandler = proxySchemeHandler
|
|
@@ -2431,6 +2439,7 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
|
|
|
2431
2439
|
}
|
|
2432
2440
|
self.progressView?.alpha = 1
|
|
2433
2441
|
self.progressView?.setProgress(Float(estimatedProgress), animated: true)
|
|
2442
|
+
self.emit("browserPageLoadProgress", data: ["progress": estimatedProgress])
|
|
2434
2443
|
|
|
2435
2444
|
if estimatedProgress >= 1.0 {
|
|
2436
2445
|
UIView.animate(withDuration: 0.3, delay: 0.3, options: .curveEaseOut, animations: {
|
|
@@ -2552,6 +2561,31 @@ public extension WKWebViewController {
|
|
|
2552
2561
|
self.webView?.allowsBackForwardNavigationGestures = self.activeNativeNavigationForWebview
|
|
2553
2562
|
}
|
|
2554
2563
|
|
|
2564
|
+
private func configureReloadGesture(for webView: WKWebView) {
|
|
2565
|
+
if let existing = webView.scrollView.refreshControl {
|
|
2566
|
+
existing.endRefreshing()
|
|
2567
|
+
existing.removeTarget(nil, action: nil, for: .allEvents)
|
|
2568
|
+
webView.scrollView.refreshControl = nil
|
|
2569
|
+
}
|
|
2570
|
+
|
|
2571
|
+
guard enableReloadGesture, !disableOverscroll else {
|
|
2572
|
+
return
|
|
2573
|
+
}
|
|
2574
|
+
|
|
2575
|
+
webView.scrollView.alwaysBounceVertical = true
|
|
2576
|
+
let refreshControl = UIRefreshControl()
|
|
2577
|
+
refreshControl.addTarget(self, action: #selector(handleReloadGesture(_:)), for: .valueChanged)
|
|
2578
|
+
webView.scrollView.refreshControl = refreshControl
|
|
2579
|
+
}
|
|
2580
|
+
|
|
2581
|
+
@objc private func handleReloadGesture(_ sender: UIRefreshControl) {
|
|
2582
|
+
reload()
|
|
2583
|
+
}
|
|
2584
|
+
|
|
2585
|
+
private func stopReloadGesture() {
|
|
2586
|
+
webView?.scrollView.refreshControl?.endRefreshing()
|
|
2587
|
+
}
|
|
2588
|
+
|
|
2555
2589
|
func cleanupWebView() {
|
|
2556
2590
|
guard let webView = self.webView else { return }
|
|
2557
2591
|
webView.stopLoading()
|
|
@@ -3451,6 +3485,7 @@ extension WKWebViewController: WKNavigationDelegate {
|
|
|
3451
3485
|
self.url = urlValue
|
|
3452
3486
|
delegate?.webViewController?(self, didStart: urlValue)
|
|
3453
3487
|
}
|
|
3488
|
+
emit("browserPageLoadStart")
|
|
3454
3489
|
}
|
|
3455
3490
|
public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
|
|
3456
3491
|
if !didpageInit && self.capBrowserPlugin?.isPresentAfterPageLoad == true {
|
|
@@ -3501,6 +3536,7 @@ extension WKWebViewController: WKNavigationDelegate {
|
|
|
3501
3536
|
lastInjectedSafeAreaInsets = nil
|
|
3502
3537
|
syncWebViewSafeAreaLayout()
|
|
3503
3538
|
emit("browserPageLoaded")
|
|
3539
|
+
stopReloadGesture()
|
|
3504
3540
|
}
|
|
3505
3541
|
|
|
3506
3542
|
public func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
|
|
@@ -3510,6 +3546,7 @@ extension WKWebViewController: WKNavigationDelegate {
|
|
|
3510
3546
|
self.url = url
|
|
3511
3547
|
delegate?.webViewController?(self, didFail: url, withError: error)
|
|
3512
3548
|
}
|
|
3549
|
+
stopReloadGesture()
|
|
3513
3550
|
emit("pageLoadError")
|
|
3514
3551
|
}
|
|
3515
3552
|
|
|
@@ -3520,6 +3557,7 @@ extension WKWebViewController: WKNavigationDelegate {
|
|
|
3520
3557
|
self.url = url
|
|
3521
3558
|
delegate?.webViewController?(self, didFail: url, withError: error)
|
|
3522
3559
|
}
|
|
3560
|
+
stopReloadGesture()
|
|
3523
3561
|
emit("pageLoadError")
|
|
3524
3562
|
}
|
|
3525
3563
|
|
|
@@ -3659,14 +3697,18 @@ extension WKWebViewController: WKNavigationDelegate {
|
|
|
3659
3697
|
|
|
3660
3698
|
/// Apply custom dimensions to the view if specified
|
|
3661
3699
|
func applyCustomDimensions() {
|
|
3662
|
-
guard let navigationController = navigationController
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3700
|
+
guard let navigationController = navigationController else {
|
|
3701
|
+
return
|
|
3702
|
+
}
|
|
3703
|
+
|
|
3704
|
+
let fallbackSize = navigationController.view.superview?.bounds.size ?? UIScreen.main.bounds.size
|
|
3705
|
+
guard let targetFrame = CustomWebViewFrameSupport.resolvedFrame(
|
|
3706
|
+
width: customWidth,
|
|
3707
|
+
height: customHeight,
|
|
3708
|
+
x: customX,
|
|
3709
|
+
y: customY,
|
|
3710
|
+
fallbackSize: fallbackSize
|
|
3711
|
+
) else {
|
|
3670
3712
|
return
|
|
3671
3713
|
}
|
|
3672
3714
|
|
|
@@ -3827,7 +3869,6 @@ class PassThroughView: UIView {
|
|
|
3827
3869
|
}
|
|
3828
3870
|
}
|
|
3829
3871
|
weak var framedContentView: UIView?
|
|
3830
|
-
weak var passthroughView: UIView?
|
|
3831
3872
|
|
|
3832
3873
|
override func layoutSubviews() {
|
|
3833
3874
|
super.layoutSubviews()
|
|
@@ -3840,12 +3881,11 @@ class PassThroughView: UIView {
|
|
|
3840
3881
|
}
|
|
3841
3882
|
|
|
3842
3883
|
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
|
3884
|
+
// Outside the browser frame: decline the hit. Callers that still use a full-screen
|
|
3885
|
+
// PassThroughView depend on the parent hierarchy continuing hit-testing; framed
|
|
3886
|
+
// front overlays avoid modal UITransitionView entirely instead.
|
|
3843
3887
|
if let frame = targetFrame, !frame.contains(point) {
|
|
3844
|
-
|
|
3845
|
-
return nil
|
|
3846
|
-
}
|
|
3847
|
-
let convertedPoint = convert(point, to: passthroughView)
|
|
3848
|
-
return passthroughView.hitTest(convertedPoint, with: event)
|
|
3888
|
+
return nil
|
|
3849
3889
|
}
|
|
3850
3890
|
|
|
3851
3891
|
return super.hitTest(point, with: event)
|