import HUD import Shared import Models import Combine import Countries import InputField import Integration import CombineSchedulers import DependencyInjection struct OnboardingPhoneViewState: Equatable { var input: String = "" var confirmation: AttributeConfirmation? var status: InputField.ValidationStatus = .unknown(nil) var country: Country = .fromMyPhone() } final class OnboardingPhoneViewModel { @Dependency private var session: SessionType var hud: AnyPublisher<HUDStatus, Never> { hudRelay.eraseToAnyPublisher() } private let hudRelay = CurrentValueSubject<HUDStatus, Never>(.none) var state: AnyPublisher<OnboardingPhoneViewState, Never> { stateRelay.eraseToAnyPublisher() } private let stateRelay = CurrentValueSubject<OnboardingPhoneViewState, Never>(.init()) var backgroundScheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler() // MARK: Public func clearUp() { stateRelay.value.confirmation = nil } func didInput(_ string: String) { stateRelay.value.input = string validate() } func didChooseCountry(_ country: Country) { stateRelay.value.country = country validate() } func didGoForward() { stateRelay.value.confirmation = nil } func didTapNext() { hudRelay.send(.on(nil)) backgroundScheduler.schedule { [weak self] in guard let self = self else { return } let content = "\(self.stateRelay.value.input)\(self.stateRelay.value.country.code)" self.session.register(.phone, value: content) { [weak self] in guard let self = self else { return } switch $0 { case .success(let confirmationId): self.hudRelay.send(.none) self.stateRelay.value.confirmation = .init( content: content, confirmationId: confirmationId ) case .failure(let error): self.hudRelay.send(.error(.init(with: error))) } } } } private func validate() { switch Validator.phone.validate((stateRelay.value.country.regex, stateRelay.value.input)) { case .success: stateRelay.value.status = .valid(nil) case .failure(let error): stateRelay.value.status = .invalid(error) } } }