Переглянути джерело

Add Three tabs implementation into the example application

Pavel Yurchenko 1 рік тому
батько
коміт
6ed81864a9

+ 16 - 18
CoordinatorSUIExamples/CoordinatorSUIExamples/Application/ApplicationCoordinator.swift

@@ -8,28 +8,26 @@
 import CoordinatorSUI
 import SwiftUI
 
-final class ApplicationCoordinator: BaseCoordinator {
+enum ApplicationTab: String {
+    case main = "Main"
+    case products = "Products"
+    case feedback = "Feedback"
+}
 
-    func run() -> some View {
-        runMainFlow()
-    }
+final class ApplicationCoordinator: BaseCoordinator, ObservableObject {
 
-    func buildDestination(_ route: Route) -> some View {
-        guard let coordinator = currentCoordinator as? MainCoordinator else {
-            fatalError("Invalid coordinator type")
-        }
-        return coordinator.buildDestination(route)
-    }
+    @Published
+    var tabSelection: ApplicationTab = .main
 
-    // MARK: - Private methods
+    let mainCoordinator = MainCoordinator()
+    let productsCoordinator = ProductsCoordinator()
+    let feedbackCoordinator = FeedbackCoordinator()
 
-    private func runMainFlow() -> some View {
-        let coordinator = MainCoordinator(router: self.currentRouter)
-        addChild(coordinator)
-        coordinator.finishFlow = { [weak self] in
-            self?.removeChild(coordinator)
-        }
-        return coordinator.run()
+    override init() {
+        super.init()
+        addChild(mainCoordinator)
+        addChild(productsCoordinator)
+        addChild(feedbackCoordinator)
     }
 }
 

+ 34 - 8
CoordinatorSUIExamples/CoordinatorSUIExamples/Application/SUIExamplesApp.swift

@@ -13,17 +13,43 @@ struct SUIExamplesApp: App {
 
     static let applicationCoordinator = ApplicationCoordinator()
 
-    private let coordinator = applicationCoordinator
-    @StateObject private var router: Router = applicationCoordinator.currentRouter
+    @StateObject private var mainRouter: Router = applicationCoordinator.mainCoordinator.currentRouter
+    @StateObject private var productsRouter: Router = applicationCoordinator.productsCoordinator.currentRouter
+    @StateObject private var feedbackRouter: Router = applicationCoordinator.feedbackCoordinator.currentRouter
+    @StateObject private var appCoordinator = applicationCoordinator
 
     var body: some Scene {
         WindowGroup {
-            NavigationStack(path: $router.path) {
-                coordinator.run()
-                .navigationDestination(
-                    for: Route.self,
-                    destination: coordinator.buildDestination
-                )
+            TabView(selection: $appCoordinator.tabSelection) {
+                Tab(ApplicationTab.main.rawValue, systemImage: "tray.and.arrow.down.fill", value: ApplicationTab.main) {
+                    NavigationStack(path: $mainRouter.path) {
+                        appCoordinator.mainCoordinator.run()
+                        .navigationDestination(
+                            for: Route.self,
+                            destination: appCoordinator.mainCoordinator.buildDestination
+                        )
+                    }
+                }
+
+                Tab(ApplicationTab.products.rawValue, systemImage: "tray.and.arrow.down.fill", value: ApplicationTab.products) {
+                    NavigationStack(path: $productsRouter.path) {
+                        appCoordinator.productsCoordinator.run()
+                        .navigationDestination(
+                            for: Route.self,
+                            destination: appCoordinator.productsCoordinator.buildDestination
+                        )
+                    }
+                }
+
+                Tab(ApplicationTab.feedback.rawValue, systemImage: "tray.and.arrow.down.fill", value: ApplicationTab.feedback) {
+                    NavigationStack(path: $feedbackRouter.path) {
+                        appCoordinator.feedbackCoordinator.run()
+                        .navigationDestination(
+                            for: Route.self,
+                            destination: appCoordinator.feedbackCoordinator.buildDestination
+                        )
+                    }
+                }
             }
         }
     }

+ 27 - 0
CoordinatorSUIExamples/CoordinatorSUIExamples/Flows/Tabs/FeedbackCoordinator.swift

@@ -0,0 +1,27 @@
+//
+//  FeedbackCoordinator.swift
+//  CoordinatorSUIExamples
+//
+//  Created by Pavel Yurchenko on 03.12.2024.
+//
+
+import CoordinatorSUI
+import SwiftUI
+
+final class FeedbackCoordinator: BaseCoordinator {
+
+    func run() -> some View {
+        showFeedbackModule()
+    }
+
+    @ViewBuilder
+    func buildDestination(_ route: Route) -> some View {
+        fatalError("This should not happen!")
+    }
+
+    // MARK: - Private methods
+
+    private func showFeedbackModule() -> some View {
+        FeedbackBuilder().build(with: .init())
+    }
+}

+ 0 - 5
CoordinatorSUIExamples/CoordinatorSUIExamples/Flows/MainCoordinator.swift → CoordinatorSUIExamples/CoordinatorSUIExamples/Flows/Tabs/MainCoordinator.swift

@@ -10,11 +10,6 @@ import SwiftUI
 
 final class MainCoordinator: BaseCoordinator {
 
-    init(router: Router) {
-        super.init()
-        self.currentRouter = router
-    }
-
     func run() -> some View {
         showMainModule()
     }

+ 69 - 0
CoordinatorSUIExamples/CoordinatorSUIExamples/Flows/Tabs/ProductsCoordinator.swift

@@ -0,0 +1,69 @@
+//
+//  ProductsCoordinator.swift
+//  CoordinatorSUIExamples
+//
+//  Created by Pavel Yurchenko on 03.12.2024.
+//
+
+import CoordinatorSUI
+import SwiftUI
+
+final class ProductsCoordinator: BaseCoordinator {
+
+    func run() -> some View {
+        showProductsModule()
+    }
+
+    @ViewBuilder
+    func buildDestination(_ route: Route) -> some View {
+        switch route {
+        case .products:
+            showProductsModule()
+        case .product(let id):
+            showProductModule(with: id)
+        case .cart:
+            showCartModule()
+        default:
+            fatalError("This should not happen!")
+        }
+    }
+
+    // MARK: - Private methods
+
+    private func showProductsModule() -> some View {
+        ProductsBuilder().build(
+            with: .init(
+                onProduct: { [weak self] in
+                    self?.currentRouter.push(Route.product(id: $0))
+                },
+                onCart: { [weak self] in
+                    self?.currentRouter.push(Route.cart)
+                }
+            )
+        )
+    }
+
+    private func showCartModule() -> some View {
+        CartBuilder().build(
+            with: .init(
+                onProducts: { [weak self] in
+                    self?.currentRouter.push(Route.products)
+                }
+            )
+        )
+    }
+
+    private func showProductModule(with id: Int) -> some View {
+        ProductBuilder().build(
+            with: .init(id: id),
+            output: .init(
+                onProducts: { [weak self] in
+                    self?.currentRouter.push(Route.products)
+                },
+                onCart: { [weak self] in
+                    self?.currentRouter.push(Route.cart)
+                }
+            )
+        )
+    }
+}