Something went wrong on our end
-
Ahmed Shehata authoredAhmed Shehata authored
OnboardingEmailConfirmationViewModel.swift 2.69 KiB
import HUD
import UIKit
import Models
import Shared
import Combine
import Defaults
import InputField
import Integration
import CombineSchedulers
import DependencyInjection
struct OnboardingEmailConfirmationViewState: Equatable {
var input: String = ""
var status: InputField.ValidationStatus = .unknown(nil)
var resendDebouncer: Int = 0
}
final class OnboardingEmailConfirmationViewModel {
@Dependency private var session: SessionType
var hud: AnyPublisher<HUDStatus, Never> { hudRelay.eraseToAnyPublisher() }
private let hudRelay = CurrentValueSubject<HUDStatus, Never>(.none)
var completionPublisher: AnyPublisher<AttributeConfirmation, Never> { completionRelay.eraseToAnyPublisher() }
private let completionRelay = PassthroughSubject<AttributeConfirmation, Never>()
var timer: Timer?
let confirmation: AttributeConfirmation
var state: AnyPublisher<OnboardingEmailConfirmationViewState, Never> { stateRelay.eraseToAnyPublisher() }
private let stateRelay = CurrentValueSubject<OnboardingEmailConfirmationViewState, Never>(.init())
var backgroundScheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()
init(_ confirmation: AttributeConfirmation) {
self.confirmation = confirmation
didTapResend()
}
func didInput(_ string: String) {
stateRelay.value.input = string
validate()
}
func didTapResend() {
guard stateRelay.value.resendDebouncer == 0 else { return }
stateRelay.value.resendDebouncer = 60
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] in
guard let self = self, self.stateRelay.value.resendDebouncer > 0 else {
$0.invalidate()
return
}
self.stateRelay.value.resendDebouncer -= 1
}
}
func didTapNext() {
hudRelay.send(.on(nil))
backgroundScheduler.schedule { [weak self] in
guard let self = self else { return }
do {
try self.session.confirm(
code: self.stateRelay.value.input,
confirmation: self.confirmation
)
self.timer?.invalidate()
self.hudRelay.send(.none)
self.completionRelay.send(self.confirmation)
} catch {
self.hudRelay.send(.error(.init(with: error)))
}
}
}
private func validate() {
switch Validator.code.validate(stateRelay.value.input) {
case .success:
stateRelay.value.status = .valid(nil)
case .failure(let error):
stateRelay.value.status = .invalid(error)
}
}
}