Skip to content
Snippets Groups Projects
ContactLookupFeature.swift 1.87 KiB
Newer Older
import ComposableArchitecture
import Foundation
import XCTestDynamicOverlay
Dariusz Rybicki's avatar
Dariusz Rybicki committed
import XXClient
import XXMessengerClient

public struct ContactLookupState: Equatable {
  public init(
    id: Data,
Dariusz Rybicki's avatar
Dariusz Rybicki committed
    isLookingUp: Bool = false,
    failure: String? = nil
  ) {
    self.id = id
    self.isLookingUp = isLookingUp
Dariusz Rybicki's avatar
Dariusz Rybicki committed
    self.failure = failure
  }

  public var id: Data
  public var isLookingUp: Bool
Dariusz Rybicki's avatar
Dariusz Rybicki committed
  public var failure: String?
}

public enum ContactLookupAction: Equatable {
  case lookupTapped
Dariusz Rybicki's avatar
Dariusz Rybicki committed
  case didLookup(XXClient.Contact)
  case didFail(NSError)
}

public struct ContactLookupEnvironment {
Dariusz Rybicki's avatar
Dariusz Rybicki committed
  public init(
    messenger: Messenger,
    mainQueue: AnySchedulerOf<DispatchQueue>,
    bgQueue: AnySchedulerOf<DispatchQueue>
  ) {
    self.messenger = messenger
    self.mainQueue = mainQueue
    self.bgQueue = bgQueue
  }

  public var messenger: Messenger
  public var mainQueue: AnySchedulerOf<DispatchQueue>
  public var bgQueue: AnySchedulerOf<DispatchQueue>
}

#if DEBUG
extension ContactLookupEnvironment {
Dariusz Rybicki's avatar
Dariusz Rybicki committed
  public static let unimplemented = ContactLookupEnvironment(
    messenger: .unimplemented,
    mainQueue: .unimplemented,
    bgQueue: .unimplemented
  )
}
#endif

public let contactLookupReducer = Reducer<ContactLookupState, ContactLookupAction, ContactLookupEnvironment>
{ state, action, env in
  switch action {
Dariusz Rybicki's avatar
Dariusz Rybicki committed
  case .lookupTapped:
    state.isLookingUp = true
    return Effect.result { [state] in
      do {
        let contact = try env.messenger.lookupContact(id: state.id)
        return .success(.didLookup(contact))
      } catch {
        return .success(.didFail(error as NSError))
      }
    }
    .subscribe(on: env.bgQueue)
    .receive(on: env.mainQueue)
    .eraseToEffect()
Dariusz Rybicki's avatar
Dariusz Rybicki committed
  case .didLookup(_):
    state.isLookingUp = false
Dariusz Rybicki's avatar
Dariusz Rybicki committed
  case .didFail(let error):
    state.failure = error.localizedDescription
    state.isLookingUp = false