From 5b765fd94e76e2e4f454d204bbd7749f386dfed7 Mon Sep 17 00:00:00 2001 From: Dariusz Rybicki <dariusz@elixxir.io> Date: Wed, 1 Jun 2022 16:19:14 +0200 Subject: [PATCH] Present errors in landing feature --- Example/ExampleApp/Package.swift | 6 ++++ .../ExampleApp/Sources/AppFeature/App.swift | 4 ++- .../Sources/ErrorFeature/ErrorFeature.swift | 2 +- .../LandingFeature/LandingFeature.swift | 31 ++++++++++++++++--- .../Sources/LandingFeature/LandingView.swift | 12 +++++++ .../LandingFeatureTests.swift | 3 ++ 6 files changed, 51 insertions(+), 7 deletions(-) diff --git a/Example/ExampleApp/Package.swift b/Example/ExampleApp/Package.swift index 9f02c271..3b02bf97 100644 --- a/Example/ExampleApp/Package.swift +++ b/Example/ExampleApp/Package.swift @@ -56,6 +56,7 @@ let package = Package( .target( name: "AppFeature", dependencies: [ + .target(name: "ErrorFeature"), .target(name: "LandingFeature"), .target(name: "SessionFeature"), .product( @@ -108,10 +109,15 @@ let package = Package( .target( name: "LandingFeature", dependencies: [ + .target(name: "ErrorFeature"), .product( name: "ComposableArchitecture", package: "swift-composable-architecture" ), + .product( + name: "ComposablePresentation", + package: "swift-composable-presentation" + ), .product( name: "ElixxirDAppsSDK", package: "elixxir-dapps-sdk-swift" diff --git a/Example/ExampleApp/Sources/AppFeature/App.swift b/Example/ExampleApp/Sources/AppFeature/App.swift index b7446b7e..1353882a 100644 --- a/Example/ExampleApp/Sources/AppFeature/App.swift +++ b/Example/ExampleApp/Sources/AppFeature/App.swift @@ -1,6 +1,7 @@ import Combine import ComposableArchitecture import ElixxirDAppsSDK +import ErrorFeature import LandingFeature import SessionFeature import SwiftUI @@ -36,7 +37,8 @@ extension AppEnvironment { ), setClient: { clientSubject.send($0) }, bgScheduler: bgScheduler, - mainScheduler: mainScheduler + mainScheduler: mainScheduler, + error: ErrorEnvironment() ), session: SessionEnvironment() ) diff --git a/Example/ExampleApp/Sources/ErrorFeature/ErrorFeature.swift b/Example/ExampleApp/Sources/ErrorFeature/ErrorFeature.swift index 756260a9..dc7d8b69 100644 --- a/Example/ExampleApp/Sources/ErrorFeature/ErrorFeature.swift +++ b/Example/ExampleApp/Sources/ErrorFeature/ErrorFeature.swift @@ -6,7 +6,7 @@ public struct ErrorState: Equatable { self.error = error } - var error: NSError + public var error: NSError } public enum ErrorAction: Equatable {} diff --git a/Example/ExampleApp/Sources/LandingFeature/LandingFeature.swift b/Example/ExampleApp/Sources/LandingFeature/LandingFeature.swift index a3b1c3b8..dfca1d37 100644 --- a/Example/ExampleApp/Sources/LandingFeature/LandingFeature.swift +++ b/Example/ExampleApp/Sources/LandingFeature/LandingFeature.swift @@ -1,21 +1,25 @@ import Combine import ComposableArchitecture import ElixxirDAppsSDK +import ErrorFeature public struct LandingState: Equatable { public init( hasStoredClient: Bool = false, isMakingClient: Bool = false, - isRemovingClient: Bool = false + isRemovingClient: Bool = false, + error: ErrorState? = nil ) { self.hasStoredClient = hasStoredClient self.isMakingClient = isMakingClient self.isRemovingClient = isRemovingClient + self.error = error } var hasStoredClient: Bool var isMakingClient: Bool var isRemovingClient: Bool + var error: ErrorState? } public enum LandingAction: Equatable { @@ -26,6 +30,8 @@ public enum LandingAction: Equatable { case removeStoredClient case didRemoveStoredClient case didFailRemovingStoredClient(NSError) + case didDismissError + case error(ErrorAction) } public struct LandingEnvironment { @@ -33,18 +39,21 @@ public struct LandingEnvironment { clientStorage: ClientStorage, setClient: @escaping (Client) -> Void, bgScheduler: AnySchedulerOf<DispatchQueue>, - mainScheduler: AnySchedulerOf<DispatchQueue> + mainScheduler: AnySchedulerOf<DispatchQueue>, + error: ErrorEnvironment ) { self.clientStorage = clientStorage self.setClient = setClient self.bgScheduler = bgScheduler self.mainScheduler = mainScheduler + self.error = error } public var clientStorage: ClientStorage public var setClient: (Client) -> Void public var bgScheduler: AnySchedulerOf<DispatchQueue> public var mainScheduler: AnySchedulerOf<DispatchQueue> + public var error: ErrorEnvironment } public let landingReducer = Reducer<LandingState, LandingAction, LandingEnvironment> @@ -80,7 +89,7 @@ public let landingReducer = Reducer<LandingState, LandingAction, LandingEnvironm case .didFailMakingClient(let error): state.isMakingClient = false state.hasStoredClient = env.clientStorage.hasStoredClient() - // TODO: handle error + state.error = ErrorState(error: error) return .none case .removeStoredClient: @@ -105,10 +114,21 @@ public let landingReducer = Reducer<LandingState, LandingAction, LandingEnvironm case .didFailRemovingStoredClient(let error): state.isRemovingClient = false state.hasStoredClient = env.clientStorage.hasStoredClient() - // TODO: handle error + state.error = ErrorState(error: error) + return .none + + case .didDismissError: + state.error = nil return .none } } +.presenting( + errorReducer, + state: .keyPath(\.error), + id: .keyPath(\.?.error), + action: /LandingAction.error, + environment: \.error +) #if DEBUG extension LandingEnvironment { @@ -116,7 +136,8 @@ extension LandingEnvironment { clientStorage: .failing, setClient: { _ in fatalError() }, bgScheduler: .failing, - mainScheduler: .failing + mainScheduler: .failing, + error: .failing ) } #endif diff --git a/Example/ExampleApp/Sources/LandingFeature/LandingView.swift b/Example/ExampleApp/Sources/LandingFeature/LandingView.swift index 325cbe63..a4dd2b73 100644 --- a/Example/ExampleApp/Sources/LandingFeature/LandingView.swift +++ b/Example/ExampleApp/Sources/LandingFeature/LandingView.swift @@ -1,4 +1,6 @@ import ComposableArchitecture +import ComposablePresentation +import ErrorFeature import SwiftUI public struct LandingView: View { @@ -59,6 +61,16 @@ public struct LandingView: View { .task { viewStore.send(.viewDidLoad) } + .sheet( + store.scope( + state: \.error, + action: LandingAction.error + ), + onDismiss: { + viewStore.send(.didDismissError) + }, + content: ErrorView.init(store:) + ) } } } diff --git a/Example/ExampleApp/Tests/LandingFeatureTests/LandingFeatureTests.swift b/Example/ExampleApp/Tests/LandingFeatureTests/LandingFeatureTests.swift index 3083d97a..df9791e7 100644 --- a/Example/ExampleApp/Tests/LandingFeatureTests/LandingFeatureTests.swift +++ b/Example/ExampleApp/Tests/LandingFeatureTests/LandingFeatureTests.swift @@ -1,4 +1,5 @@ import ComposableArchitecture +import ErrorFeature import XCTest @testable import LandingFeature @@ -115,6 +116,7 @@ final class LandingFeatureTests: XCTestCase { store.receive(.didFailMakingClient(error)) { $0.isMakingClient = false $0.hasStoredClient = false + $0.error = ErrorState(error: error) } } @@ -180,6 +182,7 @@ final class LandingFeatureTests: XCTestCase { store.receive(.didFailRemovingStoredClient(error)) { $0.isRemovingClient = false $0.hasStoredClient = true + $0.error = ErrorState(error: error) } } } -- GitLab