<commit_before>import ReactiveCocoa
import Result
import KsApi
import Models
import struct Library.Environment
import struct Library.AppEnvironment

protocol LoginViewModelInputs {
  var email: MutableProperty<String?> { get }
  var password: MutableProperty<String?> { get }
  func loginPressed()
}

protocol LoginViewModelOutputs {
  var isValid: MutableProperty<Bool> { get }
  var loggedIn: Signal<(), NoError> { get }
}

protocol LoginViewModelErrors {
  var invalidLogin: Signal<String, NoError> { get }
  var genericError: Signal<(), NoError> { get }
  var tfaChallenge: Signal<(), NoError> { get }
}

final class LoginViewModel : LoginViewModelInputs, LoginViewModelOutputs, LoginViewModelErrors {
  // MARK: Inputs
  let email = MutableProperty<String?>(nil)
  let password = MutableProperty<String?>(nil)
  private var (loginPress, loginPressObserver) = Signal<(), NoError>.pipe()
  func loginPressed() { loginPressObserver.sendNext(()) }
  var inputs: LoginViewModelInputs { return self }

  // MARK: Outputs
  let isValid = MutableProperty(false)
  let loggedIn: Signal<(), NoError>
  var outputs: LoginViewModelOutputs { return self }

  // MARK: Errors
  let invalidLogin: Signal<String, NoError>
  let genericError: Signal<(), NoError>
  let tfaChallenge: Signal<(), NoError>
  var errors: LoginViewModelErrors { return self }

  init(env: Environment = AppEnvironment.current) {
    let apiService = env.apiService
    let currentUser = env.currentUser

    let (loggedInSignal, loggedInObserver) = Signal<(), NoError>.pipe()
    loggedIn = loggedInSignal

    let (errors, errorsObserver) = Signal<ErrorEnvelope, NoError>.pipe()

    invalidLogin = errors.filter { $0.ksrCode == .InvalidXauthLogin }.map { $0.errorMessages.first }.ignoreNil()
    tfaChallenge = errors.filter { $0.ksrCode == .TfaRequired }.ignoreValues()
    genericError = errors.filter { $0.ksrCode != .InvalidXauthLogin && $0.ksrCode != .TfaRequired }.ignoreValues()

    let emailAndPassword = email.producer.ignoreNil()
      .combineLatestWith(password.producer.ignoreNil())
      .map { ep in (email: ep.0, password: ep.1) }

    isValid <~ emailAndPassword.map(isValid)

    emailAndPassword.takeWhen(loginPress)
      .filter(isValid)
      .flatMap { ep in apiService.login(email: ep.0, password: ep.1).demoteErrors(errorsObserver) }
      .start { event in
        switch event {
        case let .Next(envelope):
          currentUser.login(envelope.user, accessToken: envelope.accessToken)
          loggedInObserver.sendNext(())
        default:
          print("")
        }
    }
  }<commit_msg>Fix for demoteErrors api change.<commit_after>import ReactiveCocoa
import Result
import KsApi
import Models
import struct Library.Environment
import struct Library.AppEnvironment

protocol LoginViewModelInputs {
  var email: MutableProperty<String?> { get }
  var password: MutableProperty<String?> { get }
  func loginPressed()
}

protocol LoginViewModelOutputs {
  var isValid: MutableProperty<Bool> { get }
  var loggedIn: Signal<(), NoError> { get }
}

protocol LoginViewModelErrors {
  var invalidLogin: Signal<String, NoError> { get }
  var genericError: Signal<(), NoError> { get }
  var tfaChallenge: Signal<(), NoError> { get }
}

final class LoginViewModel : LoginViewModelInputs, LoginViewModelOutputs, LoginViewModelErrors {
  // MARK: Inputs
  let email = MutableProperty<String?>(nil)
  let password = MutableProperty<String?>(nil)
  private var (loginPress, loginPressObserver) = Signal<(), NoError>.pipe()
  func loginPressed() { loginPressObserver.sendNext(()) }
  var inputs: LoginViewModelInputs { return self }

  // MARK: Outputs
  let isValid = MutableProperty(false)
  let loggedIn: Signal<(), NoError>
  var outputs: LoginViewModelOutputs { return self }

  // MARK: Errors
  let invalidLogin: Signal<String, NoError>
  let genericError: Signal<(), NoError>
  let tfaChallenge: Signal<(), NoError>
  var errors: LoginViewModelErrors { return self }

  init(env: Environment = AppEnvironment.current) {
    let apiService = env.apiService
    let currentUser = env.currentUser

    let (loggedInSignal, loggedInObserver) = Signal<(), NoError>.pipe()
    loggedIn = loggedInSignal

    let (errors, errorsObserver) = Signal<ErrorEnvelope, NoError>.pipe()

    invalidLogin = errors.filter { $0.ksrCode == .InvalidXauthLogin }.map { $0.errorMessages.first }.ignoreNil()
    tfaChallenge = errors.filter { $0.ksrCode == .TfaRequired }.ignoreValues()
    genericError = errors.filter { $0.ksrCode != .InvalidXauthLogin && $0.ksrCode != .TfaRequired }.ignoreValues()

    let emailAndPassword = email.producer.ignoreNil()
      .combineLatestWith(password.producer.ignoreNil())
      .map { ep in (email: ep.0, password: <PASSWORD>) }

    isValid <~ emailAndPassword.map(isValid)

    emailAndPassword.takeWhen(loginPress)
      .filter(isValid)
      .flatMap { ep in apiService.login(email: ep.0, password: <PASSWORD>).demoteErrors(pipeErrorsTo: errorsObserver) }
      .start { event in
        switch event {
        case let .Next(envelope):
          currentUser.login(envelope.user, accessToken: envelope.accessToken)
          loggedInObserver.sendNext(())
        default:
          print("")
        }
    }
  }
{'fraction_non_alphanumeric': 0.11384909264565425, 'fraction_numerical': 0.0030563514804202484, 'mean_word_length': 4.068731848983543, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2005281', 'n_tokens_mistral': 1610, 'n_tokens_neox': 1547, 'n_words': 387}