Guest User

Untitled

a guest
Nov 27th, 2018
123
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.02 KB | None | 0 0
  1. enum SignInNavigationStep {
  2. case signIn
  3. }
  4.  
  5. final class SignInViewModel: BaseViewModel<
  6. SignInNavigationStep,
  7. SignInViewModel.InputFromView,
  8. SignInViewModel.Output
  9. > {
  10.  
  11. private let useCase: AuthenticationUseCase
  12.  
  13. public init(useCase: AuthenticationUseCase) {
  14. self.useCase = useCase
  15. }
  16.  
  17. override func transform(input: Input) -> Output {
  18. func userDid(_ step: SignInNavigationStep) {
  19. navigator.navigate(to: .signIn)
  20. }
  21.  
  22. let activityTracker = ActivityTracker()
  23. let errorTracker = ErrorTracker()
  24.  
  25. let isSigningIn = activityTracker.asDriver()
  26.  
  27. // Validate input
  28. let validator = InputValidator()
  29. let usernameValidation: Driver<Validation<String>> = input.fromView.username.map { validator.validate(email: $0) }
  30. let validUsername: Driver<String> = usernameValidation.map { $0.asValidated }.filterNil()
  31.  
  32. let passwordsValidation: Driver<Validation<String>> = Driver.combineLatest(input.fromView.password, input.fromView.confirmPassword) {
  33. validator.validate(password: $0, confirmedBy: $1)
  34. }
  35. let validPassword: Driver<String> = passwordsValidation.map { $0.asValidated }.filterNil()
  36.  
  37. // Make button enabled/disabled based on validation
  38. let isSignInButtonEnabled = Driver.combineLatest(
  39. usernameValidation.map { $0.isValid },
  40. passwordsValidation.map { $0.isValid }
  41. ) { $0 && $1 }
  42.  
  43. // Create request from valid input
  44. let signInRequest: Driver<SignInRequest> = Driver.combineLatest(validUsername, validPassword) {
  45. SignInRequest(username: $0, password: $1)
  46. }
  47.  
  48. // Create and dispose of `Disposable`s
  49. [
  50. // Make request
  51. input.fromView.signInTrigger.withLatestFrom(signInRequest) { $1 }
  52. .flatMapLatest { [unowned useCase] in
  53. useCase.signIn(request: $1)
  54. .trackError(errorTracker)
  55. .trackActivity(activityTracker)
  56. .asDriverOnErrorReturnEmpty()
  57. }.do(onNext: { userDid(.signIn) }) // when successful, notify coordinator
  58. .drive(),
  59.  
  60. // Let Controller display alert for error message (could also be moved to Coordinator)
  61. errorTracker.asDriver()
  62. .do(onNext: {
  63. // Remember I said ControllerInput was a bit simplified? It has an `alertSubject`
  64. // On which we can notify of an `Alert` type, to display errors or short messages.
  65. input.fromController.alertSubject.onNext(Alert(error: $0))
  66. }).drive()
  67.  
  68. ].forEach { $0.disposed(by: bag) }
  69.  
  70. // Return output to drives UI
  71. return Output(
  72. isSignInButtonEnabled: isSignInButtonEnabled,
  73. isSignInButtonEnabled: isSigningIn,
  74. usernameValidation: usernameValidation,
  75. passwordValidation: passwordValidation
  76. )
  77. }
  78. }
  79.  
  80. extension SignInViewModel {
  81.  
  82. struct InputFromView {
  83. let username: Driver<String>
  84. let password: Driver<String>
  85. let confirmPassword: Driver<String>
  86. let signInTrigger: Driver<Void>
  87. }
  88.  
  89. struct Output {
  90. let isSignInButtonEnabled: Driver<Bool>
  91. let isSigningIn: Driver<Bool>
  92. let usernameValidation: Driver<Validation<String>>
  93. let passwordValidation: Driver<Validation<String>>
  94. }
  95. }
  96.  
  97.  
  98. // MARK: - Field Validation
  99. extension SignInViewModel {
  100. struct InputValidator {
  101. // Some simple validator types, implementation omitted.
  102. private let emailValidator = EmailValidator()
  103. private let passwordValidator = PasswordValidator()
  104.  
  105. func validate(email: String) -> Validation<String> {
  106. return emailValidator.validate(input: email)
  107. }
  108.  
  109. func validate(password: String, confirmedBy confirmingPassword: String) -> Validation<String> {
  110. return passwordValidator.validate(password: password, passwordConfirmation: confirmingPassword)
  111. }
  112. }
  113. }
Add Comment
Please, Sign In to add comment