Integrate CYLTabBar center scan button and unify UIKit navigation.
Add CYLTabBarController with a global scan entry, promote MainTabBarController to the window root after login, replace RouterPath-based navigation with AppNavigator, and fix Profile diffable cell reconfiguration crashes. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@ -65,51 +65,98 @@ final class PushNotificationTests: XCTestCase {
|
||||
}
|
||||
|
||||
func testPushManagerRoutesHomeDestinationsThroughHomeNavigationStack() {
|
||||
let router = AppRouter()
|
||||
let manager = pushManager(router: router)
|
||||
let services = AppServices(apiClient: APIClient(session: PushRecordingURLSession()))
|
||||
let host = PushNavigationHost(services: services)
|
||||
let manager = pushManager(navigator: services.appNavigator)
|
||||
services.appNavigator.attach(host: host)
|
||||
|
||||
manager.handleRemoteNotification(PushPayload(userInfo: ["route": "payment_qr"]))
|
||||
XCTAssertEqual(router.selectedTab, .home)
|
||||
XCTAssertEqual(router.router(for: .home).path, [.home(.paymentCollection)])
|
||||
XCTAssertEqual(host.selectedTab, .home)
|
||||
XCTAssertTrue(host.navigationController(for: .home)?.viewControllers.last is PaymentCollectionViewController)
|
||||
|
||||
router.router(for: .home).reset()
|
||||
manager.handleRemoteNotification(PushPayload(userInfo: ["route": "task_management"]))
|
||||
XCTAssertEqual(router.router(for: .home).path, [.home(.taskManagement)])
|
||||
XCTAssertTrue(host.navigationController(for: .home)?.viewControllers.last is TaskManagementViewController)
|
||||
XCTAssertEqual(host.navigationController(for: .home)?.viewControllers.count, 2)
|
||||
|
||||
router.router(for: .home).reset()
|
||||
manager.handleRemoteNotification(PushPayload(userInfo: ["uri": "/scenic-queue"]))
|
||||
XCTAssertEqual(router.router(for: .home).path, [.home(.queueManagement)])
|
||||
XCTAssertTrue(host.navigationController(for: .home)?.viewControllers.last is QueueManagementViewController)
|
||||
XCTAssertEqual(host.navigationController(for: .home)?.viewControllers.count, 2)
|
||||
|
||||
router.router(for: .home).reset()
|
||||
manager.handleRemoteNotification(PushPayload(userInfo: ["title": "未知通知"]))
|
||||
XCTAssertEqual(router.router(for: .home).path, [.home(.messageCenter)])
|
||||
XCTAssertTrue(host.navigationController(for: .home)?.viewControllers.last is MessageCenterViewController)
|
||||
XCTAssertEqual(host.navigationController(for: .home)?.viewControllers.count, 2)
|
||||
}
|
||||
|
||||
func testPushManagerRoutesOrdersEntry() {
|
||||
let router = AppRouter()
|
||||
let manager = pushManager(router: router)
|
||||
let services = AppServices(apiClient: APIClient(session: PushRecordingURLSession()))
|
||||
let host = PushNavigationHost(services: services)
|
||||
let manager = pushManager(navigator: services.appNavigator)
|
||||
services.appNavigator.attach(host: host)
|
||||
|
||||
manager.handleRemoteNotification(PushPayload(userInfo: ["route": "photographer_orders"]))
|
||||
XCTAssertEqual(router.selectedTab, .orders)
|
||||
XCTAssertEqual(router.selectedOrdersEntry, .storeOrders)
|
||||
XCTAssertEqual(host.selectedTab, .orders)
|
||||
XCTAssertEqual(host.appliedOrdersEntry, .storeOrders)
|
||||
|
||||
manager.handleRemoteNotification(PushPayload(userInfo: ["route": "verification_order"]))
|
||||
XCTAssertEqual(router.selectedTab, .orders)
|
||||
XCTAssertEqual(router.selectedOrdersEntry, .verificationOrders)
|
||||
XCTAssertEqual(host.selectedTab, .orders)
|
||||
XCTAssertEqual(host.appliedOrdersEntry, .verificationOrders)
|
||||
}
|
||||
|
||||
private func pushManager(router: AppRouter) -> PushNotificationManager {
|
||||
private func pushManager(navigator: AppNavigator) -> PushNotificationManager {
|
||||
let session = AppSession()
|
||||
let manager = PushNotificationManager()
|
||||
manager.configure(
|
||||
api: PushAPI(client: APIClient(session: PushRecordingURLSession())),
|
||||
session: session,
|
||||
router: router
|
||||
navigator: navigator
|
||||
)
|
||||
return manager
|
||||
}
|
||||
}
|
||||
|
||||
/// 推送路由单测专用导航宿主。
|
||||
@MainActor
|
||||
private final class PushNavigationHost: AppNavigationHost {
|
||||
private var controllers: [AppTab: TabNavigationController] = [:]
|
||||
var selectedTab: AppTab = .home
|
||||
var appliedOrdersEntry: OrdersEntry?
|
||||
|
||||
/// 初始化所有 Tab 导航栈。
|
||||
init(services: AppServices) {
|
||||
for tab in AppTab.allCases {
|
||||
controllers[tab] = TabNavigationController(tab: tab, services: services)
|
||||
}
|
||||
}
|
||||
|
||||
/// 选中指定主 Tab。
|
||||
func selectTab(_ tab: AppTab) {
|
||||
selectedTab = tab
|
||||
}
|
||||
|
||||
/// 返回指定 Tab 的导航控制器。
|
||||
func navigationController(for tab: AppTab) -> TabNavigationController? {
|
||||
controllers[tab]
|
||||
}
|
||||
|
||||
/// 返回当前选中 Tab 的导航控制器。
|
||||
func selectedNavigationController() -> TabNavigationController? {
|
||||
controllers[selectedTab]
|
||||
}
|
||||
|
||||
/// 重置全部 Tab 导航栈。
|
||||
func resetAllStacks() {
|
||||
for controller in controllers.values {
|
||||
controller.popToRootViewController(animated: false)
|
||||
}
|
||||
selectedTab = .home
|
||||
}
|
||||
|
||||
/// 记录订单入口状态。
|
||||
func applyOrdersEntry(_ entry: OrdersEntry, scannedCode: String?) {
|
||||
appliedOrdersEntry = entry
|
||||
}
|
||||
}
|
||||
|
||||
private final class PushRecordingURLSession: URLSessionProtocol {
|
||||
private(set) var requests: [URLRequest] = []
|
||||
|
||||
|
||||
Reference in New Issue
Block a user