Commit 5423a46c authored by Kateryna Kostiuk's avatar Kateryna Kostiuk

UI/UX: name registration

Currently application can be used right after account creation.
It could be confused for user because name registration will be
finished after or failed at all. This patch ensure that application
receive registering name answer before completing account creation
process. This could introduce longer time for account creation
but user would have better understanding of account state.

Change-Id: I317b98624b1943bddb35859557beed9160016023
parent 0ccf6e2f
......@@ -251,6 +251,10 @@ internal enum L10n {
internal static let repeatPasswordPlaceholder = L10n.tr("Localizable", "createAccount.repeatPasswordPlaceholder")
/// username already taken
internal static let usernameAlreadyTaken = L10n.tr("Localizable", "createAccount.usernameAlreadyTaken")
/// Account was created but username was not registered
internal static let usernameNotRegisteredMessage = L10n.tr("Localizable", "createAccount.UsernameNotRegisteredMessage")
/// Network error
internal static let usernameNotRegisteredTitle = L10n.tr("Localizable", "createAccount.UsernameNotRegisteredTitle")
/// Adding account
internal static let waitCreateAccountTitle = L10n.tr("Localizable", "createAccount.waitCreateAccountTitle")
}
......
......@@ -205,6 +205,9 @@ class CreateAccountViewController: UIViewController, StoryboardBased, ViewModelB
self?.showAccountCreationInProgress()
case .success:
self?.hideAccountCreationHud()
case .nameNotRegistered:
self?.hideAccountCreationHud()
self?.showNameNotRegistered()
default:
self?.hideAccountCreationHud()
}
......@@ -285,4 +288,18 @@ class CreateAccountViewController: UIViewController, StoryboardBased, ViewModelB
alert.addAction(UIAlertAction.init(title: L10n.Global.ok, style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
private func showNameNotRegistered() {
let alert = UIAlertController
.init(title: L10n.CreateAccount.usernameNotRegisteredTitle,
message: L10n.CreateAccount.usernameNotRegisteredMessage,
preferredStyle: .alert)
let okAction =
UIAlertAction(title: L10n.Global.ok,
style: .default) { [weak self](_: UIAlertAction!) -> Void in
self?.viewModel.finish()
}
alert.addAction(okAction)
self.present(alert, animated: true, completion: nil)
}
}
......@@ -79,6 +79,7 @@ enum AccountCreationState {
case unknown
case started
case success
case nameNotRegistered
case error(error: AccountCreationError)
var isInProgress: Bool {
......@@ -268,15 +269,33 @@ class CreateAccountViewModel: Stateable, ViewModel {
let password = self.password.value
self.accountService
.addRingAccount(username: username, password: password, enable: self.notificationSwitch.value)
.addRingAccount(username: username,
password: password,
enable: self.notificationSwitch.value)
.subscribe(onNext: { [unowned self] (account) in
self.accountCreationState.value = .success
DispatchQueue.main.async {
self.stateSubject.onNext(WalkthroughState.accountCreated)
if username.isEmpty {
self.accountCreationState.value = .success
DispatchQueue.main.async {
self.stateSubject.onNext(WalkthroughState.accountCreated)
}
return
}
self.nameService.registerName(withAccount: account.id,
password: password,
name: username)
self.nameService.registerNameObservable(withAccount: account.id,
password: password,
name: username)
.subscribe(onNext: { registered in
if registered {
self.accountCreationState.value = .success
DispatchQueue.main.async {
self.stateSubject
.onNext(WalkthroughState.accountCreated)
}
} else {
self.accountCreationState.value = .nameNotRegistered
}
}, onError: { _ in
self.accountCreationState.value = .nameNotRegistered
}).disposed(by: self.disposeBag)
}, onError: { [unowned self] (error) in
if let error = error as? AccountCreationError {
self.accountCreationState.value = .error(error: error)
......@@ -288,6 +307,10 @@ class CreateAccountViewModel: Stateable, ViewModel {
self.enablePushNotifications(enable: self.notificationSwitch.value)
}
func finish() {
self.stateSubject.onNext(WalkthroughState.accountCreated)
}
func enablePushNotifications(enable: Bool) {
if !enable {
return
......
......@@ -84,6 +84,8 @@
"createAccount.PasswordInformation" = "Choose a password to encrypt your local account. Don’t forget it or you will not be able to recover your account";
"createAccount.EnableNotifications" = "Notifications";
"createAccount.Recommended" = "(Recommended)";
"createAccount.UsernameNotRegisteredTitle" = "Network error";
"createAccount.UsernameNotRegisteredMessage" = "Account was created but username was not registered";
//Link To Account form
"linkToAccount.waitLinkToAccountTitle" = "Account linking";
......
......@@ -53,9 +53,12 @@ class NameService: NameRegistrationAdapterDelegate {
Status of the current username validation request
*/
var usernameValidationStatus = PublishSubject<UsernameValidationStatus>()
fileprivate let registrationStatus = PublishSubject<ServiceEvent>()
var sharedRegistrationStatus: Observable<ServiceEvent>
init(withNameRegistrationAdapter nameRegistrationAdapter: NameRegistrationAdapter) {
self.nameRegistrationAdapter = nameRegistrationAdapter
self.sharedRegistrationStatus = registrationStatus.share()
NameRegistrationAdapter.delegate = self
}
......@@ -103,6 +106,39 @@ class NameService: NameRegistrationAdapterDelegate {
self.nameRegistrationAdapter.registerName(withAccount: account, password: password, name: name)
}
func registerNameObservable(withAccount account: String, password: String, name: String)-> Observable<Bool> {
let registerName: Single<Bool> =
Single.create(subscribe: { (single) -> Disposable in
self.nameRegistrationAdapter
.registerName(withAccount: account,
password: password,
name: name)
single(.success(true))
return Disposables.create {
}
})
let filteredDaemonSignals = self.sharedRegistrationStatus
.filter { (serviceEvent) -> Bool in
if serviceEvent.getEventInput(ServiceEventInput.accountId) != account {return false}
if serviceEvent.eventType != .nameRegistrationEnded {
return false
}
return true
}
return Observable
.combineLatest(registerName.asObservable(), filteredDaemonSignals.asObservable()) { (_, serviceEvent) -> Bool in
guard let status: NameRegistrationState = serviceEvent.getEventInput(ServiceEventInput.state)
else {return false}
switch status {
case .success:
return true
default:
return false
}
}
}
// MARK: NameService delegate
internal func registeredNameFound(with response: LookupNameResponse) {
......@@ -132,5 +168,9 @@ class NameService: NameRegistrationAdapterDelegate {
} else {
log.debug("Name Registration failed. State = \(response.state.rawValue)")
}
var event = ServiceEvent(withEventType: .nameRegistrationEnded)
event.addEventInput(.state, value: response.state)
event.addEventInput(.accountId, value: response.accountId)
self.registrationStatus.onNext(event)
}
}
......@@ -43,6 +43,7 @@ enum ServiceEventType {
case dataTransferMessageUpdated
case deviceRevocationEnded
case newIncomingMessage
case nameRegistrationEnded
}
/**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment