@capgo/capacitor-inappbrowser 8.6.29 → 8.6.31

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
  }
@@ -47,10 +47,25 @@ final class SafeAreaInsetsSupport {
47
47
  }
48
48
 
49
49
  static int resolveTopMargin(boolean enabledSafeTopMargin, boolean useTopInset, int systemBarsTop, boolean appBarHandlesTopInset) {
50
+ return resolveTopMarginWithFallback(enabledSafeTopMargin, useTopInset, systemBarsTop, appBarHandlesTopInset, 0, false);
51
+ }
52
+
53
+ static int resolveTopMarginWithFallback(
54
+ boolean enabledSafeTopMargin,
55
+ boolean useTopInset,
56
+ int systemBarsTop,
57
+ boolean appBarHandlesTopInset,
58
+ int fallbackTopInset,
59
+ boolean applyFallbackWhenZero
60
+ ) {
50
61
  if (!enabledSafeTopMargin || !useTopInset || appBarHandlesTopInset) {
51
62
  return 0;
52
63
  }
53
64
 
54
- return systemBarsTop;
65
+ if (systemBarsTop > 0 || !applyFallbackWhenZero || fallbackTopInset <= 0) {
66
+ return systemBarsTop;
67
+ }
68
+
69
+ return fallbackTopInset;
55
70
  }
56
71
  }
@@ -62,6 +62,7 @@ import android.widget.Toast;
62
62
  import android.widget.Toolbar;
63
63
  import androidx.activity.result.ActivityResult;
64
64
  import androidx.activity.result.contract.ActivityResultContracts;
65
+ import androidx.coordinatorlayout.widget.CoordinatorLayout;
65
66
  import androidx.core.content.FileProvider;
66
67
  import androidx.core.graphics.Insets;
67
68
  import androidx.core.view.ViewCompat;
@@ -2576,8 +2577,13 @@ public class WebViewDialog extends Dialog implements ProxyResponseRouting.ProxyR
2576
2577
  }
2577
2578
  }
2578
2579
 
2580
+ boolean isBlankToolbar = _options != null && TextUtils.equals(_options.getToolbarType(), "blank");
2581
+ if (isBlankToolbar) {
2582
+ configureBlankToolbarLayout();
2583
+ }
2584
+
2579
2585
  // Special handling for Android 15+
2580
- if (isAndroid15Plus) {
2586
+ if (isAndroid15Plus && !isBlankToolbar) {
2581
2587
  // Get AppBarLayout which contains the toolbar
2582
2588
  if (toolbarView != null && toolbarView.getParent() instanceof com.google.android.material.appbar.AppBarLayout appBarLayout) {
2583
2589
  // Remove elevation to eliminate shadows (only on Android 15+)
@@ -2752,18 +2758,76 @@ public class WebViewDialog extends Dialog implements ProxyResponseRouting.ProxyR
2752
2758
  _options.getEnabledSafeMargin()
2753
2759
  );
2754
2760
  int imeBottom = keyboardVisible ? ime.bottom : 0;
2755
- int navTop = SafeAreaInsetsSupport.resolveTopMargin(
2761
+ boolean applyTopFallback = _options.getEnabledSafeTopMargin() && _options.getUseTopInset();
2762
+ int fallbackTopInset = applyTopFallback ? getSystemStatusBarHeight() : 0;
2763
+ int navTop = SafeAreaInsetsSupport.resolveTopMarginWithFallback(
2756
2764
  _options.getEnabledSafeTopMargin(),
2757
2765
  _options.getUseTopInset(),
2758
2766
  bars.top,
2759
- appBarHandlesTopInset
2767
+ appBarHandlesTopInset,
2768
+ fallbackTopInset,
2769
+ applyTopFallback
2760
2770
  );
2771
+ int bottomMargin = SafeAreaInsetsSupport.resolveBottomMargin(_options.getEnabledSafeMargin(), safeBottomInset, imeBottom);
2761
2772
 
2762
2773
  mlp.topMargin = navTop;
2763
- mlp.bottomMargin = SafeAreaInsetsSupport.resolveBottomMargin(_options.getEnabledSafeMargin(), safeBottomInset, imeBottom);
2774
+ mlp.bottomMargin = bottomMargin;
2764
2775
  mlp.leftMargin = bars.left;
2765
2776
  mlp.rightMargin = bars.right;
2766
2777
  _webView.setLayoutParams(mlp);
2778
+ injectSafeAreaCssVariables(navTop, bottomMargin, bars.left, bars.right);
2779
+ }
2780
+
2781
+ private void configureBlankToolbarLayout() {
2782
+ View appBarLayout = findViewById(R.id.app_bar_layout);
2783
+ if (appBarLayout != null) {
2784
+ appBarLayout.setVisibility(View.GONE);
2785
+ }
2786
+
2787
+ View statusBarColorView = findViewById(R.id.status_bar_color_view);
2788
+ if (statusBarColorView != null) {
2789
+ statusBarColorView.setVisibility(View.GONE);
2790
+ }
2791
+
2792
+ View contentBrowserLayout = findViewById(R.id.content_browser_layout);
2793
+ if (contentBrowserLayout != null && contentBrowserLayout.getLayoutParams() instanceof CoordinatorLayout.LayoutParams) {
2794
+ CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) contentBrowserLayout.getLayoutParams();
2795
+ layoutParams.setBehavior(null);
2796
+ contentBrowserLayout.setLayoutParams(layoutParams);
2797
+ }
2798
+ }
2799
+
2800
+ private int getSystemStatusBarHeight() {
2801
+ int resourceId = getContext().getResources().getIdentifier("status_bar_height", "dimen", "android");
2802
+ if (resourceId <= 0) {
2803
+ return 0;
2804
+ }
2805
+
2806
+ return getContext().getResources().getDimensionPixelSize(resourceId);
2807
+ }
2808
+
2809
+ private void injectSafeAreaCssVariables(int top, int bottom, int left, int right) {
2810
+ if (_webView == null) {
2811
+ return;
2812
+ }
2813
+
2814
+ String script = String.format(
2815
+ Locale.US,
2816
+ "(function(){var root=document.documentElement;" +
2817
+ "root.style.setProperty('--safe-area-inset-top','%dpx');" +
2818
+ "root.style.setProperty('--safe-area-inset-bottom','%dpx');" +
2819
+ "root.style.setProperty('--safe-area-inset-left','%dpx');" +
2820
+ "root.style.setProperty('--safe-area-inset-right','%dpx');})();",
2821
+ top,
2822
+ bottom,
2823
+ left,
2824
+ right
2825
+ );
2826
+ _webView.post(() -> {
2827
+ if (_webView != null) {
2828
+ _webView.evaluateJavascript(script, null);
2829
+ }
2830
+ });
2767
2831
  }
2768
2832
 
2769
2833
  private View resolveSafeAreaInsetsSourceView() {
@@ -3595,6 +3659,8 @@ public class WebViewDialog extends Dialog implements ProxyResponseRouting.ProxyR
3595
3659
  // Status bar color is already set at the top of this method, no need to set again
3596
3660
  } else if (TextUtils.equals(_options.getToolbarType(), "blank")) {
3597
3661
  _toolbar.setVisibility(View.GONE);
3662
+ configureBlankToolbarLayout();
3663
+ requestSafeAreaInsets();
3598
3664
 
3599
3665
  // Also set window background color to match status bar for blank toolbar
3600
3666
  View statusBarColorView = findViewById(R.id.status_bar_color_view);
@@ -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.29"
101
+ private let pluginVersion: String = "8.6.31"
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
  }
@@ -687,7 +687,13 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
687
687
 
688
688
  // Status bar height
689
689
  private var statusBarHeight: CGFloat {
690
- return UIApplication.shared.windows.first?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0
690
+ let windowScene = UIApplication.shared.connectedScenes
691
+ .compactMap { $0 as? UIWindowScene }
692
+ .first { $0.activationState == .foregroundActive }
693
+ ?? UIApplication.shared.connectedScenes
694
+ .compactMap { $0 as? UIWindowScene }
695
+ .first
696
+ return windowScene?.statusBarManager?.statusBarFrame.height ?? 0
691
697
  }
692
698
 
693
699
  // Make status bar background with colored view underneath
@@ -1405,9 +1411,7 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
1405
1411
  webConfiguration.allowsInlineMediaPlayback = true
1406
1412
  webConfiguration.userContentController = userContentController
1407
1413
  // Enable background task processing
1408
- if initialWebConfiguration == nil {
1409
- webConfiguration.processPool = WKProcessPool()
1410
- }
1414
+ // WKProcessPool is shared automatically on iOS 15+; explicit assignment is deprecated.
1411
1415
 
1412
1416
  // Enable JavaScript to run automatically (needed for preShowScript and Firebase polyfill)
1413
1417
  webConfiguration.preferences.javaScriptCanOpenWindowsAutomatically = true
@@ -1629,7 +1633,7 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
1629
1633
 
1630
1634
  // Ensure status bar appearance is correct when view appears
1631
1635
  // Make sure we have the latest tint color
1632
- if let tintColor = self.tintColor {
1636
+ if self.tintColor != nil {
1633
1637
  // Update the status bar background if needed
1634
1638
  if let navController = navigationController, let backgroundColor = navController.navigationBar.backgroundColor ?? statusBarBackgroundView?.backgroundColor {
1635
1639
  setupStatusBarBackground(color: backgroundColor)
@@ -1735,6 +1739,15 @@ open class WKWebViewController: UIViewController, WKScriptMessageHandler {
1735
1739
  // MARK: - Public Methods
1736
1740
  public extension WKWebViewController {
1737
1741
 
1742
+ func goBack() -> Bool {
1743
+ if webView?.canGoBack ?? false {
1744
+ webView?.goBack()
1745
+ return true
1746
+ }
1747
+ return false
1748
+ }
1749
+
1750
+
1738
1751
  func load(source sourceValue: WKWebSource) {
1739
1752
  switch sourceValue {
1740
1753
  case .remote(let url):
@@ -1816,7 +1829,7 @@ public extension WKWebViewController {
1816
1829
  self.webView?.allowsBackForwardNavigationGestures = self.activeNativeNavigationForWebview
1817
1830
  }
1818
1831
 
1819
- open func cleanupWebView() {
1832
+ func cleanupWebView() {
1820
1833
  guard let webView = self.webView else { return }
1821
1834
  webView.stopLoading()
1822
1835
  previewItemURL = nil
@@ -2264,14 +2277,6 @@ fileprivate extension WKWebViewController {
2264
2277
  }
2265
2278
 
2266
2279
  // 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
2280
  @objc func forwardDidClick(sender: AnyObject) {
2276
2281
  webView?.goForward()
2277
2282
  }
@@ -2422,7 +2427,7 @@ fileprivate extension WKWebViewController {
2422
2427
  dismiss(animated: true, completion: nil)
2423
2428
  }
2424
2429
 
2425
- open func setUpNavigationBarAppearance() {
2430
+ func setUpNavigationBarAppearance() {
2426
2431
  // Set up basic bar appearance
2427
2432
  if let navBar = navigationController?.navigationBar {
2428
2433
  // Make navigation bar transparent
@@ -2479,15 +2484,7 @@ extension WKWebViewController: WKUIDelegate {
2479
2484
  strongCompletionHandler()
2480
2485
  }))
2481
2486
 
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
- }
2487
+ self.present(alertController, animated: true, completion: nil)
2491
2488
  }
2492
2489
  }
2493
2490
 
@@ -2880,7 +2877,7 @@ extension WKWebViewController: WKNavigationDelegate {
2880
2877
  // MARK: - Dimension Management
2881
2878
 
2882
2879
  /// Apply custom dimensions to the view if specified
2883
- open func applyCustomDimensions() {
2880
+ func applyCustomDimensions() {
2884
2881
  guard let navigationController = navigationController,
2885
2882
  let targetFrame = CustomWebViewFrameSupport.resolvedFrame(
2886
2883
  width: customWidth,
@@ -2910,7 +2907,7 @@ extension WKWebViewController: WKNavigationDelegate {
2910
2907
  }
2911
2908
 
2912
2909
  /// Update dimensions at runtime
2913
- open func updateDimensions(width: CGFloat?, height: CGFloat?, xPos: CGFloat?, yPos: CGFloat?) {
2910
+ func updateDimensions(width: CGFloat?, height: CGFloat?, xPos: CGFloat?, yPos: CGFloat?) {
2914
2911
  // Update stored dimensions
2915
2912
  if let width = width {
2916
2913
  customWidth = width
@@ -2929,7 +2926,7 @@ extension WKWebViewController: WKNavigationDelegate {
2929
2926
  applyCustomDimensions()
2930
2927
  }
2931
2928
 
2932
- open func updateSafeTopMargin(_ enabled: Bool) {
2929
+ func updateSafeTopMargin(_ enabled: Bool) {
2933
2930
  guard enabled != self.enabledSafeTopMargin else { return }
2934
2931
  self.enabledSafeTopMargin = enabled
2935
2932
  guard let webView = self.webView else { return }
@@ -2950,7 +2947,7 @@ extension WKWebViewController: WKNavigationDelegate {
2950
2947
  refreshWebViewViewportIfNeeded(force: true)
2951
2948
  }
2952
2949
 
2953
- open func updateSafeBottomMargin(_ enabled: Bool) {
2950
+ func updateSafeBottomMargin(_ enabled: Bool) {
2954
2951
  guard enabled != self.enabledSafeBottomMargin else { return }
2955
2952
  self.enabledSafeBottomMargin = enabled
2956
2953
  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.6.29",
3
+ "version": "8.6.31",
4
4
  "description": "Capacitor plugin in app browser",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",