@capgo/capacitor-native-navigation 8.4.0 → 8.4.2
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/android/build.gradle
CHANGED
|
@@ -3,7 +3,6 @@ ext {
|
|
|
3
3
|
androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.7.1'
|
|
4
4
|
androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.3.0'
|
|
5
5
|
androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.7.0'
|
|
6
|
-
materialVersion = project.hasProperty('materialVersion') ? rootProject.ext.materialVersion : '1.12.0'
|
|
7
6
|
}
|
|
8
7
|
|
|
9
8
|
buildscript {
|
|
@@ -54,7 +53,6 @@ dependencies {
|
|
|
54
53
|
implementation project(':capacitor-android')
|
|
55
54
|
annotationProcessor project(':capacitor-android')
|
|
56
55
|
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
|
|
57
|
-
implementation "com.google.android.material:material:$materialVersion"
|
|
58
56
|
testImplementation "junit:junit:$junitVersion"
|
|
59
57
|
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
|
60
58
|
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
|
|
@@ -1883,18 +1883,29 @@ public class NativeNavigationPlugin extends Plugin {
|
|
|
1883
1883
|
}
|
|
1884
1884
|
|
|
1885
1885
|
private JSObject currentInsets() {
|
|
1886
|
+
// View layout uses device pixels; CSS variables must be density-independent
|
|
1887
|
+
// or a 3x screen writes `192px` which CSS treats as 192 CSS px.
|
|
1886
1888
|
int top = navbarVisible ? statusBarInset() + dp(DEFAULT_NAVBAR_DP) : 0;
|
|
1887
1889
|
int bottom = tabbarVisible ? navigationBarInset() + dp(tabbarStyle.totalHeight()) + dp(tabbarStyle.bottomGap) : 0;
|
|
1888
1890
|
JSObject insets = new JSObject();
|
|
1889
|
-
insets.put("top", top);
|
|
1891
|
+
insets.put("top", cssPx(top));
|
|
1890
1892
|
insets.put("right", 0);
|
|
1891
|
-
insets.put("bottom", bottom);
|
|
1893
|
+
insets.put("bottom", cssPx(bottom));
|
|
1892
1894
|
insets.put("left", 0);
|
|
1893
|
-
insets.put("navbarHeight", top);
|
|
1894
|
-
insets.put("tabbarHeight", bottom);
|
|
1895
|
+
insets.put("navbarHeight", cssPx(top));
|
|
1896
|
+
insets.put("tabbarHeight", cssPx(bottom));
|
|
1895
1897
|
return insets;
|
|
1896
1898
|
}
|
|
1897
1899
|
|
|
1900
|
+
/** Converts a layout pixel value to CSS pixels for WebView CSS variables. */
|
|
1901
|
+
private int cssPx(int devicePx) {
|
|
1902
|
+
float density = getContext().getResources().getDisplayMetrics().density;
|
|
1903
|
+
if (density <= 0f) {
|
|
1904
|
+
return devicePx;
|
|
1905
|
+
}
|
|
1906
|
+
return Math.round(devicePx / density);
|
|
1907
|
+
}
|
|
1908
|
+
|
|
1898
1909
|
private JSObject insetsResult() {
|
|
1899
1910
|
JSObject result = new JSObject();
|
|
1900
1911
|
result.put("insets", currentInsets());
|
|
@@ -69,6 +69,8 @@ public class NativeNavigationPlugin: CAPPlugin, CAPBridgedPlugin, UITabBarContro
|
|
|
69
69
|
private var tabBaseImages: [UIImage?] = []
|
|
70
70
|
private var tabSelectedImages: [UIImage?] = []
|
|
71
71
|
private var suppressTabSelectEvent = false
|
|
72
|
+
private var tabSelectEmittedForReTap = false
|
|
73
|
+
private var lastSetTabbarOptions: [String: Any] = [:]
|
|
72
74
|
private var transitionSnapshot: UIView?
|
|
73
75
|
private var activeTransitionId: String?
|
|
74
76
|
private var activeTransitionDirection = "forward"
|
|
@@ -233,6 +235,9 @@ public class NativeNavigationPlugin: CAPPlugin, CAPBridgedPlugin, UITabBarContro
|
|
|
233
235
|
icons: icons
|
|
234
236
|
)
|
|
235
237
|
self.applySystemTabBarItems(items, selectedIndex: selectedIndex, animated: call.getBool("animated", false))
|
|
238
|
+
if let options = call.options as? [String: Any] {
|
|
239
|
+
self.lastSetTabbarOptions = options
|
|
240
|
+
}
|
|
236
241
|
self.applyTabBarAppearance(tabBar: tabBar, options: call)
|
|
237
242
|
if items.isEmpty {
|
|
238
243
|
self.tabbarVisible = false
|
|
@@ -543,17 +548,27 @@ public class NativeNavigationPlugin: CAPPlugin, CAPBridgedPlugin, UITabBarContro
|
|
|
543
548
|
if usesSystemLiquidGlass {
|
|
544
549
|
hostWebView(in: viewController)
|
|
545
550
|
}
|
|
551
|
+
tabSelectEmittedForReTap = false
|
|
552
|
+
if !suppressTabSelectEvent,
|
|
553
|
+
tabBarController.selectedViewController === viewController {
|
|
554
|
+
notifyTabSelect(index: viewController.tabBarItem.tag)
|
|
555
|
+
tabSelectEmittedForReTap = true
|
|
556
|
+
}
|
|
546
557
|
return true
|
|
547
558
|
}
|
|
548
559
|
|
|
549
560
|
public func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
|
|
550
561
|
guard !suppressTabSelectEvent else {
|
|
562
|
+
tabSelectEmittedForReTap = false
|
|
551
563
|
hostWebViewInSelectedSystemTab()
|
|
552
564
|
return
|
|
553
565
|
}
|
|
554
566
|
let index = viewController.tabBarItem.tag
|
|
555
567
|
hostWebViewInSelectedSystemTab()
|
|
556
|
-
|
|
568
|
+
if !tabSelectEmittedForReTap {
|
|
569
|
+
notifyTabSelect(index: index)
|
|
570
|
+
}
|
|
571
|
+
tabSelectEmittedForReTap = false
|
|
557
572
|
}
|
|
558
573
|
|
|
559
574
|
private func notifyTabSelect(index: Int) {
|
|
@@ -611,17 +626,29 @@ public class NativeNavigationPlugin: CAPPlugin, CAPBridgedPlugin, UITabBarContro
|
|
|
611
626
|
tabBarController?.view.layoutIfNeeded()
|
|
612
627
|
|
|
613
628
|
if let tabBar = tabBar {
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
629
|
+
if usesSystemLiquidGlass,
|
|
630
|
+
!lastSetTabbarOptions.isEmpty,
|
|
631
|
+
let refreshCall = CAPPluginCall(
|
|
632
|
+
callbackId: "tabbar-refresh",
|
|
633
|
+
methodName: "setTabbar",
|
|
634
|
+
options: lastSetTabbarOptions,
|
|
635
|
+
success: { _, _ in },
|
|
636
|
+
error: { _ in }
|
|
637
|
+
) {
|
|
638
|
+
applyTabBarAppearance(tabBar: tabBar, options: refreshCall)
|
|
639
|
+
} else {
|
|
640
|
+
tabBar.isTranslucent = !prefersOpaqueTabBarBackground()
|
|
641
|
+
let standardAppearance = tabBar.standardAppearance
|
|
642
|
+
tabBar.standardAppearance = standardAppearance
|
|
623
643
|
if #available(iOS 15.0, *) {
|
|
624
|
-
|
|
644
|
+
let scrollEdgeAppearance = tabBar.scrollEdgeAppearance ?? standardAppearance
|
|
645
|
+
tabBar.scrollEdgeAppearance = scrollEdgeAppearance
|
|
646
|
+
}
|
|
647
|
+
tabBar.items?.forEach { item in
|
|
648
|
+
item.standardAppearance = standardAppearance
|
|
649
|
+
if #available(iOS 15.0, *) {
|
|
650
|
+
item.scrollEdgeAppearance = tabBar.scrollEdgeAppearance
|
|
651
|
+
}
|
|
625
652
|
}
|
|
626
653
|
}
|
|
627
654
|
tabBar.setNeedsLayout()
|
|
@@ -1469,7 +1496,9 @@ public class NativeNavigationPlugin: CAPPlugin, CAPBridgedPlugin, UITabBarContro
|
|
|
1469
1496
|
private func applyTabBarAppearance(tabBar: UITabBar, options call: CAPPluginCall) {
|
|
1470
1497
|
if usesSystemLiquidGlass {
|
|
1471
1498
|
let standardAppearance = UITabBarAppearance()
|
|
1472
|
-
|
|
1499
|
+
// Match scroll-edge background so UIKit does not swap Liquid Glass for
|
|
1500
|
+
// legacy material when content scrolls under the bar (iOS 26+).
|
|
1501
|
+
configureSystemTabBarScrollEdgeBackground(standardAppearance, options: call)
|
|
1473
1502
|
applyTabBarColorOptions(standardAppearance, tabBar: tabBar, options: call)
|
|
1474
1503
|
applyTabBarBadgeOptions(standardAppearance, options: call)
|
|
1475
1504
|
|
|
@@ -1791,7 +1820,13 @@ public class NativeNavigationPlugin: CAPPlugin, CAPBridgedPlugin, UITabBarContro
|
|
|
1791
1820
|
|
|
1792
1821
|
if let container = systemTabRootContainer {
|
|
1793
1822
|
container.frame = rootView.bounds
|
|
1794
|
-
|
|
1823
|
+
// Capacitor's root view is the WKWebView. After the webview is
|
|
1824
|
+
// hosted in a tab content controller, stretching it to this
|
|
1825
|
+
// container's full bounds overflows the tab VC (clipsToBounds is
|
|
1826
|
+
// off) and paints over the system tab bar.
|
|
1827
|
+
if !isWebViewHostedInSystemTabController {
|
|
1828
|
+
webView?.frame = container.bounds
|
|
1829
|
+
}
|
|
1795
1830
|
}
|
|
1796
1831
|
|
|
1797
1832
|
if let container = navContainer {
|
|
@@ -1852,8 +1887,11 @@ public class NativeNavigationPlugin: CAPPlugin, CAPBridgedPlugin, UITabBarContro
|
|
|
1852
1887
|
|
|
1853
1888
|
private func bringChromeToFront() {
|
|
1854
1889
|
if usesSystemLiquidGlass && tabbarStyle.shape != .curve {
|
|
1890
|
+
if let tabBarController = tabBarController {
|
|
1891
|
+
(systemTabRootContainer ?? bridge?.viewController?.view)?.bringSubviewToFront(tabBarController.view)
|
|
1892
|
+
}
|
|
1855
1893
|
if let navContainer = navContainer {
|
|
1856
|
-
bridge?.viewController?.view
|
|
1894
|
+
(systemTabRootContainer ?? bridge?.viewController?.view)?.bringSubviewToFront(navContainer)
|
|
1857
1895
|
}
|
|
1858
1896
|
bringLiftedWebViewOverlaysToFront()
|
|
1859
1897
|
return
|
|
@@ -1975,7 +2013,12 @@ public class NativeNavigationPlugin: CAPPlugin, CAPBridgedPlugin, UITabBarContro
|
|
|
1975
2013
|
let usesSystemTabbar = usesSystemLiquidGlass && tabbarStyle.shape != .curve
|
|
1976
2014
|
let nativeTabHeight = max(tabBar?.frame.height ?? 0, 49 + safeInsets.bottom)
|
|
1977
2015
|
let customTabHeight = tabbarHeight + safeInsets.bottom + tabbarStyle.bottomGap
|
|
1978
|
-
|
|
2016
|
+
// Hosted in the tab content VC: the WebView already ends above the
|
|
2017
|
+
// bar. Reporting the bar height as CSS overlap lifts the FAB by a
|
|
2018
|
+
// second bar.
|
|
2019
|
+
let tabHeight = isEnabled && tabbarVisible && !isWebViewHostedInSystemTabController
|
|
2020
|
+
? (usesSystemTabbar ? nativeTabHeight : customTabHeight)
|
|
2021
|
+
: 0
|
|
1979
2022
|
return [
|
|
1980
2023
|
"top": navHeight,
|
|
1981
2024
|
"right": safeInsets.right,
|
|
@@ -2674,6 +2717,7 @@ final class NativeNavigationTabContentController: UIViewController {
|
|
|
2674
2717
|
let view = UIView()
|
|
2675
2718
|
view.backgroundColor = .systemBackground
|
|
2676
2719
|
view.isOpaque = true
|
|
2720
|
+
view.clipsToBounds = true
|
|
2677
2721
|
self.view = view
|
|
2678
2722
|
}
|
|
2679
2723
|
|
|
@@ -2714,7 +2758,8 @@ final class NativeNavigationTabContentController: UIViewController {
|
|
|
2714
2758
|
snapshotPlaceholder = nil
|
|
2715
2759
|
hostedWebView = webView
|
|
2716
2760
|
if webView.superview !== view {
|
|
2717
|
-
|
|
2761
|
+
// addSubview reparents in one step. removeFromSuperview() first
|
|
2762
|
+
// leaves a frame of this VC's backing colour (system white).
|
|
2718
2763
|
view.addSubview(webView)
|
|
2719
2764
|
}
|
|
2720
2765
|
webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capgo/capacitor-native-navigation",
|
|
3
|
-
"version": "8.4.
|
|
3
|
+
"version": "8.4.2",
|
|
4
4
|
"description": "Capacitor plugin for native navbar, tabbar, safe-area handling, and WebView snapshot transitions.",
|
|
5
5
|
"main": "dist/plugin.cjs.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|