@capgo/capacitor-inappbrowser 8.6.30 → 8.6.32

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.
@@ -2,6 +2,7 @@ package ee.forgr.capacitor_inappbrowser;
2
2
 
3
3
  import android.Manifest;
4
4
  import android.app.Activity;
5
+ import android.content.ActivityNotFoundException;
5
6
  import android.content.ComponentName;
6
7
  import android.content.Intent;
7
8
  import android.content.pm.PackageManager;
@@ -763,7 +764,26 @@ public class CapgoInAppBrowserPlugin extends Plugin implements WebViewDialog.Per
763
764
  tabsIntent.intent.putExtra("isPresentAfterPageLoad", true);
764
765
  }
765
766
 
766
- tabsIntent.launchUrl(getContext(), Uri.parse(url));
767
+ Uri targetUri = Uri.parse(url);
768
+ try {
769
+ tabsIntent.launchUrl(getContext(), targetUri);
770
+ } catch (ActivityNotFoundException e) {
771
+ Intent fallback = new Intent(Intent.ACTION_VIEW, targetUri);
772
+ fallback.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
773
+ Bundle extras = tabsIntent.intent.getExtras();
774
+ if (extras != null) {
775
+ fallback.putExtras(extras);
776
+ }
777
+ if (tabsIntent.intent.getPackage() != null) {
778
+ fallback.setPackage(tabsIntent.intent.getPackage());
779
+ }
780
+ try {
781
+ getContext().startActivity(fallback);
782
+ } catch (ActivityNotFoundException e2) {
783
+ call.reject("No browser found to open URL: " + url);
784
+ return;
785
+ }
786
+ }
767
787
 
768
788
  call.resolve();
769
789
  }
@@ -98,7 +98,7 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
98
98
  case aware = "AWARE"
99
99
  case fakeVisible = "FAKE_VISIBLE"
100
100
  }
101
- private let pluginVersion: String = "8.6.30"
101
+ private let pluginVersion: String = "8.6.32"
102
102
  public let identifier = "CapgoInAppBrowserPlugin"
103
103
  public let jsName = "CapgoInAppBrowser"
104
104
  public let pluginMethods: [CAPPluginMethod] = [
@@ -250,9 +250,7 @@ public class CapgoInAppBrowserPlugin: CAPPlugin, CAPBridgedPlugin {
250
250
  ) -> WKWebView? {
251
251
  let popupId = UUID().uuidString
252
252
  let shouldHidePopup = parentController.hiddenPopupWindow
253
- if let parentWebView = parentController.capableWebView {
254
- configuration.processPool = parentWebView.configuration.processPool
255
- }
253
+ // WKProcessPool sharing is automatic on iOS 15+; explicit assignment is deprecated.
256
254
  if let dataStore = parentController.websiteDataStore() {
257
255
  configuration.websiteDataStore = dataStore
258
256
  }
@@ -236,6 +236,49 @@ enum WebViewViewportLayoutSupport {
236
236
  }
237
237
  }
238
238
 
239
+ enum WebViewSafeAreaLayoutSupport {
240
+ static func contentInsetAdjustmentBehavior(enabledSafeBottomMargin: Bool) -> UIScrollView.ContentInsetAdjustmentBehavior {
241
+ enabledSafeBottomMargin ? .automatic : .never
242
+ }
243
+
244
+ static func shouldInsetLayoutMarginsFromSafeArea(enabledSafeBottomMargin: Bool) -> Bool {
245
+ enabledSafeBottomMargin
246
+ }
247
+
248
+ static func rawSystemBottomInset(effectiveBottomInset: CGFloat, additionalBottomInset: CGFloat) -> CGFloat {
249
+ max(0, effectiveBottomInset - additionalBottomInset)
250
+ }
251
+
252
+ static func additionalBottomSafeAreaOffset(enabledSafeBottomMargin: Bool, safeAreaBottomInset: CGFloat) -> CGFloat {
253
+ guard !enabledSafeBottomMargin, safeAreaBottomInset > 0 else {
254
+ return 0
255
+ }
256
+
257
+ return -safeAreaBottomInset
258
+ }
259
+
260
+ static func cssBottomInset(enabledSafeBottomMargin: Bool, safeAreaBottomInset: CGFloat) -> CGFloat {
261
+ enabledSafeBottomMargin ? safeAreaBottomInset : 0
262
+ }
263
+
264
+ static func cssTopInset(enabledSafeTopMargin: Bool, safeAreaTopInset: CGFloat) -> CGFloat {
265
+ enabledSafeTopMargin ? safeAreaTopInset : 0
266
+ }
267
+
268
+ static func safeAreaCssVariablesScript(top: CGFloat, bottom: CGFloat, left: CGFloat, right: CGFloat) -> String {
269
+ let topValue = Int(top.rounded())
270
+ let bottomValue = Int(bottom.rounded())
271
+ let leftValue = Int(left.rounded())
272
+ let rightValue = Int(right.rounded())
273
+
274
+ return "(function(){var root=document.documentElement;" +
275
+ "root.style.setProperty('--safe-area-inset-top','\(topValue)px');" +
276
+ "root.style.setProperty('--safe-area-inset-bottom','\(bottomValue)px');" +
277
+ "root.style.setProperty('--safe-area-inset-left','\(leftValue)px');" +
278
+ "root.style.setProperty('--safe-area-inset-right','\(rightValue)px');})();"
279
+ }
280
+ }
281
+
239
282
  open class WKWebViewController: UIViewController, WKScriptMessageHandler {
240
283
 
241
284
  public init() {
@@ -395,6 +438,14 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
395
438
  private var isWebViewInitialized = false
396
439
  private var isObservingKeyboardViewportChanges = false
397
440
  private var lastViewportRefreshSize: CGSize?
441
+ private struct InjectedSafeAreaInsets: Equatable {
442
+ let top: Int
443
+ let bottom: Int
444
+ let left: Int
445
+ let right: Int
446
+ }
447
+
448
+ private var lastInjectedSafeAreaInsets: InjectedSafeAreaInsets?
398
449
  private var downloadStates: [ObjectIdentifier: WKDownloadState] = [:]
399
450
  private var previewItemURL: URL?
400
451
 
@@ -687,7 +738,13 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
687
738
 
688
739
  // Status bar height
689
740
  private var statusBarHeight: CGFloat {
690
- return UIApplication.shared.windows.first?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0
741
+ let windowScene = UIApplication.shared.connectedScenes
742
+ .compactMap { $0 as? UIWindowScene }
743
+ .first { $0.activationState == .foregroundActive }
744
+ ?? UIApplication.shared.connectedScenes
745
+ .compactMap { $0 as? UIWindowScene }
746
+ .first
747
+ return windowScene?.statusBarManager?.statusBarFrame.height ?? 0
691
748
  }
692
749
 
693
750
  // Make status bar background with colored view underneath
@@ -898,9 +955,15 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
898
955
 
899
956
  override open func viewDidLayoutSubviews() {
900
957
  super.viewDidLayoutSubviews()
958
+ syncWebViewSafeAreaLayout()
901
959
  refreshWebViewViewportIfNeeded()
902
960
  }
903
961
 
962
+ override open func viewSafeAreaInsetsDidChange() {
963
+ super.viewSafeAreaInsetsDidChange()
964
+ syncWebViewSafeAreaLayout()
965
+ }
966
+
904
967
  func updateButtonTintColors() {
905
968
  // Ensure all button items use the navigation bar's tint color
906
969
  if let tintColor = navigationController?.navigationBar.tintColor {
@@ -1058,6 +1121,72 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
1058
1121
  webView.evaluateJavaScript("window.dispatchEvent(new Event('resize'));", completionHandler: nil)
1059
1122
  }
1060
1123
 
1124
+ private func configureWebViewScrollViewSafeArea(_ webView: WKWebView) {
1125
+ if #available(iOS 11.0, *) {
1126
+ webView.scrollView.contentInsetAdjustmentBehavior = WebViewSafeAreaLayoutSupport
1127
+ .contentInsetAdjustmentBehavior(enabledSafeBottomMargin: enabledSafeBottomMargin)
1128
+ }
1129
+
1130
+ webView.insetsLayoutMarginsFromSafeArea = WebViewSafeAreaLayoutSupport
1131
+ .shouldInsetLayoutMarginsFromSafeArea(enabledSafeBottomMargin: enabledSafeBottomMargin)
1132
+
1133
+ if !enabledSafeBottomMargin {
1134
+ webView.scrollView.contentInset = .zero
1135
+ webView.scrollView.scrollIndicatorInsets = .zero
1136
+ }
1137
+ }
1138
+
1139
+ private func syncWebViewSafeAreaLayout() {
1140
+ guard let webView = self.webView, webView.superview != nil else {
1141
+ return
1142
+ }
1143
+
1144
+ let rawSafeAreaBottomInset = WebViewSafeAreaLayoutSupport.rawSystemBottomInset(
1145
+ effectiveBottomInset: view.safeAreaInsets.bottom,
1146
+ additionalBottomInset: additionalSafeAreaInsets.bottom
1147
+ )
1148
+
1149
+ let bottomOffset = WebViewSafeAreaLayoutSupport.additionalBottomSafeAreaOffset(
1150
+ enabledSafeBottomMargin: enabledSafeBottomMargin,
1151
+ safeAreaBottomInset: rawSafeAreaBottomInset
1152
+ )
1153
+ if additionalSafeAreaInsets.bottom != bottomOffset {
1154
+ additionalSafeAreaInsets.bottom = bottomOffset
1155
+ }
1156
+
1157
+ configureWebViewScrollViewSafeArea(webView)
1158
+
1159
+ let topInset = WebViewSafeAreaLayoutSupport.cssTopInset(
1160
+ enabledSafeTopMargin: enabledSafeTopMargin,
1161
+ safeAreaTopInset: view.safeAreaInsets.top
1162
+ )
1163
+ let bottomInset = WebViewSafeAreaLayoutSupport.cssBottomInset(
1164
+ enabledSafeBottomMargin: enabledSafeBottomMargin,
1165
+ safeAreaBottomInset: rawSafeAreaBottomInset
1166
+ )
1167
+ let leftInset = view.safeAreaInsets.left
1168
+ let rightInset = view.safeAreaInsets.right
1169
+
1170
+ let roundedInsets = InjectedSafeAreaInsets(
1171
+ top: Int(topInset.rounded()),
1172
+ bottom: Int(bottomInset.rounded()),
1173
+ left: Int(leftInset.rounded()),
1174
+ right: Int(rightInset.rounded())
1175
+ )
1176
+ if lastInjectedSafeAreaInsets == roundedInsets {
1177
+ return
1178
+ }
1179
+ lastInjectedSafeAreaInsets = roundedInsets
1180
+
1181
+ let script = WebViewSafeAreaLayoutSupport.safeAreaCssVariablesScript(
1182
+ top: topInset,
1183
+ bottom: bottomInset,
1184
+ left: leftInset,
1185
+ right: rightInset
1186
+ )
1187
+ webView.evaluateJavaScript(script, completionHandler: nil)
1188
+ }
1189
+
1061
1190
  private func jsonString(from object: Any) -> String? {
1062
1191
  guard JSONSerialization.isValidJSONObject(object),
1063
1192
  let data = try? JSONSerialization.data(withJSONObject: object),
@@ -1405,9 +1534,7 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
1405
1534
  webConfiguration.allowsInlineMediaPlayback = true
1406
1535
  webConfiguration.userContentController = userContentController
1407
1536
  // Enable background task processing
1408
- if initialWebConfiguration == nil {
1409
- webConfiguration.processPool = WKProcessPool()
1410
- }
1537
+ // WKProcessPool is shared automatically on iOS 15+; explicit assignment is deprecated.
1411
1538
 
1412
1539
  // Enable JavaScript to run automatically (needed for preShowScript and Firebase polyfill)
1413
1540
  webConfiguration.preferences.javaScriptCanOpenWindowsAutomatically = true
@@ -1500,6 +1627,7 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
1500
1627
 
1501
1628
  // Disable bounce effect by setting scrollView.bounces to false when disableOverscroll is true
1502
1629
  webView.scrollView.bounces = !self.disableOverscroll
1630
+ configureWebViewScrollViewSafeArea(webView)
1503
1631
 
1504
1632
  webView.addObserver(self, forKeyPath: estimatedProgressKeyPath, options: .new, context: nil)
1505
1633
  if websiteTitleInNavigationBar {
@@ -1629,7 +1757,7 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
1629
1757
 
1630
1758
  // Ensure status bar appearance is correct when view appears
1631
1759
  // Make sure we have the latest tint color
1632
- if let tintColor = self.tintColor {
1760
+ if self.tintColor != nil {
1633
1761
  // Update the status bar background if needed
1634
1762
  if let navController = navigationController, let backgroundColor = navController.navigationBar.backgroundColor ?? statusBarBackgroundView?.backgroundColor {
1635
1763
  setupStatusBarBackground(color: backgroundColor)
@@ -1735,6 +1863,15 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
1735
1863
  // MARK: - Public Methods
1736
1864
  public extension WKWebViewController {
1737
1865
 
1866
+ func goBack() -> Bool {
1867
+ if webView?.canGoBack ?? false {
1868
+ webView?.goBack()
1869
+ return true
1870
+ }
1871
+ return false
1872
+ }
1873
+
1874
+
1738
1875
  func load(source sourceValue: WKWebSource) {
1739
1876
  switch sourceValue {
1740
1877
  case .remote(let url):
@@ -1816,7 +1953,7 @@ public extension WKWebViewController {
1816
1953
  self.webView?.allowsBackForwardNavigationGestures = self.activeNativeNavigationForWebview
1817
1954
  }
1818
1955
 
1819
- open func cleanupWebView() {
1956
+ func cleanupWebView() {
1820
1957
  guard let webView = self.webView else { return }
1821
1958
  webView.stopLoading()
1822
1959
  previewItemURL = nil
@@ -2062,10 +2199,10 @@ fileprivate extension WKWebViewController {
2062
2199
  }
2063
2200
 
2064
2201
  func setUpState() {
2065
- navigationController?.setNavigationBarHidden(false, animated: true)
2202
+ navigationController?.setNavigationBarHidden(blankNavigationTab, animated: false)
2066
2203
 
2067
2204
  // Always hide toolbar since we never want it
2068
- navigationController?.setToolbarHidden(true, animated: true)
2205
+ navigationController?.setToolbarHidden(true, animated: false)
2069
2206
 
2070
2207
  // Set tint colors but don't override specific colors
2071
2208
  if tintColor == nil {
@@ -2264,14 +2401,6 @@ fileprivate extension WKWebViewController {
2264
2401
  }
2265
2402
 
2266
2403
  // Public method for safe back navigation
2267
- public func goBack() -> Bool {
2268
- if webView?.canGoBack ?? false {
2269
- webView?.goBack()
2270
- return true
2271
- }
2272
- return false
2273
- }
2274
-
2275
2404
  @objc func forwardDidClick(sender: AnyObject) {
2276
2405
  webView?.goForward()
2277
2406
  }
@@ -2422,7 +2551,7 @@ fileprivate extension WKWebViewController {
2422
2551
  dismiss(animated: true, completion: nil)
2423
2552
  }
2424
2553
 
2425
- open func setUpNavigationBarAppearance() {
2554
+ func setUpNavigationBarAppearance() {
2426
2555
  // Set up basic bar appearance
2427
2556
  if let navBar = navigationController?.navigationBar {
2428
2557
  // Make navigation bar transparent
@@ -2479,15 +2608,7 @@ extension WKWebViewController: WKUIDelegate {
2479
2608
  strongCompletionHandler()
2480
2609
  }))
2481
2610
 
2482
- // Try to present the alert
2483
- do {
2484
- self.present(alertController, animated: true, completion: nil)
2485
- } catch {
2486
- // This won't typically be triggered as present doesn't throw,
2487
- // but adding as a safeguard
2488
- print("[InAppBrowser] Error presenting alert: \(error)")
2489
- strongCompletionHandler()
2490
- }
2611
+ self.present(alertController, animated: true, completion: nil)
2491
2612
  }
2492
2613
  }
2493
2614
 
@@ -2733,6 +2854,8 @@ extension WKWebViewController: WKNavigationDelegate {
2733
2854
  delegate?.webViewController?(self, didFinish: url)
2734
2855
  }
2735
2856
  self.injectJavaScriptInterface()
2857
+ lastInjectedSafeAreaInsets = nil
2858
+ syncWebViewSafeAreaLayout()
2736
2859
  emit("browserPageLoaded")
2737
2860
  }
2738
2861
 
@@ -2880,7 +3003,7 @@ extension WKWebViewController: WKNavigationDelegate {
2880
3003
  // MARK: - Dimension Management
2881
3004
 
2882
3005
  /// Apply custom dimensions to the view if specified
2883
- open func applyCustomDimensions() {
3006
+ func applyCustomDimensions() {
2884
3007
  guard let navigationController = navigationController,
2885
3008
  let targetFrame = CustomWebViewFrameSupport.resolvedFrame(
2886
3009
  width: customWidth,
@@ -2910,7 +3033,7 @@ extension WKWebViewController: WKNavigationDelegate {
2910
3033
  }
2911
3034
 
2912
3035
  /// Update dimensions at runtime
2913
- open func updateDimensions(width: CGFloat?, height: CGFloat?, xPos: CGFloat?, yPos: CGFloat?) {
3036
+ func updateDimensions(width: CGFloat?, height: CGFloat?, xPos: CGFloat?, yPos: CGFloat?) {
2914
3037
  // Update stored dimensions
2915
3038
  if let width = width {
2916
3039
  customWidth = width
@@ -2929,7 +3052,7 @@ extension WKWebViewController: WKNavigationDelegate {
2929
3052
  applyCustomDimensions()
2930
3053
  }
2931
3054
 
2932
- open func updateSafeTopMargin(_ enabled: Bool) {
3055
+ func updateSafeTopMargin(_ enabled: Bool) {
2933
3056
  guard enabled != self.enabledSafeTopMargin else { return }
2934
3057
  self.enabledSafeTopMargin = enabled
2935
3058
  guard let webView = self.webView else { return }
@@ -2947,10 +3070,11 @@ extension WKWebViewController: WKNavigationDelegate {
2947
3070
  webView.topAnchor.constraint(equalTo: topAnchor)
2948
3071
  ])
2949
3072
  self.view.layoutIfNeeded()
3073
+ syncWebViewSafeAreaLayout()
2950
3074
  refreshWebViewViewportIfNeeded(force: true)
2951
3075
  }
2952
3076
 
2953
- open func updateSafeBottomMargin(_ enabled: Bool) {
3077
+ func updateSafeBottomMargin(_ enabled: Bool) {
2954
3078
  guard enabled != self.enabledSafeBottomMargin else { return }
2955
3079
  self.enabledSafeBottomMargin = enabled
2956
3080
  guard let webView = self.webView else { return }
@@ -2968,6 +3092,7 @@ extension WKWebViewController: WKNavigationDelegate {
2968
3092
  webView.bottomAnchor.constraint(equalTo: bottomAnchor)
2969
3093
  ])
2970
3094
  self.view.layoutIfNeeded()
3095
+ syncWebViewSafeAreaLayout()
2971
3096
  refreshWebViewViewportIfNeeded(force: true)
2972
3097
  }
2973
3098
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/capacitor-inappbrowser",
3
- "version": "8.6.30",
3
+ "version": "8.6.32",
4
4
  "description": "Capacitor plugin in app browser",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",