@capgo/capacitor-inappbrowser 8.19.0 → 8.20.1

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.
@@ -446,13 +446,15 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
446
446
  case aware = "AWARE"
447
447
  case fakeVisible = "FAKE_VISIBLE"
448
448
  }
449
- private let pluginVersion: String = "8.19.0"
449
+ private let pluginVersion: String = "8.20.1"
450
450
  public let identifier = "CapgoInAppBrowserPlugin"
451
451
  public let jsName = "CapgoInAppBrowser"
452
452
  public let pluginMethods: [CAPPluginMethod] = [
453
453
  CAPPluginMethod(name: "goBack", returnType: CAPPluginReturnPromise),
454
454
  CAPPluginMethod(name: "open", returnType: CAPPluginReturnPromise),
455
455
  CAPPluginMethod(name: "openWebView", returnType: CAPPluginReturnPromise),
456
+ CAPPluginMethod(name: "setFullscreen", returnType: CAPPluginReturnPromise),
457
+ CAPPluginMethod(name: "getFullscreen", returnType: CAPPluginReturnPromise),
456
458
  CAPPluginMethod(name: "clearCookies", returnType: CAPPluginReturnPromise),
457
459
  CAPPluginMethod(name: "getCookies", returnType: CAPPluginReturnPromise),
458
460
  CAPPluginMethod(name: "clearAllCookies", returnType: CAPPluginReturnPromise),
@@ -555,6 +557,7 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
555
557
  }
556
558
 
557
559
  private func unregisterWebView(id: String) {
560
+ webViewControllers[id]?.setBrowserFullscreen(false)
558
561
  detachFramedOverlayWebView(id: id)
559
562
  detachLayeredWebView(id: id)
560
563
  if let webView = webViewControllers[id]?.capableWebView {
@@ -649,7 +652,7 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
649
652
  return nil
650
653
  }
651
654
 
652
- let navigationController = UINavigationController(rootViewController: popupController)
655
+ let navigationController = BrowserNavigationController(rootViewController: popupController)
653
656
  cloneNavigationAppearance(from: parentController.navigationController, to: navigationController)
654
657
  let shouldActivatePopup = ActiveWebViewSupport.shouldActivateNewWebView(
655
658
  isHidden: shouldHidePopup,
@@ -827,7 +830,15 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
827
830
  dismissActiveKeyboard()
828
831
  let presenter = self.bridge?.viewController?.presentedViewController ?? self.bridge?.viewController
829
832
  presentNavigationControllerSafely(navigationController, from: presenter, animated: isAnimated) { presented in
830
- if !presented {
833
+ if presented {
834
+ if let resolvedId,
835
+ let controller = self.webViewControllers[resolvedId],
836
+ self.navigationControllers[resolvedId] === navigationController,
837
+ navigationController.presentedViewController == nil,
838
+ !navigationController.isBeingDismissed {
839
+ self.setActiveWebView(id: resolvedId, webView: controller, navigationController: navigationController)
840
+ }
841
+ } else {
831
842
  // openWebView already resolves with the webView id on success.
832
843
  // Resolving here caused a double-resolve (empty, then with id). See #631.
833
844
  self.currentPluginCall?.reject("Failed to present webview")
@@ -1486,6 +1497,11 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
1486
1497
  let height = call.getFloat("height")
1487
1498
  let xPos = call.getFloat("x")
1488
1499
  let yPos = call.getFloat("y")
1500
+ let fullscreen = call.getBool("fullscreen", false)
1501
+ if fullscreen && (toBack || width != nil || height != nil || xPos != nil || yPos != nil) {
1502
+ call.reject("Fullscreen is not supported for framed or behind-host WebViews")
1503
+ return
1504
+ }
1489
1505
 
1490
1506
  // Read disableOverscroll option (iOS only - controls WebView bounce effect)
1491
1507
  let disableOverscroll = call.getBool("disableOverscroll", false)
@@ -1753,7 +1769,7 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
1753
1769
  }
1754
1770
  }
1755
1771
 
1756
- self.navigationWebViewController = UINavigationController.init(rootViewController: webViewController)
1772
+ self.navigationWebViewController = BrowserNavigationController(rootViewController: webViewController)
1757
1773
  if let navigationController = self.navigationWebViewController {
1758
1774
  self.registerWebView(id: webViewId, webView: webViewController, navigationController: navigationController)
1759
1775
  }
@@ -1855,6 +1871,8 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
1855
1871
 
1856
1872
  }
1857
1873
 
1874
+ webViewController.pendingStartupFullscreen = fullscreen
1875
+
1858
1876
  // We don't use the toolbar anymore, always hide it
1859
1877
  self.navigationWebViewController?.setToolbarHidden(true, animated: false)
1860
1878
 
@@ -1952,6 +1970,7 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
1952
1970
  self.isHidden = hidden
1953
1971
 
1954
1972
  if hidden {
1973
+ webViewController.setBrowserFullscreen(false)
1955
1974
  if let resolvedId {
1956
1975
  self.detachFramedOverlayWebView(id: resolvedId)
1957
1976
  self.detachLayeredWebView(id: resolvedId)
@@ -2045,6 +2064,7 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
2045
2064
  }
2046
2065
 
2047
2066
  let transparentBackground = call.getBool("transparentBackground", true)
2067
+ webViewController.setBrowserFullscreen(false)
2048
2068
  self.dismissNavigationControllerIfPresented(navigationController) {
2049
2069
  webViewController.isLayeredBehind = true
2050
2070
  webViewController.transparentHostBackground = transparentBackground
@@ -2661,9 +2681,21 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
2661
2681
 
2662
2682
  @objc func appDidBecomeActive(_ notification: NSNotification) {
2663
2683
  self.hidePrivacyScreen()
2684
+ guard let controller = webViewController,
2685
+ controller.pendingStartupFullscreen,
2686
+ let navigation = controller.navigationController,
2687
+ navigation.presentingViewController != nil,
2688
+ navigation.presentedViewController == nil,
2689
+ controller.presentedViewController == nil,
2690
+ controller.viewIfLoaded?.window != nil,
2691
+ controller.capableWebView?.superview === controller.viewIfLoaded else { return }
2692
+ controller.setBrowserFullscreen(true)
2664
2693
  }
2665
2694
 
2666
2695
  @objc func appWillResignActive(_ notification: NSNotification) {
2696
+ for controller in webViewControllers.values {
2697
+ controller.setBrowserFullscreen(false)
2698
+ }
2667
2699
  self.showPrivacyScreen()
2668
2700
  }
2669
2701
 
@@ -2991,3 +3023,50 @@ extension CapgoInAppBrowserPlugin {
2991
3023
 
2992
3024
  }
2993
3025
 
3026
+
3027
+ extension CapgoInAppBrowserPlugin {
3028
+ @objc func setFullscreen(_ call: CAPPluginCall) {
3029
+ guard let value = call.options["enabled"] as? NSNumber,
3030
+ CFGetTypeID(value) == CFBooleanGetTypeID() else {
3031
+ call.reject("enabled must be a boolean")
3032
+ return
3033
+ }
3034
+ let enabled = value.boolValue
3035
+ DispatchQueue.main.async {
3036
+ guard let id = call.getString("id") ?? self.activeWebViewId,
3037
+ let controller = self.webViewControllers[id],
3038
+ controller.capableWebView != nil else {
3039
+ call.reject("WebView is not initialized or does not support fullscreen")
3040
+ return
3041
+ }
3042
+ if enabled {
3043
+ guard controller.supportsBrowserFullscreen,
3044
+ let navigation = self.navigationControllers[id],
3045
+ navigation.presentingViewController != nil,
3046
+ navigation.presentedViewController == nil,
3047
+ controller.presentedViewController == nil,
3048
+ controller.viewIfLoaded?.window != nil,
3049
+ controller.capableWebView?.superview === controller.view,
3050
+ UIApplication.shared.applicationState == .active else {
3051
+ call.reject("Fullscreen requires a visible, frontmost, unframed WebView")
3052
+ return
3053
+ }
3054
+ }
3055
+ controller.setBrowserFullscreen(enabled)
3056
+ call.resolve()
3057
+ }
3058
+ }
3059
+
3060
+ @objc func getFullscreen(_ call: CAPPluginCall) {
3061
+ DispatchQueue.main.async {
3062
+ guard let id = call.getString("id") ?? self.activeWebViewId,
3063
+ let controller = self.webViewControllers[id],
3064
+ controller.capableWebView != nil else {
3065
+ call.reject("WebView is not initialized or does not support fullscreen")
3066
+ return
3067
+ }
3068
+ call.resolve(["enabled": controller.isBrowserFullscreen])
3069
+ }
3070
+ }
3071
+
3072
+ }
@@ -446,6 +446,11 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
446
446
  open var capBrowserPlugin: CapgoInAppBrowserPlugin?
447
447
  open var isInspectable: Bool = false
448
448
  var instanceId: String = ""
449
+ var browserFullscreen = BrowserFullscreenState()
450
+
451
+ override open var prefersStatusBarHidden: Bool { isBrowserFullscreen }
452
+ override open var prefersHomeIndicatorAutoHidden: Bool { isBrowserFullscreen }
453
+
449
454
  var shareDisclaimer: [String: Any]?
450
455
  var shareSubject: String?
451
456
  var didpageInit = false
@@ -1235,6 +1240,7 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
1235
1240
  hostView.insertSubview(backgroundView, at: 0)
1236
1241
  backgroundView.translatesAutoresizingMaskIntoConstraints = false
1237
1242
  backgroundView.backgroundColor = color
1243
+ backgroundView.isHidden = isBrowserFullscreen
1238
1244
 
1239
1245
  var constraints = [
1240
1246
  backgroundView.topAnchor.constraint(equalTo: hostView.topAnchor),
@@ -1475,6 +1481,7 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
1475
1481
  override open func viewDidLayoutSubviews() {
1476
1482
  super.viewDidLayoutSubviews()
1477
1483
  syncWebViewSafeAreaLayout()
1484
+ updateFullscreenExitButtonPosition()
1478
1485
  refreshWebViewViewportIfNeeded()
1479
1486
  }
1480
1487
 
@@ -2379,7 +2386,7 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
2379
2386
  }
2380
2387
 
2381
2388
  private func applyNavigationVisibility() {
2382
- navigationController?.setNavigationBarHidden(blankNavigationTab, animated: false)
2389
+ navigationController?.setNavigationBarHidden(isBrowserFullscreen || blankNavigationTab, animated: false)
2383
2390
  // Always hide toolbar since we never want it.
2384
2391
  navigationController?.setToolbarHidden(true, animated: false)
2385
2392
  }
@@ -2412,6 +2419,11 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
2412
2419
  }
2413
2420
  }
2414
2421
 
2422
+ // Apply only when presented; hidden startup must not change the host's system bars.
2423
+ if pendingStartupFullscreen && UIApplication.shared.applicationState == .active {
2424
+ setBrowserFullscreen(true)
2425
+ }
2426
+
2415
2427
  // Update status bar style
2416
2428
  updateStatusBarStyle()
2417
2429
 
@@ -2462,7 +2474,12 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
2462
2474
 
2463
2475
  override open func viewWillDisappear(_ animated: Bool) {
2464
2476
  super.viewWillDisappear(animated)
2465
- rollbackState()
2477
+ if isBeingDismissed || isMovingFromParent || navigationController?.isBeingDismissed == true {
2478
+ setBrowserFullscreen(false)
2479
+ }
2480
+ if !isBrowserFullscreen {
2481
+ rollbackState()
2482
+ }
2466
2483
  }
2467
2484
 
2468
2485
  override open func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
@@ -2597,6 +2614,7 @@ public extension WKWebViewController {
2597
2614
  }
2598
2615
 
2599
2616
  func cleanupWebView() {
2617
+ setBrowserFullscreen(false)
2600
2618
  guard let webView = self.webView else { return }
2601
2619
  webView.stopLoading()
2602
2620
  previewItemURL = nil
@@ -3650,6 +3668,10 @@ extension WKWebViewController: WKNavigationDelegate {
3650
3668
  return
3651
3669
  }
3652
3670
 
3671
+ if navigationAction.targetFrame?.isMainFrame == true {
3672
+ exitFullscreenIfOriginChanges(to: url)
3673
+ }
3674
+
3653
3675
  if handleDownloads, url.scheme?.lowercased() == "blob" {
3654
3676
  handleBlobDownloadFromPage(
3655
3677
  blobUrl: url.absoluteString,
@@ -3725,6 +3747,9 @@ extension WKWebViewController: WKNavigationDelegate {
3725
3747
  }
3726
3748
 
3727
3749
  public func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
3750
+ if navigationResponse.isForMainFrame {
3751
+ exitFullscreenIfOriginChanges(to: navigationResponse.response.url)
3752
+ }
3728
3753
  if shouldInterceptDownload(for: navigationResponse) {
3729
3754
  decisionHandler(.download)
3730
3755
  return
@@ -3743,10 +3768,6 @@ extension WKWebViewController: WKNavigationDelegate {
3743
3768
  stopReloadGesture()
3744
3769
  }
3745
3770
 
3746
- public func webViewWebContentProcessDidTerminate(_ webView: WKWebView) {
3747
- stopReloadGesture()
3748
- }
3749
-
3750
3771
  // MARK: - Dimension Management
3751
3772
 
3752
3773
  func applyCustomDimensions() {
@@ -3799,6 +3820,7 @@ extension WKWebViewController: WKNavigationDelegate {
3799
3820
 
3800
3821
  /// Update dimensions at runtime
3801
3822
  func updateDimensions(width: CGFloat?, height: CGFloat?, xPos: CGFloat?, yPos: CGFloat?) {
3823
+ setBrowserFullscreen(false)
3802
3824
  // Update stored dimensions
3803
3825
  if let width = width {
3804
3826
  customWidth = width
@@ -3818,6 +3840,10 @@ extension WKWebViewController: WKNavigationDelegate {
3818
3840
  }
3819
3841
 
3820
3842
  func updateSafeTopMargin(_ enabled: Bool) {
3843
+ if isBrowserFullscreen && !browserFullscreen.applyingLayout {
3844
+ browserFullscreen.baseline?.safeTop = enabled
3845
+ return
3846
+ }
3821
3847
  guard enabled != self.enabledSafeTopMargin else { return }
3822
3848
  self.enabledSafeTopMargin = enabled
3823
3849
  guard let webView = self.webView else { return }
@@ -3840,6 +3866,10 @@ extension WKWebViewController: WKNavigationDelegate {
3840
3866
  }
3841
3867
 
3842
3868
  func updateSafeBottomMargin(_ enabled: Bool) {
3869
+ if isBrowserFullscreen && !browserFullscreen.applyingLayout {
3870
+ browserFullscreen.baseline?.safeBottom = enabled
3871
+ return
3872
+ }
3843
3873
  guard enabled != self.enabledSafeBottomMargin else { return }
3844
3874
  self.enabledSafeBottomMargin = enabled
3845
3875
  guard let webView = self.webView else { return }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/capacitor-inappbrowser",
3
- "version": "8.19.0",
3
+ "version": "8.20.1",
4
4
  "description": "Capacitor plugin in app browser",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",
@@ -35,7 +35,7 @@
35
35
  "verify:ios": "bun run build:proxy-bridge && xcodebuild -scheme CapgoCapacitorInappbrowser -destination generic/platform=iOS",
36
36
  "verify:android": "cd android && ./gradlew clean build test && cd ..",
37
37
  "verify:web": "bun run build && bun run test:web",
38
- "test:web": "bun test src/proxy-bridge-support.test.ts src/bundled-asset-support.test.ts",
38
+ "test:web": "bun test src/proxy-bridge-support.test.ts src/bundled-asset-support.test.ts src/fullscreen-web.test.ts",
39
39
  "test:maestro:android": "./scripts/test-maestro-android.sh",
40
40
  "lint": "bun run eslint && bun run prettier -- --check && bun run swiftlint -- lint",
41
41
  "fmt": "bun run eslint -- --fix && bun run prettier -- --write && bun run swiftlint -- --fix --format",