diff --git a/Examples/xx-messenger/Sources/ConfirmRequestFeature/ConfirmRequestComponent.swift b/Examples/xx-messenger/Sources/ConfirmRequestFeature/ConfirmRequestComponent.swift new file mode 100644 index 0000000000000000000000000000000000000000..3a67c2e9d018cded645299e1853f78def0c8c806 --- /dev/null +++ b/Examples/xx-messenger/Sources/ConfirmRequestFeature/ConfirmRequestComponent.swift @@ -0,0 +1,76 @@ +import AppCore +import ComposableArchitecture +import Foundation +import XCTestDynamicOverlay +import XXClient +import XXMessengerClient +import XXModels + +public struct ConfirmRequestComponent: ReducerProtocol { + public struct State: Equatable { + public enum Result: Equatable { + case success + case failure(String) + } + + public init( + contact: XXClient.Contact, + isConfirming: Bool = false, + result: Result? = nil + ) { + self.contact = contact + self.isConfirming = isConfirming + self.result = result + } + + public var contact: XXClient.Contact + public var isConfirming: Bool + public var result: Result? + } + + public enum Action: Equatable { + case confirmTapped + case didConfirm(State.Result) + } + + public init() {} + + @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 func reduce(into state: inout State, action: Action) -> EffectTask<Action> { + switch action { + case .confirmTapped: + state.isConfirming = true + state.result = nil + return Effect.result { [state] in + func updateStatus(_ status: XXModels.Contact.AuthStatus) throws { + try db().bulkUpdateContacts.callAsFunction( + .init(id: [try state.contact.getId()]), + .init(authStatus: status) + ) + } + do { + try updateStatus(.confirming) + let e2e = try messenger.e2e.tryGet() + _ = try e2e.confirmReceivedRequest(partner: state.contact) + try updateStatus(.friend) + return .success(.didConfirm(.success)) + } catch { + try? updateStatus(.confirmationFailed) + return .success(.didConfirm(.failure(error.localizedDescription))) + } + } + .subscribe(on: bgQueue) + .receive(on: mainQueue) + .eraseToEffect() + + case .didConfirm(let result): + state.isConfirming = false + state.result = result + return .none + } + } +} diff --git a/Examples/xx-messenger/Sources/ConfirmRequestFeature/ConfirmRequestFeature.swift b/Examples/xx-messenger/Sources/ConfirmRequestFeature/ConfirmRequestFeature.swift deleted file mode 100644 index 7cc40da0b7e268ce6ca78bb1b57b07e00784b148..0000000000000000000000000000000000000000 --- a/Examples/xx-messenger/Sources/ConfirmRequestFeature/ConfirmRequestFeature.swift +++ /dev/null @@ -1,98 +0,0 @@ -import AppCore -import ComposableArchitecture -import Foundation -import XCTestDynamicOverlay -import XXClient -import XXMessengerClient -import XXModels - -public struct ConfirmRequestState: Equatable { - public enum Result: Equatable { - case success - case failure(String) - } - - public init( - contact: XXClient.Contact, - isConfirming: Bool = false, - result: Result? = nil - ) { - self.contact = contact - self.isConfirming = isConfirming - self.result = result - } - - public var contact: XXClient.Contact - public var isConfirming: Bool - public var result: Result? -} - -public enum ConfirmRequestAction: Equatable { - case confirmTapped - case didConfirm(ConfirmRequestState.Result) -} - -public struct ConfirmRequestEnvironment { - 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 ConfirmRequestEnvironment { - public static let unimplemented = ConfirmRequestEnvironment( - messenger: .unimplemented, - db: .unimplemented, - mainQueue: .unimplemented, - bgQueue: .unimplemented - ) -} -#endif - -public let confirmRequestReducer = Reducer<ConfirmRequestState, ConfirmRequestAction, ConfirmRequestEnvironment> -{ state, action, env in - switch action { - case .confirmTapped: - state.isConfirming = true - state.result = nil - return Effect.result { [state] in - func updateStatus(_ status: XXModels.Contact.AuthStatus) throws { - try env.db().bulkUpdateContacts.callAsFunction( - .init(id: [try state.contact.getId()]), - .init(authStatus: status) - ) - } - do { - try updateStatus(.confirming) - let e2e = try env.messenger.e2e.tryGet() - _ = try e2e.confirmReceivedRequest(partner: state.contact) - try updateStatus(.friend) - return .success(.didConfirm(.success)) - } catch { - try? updateStatus(.confirmationFailed) - return .success(.didConfirm(.failure(error.localizedDescription))) - } - } - .subscribe(on: env.bgQueue) - .receive(on: env.mainQueue) - .eraseToEffect() - - case .didConfirm(let result): - state.isConfirming = false - state.result = result - return .none - } -} diff --git a/Examples/xx-messenger/Sources/ConfirmRequestFeature/ConfirmRequestView.swift b/Examples/xx-messenger/Sources/ConfirmRequestFeature/ConfirmRequestView.swift index 90ebc70e4490d51792db636a47d2e02b318f5820..69f9d03ec076105c84956a9db41ed4dfe5153265 100644 --- a/Examples/xx-messenger/Sources/ConfirmRequestFeature/ConfirmRequestView.swift +++ b/Examples/xx-messenger/Sources/ConfirmRequestFeature/ConfirmRequestView.swift @@ -2,20 +2,20 @@ import ComposableArchitecture import SwiftUI public struct ConfirmRequestView: View { - public init(store: Store<ConfirmRequestState, ConfirmRequestAction>) { + public init(store: StoreOf<ConfirmRequestComponent>) { self.store = store } - let store: Store<ConfirmRequestState, ConfirmRequestAction> + let store: StoreOf<ConfirmRequestComponent> struct ViewState: Equatable { var username: String? var email: String? var phone: String? var isConfirming: Bool - var result: ConfirmRequestState.Result? + var result: ConfirmRequestComponent.State.Result? - init(state: ConfirmRequestState) { + init(state: ConfirmRequestComponent.State) { username = try? state.contact.getFact(.username)?.value email = try? state.contact.getFact(.email)?.value phone = try? state.contact.getFact(.phone)?.value @@ -84,11 +84,10 @@ public struct ConfirmRequestView: View { public struct ConfirmRequestView_Previews: PreviewProvider { public static var previews: some View { ConfirmRequestView(store: Store( - initialState: ConfirmRequestState( + initialState: ConfirmRequestComponent.State( contact: .unimplemented("contact-data".data(using: .utf8)!) ), - reducer: .empty, - environment: () + reducer: EmptyReducer() )) } } diff --git a/Examples/xx-messenger/Tests/ConfirmRequestFeatureTests/ConfirmRequestFeatureTests.swift b/Examples/xx-messenger/Tests/ConfirmRequestFeatureTests/ConfirmRequestComponentTests.swift similarity index 82% rename from Examples/xx-messenger/Tests/ConfirmRequestFeatureTests/ConfirmRequestFeatureTests.swift rename to Examples/xx-messenger/Tests/ConfirmRequestFeatureTests/ConfirmRequestComponentTests.swift index bc84224a8671219aeb7dbed33f5f8552b3302d59..263363f14b47b76f72c4945932c3e003ab200702 100644 --- a/Examples/xx-messenger/Tests/ConfirmRequestFeatureTests/ConfirmRequestFeatureTests.swift +++ b/Examples/xx-messenger/Tests/ConfirmRequestFeatureTests/ConfirmRequestComponentTests.swift @@ -5,27 +5,26 @@ import XXClient import XXModels @testable import ConfirmRequestFeature -final class ConfirmRequestFeatureTests: XCTestCase { +final class ConfirmRequestComponentTests: XCTestCase { func testConfirm() { 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: ConfirmRequestState( + initialState: ConfirmRequestComponent.State( contact: contact ), - reducer: confirmRequestReducer, - environment: .unimplemented + reducer: ConfirmRequestComponent() ) var didConfirmRequestFromContact: [XXClient.Contact] = [] 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.confirmReceivedRequest.run = { contact in didConfirmRequestFromContact.append(contact) @@ -33,7 +32,7 @@ final class ConfirmRequestFeatureTests: 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) @@ -70,11 +69,10 @@ final class ConfirmRequestFeatureTests: XCTestCase { contact.getIdFromContact.run = { _ in contactId } let store = TestStore( - initialState: ConfirmRequestState( + initialState: ConfirmRequestComponent.State( contact: contact ), - reducer: confirmRequestReducer, - environment: .unimplemented + reducer: ConfirmRequestComponent() ) struct Failure: Error {} @@ -83,14 +81,14 @@ final class ConfirmRequestFeatureTests: XCTestCase { 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.confirmReceivedRequest.run = { _ in throw error } 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)