@capgo/capacitor-native-navigation 8.0.11 → 8.0.13
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
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# @capgo/capacitor-native-navigation
|
|
2
|
-
<a href="https://capgo.app/"><img src="https://
|
|
2
|
+
<a href="https://capgo.app/"><img src="https://capgo.app/readme-banner.svg?repo=Cap-go/capacitor-native-navigation" alt="Capgo - Instant updates for Capacitor" /></a>
|
|
3
3
|
|
|
4
4
|
<div align="center">
|
|
5
5
|
<h2><a href="https://capgo.app/?ref=plugin_native_navigation">Get instant updates for your app with Capgo</a></h2>
|
|
@@ -44,6 +44,10 @@ public class NativeNavigationPlugin: CAPPlugin, CAPBridgedPlugin, UITabBarContro
|
|
|
44
44
|
private var tabBar: UITabBar?
|
|
45
45
|
private var tabBarController: NativeNavigationTabController?
|
|
46
46
|
private var tabViewControllers: [UIViewController] = []
|
|
47
|
+
private weak var originalWebViewSuperview: UIView?
|
|
48
|
+
private var originalWebViewIndex: Int?
|
|
49
|
+
private var originalWebViewAutoresizingMask: UIView.AutoresizingMask?
|
|
50
|
+
private var isWebViewHostedInSystemTabController = false
|
|
47
51
|
private var navbarHeight: CGFloat = 44
|
|
48
52
|
private var tabbarHeight: CGFloat = 64
|
|
49
53
|
private let floatingTabbarHorizontalMargin: CGFloat = 24
|
|
@@ -96,6 +100,7 @@ public class NativeNavigationPlugin: CAPPlugin, CAPBridgedPlugin, UITabBarContro
|
|
|
96
100
|
if !self.isEnabled {
|
|
97
101
|
self.navContainer?.isHidden = true
|
|
98
102
|
self.tabContainer?.isHidden = true
|
|
103
|
+
self.restoreWebViewFromSystemTabController()
|
|
99
104
|
self.tabBarController?.view.isHidden = true
|
|
100
105
|
self.tabBar?.isHidden = true
|
|
101
106
|
}
|
|
@@ -170,9 +175,7 @@ public class NativeNavigationPlugin: CAPPlugin, CAPBridgedPlugin, UITabBarContro
|
|
|
170
175
|
self.tabbarVisible = !hidden
|
|
171
176
|
|
|
172
177
|
guard !hidden else {
|
|
173
|
-
self.
|
|
174
|
-
self.tabBarController?.view.isHidden = true
|
|
175
|
-
self.tabBar?.isHidden = true
|
|
178
|
+
self.hideTabBarChrome()
|
|
176
179
|
self.updateInsetsAndNotify()
|
|
177
180
|
call.resolve(self.insetsResult())
|
|
178
181
|
return
|
|
@@ -204,9 +207,7 @@ public class NativeNavigationPlugin: CAPPlugin, CAPBridgedPlugin, UITabBarContro
|
|
|
204
207
|
}
|
|
205
208
|
|
|
206
209
|
self.applyTabBarAppearance(tabBar: tabBar, options: call)
|
|
207
|
-
self.
|
|
208
|
-
self.tabBarController?.view.isHidden = false
|
|
209
|
-
tabBar.isHidden = false
|
|
210
|
+
self.showTabBarChrome(tabBar)
|
|
210
211
|
self.layoutChrome()
|
|
211
212
|
self.updateInsetsAndNotify()
|
|
212
213
|
call.resolve(self.insetsResult())
|
|
@@ -215,7 +216,8 @@ public class NativeNavigationPlugin: CAPPlugin, CAPBridgedPlugin, UITabBarContro
|
|
|
215
216
|
|
|
216
217
|
@objc func beginTransition(_ call: CAPPluginCall) {
|
|
217
218
|
DispatchQueue.main.async {
|
|
218
|
-
guard let webView = self.webView,
|
|
219
|
+
guard let webView = self.webView,
|
|
220
|
+
let transitionContainer = webView.superview else {
|
|
219
221
|
call.reject("WebView unavailable")
|
|
220
222
|
return
|
|
221
223
|
}
|
|
@@ -224,7 +226,7 @@ public class NativeNavigationPlugin: CAPPlugin, CAPBridgedPlugin, UITabBarContro
|
|
|
224
226
|
let direction = call.getString("direction") ?? "forward"
|
|
225
227
|
let durationMs = Int((call.getDouble("duration") ?? self.defaultTransitionDuration * 1_000).rounded())
|
|
226
228
|
let zoomSourceRect = direction == "zoom" ? self.transitionRect(call.getObject("sourceRect")) : nil
|
|
227
|
-
let zoomSourceFrame = zoomSourceRect.map { self.
|
|
229
|
+
let zoomSourceFrame = zoomSourceRect.map { self.transitionFrame(for: $0, webView: webView) }
|
|
228
230
|
let cornerRadius = CGFloat(call.getDouble("cornerRadius") ?? 0)
|
|
229
231
|
|
|
230
232
|
self.transitionSnapshot?.removeFromSuperview()
|
|
@@ -233,7 +235,7 @@ public class NativeNavigationPlugin: CAPPlugin, CAPBridgedPlugin, UITabBarContro
|
|
|
233
235
|
snapshot.autoresizingMask = zoomSourceFrame == nil ? [.flexibleWidth, .flexibleHeight] : []
|
|
234
236
|
snapshot.layer.cornerRadius = cornerRadius
|
|
235
237
|
snapshot.clipsToBounds = cornerRadius > 0
|
|
236
|
-
|
|
238
|
+
transitionContainer.insertSubview(snapshot, aboveSubview: webView)
|
|
237
239
|
self.bringChromeToFront()
|
|
238
240
|
self.transitionSnapshot = snapshot
|
|
239
241
|
self.activeTransitionId = transitionId
|
|
@@ -274,8 +276,8 @@ public class NativeNavigationPlugin: CAPPlugin, CAPBridgedPlugin, UITabBarContro
|
|
|
274
276
|
let targetRect = self.transitionRect(call.getObject("targetRect"))
|
|
275
277
|
self.finishZoomTransition(NativeNavigationZoomTransitionContext(
|
|
276
278
|
transition: transition,
|
|
277
|
-
sourceFrame: sourceRect.map { self.
|
|
278
|
-
targetFrame: targetRect.map { self.
|
|
279
|
+
sourceFrame: sourceRect.map { self.transitionFrame(for: $0, webView: webView) },
|
|
280
|
+
targetFrame: targetRect.map { self.transitionFrame(for: $0, webView: webView) },
|
|
279
281
|
cornerRadius: CGFloat(call.getDouble("cornerRadius") ?? Double(self.activeZoomCornerRadius))
|
|
280
282
|
))
|
|
281
283
|
return
|
|
@@ -437,9 +439,11 @@ public class NativeNavigationPlugin: CAPPlugin, CAPBridgedPlugin, UITabBarContro
|
|
|
437
439
|
|
|
438
440
|
public func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
|
|
439
441
|
guard !suppressTabSelectEvent else {
|
|
442
|
+
hostWebViewInSelectedSystemTab()
|
|
440
443
|
return
|
|
441
444
|
}
|
|
442
445
|
let index = tabBarController.viewControllers?.firstIndex(of: viewController) ?? viewController.tabBarItem.tag
|
|
446
|
+
hostWebViewInSelectedSystemTab()
|
|
443
447
|
notifyTabSelect(index: index)
|
|
444
448
|
}
|
|
445
449
|
|
|
@@ -538,6 +542,7 @@ public class NativeNavigationPlugin: CAPPlugin, CAPBridgedPlugin, UITabBarContro
|
|
|
538
542
|
|
|
539
543
|
private func ensureSystemTabBar() -> UITabBar {
|
|
540
544
|
if let tabBarController = tabBarController {
|
|
545
|
+
hostWebViewInSelectedSystemTab()
|
|
541
546
|
return tabBarController.tabBar
|
|
542
547
|
}
|
|
543
548
|
|
|
@@ -554,6 +559,7 @@ public class NativeNavigationPlugin: CAPPlugin, CAPBridgedPlugin, UITabBarContro
|
|
|
554
559
|
|
|
555
560
|
self.tabBarController = controller
|
|
556
561
|
self.tabBar = controller.tabBar
|
|
562
|
+
hostWebViewInSelectedSystemTab()
|
|
557
563
|
return controller.tabBar
|
|
558
564
|
}
|
|
559
565
|
|
|
@@ -577,11 +583,93 @@ public class NativeNavigationPlugin: CAPPlugin, CAPBridgedPlugin, UITabBarContro
|
|
|
577
583
|
let index = min(max(fallbackIndex, 0), controllers.count - 1)
|
|
578
584
|
tabBarController.selectedIndex = index
|
|
579
585
|
}
|
|
586
|
+
hostWebViewInSelectedSystemTab()
|
|
580
587
|
suppressTabSelectEvent = false
|
|
581
588
|
|
|
582
589
|
tabViewControllers = controllers
|
|
583
590
|
}
|
|
584
591
|
|
|
592
|
+
private func setSystemTabBarHidden(_ hidden: Bool) {
|
|
593
|
+
guard let tabBarController = tabBarController else {
|
|
594
|
+
return
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
if #available(iOS 18.0, *) {
|
|
598
|
+
tabBarController.setTabBarHidden(hidden, animated: false)
|
|
599
|
+
} else {
|
|
600
|
+
tabBarController.tabBar.isHidden = hidden
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
private func hideTabBarChrome() {
|
|
605
|
+
if usesSystemLiquidGlass {
|
|
606
|
+
setSystemTabBarHidden(true)
|
|
607
|
+
tabBarController?.view.isHidden = false
|
|
608
|
+
hostWebViewInSelectedSystemTab()
|
|
609
|
+
} else {
|
|
610
|
+
tabContainer?.isHidden = true
|
|
611
|
+
tabBar?.isHidden = true
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
private func showTabBarChrome(_ tabBar: UITabBar) {
|
|
616
|
+
tabContainer?.isHidden = false
|
|
617
|
+
tabBarController?.view.isHidden = false
|
|
618
|
+
if usesSystemLiquidGlass {
|
|
619
|
+
setSystemTabBarHidden(false)
|
|
620
|
+
hostWebViewInSelectedSystemTab()
|
|
621
|
+
} else {
|
|
622
|
+
tabBar.isHidden = false
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
private func captureOriginalWebViewPlacementIfNeeded(_ webView: UIView) {
|
|
627
|
+
guard originalWebViewSuperview == nil, let superview = webView.superview else {
|
|
628
|
+
return
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
originalWebViewSuperview = superview
|
|
632
|
+
originalWebViewIndex = superview.subviews.firstIndex(of: webView)
|
|
633
|
+
originalWebViewAutoresizingMask = webView.autoresizingMask
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
private func hostWebViewInSelectedSystemTab() {
|
|
637
|
+
guard usesSystemLiquidGlass,
|
|
638
|
+
let webView = webView,
|
|
639
|
+
let selectedController = tabBarController?.selectedViewController as? NativeNavigationTabContentController else {
|
|
640
|
+
return
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
captureOriginalWebViewPlacementIfNeeded(webView)
|
|
644
|
+
clearHostedWebViews(matching: webView, except: selectedController)
|
|
645
|
+
selectedController.host(webView: webView)
|
|
646
|
+
clearHostedWebViews(matching: webView, except: selectedController)
|
|
647
|
+
isWebViewHostedInSystemTabController = true
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
private func restoreWebViewFromSystemTabController() {
|
|
651
|
+
guard isWebViewHostedInSystemTabController,
|
|
652
|
+
let webView = webView,
|
|
653
|
+
let targetSuperview = originalWebViewSuperview ?? bridge?.viewController?.view else {
|
|
654
|
+
return
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
let insertionIndex = min(originalWebViewIndex ?? targetSuperview.subviews.count, targetSuperview.subviews.count)
|
|
658
|
+
clearHostedWebViews(matching: webView)
|
|
659
|
+
webView.removeFromSuperview()
|
|
660
|
+
targetSuperview.insertSubview(webView, at: insertionIndex)
|
|
661
|
+
webView.autoresizingMask = originalWebViewAutoresizingMask ?? [.flexibleWidth, .flexibleHeight]
|
|
662
|
+
webView.frame = targetSuperview.bounds
|
|
663
|
+
isWebViewHostedInSystemTabController = false
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
private func clearHostedWebViews(matching webView: UIView, except owner: NativeNavigationTabContentController? = nil) {
|
|
667
|
+
tabViewControllers
|
|
668
|
+
.compactMap { $0 as? NativeNavigationTabContentController }
|
|
669
|
+
.filter { $0 !== owner }
|
|
670
|
+
.forEach { $0.clearHostedWebView(ifMatching: webView) }
|
|
671
|
+
}
|
|
672
|
+
|
|
585
673
|
private func makeBarButtonItems(_ rawItems: [[String: Any]], placement: String) -> [UIBarButtonItem] {
|
|
586
674
|
return rawItems.map { rawItem in
|
|
587
675
|
let id = rawItem["id"] as? String ?? UUID().uuidString
|
|
@@ -761,13 +849,16 @@ public class NativeNavigationPlugin: CAPPlugin, CAPBridgedPlugin, UITabBarContro
|
|
|
761
849
|
)
|
|
762
850
|
}
|
|
763
851
|
|
|
764
|
-
private func
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
852
|
+
private func transitionFrame(for viewportRect: CGRect, webView: UIView) -> CGRect {
|
|
853
|
+
guard let transitionContainer = webView.superview else {
|
|
854
|
+
return CGRect(
|
|
855
|
+
x: webView.frame.minX + viewportRect.minX,
|
|
856
|
+
y: webView.frame.minY + viewportRect.minY,
|
|
857
|
+
width: viewportRect.width,
|
|
858
|
+
height: viewportRect.height
|
|
859
|
+
)
|
|
860
|
+
}
|
|
861
|
+
return webView.convert(viewportRect, to: transitionContainer)
|
|
771
862
|
}
|
|
772
863
|
|
|
773
864
|
private func transitionSnapshotView(from webView: UIView, sourceRect: CGRect?) -> UIView {
|
|
@@ -1010,6 +1101,13 @@ public class NativeNavigationPlugin: CAPPlugin, CAPBridgedPlugin, UITabBarContro
|
|
|
1010
1101
|
}
|
|
1011
1102
|
|
|
1012
1103
|
private func bringChromeToFront() {
|
|
1104
|
+
if usesSystemLiquidGlass {
|
|
1105
|
+
if let navContainer = navContainer {
|
|
1106
|
+
bridge?.viewController?.view.bringSubviewToFront(navContainer)
|
|
1107
|
+
}
|
|
1108
|
+
return
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1013
1111
|
if let navContainer = navContainer {
|
|
1014
1112
|
bridge?.viewController?.view.bringSubviewToFront(navContainer)
|
|
1015
1113
|
}
|
|
@@ -1233,41 +1331,51 @@ private final class NativeNavigationBar: UINavigationBar {
|
|
|
1233
1331
|
}
|
|
1234
1332
|
|
|
1235
1333
|
private final class NativeNavigationTabController: UITabBarController {
|
|
1236
|
-
override func loadView() {
|
|
1237
|
-
let view = NativeNavigationTabControllerView()
|
|
1238
|
-
view.backgroundColor = .clear
|
|
1239
|
-
view.isOpaque = false
|
|
1240
|
-
self.view = view
|
|
1241
|
-
}
|
|
1242
|
-
|
|
1243
1334
|
override func viewDidLoad() {
|
|
1244
1335
|
super.viewDidLoad()
|
|
1245
1336
|
view.backgroundColor = .clear
|
|
1246
1337
|
view.isOpaque = false
|
|
1247
1338
|
tabBar.isTranslucent = true
|
|
1248
|
-
(view as? NativeNavigationTabControllerView)?.tabBar = tabBar
|
|
1249
|
-
}
|
|
1250
|
-
}
|
|
1251
|
-
|
|
1252
|
-
private final class NativeNavigationTabControllerView: UIView {
|
|
1253
|
-
weak var tabBar: UITabBar?
|
|
1254
|
-
|
|
1255
|
-
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
|
|
1256
|
-
guard let tabBar = tabBar, !tabBar.isHidden, tabBar.alpha > 0.01 else {
|
|
1257
|
-
return false
|
|
1258
|
-
}
|
|
1259
|
-
let tabPoint = convert(point, to: tabBar)
|
|
1260
|
-
return tabBar.point(inside: tabPoint, with: event)
|
|
1261
1339
|
}
|
|
1262
1340
|
}
|
|
1263
1341
|
|
|
1264
1342
|
private final class NativeNavigationTabContentController: UIViewController {
|
|
1343
|
+
private weak var hostedWebView: UIView?
|
|
1344
|
+
|
|
1265
1345
|
override func loadView() {
|
|
1266
1346
|
let view = UIView()
|
|
1267
1347
|
view.backgroundColor = .clear
|
|
1268
1348
|
view.isOpaque = false
|
|
1269
1349
|
self.view = view
|
|
1270
1350
|
}
|
|
1351
|
+
|
|
1352
|
+
override func viewDidLayoutSubviews() {
|
|
1353
|
+
super.viewDidLayoutSubviews()
|
|
1354
|
+
guard hostedWebView?.superview === view else {
|
|
1355
|
+
hostedWebView = nil
|
|
1356
|
+
return
|
|
1357
|
+
}
|
|
1358
|
+
hostedWebView?.frame = view.bounds
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
func clearHostedWebView(ifMatching webView: UIView? = nil) {
|
|
1362
|
+
guard webView == nil || hostedWebView === webView else {
|
|
1363
|
+
return
|
|
1364
|
+
}
|
|
1365
|
+
hostedWebView = nil
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
func host(webView: UIView) {
|
|
1369
|
+
if hostedWebView !== webView {
|
|
1370
|
+
hostedWebView = webView
|
|
1371
|
+
}
|
|
1372
|
+
if webView.superview !== view {
|
|
1373
|
+
webView.removeFromSuperview()
|
|
1374
|
+
view.addSubview(webView)
|
|
1375
|
+
}
|
|
1376
|
+
webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
|
1377
|
+
webView.frame = view.bounds
|
|
1378
|
+
}
|
|
1271
1379
|
}
|
|
1272
1380
|
|
|
1273
1381
|
private final class SVGIconRenderer: NSObject, XMLParserDelegate {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capgo/capacitor-native-navigation",
|
|
3
|
-
"version": "8.0.
|
|
3
|
+
"version": "8.0.13",
|
|
4
4
|
"description": "Capacitor plugin for native navbar, tabbar, and route transition chrome over a WebView.",
|
|
5
5
|
"main": "dist/plugin.cjs.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|