import AppCore import ComposableArchitecture import Foundation import XCTestDynamicOverlay import XXClient import XXMessengerClient import XXModels public struct VerifyContactState: Equatable { public enum Result: Equatable { case success(Bool) case failure(String) } public init( contact: XXClient.Contact, isVerifying: Bool = false, result: Result? = nil ) { self.contact = contact self.isVerifying = isVerifying self.result = result } public var contact: XXClient.Contact public var isVerifying: Bool public var result: Result? } public enum VerifyContactAction: Equatable { case verifyTapped case didVerify(VerifyContactState.Result) } public struct VerifyContactEnvironment { 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 VerifyContactEnvironment { public static let unimplemented = VerifyContactEnvironment( messenger: .unimplemented, db: .unimplemented, mainQueue: .unimplemented, bgQueue: .unimplemented ) } #endif public let verifyContactReducer = Reducer<VerifyContactState, VerifyContactAction, VerifyContactEnvironment> { state, action, env in switch action { case .verifyTapped: state.isVerifying = 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(.verificationInProgress) let result = try env.messenger.verifyContact(state.contact) try updateStatus(result ? .verified : .verificationFailed) return .success(.didVerify(.success(result))) } catch { try? updateStatus(.verificationFailed) return .success(.didVerify(.failure(error.localizedDescription))) } } .subscribe(on: env.bgQueue) .receive(on: env.mainQueue) .eraseToEffect() case .didVerify(let result): state.isVerifying = false state.result = result return .none } }