From 7da0db38b162ad9cb8e346d79e85b057e3b4639f Mon Sep 17 00:00:00 2001
From: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
Date: Fri, 27 Oct 2017 15:23:52 -0400
Subject: [PATCH] UI/UX: fix username and ringId appearance

Because Account View Model is created at the very beginning of app
launching, it is possible to create it when account does not exists.
This patch makes variables lazy, so all values will be rendered when
screen become visible. Also it adds name lookup, account does not have
username.

Change-Id: Ia4747bdb2efaffd8b0f39109407946e736ab09e5
Reviewed-by: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
---
 .../Me/Me/MeViewController.storyboard         | 11 ++--
 .../Features/Me/Me/MeViewController.swift     |  2 +-
 Ring/Ring/Features/Me/Me/MeViewModel.swift    | 54 ++++++++++++++-----
 3 files changed, 47 insertions(+), 20 deletions(-)

diff --git a/Ring/Ring/Features/Me/Me/MeViewController.storyboard b/Ring/Ring/Features/Me/Me/MeViewController.storyboard
index 095ce3c19..007de3fae 100644
--- a/Ring/Ring/Features/Me/Me/MeViewController.storyboard
+++ b/Ring/Ring/Features/Me/Me/MeViewController.storyboard
@@ -27,12 +27,12 @@
                         <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                         <subviews>
-                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Ring id" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="11" translatesAutoresizingMaskIntoConstraints="NO" id="rC6-Ga-QjY" userLabel="RingId Label">
-                                <rect key="frame" x="21" y="249" width="333" height="18"/>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Ring id" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="11" translatesAutoresizingMaskIntoConstraints="NO" id="rC6-Ga-QjY" userLabel="RingId Label">
+                                <rect key="frame" x="21" y="209" width="333" height="18"/>
                                 <constraints>
                                     <constraint firstAttribute="height" constant="18" id="UsR-G7-bkE"/>
                                 </constraints>
-                                <fontDescription key="fontDescription" type="system" pointSize="13"/>
+                                <fontDescription key="fontDescription" type="system" pointSize="14"/>
                                 <color key="textColor" red="0.29803922770000002" green="0.29803922770000002" blue="0.29803922770000002" alpha="1" colorSpace="calibratedRGB"/>
                                 <nil key="highlightedColor"/>
                             </label>
@@ -75,13 +75,14 @@
                             </label>
                             <imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="ic_contact_picture" translatesAutoresizingMaskIntoConstraints="NO" id="8HY-Zl-94u">
                                 <rect key="frame" x="137" y="70" width="100" height="100"/>
+                                <rect key="frame" x="137" y="30" width="100" height="100"/>
                                 <constraints>
                                     <constraint firstAttribute="height" constant="100" id="3Ik-A7-Cyx"/>
                                     <constraint firstAttribute="width" constant="100" id="xE6-h0-miE"/>
                                 </constraints>
                             </imageView>
-                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="PERSON  PLACEHOLDER" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="w8x-Sv-T50">
-                                <rect key="frame" x="21" y="272" width="333" height="23"/>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Username is not registered" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="w8x-Sv-T50">
+                                <rect key="frame" x="21" y="232" width="333" height="23"/>
                                 <fontDescription key="fontDescription" type="system" pointSize="19"/>
                                 <color key="textColor" red="0.20000000300000001" green="0.20000000300000001" blue="0.20000000300000001" alpha="1" colorSpace="calibratedRGB"/>
                                 <nil key="highlightedColor"/>
diff --git a/Ring/Ring/Features/Me/Me/MeViewController.swift b/Ring/Ring/Features/Me/Me/MeViewController.swift
index e4d3079d6..2f3db4053 100644
--- a/Ring/Ring/Features/Me/Me/MeViewController.swift
+++ b/Ring/Ring/Features/Me/Me/MeViewController.swift
@@ -45,7 +45,7 @@ class MeViewController: EditProfileViewController, StoryboardBased, ViewModelBas
     }
 
     override func setupUI() {
-        self.viewModel.userName.asObservable()
+        self.viewModel.userName
             .bind(to: self.nameLabel.rx.text)
             .disposed(by: disposeBag)
 
diff --git a/Ring/Ring/Features/Me/Me/MeViewModel.swift b/Ring/Ring/Features/Me/Me/MeViewModel.swift
index 76a44a111..b9d9fefd7 100644
--- a/Ring/Ring/Features/Me/Me/MeViewModel.swift
+++ b/Ring/Ring/Features/Me/Me/MeViewModel.swift
@@ -73,25 +73,48 @@ class MeViewModel: ViewModel, Stateable {
     // MARK: - Rx Stateable
     private let stateSubject = PublishSubject<State>()
 
-    var userName: Single<String?>
-    let ringId: Single<String?>
+    lazy var userName: Observable<String?> = {
+        // return username if exists, is no start name lookup
+        let accountName = self.accountService.currentAccount?.volatileDetails?.get(withConfigKeyModel: ConfigKeyModel(withKey: ConfigKey.accountRegisteredName))
+        if accountName != nil && !accountName!.isEmpty {
+            return Observable.from(optional: accountName)
+        }
+        guard let account = self.accountService.currentAccount else {
+            return Observable.from(optional: accountName)
+        }
+        let accountHelper = AccountModelHelper(withAccount: account)
+        guard let uri = accountHelper.ringId else {
+            return Observable.from(optional: accountName)
+        }
+        let time = DispatchTime.now() + 2
+        DispatchQueue.main.asyncAfter(deadline: time) {
+            self.nameService.lookupAddress(withAccount: "", nameserver: "", address: uri)
+        }
+        return self.nameService.usernameLookupStatus
+            .filter({ lookupNameResponse in
+                return lookupNameResponse.address != nil &&
+                    lookupNameResponse.address == uri && lookupNameResponse.state == .found
+            })
+            .map({ lookupNameResponse in
+                return lookupNameResponse.name
+            })
+    }()
+
+    lazy var ringId: Observable<String?> = {
+        return Observable.from(optional: self.accountService.currentAccount?.details?.get(withConfigKeyModel: ConfigKeyModel(withKey: .accountUsername)))
+    }()
 
     lazy var state: Observable<State> = {
         return self.stateSubject.asObservable()
     }()
-
     let disposeBag = DisposeBag()
 
     let accountService: AccountsService
+    let nameService: NameService
 
     //table section
-    var settings: Observable<[SettingsSection]> = Observable.just([SettingsSection]())
-
-    required init(with injectionBag: InjectionBag) {
-        self.accountService = injectionBag.accountService
-        self.userName = Single.just(accountService.currentAccount?.volatileDetails?.get(withConfigKeyModel: ConfigKeyModel(withKey: ConfigKey.accountRegisteredName)))
-        self.ringId = Single.just(accountService.currentAccount?.details?.get(withConfigKeyModel: ConfigKeyModel(withKey: .accountUsername)))
-        if let account = accountService.currentAccount {
+    lazy var settings: Observable<[SettingsSection]> = {
+        if let account = self.accountService.currentAccount {
             let accountHelper = AccountModelHelper(withAccount: account)
             let uri = accountHelper.ringId
             let devices = Observable.from(optional: account.devices)
@@ -104,15 +127,12 @@ class MeViewModel: ViewModel, Stateable {
                     return account.devices
                 })
 
-            self.settings = devices.concat(accountDevice)
+            return devices.concat(accountDevice)
                 .map { devices in
-
                     let addNewDevice = SettingsSection.linkNewDevice(header: "", items: [SettingsSection.SectionRow.linkNew])
-
                     var rows: [SettingsSection.SectionRow]?
 
                     if !devices.isEmpty {
-
                         rows = [SettingsSection.SectionRow.device(device: devices[0])]
                         for i in 1 ..< devices.count {
                             let device = devices[i]
@@ -128,6 +148,12 @@ class MeViewModel: ViewModel, Stateable {
                     }
             }
         }
+        return Observable.just([SettingsSection]())
+    }()
+
+    required init (with injectionBag: InjectionBag) {
+        self.accountService = injectionBag.accountService
+        self.nameService = injectionBag.nameService
     }
 
     func linkDevice() {
-- 
GitLab