From f62a36ac5423489a59954c8cb721b8257ac67081 Mon Sep 17 00:00:00 2001
From: Ming Rui Zhang <mingrui.zhang@savoirfairelinux.com>
Date: Mon, 2 Nov 2020 11:44:20 -0500
Subject: [PATCH] wizardview: make user avatar in profile page change
 accordingly

Gitlab: #161
Change-Id: I79d8f5e28f2025bd685ea760cd813eeca2e60c8b
---
 src/accountadapter.cpp                    | 33 +++++++++------
 src/accountadapter.h                      |  3 +-
 src/avatarimageprovider.h                 |  6 ++-
 src/commoncomponents/AvatarImage.qml      | 15 +++----
 src/commoncomponents/PhotoboothView.qml   | 50 +++++++++++++++--------
 src/wizardview/WizardView.qml             |  8 +++-
 src/wizardview/components/ProfilePage.qml | 38 +++++++++++++----
 7 files changed, 105 insertions(+), 48 deletions(-)

diff --git a/src/accountadapter.cpp b/src/accountadapter.cpp
index 545eff0a7..ebf0de238 100644
--- a/src/accountadapter.cpp
+++ b/src/accountadapter.cpp
@@ -100,21 +100,28 @@ AccountAdapter::createJamiAccount(QString registeredName,
                               && !AppSettingsManager::getValue(Settings::Key::NeverShowMeAgain)
                                       .toBool();
             if (!registeredName.isEmpty()) {
-                Utils::oneShotConnect(&LRCInstance::accountModel(),
-                                      &lrc::api::NewAccountModel::nameRegistrationEnded,
-                                      [this, showBackup](const QString& accountId) {
-                                          emit LRCInstance::instance().accountListChanged();
-                                          emit accountAdded(showBackup,
-                                                            LRCInstance::accountModel()
-                                                                .getAccountList()
-                                                                .indexOf(accountId));
-                                      });
+                QObject::disconnect(registeredNameSavedConnection_);
+                registeredNameSavedConnection_ = connect(
+                    &LRCInstance::accountModel(),
+                    &lrc::api::NewAccountModel::profileUpdated,
+                    [this, showBackup, addedAccountId = accountId](const QString& accountId) {
+                        if (addedAccountId == accountId) {
+                            emit LRCInstance::instance().accountListChanged();
+                            emit accountAdded(accountId,
+                                              showBackup,
+                                              LRCInstance::accountModel().getAccountList().indexOf(
+                                                  accountId));
+                            QObject::disconnect(registeredNameSavedConnection_);
+                        }
+                    });
+
                 LRCInstance::accountModel().registerName(accountId,
                                                          settings["password"].toString(),
                                                          registeredName);
             } else {
                 emit LRCInstance::instance().accountListChanged();
-                emit accountAdded(showBackup,
+                emit accountAdded(accountId,
+                                  showBackup,
                                   LRCInstance::accountModel().getAccountList().indexOf(accountId));
             }
 
@@ -175,7 +182,8 @@ AccountAdapter::createSIPAccount(const QVariantMap& settings, QString photoBooth
                               }
 
                               emit LRCInstance::instance().accountListChanged();
-                              emit accountAdded(false,
+                              emit accountAdded(accountId,
+                                                false,
                                                 LRCInstance::accountModel().getAccountList().indexOf(
                                                     accountId));
                           });
@@ -206,7 +214,8 @@ AccountAdapter::createJAMSAccount(const QVariantMap& settings)
                               Q_UNUSED(accountId)
                               if (!LRCInstance::accountModel().getAccountList().size())
                                   return;
-                              emit accountAdded(false,
+                              emit accountAdded(accountId,
+                                                false,
                                                 LRCInstance::accountModel().getAccountList().indexOf(
                                                     accountId));
                               emit LRCInstance::instance().accountListChanged();
diff --git a/src/accountadapter.h b/src/accountadapter.h
index 562c38e92..4405e345e 100644
--- a/src/accountadapter.h
+++ b/src/accountadapter.h
@@ -112,7 +112,7 @@ signals:
      * send report failure to QML to make it show the right UI state .
      */
     void reportFailure();
-    void accountAdded(bool showBackUp, int index);
+    void accountAdded(QString accountId, bool showBackUp, int index);
     void contactUnbanned();
 
 private slots:
@@ -145,5 +145,6 @@ private:
     QMetaObject::Connection addedToConferenceConnection_;
     QMetaObject::Connection accountProfileChangedConnection_;
     QMetaObject::Connection contactUnbannedConnection_;
+    QMetaObject::Connection registeredNameSavedConnection_;
 };
 Q_DECLARE_METATYPE(AccountAdapter*)
diff --git a/src/avatarimageprovider.h b/src/avatarimageprovider.h
index b0cafc1c2..336a22bb3 100644
--- a/src/avatarimageprovider.h
+++ b/src/avatarimageprovider.h
@@ -49,7 +49,7 @@ public:
         // Id content -> every after account_
         auto idContent = id.mid(id.indexOf(idType) + idType.length() + 1);
 
-        if (idContent.isEmpty())
+        if (idContent.isEmpty() && idType != "default")
             return QImage();
 
         if (idType == "account") {
@@ -61,6 +61,10 @@ public:
             return Utils::contactPhoto(conv.participants[0], requestedSize);
         } else if (idType == "contact") {
             return Utils::contactPhoto(idContent, requestedSize);
+        } else if (idType == "fallback") {
+            return Utils::fallbackAvatar(QString(), idContent, requestedSize);
+        } else if (idType == "default") {
+            return Utils::fallbackAvatar(QString(), QString(), requestedSize);
         } else {
             auto image = Utils::cropImage(QImage(idContent));
             return image.scaled(requestedSize,
diff --git a/src/commoncomponents/AvatarImage.qml b/src/commoncomponents/AvatarImage.qml
index 28497a438..715350128 100644
--- a/src/commoncomponents/AvatarImage.qml
+++ b/src/commoncomponents/AvatarImage.qml
@@ -31,6 +31,7 @@ Item {
         FromContactUri,
         FromConvUid,
         FromUrl,
+        FromTemporaryName,
         Default
     }
 
@@ -47,6 +48,10 @@ Item {
             return "contact_"
         case AvatarImage.Mode.FromConvUid:
             return "conversation_"
+        case AvatarImage.Mode.FromTemporaryName:
+            return "fallback_"
+        case AvatarImage.Mode.Default:
+            return "default_"
         default:
             return ""
         }
@@ -56,7 +61,6 @@ Item {
     property string imageProviderUrl: "image://avatarImage/" + forceUpdateUrl + "_" +
                                       imageProviderIdPrefix
     property string imageId: ""
-    property string defaultImgUrl: "qrc:/images/default_avatar_overlay.svg"
     property string forceUpdateUrl: Date.now()
     property alias presenceStatus: presenceIndicator.status
     property bool showPresenceIndicator: true
@@ -73,15 +77,10 @@ Item {
 
         if (mode === AvatarImage.Mode.FromUrl)
             rootImage.source = imageId
-        else if (imageId)
+        else
             rootImage.source = imageProviderUrl + imageId
     }
 
-    onModeChanged: {
-        if (mode === AvatarImage.Mode.Default)
-            rootImage.source = defaultImgUrl
-    }
-
     Image {
         id: rootImage
 
@@ -89,6 +88,7 @@ Item {
 
         smooth: false
         antialiasing: true
+        asynchronous: true
 
         sourceSize.width: Math.max(24, width)
         sourceSize.height: Math.max(24, height)
@@ -115,6 +115,7 @@ Item {
 
             smooth: false
             antialiasing: true
+            asynchronous: true
 
             sourceSize.width: Math.max(24, width)
             sourceSize.height: Math.max(24, height)
diff --git a/src/commoncomponents/PhotoboothView.qml b/src/commoncomponents/PhotoboothView.qml
index 1b7e2a0ef..c375d4546 100644
--- a/src/commoncomponents/PhotoboothView.qml
+++ b/src/commoncomponents/PhotoboothView.qml
@@ -8,8 +8,8 @@ import net.jami.Models 1.0
 import net.jami.Adapters 1.0
 
 ColumnLayout {
-    property bool takePhotoState: false
-    property bool hasAvatar: false
+    property int photoState: PhotoboothView.PhotoState.Default
+    property bool avatarSet: false
     // saveToConfig is to specify whether the image should be saved to account config
     property bool saveToConfig: false
     property string fileName: ""
@@ -17,14 +17,25 @@ ColumnLayout {
 
     property int boothWidth: 224
 
+    enum PhotoState {
+        Default = 0,
+        CameraRendering,
+        Taken
+    }
+
     readonly property int size: boothWidth +
                                 buttonsRowLayout.height +
                                 JamiTheme.preferredMarginSize / 2
 
-    function startBooth(force = false){
-        hasAvatar = false
+    function initUI() {
+        photoState = PhotoboothView.PhotoState.Default
+        avatarSet = false
+        setAvatarImage(AvatarImage.Mode.Default, "")
+    }
+
+    function startBooth(force = false) {
         AccountAdapter.startPreviewing(force)
-        takePhotoState = true
+        photoState = PhotoboothView.PhotoState.CameraRendering
     }
 
     function stopBooth(){
@@ -33,17 +44,18 @@ ColumnLayout {
                 AccountAdapter.stopPreviewing()
             }
         } catch(erro){console.log("Exception: " +  erro.message)}
-
-        takePhotoState = false
     }
 
     function setAvatarImage(mode = AvatarImage.Mode.FromAccount,
                             imageId = AccountAdapter.currentAccountId){
-        if (mode === AvatarImage.Mode.Default)
-            boothImg = ""
-
         avatarImg.mode = mode
 
+        if (mode === AvatarImage.Mode.Default) {
+            boothImg = ""
+            avatarImg.updateImage(imageId)
+            return
+        }
+
         if (imageId)
             avatarImg.updateImage(imageId)
     }
@@ -67,6 +79,9 @@ ColumnLayout {
                 "All files") + " (*)"]
 
         onAccepted: {
+            avatarSet = true
+            photoState = PhotoboothView.PhotoState.Default
+
             fileName = file
             if (fileName.length === 0) {
                 SettingsAdapter.clearCurrentAvatar()
@@ -82,7 +97,7 @@ ColumnLayout {
     Label {
         id: avatarLabel
 
-        visible: !takePhotoState
+        visible: photoState !== PhotoboothView.PhotoState.CameraRendering
 
         Layout.fillWidth: true
         Layout.maximumWidth: boothWidth
@@ -101,8 +116,6 @@ ColumnLayout {
 
                 anchors.fill: parent
 
-                imageId: AccountAdapter.currentAccountId
-
                 showPresenceIndicator: false
 
                 fillMode: Image.PreserveAspectCrop
@@ -139,7 +152,7 @@ ColumnLayout {
 
         onHideBooth: stopBooth()
 
-        visible: takePhotoState
+        visible: photoState === PhotoboothView.PhotoState.CameraRendering
         focus: visible
 
         Layout.alignment: Qt.AlignHCenter
@@ -201,12 +214,12 @@ ColumnLayout {
 
             radius: height / 6
             source: {
-                if(takePhotoState) {
+                if(photoState === PhotoboothView.PhotoState.Default) {
                     toolTipText = qsTr("Take photo")
                     return cameraAltIconUrl
                 }
 
-                if(hasAvatar){
+                if(photoState === PhotoboothView.PhotoState.Taken){
                     toolTipText = qsTr("Retake photo")
                     return refreshIconUrl
                 } else {
@@ -216,7 +229,7 @@ ColumnLayout {
             }
 
             onClicked: {
-                if(!takePhotoState){
+                if(photoState !== PhotoboothView.PhotoState.CameraRendering){
                     startBooth()
                     return
                 } else {
@@ -228,7 +241,8 @@ ColumnLayout {
 
                         setAvatarImage(AvatarImage.Mode.FromUrl, result.url)
 
-                        hasAvatar = true
+                        photoState = PhotoboothView.PhotoState.Taken
+                        avatarSet = true
                         stopBooth()
                     })
                 }
diff --git a/src/wizardview/WizardView.qml b/src/wizardview/WizardView.qml
index e836c060d..96f249a3d 100644
--- a/src/wizardview/WizardView.qml
+++ b/src/wizardview/WizardView.qml
@@ -80,16 +80,20 @@ Rectangle {
     Connections{
         target: AccountAdapter
 
-        function onAccountAdded(showBackUp, index) {
+        enabled: controlPanelStackView.currentIndex !== WizardView.WizardViewPageIndex.WELCOMEPAGE
+
+        function onAccountAdded(accountId, showBackUp, index) {
             addedAccountIndex = index
             AccountAdapter.accountChanged(index)
             if (showProfile) {
                 changePageQML(WizardView.WizardViewPageIndex.PROFILEPAGE)
                 profilePage.readyToSaveDetails()
                 profilePage.isRdv = isRdv
+                profilePage.createdAccountId = accountId
             } else if (controlPanelStackView.currentIndex === WizardView.WizardViewPageIndex.PROFILEPAGE) {
                 profilePage.readyToSaveDetails()
                 profilePage.isRdv = isRdv
+                profilePage.createdAccountId = accountId
             } else if (showBackUp) {
                 changePageQML(WizardView.WizardViewPageIndex.BACKUPKEYSPAGE)
             } else {
@@ -382,6 +386,8 @@ Rectangle {
                         changePageQML(WizardView.WizardViewPageIndex.WELCOMEPAGE)
                         needToShowMainViewWindow(addedAccountIndex)
                     }
+
+                    profilePage.initializeOnShowUp()
                 }
 
                 onSaveProfile: {
diff --git a/src/wizardview/components/ProfilePage.qml b/src/wizardview/components/ProfilePage.qml
index adc7ac5d3..87efaf6cd 100644
--- a/src/wizardview/components/ProfilePage.qml
+++ b/src/wizardview/components/ProfilePage.qml
@@ -26,12 +26,18 @@ import "../../commoncomponents"
 Rectangle {
     id: root
 
+    property string createdAccountId: ""
     property alias profileImg: setAvatarWidget.boothImg
     property int preferredHeight: profilePageColumnLayout.implicitHeight
+    property var showBottom: false
+    property alias displayName: aliasEdit.text
+    property bool isRdv: false
+
+    signal leavePage
+    signal saveProfile
 
     function initializeOnShowUp() {
-        setAvatarWidget.hasAvatar = false
-        setAvatarWidget.setAvatarImage(AvatarImage.Mode.Default, "")
+        setAvatarWidget.initUI()
         clearAllTextFields()
         saveProfileBtn.spinnerTriggered = true
     }
@@ -46,12 +52,10 @@ Rectangle {
 
     color: JamiTheme.backgroundColor
 
-    signal leavePage
-    signal saveProfile
-
-    property var showBottom: false
-    property alias displayName: aliasEdit.text
-    property bool isRdv: false
+    onCreatedAccountIdChanged: {
+        setAvatarWidget.setAvatarImage(AvatarImage.Mode.FromAccount,
+                                       createdAccountId)
+    }
 
     ColumnLayout {
         id: profilePageColumnLayout
@@ -102,6 +106,8 @@ Rectangle {
         MaterialLineEdit {
             id: aliasEdit
 
+            property string lastInitialCharacter: ""
+
             Layout.preferredHeight: fieldLayoutHeight
             Layout.preferredWidth: fieldLayoutWidth
             Layout.alignment: Qt.AlignCenter
@@ -114,6 +120,22 @@ Rectangle {
             borderColorMode: MaterialLineEdit.NORMAL
 
             fieldLayoutWidth: saveProfileBtn.width
+
+            onTextEdited: {
+                if (!(setAvatarWidget.avatarSet)) {
+                    if (text.length === 0) {
+                        setAvatarWidget.setAvatarImage(AvatarImage.Mode.FromAccount,
+                                                       createdAccountId)
+                        return
+                    }
+
+                    if (text.length == 1 && text.charAt(0) !== lastInitialCharacter) {
+                        lastInitialCharacter = text.charAt(0)
+                        setAvatarWidget.setAvatarImage(AvatarImage.Mode.FromTemporaryName,
+                                                       text)
+                    }
+                }
+            }
         }
 
         SpinnerButton {
-- 
GitLab