Skip to content

Instantly share code, notes, and snippets.

@ksoftllc
Created February 20, 2019 21:47
Show Gist options
  • Save ksoftllc/138998c26d6ef63f82be7ce2f8f864f1 to your computer and use it in GitHub Desktop.
Save ksoftllc/138998c26d6ef63f82be7ce2f8f864f1 to your computer and use it in GitHub Desktop.
//
// GithubSignupViewModel2.swift
// RxExample
//
// Created by Krunoslav Zaher on 12/6/15.
// Modified by Chuck Krutsinger on 2/20/19.
//
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
//
import RxSwift
import RxCocoa
func GithubSignupViewModel2(
input: (
username: Driver<String>,
password: Driver<String>,
repeatedPassword: Driver<String>,
loginTaps: Signal<()>
),
dependency: (
API: GitHubAPI,
validationService: GitHubValidationService,
wireframe: Wireframe
)
)
-> (
validatedUsername: Driver<ValidationResult>,
validatedPassword: Driver<ValidationResult>,
validatedPasswordRepeated: Driver<ValidationResult>,
signupEnabled: Driver<Bool>,
signedIn: Driver<Bool>,
signingIn: Driver<Bool>
) {
let API = dependency.API
let validationService = dependency.validationService
let wireframe = dependency.wireframe
/**
Notice how no subscribe call is being made.
Everything is just a definition.
Pure transformation of input sequences to output sequences.
When using `Driver`, underlying observable sequence elements are shared because
driver automagically adds "shareReplay(1)" under the hood.
.observeOn(MainScheduler.instance)
.catchErrorJustReturn(.Failed(message: "Error contacting server"))
... are squashed into single `.asDriver(onErrorJustReturn: .Failed(message: "Error contacting server"))`
*/
let validatedUsername = input.username
.flatMapLatest { username in
return validationService.validateUsername(username)
.asDriver(onErrorJustReturn: .failed(message: "Error contacting server"))
}
let validatedPassword = input.password
.map { password in
return validationService.validatePassword(password)
}
let validatedPasswordRepeated = Driver.combineLatest(input.password, input.repeatedPassword, resultSelector: validationService.validateRepeatedPassword)
let signingInActivityIndicator = ActivityIndicator()
let signingIn = signingInActivityIndicator.asDriver()
let usernameAndPassword = Driver.combineLatest(input.username, input.password) { (username: $0, password: $1) }
let signedIn = input.loginTaps.withLatestFrom(usernameAndPassword)
.flatMapLatest { pair in
return API.signup(pair.username, password: pair.password)
.trackActivity(signingInActivityIndicator)
.asDriver(onErrorJustReturn: false)
}
.flatMapLatest { loggedIn -> Driver<Bool> in
let message = loggedIn ? "Mock: Signed in to GitHub." : "Mock: Sign in to GitHub failed"
return wireframe.promptFor(message, cancelAction: "OK", actions: [])
// propagate original value
.map { _ in
loggedIn
}
.asDriver(onErrorJustReturn: false)
}
let signupEnabled = Driver.combineLatest(
validatedUsername,
validatedPassword,
validatedPasswordRepeated,
signingIn
) { username, password, repeatPassword, signingIn in
username.isValid &&
password.isValid &&
repeatPassword.isValid &&
!signingIn
}
.distinctUntilChanged()
return (
validatedUsername: validatedUsername,
validatedPassword: validatedPassword,
validatedPasswordRepeated: validatedPasswordRepeated,
signupEnabled: signupEnabled,
signedIn: signedIn,
signingIn: signingIn
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment