From 5967bd91c6eb3b5eb6716b87e595ed558bd7a52d Mon Sep 17 00:00:00 2001
From: kkostiuk <kateryna.kostiuk@savoirfairelinux.com>
Date: Tue, 20 Apr 2021 17:22:51 -0400
Subject: [PATCH] account: show when username available

Change-Id: I8300e04446b37c68d4c19b457125410507c09b5c
---
 Ring/Ring/Constants/Generated/Strings.swift   |  2 ++
 .../Features/Me/Me/MeViewController.swift     | 11 +++-----
 Ring/Ring/Features/Me/Me/MeViewModel.swift    |  4 ++-
 .../CreateAccountViewController.storyboard    | 26 ++++++++++++++-----
 .../CreateAccountViewController.swift         | 10 ++++++-
 .../CreateAccountViewModel.swift              | 21 ++++++++++++---
 .../Resources/en.lproj/Localizable.strings    |  1 +
 7 files changed, 56 insertions(+), 19 deletions(-)

diff --git a/Ring/Ring/Constants/Generated/Strings.swift b/Ring/Ring/Constants/Generated/Strings.swift
index 32308c53d..caa3c3ae7 100644
--- a/Ring/Ring/Constants/Generated/Strings.swift
+++ b/Ring/Ring/Constants/Generated/Strings.swift
@@ -370,6 +370,8 @@ internal enum L10n {
     internal static let usernameNotRegisteredMessage = L10n.tr("Localizable", "createAccount.UsernameNotRegisteredMessage")
     /// Network error
     internal static let usernameNotRegisteredTitle = L10n.tr("Localizable", "createAccount.UsernameNotRegisteredTitle")
+    /// username is available
+    internal static let usernameValid = L10n.tr("Localizable", "createAccount.usernameValid")
     /// Adding account
     internal static let waitCreateAccountTitle = L10n.tr("Localizable", "createAccount.waitCreateAccountTitle")
   }
diff --git a/Ring/Ring/Features/Me/Me/MeViewController.swift b/Ring/Ring/Features/Me/Me/MeViewController.swift
index a236c2c61..7fe8cbfc8 100644
--- a/Ring/Ring/Features/Me/Me/MeViewController.swift
+++ b/Ring/Ring/Features/Me/Me/MeViewController.swift
@@ -979,13 +979,10 @@ class MeViewController: EditProfileViewController, StoryboardBased, ViewModelBas
             .subscribe(onNext: { [weak controller] (state) in
                 //update name lookup message
                 guard let textFields = controller?.textFields,
-                    textFields.count >= 2 else { return }
-                if state.isAvailable {
-                    textFields[1].text = ""
-                } else {
-                    textFields[1].text = state.message
-                }
-                }, onError: { (_) in
+                      textFields.count >= 2 else { return }
+                textFields[1].text = state.message
+                textFields[1].textColor = state.isAvailable ? UIColor.jamiSuccess : UIColor.jamiFailure
+            }, onError: { (_) in
             })
             .disposed(by: nameRegistrationBag)
         guard let textFields = controller.textFields else {
diff --git a/Ring/Ring/Features/Me/Me/MeViewModel.swift b/Ring/Ring/Features/Me/Me/MeViewModel.swift
index 45de8c5a9..c2c9f5ac5 100644
--- a/Ring/Ring/Features/Me/Me/MeViewModel.swift
+++ b/Ring/Ring/Features/Me/Me/MeViewModel.swift
@@ -440,8 +440,10 @@ class MeViewModel: ViewModel, Stateable {
                     self?.usernameValidationState.accept(.invalid(message: L10n.CreateAccount.invalidUsername))
                 case .alreadyTaken:
                     self?.usernameValidationState.accept(.unavailable(message: L10n.CreateAccount.usernameAlreadyTaken))
+                case .valid:
+                    self?.usernameValidationState.accept(.available(message: L10n.CreateAccount.usernameValid))
                 default:
-                    self?.usernameValidationState.accept(.available)
+                    self?.usernameValidationState.accept(.unknown)
                 }
             })
             .disposed(by: disposeBug)
diff --git a/Ring/Ring/Features/Walkthrough/CreateAccount/CreateAccountViewController.storyboard b/Ring/Ring/Features/Walkthrough/CreateAccount/CreateAccountViewController.storyboard
index 54b444b78..2d8a58194 100644
--- a/Ring/Ring/Features/Walkthrough/CreateAccount/CreateAccountViewController.storyboard
+++ b/Ring/Ring/Features/Walkthrough/CreateAccount/CreateAccountViewController.storyboard
@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16096" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="jUh-Lp-ulu">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="jUh-Lp-ulu">
     <device id="retina5_5" orientation="portrait" appearance="light"/>
     <dependencies>
         <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
     <scenes>
@@ -70,8 +70,8 @@
                                                             <userDefinedRuntimeAttribute type="boolean" keyPath="roundedCorners" value="YES"/>
                                                         </userDefinedRuntimeAttributes>
                                                     </textField>
-                                                    <label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="this username is not available" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qDW-b2-4NQ">
-                                                        <rect key="frame" x="15" y="55" width="179" height="16"/>
+                                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qDW-b2-4NQ">
+                                                        <rect key="frame" x="15" y="55" width="0.0" height="0.0"/>
                                                         <fontDescription key="fontDescription" type="system" pointSize="13"/>
                                                         <color key="textColor" red="0.83137254900000002" green="0.054901960780000002" blue="0.070588235289999995" alpha="0.90000000000000002" colorSpace="custom" customColorSpace="calibratedRGB"/>
                                                         <nil key="highlightedColor"/>
@@ -173,12 +173,12 @@
                                                 <color key="onTintColor" red="0.12156862745098039" green="0.28627450980392155" blue="0.44313725490196076" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                             </switch>
                                             <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Enable notifications" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="v2K-7x-35g" userLabel="Enable Notifications Label">
-                                                <rect key="frame" x="30" y="210.66666666666666" width="151.66666666666666" height="21"/>
+                                                <rect key="frame" x="30" y="210.66666666666666" width="152" height="21"/>
                                                 <fontDescription key="fontDescription" type="system" weight="thin" pointSize="18"/>
                                                 <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="0.5" colorSpace="custom" customColorSpace="sRGB"/>
                                                 <nil key="highlightedColor"/>
                                             </label>
-                                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="05l-0O-Ql0" customClass="DesignableButton" customModule="Ring" customModuleProvider="target">
+                                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="05l-0O-Ql0" customClass="DesignableButton" customModule="Ring" customModuleProvider="target">
                                                 <rect key="frame" x="20" y="266.66666666666669" width="374" height="50"/>
                                                 <constraints>
                                                     <constraint firstAttribute="height" relation="greaterThanOrEqual" constant="50" id="501-bI-E5J"/>
@@ -275,4 +275,18 @@
             <point key="canvasLocation" x="1944.8" y="563.56821589205401"/>
         </scene>
     </scenes>
+    <designables>
+        <designable name="05l-0O-Ql0">
+            <size key="intrinsicContentSize" width="121" height="34"/>
+        </designable>
+        <designable name="E18-Hh-7He">
+            <size key="intrinsicContentSize" width="81" height="23.333333333333332"/>
+        </designable>
+        <designable name="ODL-4B-fCm">
+            <size key="intrinsicContentSize" width="142.33333333333334" height="22"/>
+        </designable>
+        <designable name="jhr-UL-eCl">
+            <size key="intrinsicContentSize" width="75.333333333333329" height="22"/>
+        </designable>
+    </designables>
 </document>
diff --git a/Ring/Ring/Features/Walkthrough/CreateAccount/CreateAccountViewController.swift b/Ring/Ring/Features/Walkthrough/CreateAccount/CreateAccountViewController.swift
index 6e15130fa..bb8b01a5a 100644
--- a/Ring/Ring/Features/Walkthrough/CreateAccount/CreateAccountViewController.swift
+++ b/Ring/Ring/Features/Walkthrough/CreateAccount/CreateAccountViewController.swift
@@ -230,7 +230,7 @@ class CreateAccountViewController: UIViewController, StoryboardBased, ViewModelB
 
         // handle registration error
         self.viewModel.usernameValidationState.asObservable()
-            .map { $0.isAvailable }
+            .map { $0.isDefault }
             .skipUntil(self.usernameTextField.rx.controlEvent(UIControl.Event.editingDidBegin))
             .bind(to: self.registerUsernameErrorLabel.rx.isHidden)
             .disposed(by: self.disposeBag)
@@ -239,6 +239,14 @@ class CreateAccountViewController: UIViewController, StoryboardBased, ViewModelB
             .skipUntil(self.usernameTextField.rx.controlEvent(UIControl.Event.editingDidBegin))
             .bind(to: self.registerUsernameErrorLabel.rx.text)
             .disposed(by: self.disposeBag)
+        self.viewModel.usernameValidationState.asObservable()
+            .map { $0.isAvailable }
+            .skipUntil(self.usernameTextField.rx.controlEvent(UIControl.Event.editingDidBegin))
+            .observeOn(MainScheduler.instance)
+            .subscribe { [weak self] available in
+                self?.registerUsernameErrorLabel.textColor = available ? UIColor.jamiSuccess : UIColor.jamiFailure
+            }
+            .disposed(by: self.disposeBag)
 
         // handle creation state
         self.viewModel.createState
diff --git a/Ring/Ring/Features/Walkthrough/CreateAccount/CreateAccountViewModel.swift b/Ring/Ring/Features/Walkthrough/CreateAccount/CreateAccountViewModel.swift
index 7ef494f9b..301586fe4 100644
--- a/Ring/Ring/Features/Walkthrough/CreateAccount/CreateAccountViewModel.swift
+++ b/Ring/Ring/Features/Walkthrough/CreateAccount/CreateAccountViewModel.swift
@@ -48,14 +48,23 @@ enum PasswordValidationState {
 
 enum UsernameValidationState {
     case unknown
-    case available
+    case available(message: String)
     case lookingForAvailibility(message: String)
     case invalid(message: String)
     case unavailable(message: String)
 
     var isAvailable: Bool {
         switch self {
-        case .available, .unknown:
+        case .available:
+            return true
+        default:
+            return false
+        }
+    }
+
+    var isDefault: Bool {
+        switch self {
+        case .unknown:
             return true
         default:
             return false
@@ -64,8 +73,10 @@ enum UsernameValidationState {
 
     var message: String {
         switch self {
-        case .available, .unknown:
+        case .unknown:
             return ""
+        case .available(let message):
+            return message
         case .lookingForAvailibility(let message):
             return message
         case .invalid(let message):
@@ -274,8 +285,10 @@ class CreateAccountViewModel: Stateable, ViewModel {
                     self?.usernameValidationState.accept(.invalid(message: L10n.CreateAccount.invalidUsername))
                 case .alreadyTaken:
                     self?.usernameValidationState.accept(.unavailable(message: L10n.CreateAccount.usernameAlreadyTaken))
+                case .valid:
+                    self?.usernameValidationState.accept(.available(message: L10n.CreateAccount.usernameValid))
                 default:
-                    self?.usernameValidationState.accept(.available)
+                    self?.usernameValidationState.accept(.unknown)
                 }
             })
             .disposed(by: self.disposeBag)
diff --git a/Ring/Ring/Resources/en.lproj/Localizable.strings b/Ring/Ring/Resources/en.lproj/Localizable.strings
index bace2cca5..c44b4d6a7 100644
--- a/Ring/Ring/Resources/en.lproj/Localizable.strings
+++ b/Ring/Ring/Resources/en.lproj/Localizable.strings
@@ -83,6 +83,7 @@
 "createAccount.lookingForUsernameAvailability" = "looking for availability…";
 "createAccount.invalidUsername" = "invalid username";
 "createAccount.usernameAlreadyTaken" = "username already taken";
+"createAccount.usernameValid" = "username is available";
 "createAccount.loading" = "Loading";
 "createAccount.waitCreateAccountTitle" = "Adding account";
 "createAccount.RegisterAUsername" = "Register a username";
-- 
GitLab