From efd9380f228ae5bddde41d71f0e9ba6b2ae1a6b1 Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Tue, 19 May 2026 00:12:24 +0800 Subject: [PATCH] fix: path bookkeeping --- ios/App/App/AppDelegate.swift | 19 +++++++++++++++---- ios/App/App/LiquidTabsPlugin.swift | 4 ++-- ios/App/App/LiquidTabsRootView.swift | 4 ++-- ios/App/App/SharedWebViewController.swift | 2 +- src/main/mobile/bottom_tabs.cljs | 4 ++-- 5 files changed, 22 insertions(+), 11 deletions(-) diff --git a/ios/App/App/AppDelegate.swift b/ios/App/App/AppDelegate.swift index 26634a85d0..cdab90892f 100644 --- a/ios/App/App/AppDelegate.swift +++ b/ios/App/App/AppDelegate.swift @@ -34,6 +34,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UINavigationControllerDel // Each stack has its own native VC stack, just like paths. private var stackViewControllerStacks: [String: [UIViewController]] = [:] + private var routeChangeObserver: NSObjectProtocol? + // --------------------------------------------------------- // MARK: Helpers // --------------------------------------------------------- @@ -278,9 +280,14 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UINavigationControllerDel // ----------------------------- let previousStack = pathStack - if pathStack.count > 1 { + if let to = toIndex { + pathStack = Array(pathStack.prefix(to + 1)) + } else if pathStack.count > 1 { _ = pathStack.popLast() } + if pathStack.isEmpty { + pathStack = [toVC.targetPath] + } if let last = pathStack.last, last != toVC.targetPath { pathStack[pathStack.count - 1] = toVC.targetPath } @@ -382,7 +389,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UINavigationControllerDel // --------------------------------------------------------- private func observeRouteChanges() { - NotificationCenter.default.addObserver( + if routeChangeObserver != nil { + return + } + + routeChangeObserver = NotificationCenter.default.addObserver( forName: UILocalPlugin.routeChangeNotification, object: nil, queue: .main @@ -417,8 +428,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UINavigationControllerDel let vc = NativePageViewController(path: "/") nav.setViewControllers([vc], animated: false) self.setViewControllers([vc], for: "home") - - // 👈 Do NOTHING to nav.viewControllers or SharedWebViewController here. + SharedWebViewController.instance.clearPlaceholder() + SharedWebViewController.instance.attach(to: vc) return } diff --git a/ios/App/App/LiquidTabsPlugin.swift b/ios/App/App/LiquidTabsPlugin.swift index 71ada8bc0f..576cc8ecc6 100644 --- a/ios/App/App/LiquidTabsPlugin.swift +++ b/ios/App/App/LiquidTabsPlugin.swift @@ -107,8 +107,8 @@ public class LiquidTabsPlugin: CAPPlugin, CAPBridgedPlugin { // MARK: - Events to JS - func notifyTabSelected(id: String) { - notifyListeners("tabSelected", data: ["id": id]) + func notifyTabSelected(id: String, reselected: Bool = false) { + notifyListeners("tabSelected", data: ["id": id, "reselected": reselected]) } func notifySearchChanged(query: String) { diff --git a/ios/App/App/LiquidTabsRootView.swift b/ios/App/App/LiquidTabsRootView.swift index 2fdce3a820..1a038d4795 100644 --- a/ios/App/App/LiquidTabsRootView.swift +++ b/ios/App/App/LiquidTabsRootView.swift @@ -146,7 +146,7 @@ private struct LiquidTabs26View: View { navController.popToRootViewController(animated: true) if let id = store.tabId(for: selection) { - LiquidTabsPlugin.shared?.notifyTabSelected(id: id) + LiquidTabsPlugin.shared?.notifyTabSelected(id: id, reselected: true) } } @@ -386,7 +386,7 @@ private struct LiquidTabs16View: View { // Re-tap: pop to root if id == store.selectedId { navController.popToRootViewController(animated: true) - LiquidTabsPlugin.shared?.notifyTabSelected(id: id) + LiquidTabsPlugin.shared?.notifyTabSelected(id: id, reselected: true) } else { store.selectedId = id LiquidTabsPlugin.shared?.notifyTabSelected(id: id) diff --git a/ios/App/App/SharedWebViewController.swift b/ios/App/App/SharedWebViewController.swift index f7637abb9e..fcdb2533a0 100644 --- a/ios/App/App/SharedWebViewController.swift +++ b/ios/App/App/SharedWebViewController.swift @@ -49,7 +49,7 @@ import Capacitor } // 2) Detach from previous parent - if let previous = currentParent { + if let previous = vc.parent { vc.willMove(toParent: nil) vc.view.removeFromSuperview() vc.removeFromParent() diff --git a/src/main/mobile/bottom_tabs.cljs b/src/main/mobile/bottom_tabs.cljs index 7f4e49bede..2adf5c2824 100644 --- a/src/main/mobile/bottom_tabs.cljs +++ b/src/main/mobile/bottom_tabs.cljs @@ -82,7 +82,7 @@ (fn [data] (when-let [id (.-id data)] (when-not (string/blank? id) - (route-handler/redirect-to-page! id {:push (mobile-util/native-android?)}))))))) + (route-handler/redirect-to-page! id {:push (mobile-util/native-platform?)}))))))) (defn add-keyboard-hack-listener! "Listen for Backspace or Enter while the invisible keyboard field is focused." @@ -112,7 +112,7 @@ (cond reselected? (do - (when (mobile-util/native-android?) + (when (mobile-util/native-platform?) (mobile-nav/pop-to-root! tab)) (mobile-state/set-tab! tab) (when (= "home" tab)