Ver código fonte

Implement support to present alerts from coordinators

Pavel Yurchenko 1 ano atrás
pai
commit
f6e89180cd

+ 16 - 2
CoordinatorSUIExamples/CoordinatorSUIExamples/Flows/ModalProductsCoordinator.swift

@@ -10,6 +10,8 @@ import SwiftUI
 
 final class ModalProductsCoordinator: BaseCoordinator {
 
+    var alertPresenter = AlertPresenter()
+
     func run() -> some View {
         showProductsModule()
     }
@@ -44,7 +46,13 @@ final class ModalProductsCoordinator: BaseCoordinator {
                 showCart: false,
                 showProducts: false
             ),
-            output: .init()
+            output: .init(
+                onAlert: { [weak self] title in
+                    self?.alertPresenter.showSimpleAlert(title) {
+                        print("On alert OK!")
+                    }
+                }
+            )
         )
     }
 }
@@ -55,10 +63,12 @@ struct ModalProductsNavigationView: View {
 
     @StateObject private var coordinator: ModalProductsCoordinator
     @StateObject private var router: Router
+    @StateObject private var alertPresenter: AlertPresenter
 
     init(_ coordinator: ModalProductsCoordinator) {
         _coordinator = StateObject(wrappedValue: coordinator)
         _router = StateObject(wrappedValue: coordinator.currentRouter)
+        _alertPresenter = StateObject(wrappedValue: coordinator.alertPresenter)
     }
 
     var body: some View {
@@ -68,6 +78,10 @@ struct ModalProductsNavigationView: View {
                 for: Route.self,
                 destination: coordinator.buildDestination
             )
-        }
+        }.alert(
+            alertPresenter.title,
+            isPresented: $alertPresenter.isPresenting,
+            actions: alertPresenter.buildButtons
+        )
     }
 }

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

@@ -48,4 +48,3 @@ struct FeedbackNavigationView: View {
         }
     }
 }
-

+ 14 - 1
CoordinatorSUIExamples/CoordinatorSUIExamples/Flows/Tabs/MainCoordinator.swift

@@ -13,6 +13,8 @@ final class MainCoordinator: BaseCoordinator {
     @Published
     var presentation: Route?
 
+    var alertPresenter = AlertPresenter()
+
     func run() -> some View {
         showMainModule()
     }
@@ -46,7 +48,7 @@ final class MainCoordinator: BaseCoordinator {
     }
 
     func onDismissPresentation() {
-        
+
     }
 
     // MARK: - Private methods
@@ -113,6 +115,11 @@ final class MainCoordinator: BaseCoordinator {
                 },
                 onCart: { [weak self] in
                     self?.currentRouter.push(Route.cart)
+                },
+                onAlert: { [weak self] title in
+                    self?.alertPresenter.showSimpleAlert(title) {
+                        print("Alert OK")
+                    }
                 }
             )
         )
@@ -129,10 +136,12 @@ struct MainNavigationView: View {
 
     @StateObject private var coordinator: MainCoordinator
     @StateObject private var router: Router
+    @StateObject private var alertPresenter: AlertPresenter
 
     init(_ coordinator: MainCoordinator) {
         _coordinator = StateObject(wrappedValue: coordinator)
         _router = StateObject(wrappedValue: coordinator.currentRouter)
+        _alertPresenter = StateObject(wrappedValue: coordinator.alertPresenter)
     }
 
     var body: some View {
@@ -146,6 +155,10 @@ struct MainNavigationView: View {
             item: $coordinator.presentation,
             onDismiss: coordinator.onDismissPresentation,
             content: coordinator.buildPresentation
+        ).alert(
+            alertPresenter.title,
+            isPresented: $alertPresenter.isPresenting,
+            actions: alertPresenter.buildButtons
         )
     }
 }

+ 7 - 0
CoordinatorSUIExamples/CoordinatorSUIExamples/Modules/Product/ProductVM.swift

@@ -7,6 +7,8 @@
 
 import SwiftUI
 
+typealias StringAction = (String) -> Void
+
 @Observable
 final class ProductVM {
 
@@ -19,6 +21,7 @@ final class ProductVM {
     struct Output {
         var onProducts: Action?
         var onCart: Action?
+        var onAlert: StringAction?
     }
 
     let output: Output
@@ -40,4 +43,8 @@ final class ProductVM {
             self.objectId = input.id + 5
         }
     }
+
+    func showAlert() {
+        output.onAlert?("Hello this is product #\(input.id)")
+    }
 }

+ 4 - 0
CoordinatorSUIExamples/CoordinatorSUIExamples/Modules/Product/ProductView.swift

@@ -16,6 +16,10 @@ struct ProductView: View {
             Spacer()
             Text("#\(vm.objectId)")
             Spacer()
+            Button("Show alert") {
+                vm.showAlert()
+            }
+            Spacer()
             if vm.showProducts {
                 Button("Products") {
                     vm.output.onProducts?()

+ 48 - 0
CoordinatorSUIExamples/CoordinatorSUIExamples/Presenters/AlertPresenter.swift

@@ -0,0 +1,48 @@
+//
+//  AlertPresenter.swift
+//  CoordinatorSUIExamples
+//
+//  Created by Pavel Yurchenko on 04.12.2024.
+//
+
+import SwiftUI
+
+final class AlertPresenter: ObservableObject {
+
+    private struct AlertConfiguration {
+        let title: String
+        let buttons: [AlertButton]
+    }
+
+    struct AlertButton {
+        let title: String
+        let role: ButtonRole
+        let action: Action
+    }
+
+    private var alertConfiguration = AlertConfiguration(title: "", buttons: [])
+
+    @Published
+    var isPresenting: Bool = false
+
+    var title: String {
+        alertConfiguration.title
+    }
+
+    @ViewBuilder
+    func buildButtons() -> some View {
+        ForEach(alertConfiguration.buttons.indices) { index in
+            let button = self.alertConfiguration.buttons[index]
+            Button(button.title, role: button.role, action: button.action)
+        }
+    }
+
+    func showAlert(_ title: String, buttons: [AlertButton]) {
+        self.alertConfiguration = AlertConfiguration(title: title, buttons: buttons)
+        self.isPresenting = true
+    }
+
+    func showSimpleAlert(_ title: String, action: @escaping Action) {
+        showAlert(title, buttons: [AlertButton(title: "OK", role: .cancel, action: action)])
+    }
+}