From a8031c0769a5b1c7003bdb70ccf9ccffd5434033 Mon Sep 17 00:00:00 2001 From: Dariusz Rybicki <dariusz@elixxir.io> Date: Fri, 21 Oct 2022 11:24:00 +0200 Subject: [PATCH] Migrate CheckContactAuthFeature to ReducerProtocol --- .../CheckContactAuthComponent.swift | 72 ++++++++++++++ .../CheckContactAuthFeature.swift | 94 ------------------- .../CheckContactAuthView.swift | 13 ++- ...t => CheckContactAuthComponentTests.swift} | 39 ++++---- 4 files changed, 96 insertions(+), 122 deletions(-) create mode 100644 Examples/xx-messenger/Sources/CheckContactAuthFeature/CheckContactAuthComponent.swift delete mode 100644 Examples/xx-messenger/Sources/CheckContactAuthFeature/CheckContactAuthFeature.swift rename Examples/xx-messenger/Tests/CheckContactAuthFeatureTests/{CheckContactAuthFeatureTests.swift => CheckContactAuthComponentTests.swift} (80%) diff --git a/Examples/xx-messenger/Sources/CheckContactAuthFeature/CheckContactAuthComponent.swift b/Examples/xx-messenger/Sources/CheckContactAuthFeature/CheckContactAuthComponent.swift new file mode 100644 index 00000000..5c62fa8f --- /dev/null +++ b/Examples/xx-messenger/Sources/CheckContactAuthFeature/CheckContactAuthComponent.swift @@ -0,0 +1,72 @@ +import AppCore +import ComposableArchitecture +import Foundation +import XCTestDynamicOverlay +import XXClient +import XXMessengerClient +import XXModels + +public struct CheckContactAuthComponent: ReducerProtocol { + public struct State: Equatable { + public enum Result: Equatable { + case success(Bool) + case failure(String) + } + + public init( + contact: XXClient.Contact, + isChecking: Bool = false, + result: Result? = nil + ) { + self.contact = contact + self.isChecking = isChecking + self.result = result + } + + public var contact: XXClient.Contact + public var isChecking: Bool + public var result: Result? + } + + public enum Action: Equatable { + case checkTapped + case didCheck(State.Result) + } + + @Dependency(\.app.messenger) var messenger: Messenger + @Dependency(\.app.dbManager.getDB) var db: DBManagerGetDB + @Dependency(\.app.mainQueue) var mainQueue: AnySchedulerOf<DispatchQueue> + @Dependency(\.app.bgQueue) var bgQueue: AnySchedulerOf<DispatchQueue> + + public init() {} + + public func reduce(into state: inout State, action: Action) -> EffectTask<Action> { + switch action { + case .checkTapped: + state.isChecking = true + state.result = nil + return Effect.result { [state] in + do { + let e2e = try messenger.e2e.tryGet() + let contactId = try state.contact.getId() + let result = try e2e.hasAuthenticatedChannel(partnerId: contactId) + try db().bulkUpdateContacts.callAsFunction( + .init(id: [contactId]), + .init(authStatus: result ? .friend : .stranger) + ) + return .success(.didCheck(.success(result))) + } catch { + return .success(.didCheck(.failure(error.localizedDescription))) + } + } + .subscribe(on: bgQueue) + .receive(on: mainQueue) + .eraseToEffect() + + case .didCheck(let result): + state.isChecking = false + state.result = result + return .none + } + } +} diff --git a/Examples/xx-messenger/Sources/CheckContactAuthFeature/CheckContactAuthFeature.swift b/Examples/xx-messenger/Sources/CheckContactAuthFeature/CheckContactAuthFeature.swift deleted file mode 100644 index 1f768be8..00000000 --- a/Examples/xx-messenger/Sources/CheckContactAuthFeature/CheckContactAuthFeature.swift +++ /dev/null @@ -1,94 +0,0 @@ -import AppCore -import ComposableArchitecture -import Foundation -import XCTestDynamicOverlay -import XXClient -import XXMessengerClient -import XXModels - -public struct CheckContactAuthState: Equatable { - public enum Result: Equatable { - case success(Bool) - case failure(String) - } - - public init( - contact: XXClient.Contact, - isChecking: Bool = false, - result: Result? = nil - ) { - self.contact = contact - self.isChecking = isChecking - self.result = result - } - - public var contact: XXClient.Contact - public var isChecking: Bool - public var result: Result? -} - -public enum CheckContactAuthAction: Equatable { - case checkTapped - case didCheck(CheckContactAuthState.Result) -} - -public struct CheckContactAuthEnvironment { - public init( - messenger: Messenger, - db: DBManagerGetDB, - mainQueue: AnySchedulerOf<DispatchQueue>, - bgQueue: AnySchedulerOf<DispatchQueue> - ) { - self.messenger = messenger - self.db = db - self.mainQueue = mainQueue - self.bgQueue = bgQueue - } - - public var messenger: Messenger - public var db: DBManagerGetDB - public var mainQueue: AnySchedulerOf<DispatchQueue> - public var bgQueue: AnySchedulerOf<DispatchQueue> -} - -#if DEBUG -extension CheckContactAuthEnvironment { - public static let unimplemented = CheckContactAuthEnvironment( - messenger: .unimplemented, - db: .unimplemented, - mainQueue: .unimplemented, - bgQueue: .unimplemented - ) -} -#endif - -public let checkContactAuthReducer = Reducer<CheckContactAuthState, CheckContactAuthAction, CheckContactAuthEnvironment> -{ state, action, env in - switch action { - case .checkTapped: - state.isChecking = true - state.result = nil - return Effect.result { [state] in - do { - let e2e = try env.messenger.e2e.tryGet() - let contactId = try state.contact.getId() - let result = try e2e.hasAuthenticatedChannel(partnerId: contactId) - try env.db().bulkUpdateContacts.callAsFunction( - .init(id: [contactId]), - .init(authStatus: result ? .friend : .stranger) - ) - return .success(.didCheck(.success(result))) - } catch { - return .success(.didCheck(.failure(error.localizedDescription))) - } - } - .subscribe(on: env.bgQueue) - .receive(on: env.mainQueue) - .eraseToEffect() - - case .didCheck(let result): - state.isChecking = false - state.result = result - return .none - } -} diff --git a/Examples/xx-messenger/Sources/CheckContactAuthFeature/CheckContactAuthView.swift b/Examples/xx-messenger/Sources/CheckContactAuthFeature/CheckContactAuthView.swift index dd2e7894..b4b75bbc 100644 --- a/Examples/xx-messenger/Sources/CheckContactAuthFeature/CheckContactAuthView.swift +++ b/Examples/xx-messenger/Sources/CheckContactAuthFeature/CheckContactAuthView.swift @@ -3,20 +3,20 @@ import SwiftUI import XXClient public struct CheckContactAuthView: View { - public init(store: Store<CheckContactAuthState, CheckContactAuthAction>) { + public init(store: StoreOf<CheckContactAuthComponent>) { self.store = store } - let store: Store<CheckContactAuthState, CheckContactAuthAction> + let store: StoreOf<CheckContactAuthComponent> struct ViewState: Equatable { var username: String? var email: String? var phone: String? var isChecking: Bool - var result: CheckContactAuthState.Result? + var result: CheckContactAuthComponent.State.Result? - init(state: CheckContactAuthState) { + init(state: CheckContactAuthComponent.State) { username = try? state.contact.getFact(.username)?.value email = try? state.contact.getFact(.email)?.value phone = try? state.contact.getFact(.phone)?.value @@ -90,11 +90,10 @@ public struct CheckContactAuthView: View { public struct CheckContactAuthView_Previews: PreviewProvider { public static var previews: some View { CheckContactAuthView(store: Store( - initialState: CheckContactAuthState( + initialState: CheckContactAuthComponent.State( contact: .unimplemented("contact-data".data(using: .utf8)!) ), - reducer: .empty, - environment: () + reducer: EmptyReducer() )) } } diff --git a/Examples/xx-messenger/Tests/CheckContactAuthFeatureTests/CheckContactAuthFeatureTests.swift b/Examples/xx-messenger/Tests/CheckContactAuthFeatureTests/CheckContactAuthComponentTests.swift similarity index 80% rename from Examples/xx-messenger/Tests/CheckContactAuthFeatureTests/CheckContactAuthFeatureTests.swift rename to Examples/xx-messenger/Tests/CheckContactAuthFeatureTests/CheckContactAuthComponentTests.swift index a13645f2..78031cb5 100644 --- a/Examples/xx-messenger/Tests/CheckContactAuthFeatureTests/CheckContactAuthFeatureTests.swift +++ b/Examples/xx-messenger/Tests/CheckContactAuthFeatureTests/CheckContactAuthComponentTests.swift @@ -5,27 +5,26 @@ import XXClient import XXModels @testable import CheckContactAuthFeature -final class CheckContactAuthFeatureTests: XCTestCase { +final class CheckContactAuthComponentTests: XCTestCase { func testCheck() { var contact = XXClient.Contact.unimplemented("contact-data".data(using: .utf8)!) let contactId = "contact-id".data(using: .utf8)! contact.getIdFromContact.run = { _ in contactId } let store = TestStore( - initialState: CheckContactAuthState( + initialState: CheckContactAuthComponent.State( contact: contact ), - reducer: checkContactAuthReducer, - environment: .unimplemented + reducer: CheckContactAuthComponent() ) var didCheckPartnerId: [Data] = [] var didBulkUpdateContactsWithQuery: [XXModels.Contact.Query] = [] var didBulkUpdateContactsWithAssignments: [XXModels.Contact.Assignments] = [] - store.environment.mainQueue = .immediate - store.environment.bgQueue = .immediate - store.environment.messenger.e2e.get = { + store.dependencies.app.mainQueue = .immediate + store.dependencies.app.bgQueue = .immediate + store.dependencies.app.messenger.e2e.get = { var e2e: E2E = .unimplemented e2e.hasAuthenticatedChannel.run = { partnerId in didCheckPartnerId.append(partnerId) @@ -33,7 +32,7 @@ final class CheckContactAuthFeatureTests: XCTestCase { } return e2e } - store.environment.db.run = { + store.dependencies.app.dbManager.getDB.run = { var db: Database = .unimplemented db.bulkUpdateContacts.run = { query, assignments in didBulkUpdateContactsWithQuery.append(query) @@ -64,20 +63,19 @@ final class CheckContactAuthFeatureTests: XCTestCase { contact.getIdFromContact.run = { _ in contactId } let store = TestStore( - initialState: CheckContactAuthState( + initialState: CheckContactAuthComponent.State( contact: contact ), - reducer: checkContactAuthReducer, - environment: .unimplemented + reducer: CheckContactAuthComponent() ) var didCheckPartnerId: [Data] = [] var didBulkUpdateContactsWithQuery: [XXModels.Contact.Query] = [] var didBulkUpdateContactsWithAssignments: [XXModels.Contact.Assignments] = [] - store.environment.mainQueue = .immediate - store.environment.bgQueue = .immediate - store.environment.messenger.e2e.get = { + store.dependencies.app.mainQueue = .immediate + store.dependencies.app.bgQueue = .immediate + store.dependencies.app.messenger.e2e.get = { var e2e: E2E = .unimplemented e2e.hasAuthenticatedChannel.run = { partnerId in didCheckPartnerId.append(partnerId) @@ -85,7 +83,7 @@ final class CheckContactAuthFeatureTests: XCTestCase { } return e2e } - store.environment.db.run = { + store.dependencies.app.dbManager.getDB.run = { var db: Database = .unimplemented db.bulkUpdateContacts.run = { query, assignments in didBulkUpdateContactsWithQuery.append(query) @@ -116,19 +114,18 @@ final class CheckContactAuthFeatureTests: XCTestCase { contact.getIdFromContact.run = { _ in contactId } let store = TestStore( - initialState: CheckContactAuthState( + initialState: CheckContactAuthComponent.State( contact: contact ), - reducer: checkContactAuthReducer, - environment: .unimplemented + reducer: CheckContactAuthComponent() ) struct Failure: Error {} let error = Failure() - store.environment.mainQueue = .immediate - store.environment.bgQueue = .immediate - store.environment.messenger.e2e.get = { + store.dependencies.app.mainQueue = .immediate + store.dependencies.app.bgQueue = .immediate + store.dependencies.app.messenger.e2e.get = { var e2e: E2E = .unimplemented e2e.hasAuthenticatedChannel.run = { _ in throw error } return e2e -- GitLab