| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- //
- // ConferenceRoute.swift
- // TUIRoomKit
- //
- // Created by aby on 2024/6/19.
- //
- import Combine
- protocol Route: ActionDispatcher {
- func initializeRoute(viewController: UIViewController, rootRoute: ConferenceRoute)
- func uninitialize()
- func pushTo(route: ConferenceRoute)
- func present(route: ConferenceRoute)
- func dismiss(animated: Bool)
- func pop()
- func popTo(route: ConferenceRoute)
- func pop(route: ConferenceRoute)
- func showContactView(delegate: ContactViewSelectDelegate, participants: ConferenceParticipants)
- }
- private let currentRouteActionSelector = Selector(keyPath: \ConferenceRouteState.currentRouteAction)
- class ConferenceRouter: NSObject {
- override init() {
- super.init()
- }
- // MARK: - private property.
- private var cancellableSet = Set<AnyCancellable>()
- private weak var navigationController: UINavigationController?
- private weak var rootViewController: UIViewController?
- private weak var navigationControllerDelegate: UINavigationControllerDelegate?
- private let store: Store<ConferenceRouteState, Void> = {
- let store = Store.init(initialState: ConferenceRouteState(), reducers: [routeReducer])
- #if DEBUG
- store.register(interceptor: PrintRouteInterceptor())
- #endif
- return store
- }()
- }
- extension ConferenceRouter: Route {
-
- func initializeRoute(viewController: UIViewController, rootRoute: ConferenceRoute) {
- guard self.rootViewController == nil else { return }
- self.rootViewController = viewController
- if let nav = viewController.navigationController {
- self.navigationController = nav
- if nav.delegate == nil {
- nav.delegate = self
- } else {
- self.navigationControllerDelegate = nav.delegate
- nav.delegate = self
- }
- } else {
- let navigationController = UINavigationController.init(rootViewController: viewController)
- self.navigationController = navigationController
- }
- store.dispatch(action: ConferenceNavigationAction.navigate(payload: ConferenceNavigation.presented(route: rootRoute)))
- let navigationPublisher = store.select(currentRouteActionSelector)
- subscribe(to: navigationPublisher)
- }
-
- func pushTo(route: ConferenceRoute) {
- store.dispatch(action: ConferenceNavigationAction.navigate(payload: .push(route: route)))
- }
-
- func present(route: ConferenceRoute) {
- store.dispatch(action: ConferenceNavigationAction.navigate(payload: .present(route: route)))
- }
-
- func dismiss(animated: Bool) {
- guard let viewController = self.navigationController?.topViewController ?? self.navigationController else { return }
- if let presentedViewController = viewController.presentedViewController {
- presentedViewController.dismiss(animated: animated) {
- [weak self] in
- guard let self = self else { return }
- if let rootVC = self.rootViewController {
- let viewRoute = ConferenceRoute.init(viewController: rootVC)
- self.store.dispatch(action: ConferenceNavigationAction.navigate(payload: ConferenceNavigation.presented(route: viewRoute)))
- }
- }
- }
- }
-
- func pop() {
- self.navigationController?.popViewController(animated: true)
- }
-
- func popTo(route: ConferenceRoute) {
- guard let viewControllers = self.navigationController?.viewControllers else { return }
- if let targetVC = viewControllers.first(where: { viewController in
- let iterateRoute = ConferenceRoute(viewController: viewController)
- return iterateRoute == route
- }) {
- self.navigationController?.popToViewController(targetVC, animated: false)
- }
- }
-
- func pop(route: ConferenceRoute) {
- guard var viewControllers = self.navigationController?.viewControllers else { return }
- if let index = viewControllers.firstIndex(where: { viewController in
- let iterateRoute = ConferenceRoute(viewController: viewController)
- return iterateRoute == route
- }) {
- viewControllers.remove(at: index)
- self.navigationController?.viewControllers = viewControllers
- }
- }
-
- func uninitialize() {
- if let delegate = self.navigationControllerDelegate {
- self.navigationController?.delegate = delegate
- }
- }
-
- func showContactView(delegate: ContactViewSelectDelegate, participants: ConferenceParticipants) {
- let selectParams = MemberSelectParams(participants: participants, delegate: delegate)
- store.dispatch(action: ConferenceNavigationAction.navigate(payload: .push(route: .selectMember(memberSelectParams: selectParams))))
- RoomKitReport.reportData(.metricsConferenceAttendee)
- }
-
- func dispatch(action: Action) {
- store.dispatch(action: action)
- }
- }
- extension ConferenceRouter {
- var viewController: UIViewController? {
- return navigationController ?? rootViewController
- }
- }
- extension ConferenceRouter {
- private func subscribe(to navigationPublisher: AnyPublisher<ConferenceNavigation, Never>) {
- navigationPublisher
- .receive(on: RunLoop.main)
- .removeDuplicates()
- .sink { [weak self] action in
- guard let self = self else { return }
- self.respond(to: action)
- }
- .store(in: &cancellableSet)
- }
-
- private func respond(to action: ConferenceNavigation) {
- switch action {
- case let .present(route: route):
- present(viewRoute: route)
- case let .push(route: route):
- push(viewRoute: route)
- case .presented:
- break
- }
- }
-
- private func present(viewRoute: ConferenceRoute) {
- guard let viewController = self.navigationController?.topViewController ?? self.navigationController else { return }
- if viewController.presentedViewController != nil {
- self.dismiss(animated: false)
- }
- var animated: Bool = true
- if case .invitation = viewRoute {
- animated = false
- }
- viewController.present(viewRoute.viewController, animated: animated) { [weak self] in
- guard let self = self else { return }
- self.store.dispatch(action: ConferenceNavigationAction.navigate(payload: ConferenceNavigation.presented(route: viewRoute)))
- }
- }
-
- private func push(viewRoute: ConferenceRoute) {
- guard let navigationController = self.navigationController else { return }
- navigationController.pushViewController(viewRoute.viewController, animated: true)
- }
- }
- extension ConferenceRouter {
- func toggleNavigationBar(for view: ConferenceRoute, animated: Bool, navigationController: UINavigationController) {
- if view.hideNavigationBar() {
- hideNavigationBar(navigationController: navigationController, animated: animated)
- }
- else {
- showNavigationBar(navigationController: navigationController, animated: animated)
- }
- }
-
- func hideNavigationBar(navigationController: UINavigationController, animated: Bool) {
- if animated {
- navigationController.transitionCoordinator?.animate(alongsideTransition: {
- context in
- navigationController.setNavigationBarHidden(true, animated: true)
- })
- }
- else {
- navigationController.setNavigationBarHidden(true, animated: false)
- }
- }
-
- func showNavigationBar(navigationController: UINavigationController, animated: Bool) {
- if navigationController.isNavigationBarHidden {
- if animated {
- navigationController.transitionCoordinator?.animate(alongsideTransition: {
- context in
- navigationController.setNavigationBarHidden(false, animated: true)
- })
- }
- else {
- navigationController.setNavigationBarHidden(false, animated: false)
- }
- }
- }
- }
- extension ConferenceRouter: UINavigationControllerDelegate {
- /// Animate the navigation bar display with view controller transition.
- func navigationController(
- _ navigationController: UINavigationController,
- willShow viewController: UIViewController,
- animated: Bool) {
- let destRoute = ConferenceRoute.init(viewController: viewController)
- guard destRoute != .none else { return }
- toggleNavigationBar(for: destRoute, animated: animated, navigationController: navigationController)
- }
-
- /// Trigger a `ConferenceNavigationAction` event according to the destination view type.
- func navigationController(
- _ navigationController: UINavigationController,
- didShow viewController: UIViewController,
- animated: Bool) {
- let destRoute = ConferenceRoute.init(viewController: viewController)
- guard destRoute != .none else { return }
- self.store.dispatch(action: ConferenceNavigationAction.navigate(payload: ConferenceNavigation.presented(route: destRoute)))
- }
- }
|