From 56b8aa16e7be7ca1801aab9016c310478015c32a Mon Sep 17 00:00:00 2001
From: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
Date: Mon, 20 Jan 2025 10:57:57 -0500
Subject: [PATCH] account: allow non-ASCII letters and numbers in name

Adapt to daemon changes that enable registered names
to include letters and numbers from all languages.

https://git.jami.net/savoirfairelinux/jami-daemon/-/issues/1097
Change-Id: Ibc4ab33e27743c78fb42de074223106c77d6d813
---
 daemon                                             |  2 +-
 .../IdentifierUsernameTextEdit.qml                 |  7 ++++---
 src/app/commoncomponents/ModalTextEdit.qml         |  7 ++++---
 src/app/commoncomponents/UsernameTextEdit.qml      | 13 +++++++------
 src/app/conversationsadapter.cpp                   |  5 +++--
 src/app/mainview/components/ParticipantsLayer.qml  |  4 ++--
 src/libclient/accountmodel.cpp                     | 11 +++++++----
 src/libclient/api/accountmodel.h                   |  6 ++++--
 src/libclient/callbackshandler.cpp                 |  5 +++--
 src/libclient/callbackshandler.h                   | 14 ++++++++++----
 src/libclient/contactmodel.cpp                     |  9 ++++++---
 src/libclient/namedirectory.cpp                    | 12 +++++++-----
 src/libclient/namedirectory.h                      |  5 ++++-
 src/libclient/private/namedirectory_p.h            |  3 ++-
 .../qtwrapper/configurationmanager_wrap.h          |  5 ++++-
 15 files changed, 68 insertions(+), 40 deletions(-)

diff --git a/daemon b/daemon
index 70a9c0b8a..cbf9457ae 160000
--- a/daemon
+++ b/daemon
@@ -1 +1 @@
-Subproject commit 70a9c0b8a88d2be0ccaced584f0aca8798ef88b7
+Subproject commit cbf9457ae707ffadb8035854a51669fd95cbc68a
diff --git a/src/app/commoncomponents/IdentifierUsernameTextEdit.qml b/src/app/commoncomponents/IdentifierUsernameTextEdit.qml
index dd99dddbf..65d57c90a 100644
--- a/src/app/commoncomponents/IdentifierUsernameTextEdit.qml
+++ b/src/app/commoncomponents/IdentifierUsernameTextEdit.qml
@@ -65,7 +65,8 @@ Item {
     property string dynamicText
 
     property QtObject textValidator: RegularExpressionValidator {
-        regularExpression: /[A-Za-z0-9-]{0,32}/
+        // up to 32 unicode code points
+        regularExpression: /^.{0,32}$/
     }
 
     enum NameRegistrationState {
@@ -97,8 +98,8 @@ Item {
         target: NameDirectory
         enabled: dynamicText.length !== 0
 
-        function onRegisteredNameFound(status, address, name) {
-            if (dynamicText === name) {
+        function onRegisteredNameFound(status, address, registeredName, requestedName) {
+            if (dynamicText === requestedName) {
                 switch (status) {
                 case NameDirectory.LookupStatus.NOT_FOUND:
                     nameRegistrationState = UsernameTextEdit.NameRegistrationState.FREE;
diff --git a/src/app/commoncomponents/ModalTextEdit.qml b/src/app/commoncomponents/ModalTextEdit.qml
index 83217fe5c..5a14768b7 100644
--- a/src/app/commoncomponents/ModalTextEdit.qml
+++ b/src/app/commoncomponents/ModalTextEdit.qml
@@ -45,9 +45,6 @@ Loader {
     property bool fontBold: false
 
     property int echoMode: TextInput.Normal
-    property QtObject textValidator: RegularExpressionValidator {
-        id: defaultValidator
-    }
 
     property var icon
     property bool isSettings
@@ -56,6 +53,10 @@ Loader {
     property bool readOnly: false
     property bool isEditing: false
 
+    property QtObject textValidator: RegularExpressionValidator {
+        id: defaultValidator
+    }
+
     onStatusChanged: {
         if (status == Loader.Ready && icon)
             root.item.icon = icon;
diff --git a/src/app/commoncomponents/UsernameTextEdit.qml b/src/app/commoncomponents/UsernameTextEdit.qml
index 681860e58..1a40f00bc 100644
--- a/src/app/commoncomponents/UsernameTextEdit.qml
+++ b/src/app/commoncomponents/UsernameTextEdit.qml
@@ -58,10 +58,6 @@ ModalTextEdit {
     infoTipText: JamiStrings.usernameToolTip
     placeholderText: JamiStrings.chooseAUsername
 
-    textValidator: RegularExpressionValidator {
-        regularExpression: /[A-Za-z0-9-]{0,32}/
-    }
-
     enum NameRegistrationState {
         BLANK,
         INVALID,
@@ -73,6 +69,11 @@ ModalTextEdit {
 
     inputIsValid: dynamicText.length === 0 || nameRegistrationState === UsernameTextEdit.NameRegistrationState.FREE
 
+    textValidator: RegularExpressionValidator {
+        // up to 32 unicode code points
+        regularExpression: /^.{0,32}$/
+    }
+
     onActiveChanged: function (active) {
         root.isActive = active;
     }
@@ -91,8 +92,8 @@ ModalTextEdit {
         target: NameDirectory
         enabled: dynamicText.length !== 0
 
-        function onRegisteredNameFound(status, address, name) {
-            if (dynamicText === name) {
+        function onRegisteredNameFound(status, address, registeredName, requestedName) {
+            if (dynamicText === requestedName) {
                 switch (status) {
                 case NameDirectory.LookupStatus.NOT_FOUND:
                     nameRegistrationState = UsernameTextEdit.NameRegistrationState.FREE;
diff --git a/src/app/conversationsadapter.cpp b/src/app/conversationsadapter.cpp
index 56e4d00d8..950cac5bc 100644
--- a/src/app/conversationsadapter.cpp
+++ b/src/app/conversationsadapter.cpp
@@ -260,10 +260,11 @@ ConversationsAdapter::onNewTrustRequest(const QString& accountId,
                               this,
                               [this, accountId, peerUri, cb](NameDirectory::LookupStatus status,
                                                              const QString& address,
-                                                             const QString& name) {
+                                                             const QString& registeredName,
+                                                             const QString& requestedName) {
                                   if (address == peerUri) {
                                       if (status == NameDirectory::LookupStatus::SUCCESS)
-                                          cb(name);
+                                          cb(registeredName);
                                       else {
                                           auto& accInfo = lrcInstance_->getAccountInfo(accountId);
                                           cb(accInfo.contactModel->bestNameForContact(peerUri));
diff --git a/src/app/mainview/components/ParticipantsLayer.qml b/src/app/mainview/components/ParticipantsLayer.qml
index a014970cf..bcfdee168 100644
--- a/src/app/mainview/components/ParticipantsLayer.qml
+++ b/src/app/mainview/components/ParticipantsLayer.qml
@@ -87,9 +87,9 @@ Item {
                 target: NameDirectory
                 enabled: bestName_ === uri_
 
-                function onRegisteredNameFound(status, address, name) {
+                function onRegisteredNameFound(status, address, registeredName, requestedName) {
                     if (address === uri_ && status === NameDirectory.LookupStatus.SUCCESS) {
-                        bestName_ = name;
+                        bestName_ = registeredName;
                     }
                 }
             }
diff --git a/src/libclient/accountmodel.cpp b/src/libclient/accountmodel.cpp
index ceb915d6f..09641469a 100644
--- a/src/libclient/accountmodel.cpp
+++ b/src/libclient/accountmodel.cpp
@@ -151,14 +151,16 @@ public Q_SLOTS:
     /**
      * Emit registeredNameFound
      * @param accountId
+     * @param requestedName the name requested
      * @param status
      * @param address
-     * @param name
+     * @param registeredName the name found, have same normalized form as requestedName
      */
     void slotRegisteredNameFound(const QString& accountId,
+                                 const QString& requestedName,
                                  int status,
                                  const QString& address,
-                                 const QString& name);
+                                 const QString& registeredName);
 
     /**
      * Emit migrationEnded
@@ -653,9 +655,10 @@ AccountModelPimpl::slotNameRegistrationEnded(const QString& accountId,
 
 void
 AccountModelPimpl::slotRegisteredNameFound(const QString& accountId,
+                                           const QString& requestedName,
                                            int status,
                                            const QString& address,
-                                           const QString& name)
+                                           const QString& registeredName)
 {
     account::LookupStatus convertedStatus = account::LookupStatus::INVALID;
     switch (status) {
@@ -674,7 +677,7 @@ AccountModelPimpl::slotRegisteredNameFound(const QString& accountId,
     default:
         break;
     }
-    Q_EMIT linked.registeredNameFound(accountId, convertedStatus, address, name);
+    Q_EMIT linked.registeredNameFound(accountId, requestedName, convertedStatus, address, registeredName);
 }
 
 void
diff --git a/src/libclient/api/accountmodel.h b/src/libclient/api/accountmodel.h
index 73b193ddf..e3aa903bd 100644
--- a/src/libclient/api/accountmodel.h
+++ b/src/libclient/api/accountmodel.h
@@ -321,13 +321,15 @@ Q_SIGNALS:
     /**
      * Name registration has been found
      * @param accountId
+     * @param requestedName the name requested
      * @param status
-     * @param name
+     * @param registeredName the name found, have same normalized form as requestedName
      */
     void registeredNameFound(const QString& accountId,
+                             const QString& requestedName,
                              account::LookupStatus status,
                              const QString& address,
-                             const QString& name);
+                             const QString& registeredName);
 
     /**
      * Migration has finished
diff --git a/src/libclient/callbackshandler.cpp b/src/libclient/callbackshandler.cpp
index e6e522d9e..092f2abbf 100644
--- a/src/libclient/callbackshandler.cpp
+++ b/src/libclient/callbackshandler.cpp
@@ -695,11 +695,12 @@ CallbacksHandler::slotNameRegistrationEnded(const QString& accountId,
 
 void
 CallbacksHandler::slotRegisteredNameFound(const QString& accountId,
+                                          const QString& requestedName,
                                           int status,
                                           const QString& address,
-                                          const QString& name)
+                                          const QString& registeredName)
 {
-    Q_EMIT registeredNameFound(accountId, status, address, name);
+    Q_EMIT registeredNameFound(accountId, requestedName, status, address, registeredName);
 }
 
 void
diff --git a/src/libclient/callbackshandler.h b/src/libclient/callbackshandler.h
index d96c13936..bd75e6b08 100644
--- a/src/libclient/callbackshandler.h
+++ b/src/libclient/callbackshandler.h
@@ -255,13 +255,16 @@ Q_SIGNALS:
     /**
      * Name registration has been found
      * @param accountId
+     * @param requestedName the name requested
      * @param status
-     * @param name
+     * @param address
+     * @param registeredName the name found, have same normalized form as requestedName
      */
     void registeredNameFound(const QString& accountId,
+                             const QString& requestedName,
                              int status,
                              const QString& address,
-                             const QString& name);
+                             const QString& registeredName);
 
     /**
      * Migration ended
@@ -591,13 +594,16 @@ private Q_SLOTS:
     /**
      * Emit registeredNameFound
      * @param accountId
+     * @param requestedName requested name
      * @param status
-     * @param name
+     * @param address
+     * @param registeredName found name, have same normalized form as requestedName
      */
     void slotRegisteredNameFound(const QString& accountId,
+                                 const QString& requestedName,
                                  int status,
                                  const QString& address,
-                                 const QString& name);
+                                 const QString& registeredName);
 
     /**
      * emit migrationEnded
diff --git a/src/libclient/contactmodel.cpp b/src/libclient/contactmodel.cpp
index c77e61acf..5ffb399b3 100644
--- a/src/libclient/contactmodel.cpp
+++ b/src/libclient/contactmodel.cpp
@@ -164,11 +164,13 @@ public Q_SLOTS:
     /**
      * Listen CallbacksHandler when a registeredName is found
      * @param accountId account linked
+     * @param requestedName the name requested
      * @param status (0 = SUCCESS, 1 = Not found, 2 = Network error)
      * @param uri of the contact found
-     * @param registeredName of the contact found
+     * @param registeredName of the contact found, have same normalized form as requestedName
      */
     void slotRegisteredNameFound(const QString& accountId,
+                                 const QString& requestedName,
                                  int status,
                                  const QString& uri,
                                  const QString& registeredName);
@@ -947,6 +949,7 @@ ContactModelPimpl::addToContacts(const QString& contactUri,
 
 void
 ContactModelPimpl::slotRegisteredNameFound(const QString& accountId,
+                                           const QString& requestedName,
                                            int status,
                                            const QString& uri,
                                            const QString& registeredName)
@@ -963,7 +966,7 @@ ContactModelPimpl::slotRegisteredNameFound(const QString& accountId,
             searchResult.clear();
         } else {
             nonContactLookup_[uri] = foundName;
-            if ((searchQuery != uri && searchQuery != registeredName) || searchQuery.isEmpty()) {
+            if ((searchQuery != uri && searchQuery != requestedName) || searchQuery.isEmpty()) {
                 // we are notified that a previous lookup ended
                 return;
             }
@@ -979,7 +982,7 @@ ContactModelPimpl::slotRegisteredNameFound(const QString& accountId,
                 return;
             }
         }
-        if ((searchQuery != uri && searchQuery != registeredName) || searchQuery.isEmpty()) {
+        if ((searchQuery != uri && searchQuery != requestedName) || searchQuery.isEmpty()) {
             // we are notified that a previous lookup ended
             return;
         }
diff --git a/src/libclient/namedirectory.cpp b/src/libclient/namedirectory.cpp
index 7aeda10f4..bfafdc61e 100644
--- a/src/libclient/namedirectory.cpp
+++ b/src/libclient/namedirectory.cpp
@@ -73,21 +73,22 @@ NameDirectoryPrivate::slotNameRegistrationEnded(const QString& accountId,
 // Registered Name found
 void
 NameDirectoryPrivate::slotRegisteredNameFound(const QString& accountId,
+                                              const QString& requestedName,
                                               int status,
                                               const QString& address,
-                                              const QString& name)
+                                              const QString& registeredName)
 {
     switch (static_cast<NameDirectory::LookupStatus>(status)) {
     case NameDirectory::LookupStatus::INVALID_NAME:
-        LC_DBG << "lookup name is INVALID: address: " << address << " name: " << name
+        LC_DBG << "lookup name is INVALID: address: " << address << " name: " << requestedName
                << " accountId: " << accountId;
         break;
     case NameDirectory::LookupStatus::NOT_FOUND:
-        LC_DBG << "lookup name NOT FOUND: address: " << address << " name: " << name
+        LC_DBG << "lookup name NOT FOUND: address: " << address << " name: " << requestedName
                << " accountId: " << accountId;
         break;
     case NameDirectory::LookupStatus::ERROR:
-        LC_DBG << "lookup name ERROR: address: " << address << " name: " << name
+        LC_DBG << "lookup name ERROR: address: " << address << " name: " << requestedName
                << " accountId: " << accountId;
         break;
     case NameDirectory::LookupStatus::SUCCESS:
@@ -96,7 +97,8 @@ NameDirectoryPrivate::slotRegisteredNameFound(const QString& accountId,
 
     Q_EMIT q_ptr->registeredNameFound(static_cast<NameDirectory::LookupStatus>(status),
                                       address,
-                                      name);
+                                      registeredName,
+                                      requestedName);
 }
 
 // Export account has ended with pin generated
diff --git a/src/libclient/namedirectory.h b/src/libclient/namedirectory.h
index 0743bde2e..961b0ce38 100644
--- a/src/libclient/namedirectory.h
+++ b/src/libclient/namedirectory.h
@@ -66,9 +66,12 @@ Q_SIGNALS:
     void nameRegistrationEnded(NameDirectory::RegisterNameStatus status, const QString& name);
 
     /// Name or address lookup has completed
+    /// requestedName - name for what lookup was requested
+    /// registeredName - name found in the lookup, have same normalized form as requestedName
     void registeredNameFound(NameDirectory::LookupStatus status,
                              const QString& address,
-                             const QString& name);
+                             const QString& registeredName,
+                             const QString& requestedName);
 
     // Export account has ended with pin generated
     void exportOnRingEnded(NameDirectory::ExportOnRingStatus status, const QString& pin);
diff --git a/src/libclient/private/namedirectory_p.h b/src/libclient/private/namedirectory_p.h
index b935362f2..ec7c62d09 100644
--- a/src/libclient/private/namedirectory_p.h
+++ b/src/libclient/private/namedirectory_p.h
@@ -34,8 +34,9 @@ public:
 public Q_SLOTS:
     void slotNameRegistrationEnded(const QString& accountId, int status, const QString& name);
     void slotRegisteredNameFound(const QString& accountId,
+                                 const QString& requestedName,
                                  int status,
                                  const QString& address,
-                                 const QString& name);
+                                 const QString& registeredName);
     void slotExportOnRingEnded(const QString& accountId, int status, const QString& pin);
 };
diff --git a/src/libclient/qtwrapper/configurationmanager_wrap.h b/src/libclient/qtwrapper/configurationmanager_wrap.h
index 7b89048fa..135f803c1 100644
--- a/src/libclient/qtwrapper/configurationmanager_wrap.h
+++ b/src/libclient/qtwrapper/configurationmanager_wrap.h
@@ -166,10 +166,12 @@ public:
                 }),
             exportable_callback<ConfigurationSignal::RegisteredNameFound>(
                 [this](const std::string& accountId,
+                       const std::string& requestedName,
                        int status,
                        const std::string& address,
                        const std::string& name) {
                     Q_EMIT this->registeredNameFound(QString(accountId.c_str()),
+                                                     QString(requestedName.c_str()),
                                                      status,
                                                      QString(address.c_str()),
                                                      QString(name.c_str()));
@@ -1213,9 +1215,10 @@ Q_SIGNALS: // SIGNALS
     void needsHost(const QString& accountId, const QString& conversationId);
     void nameRegistrationEnded(const QString& accountId, int status, const QString& name);
     void registeredNameFound(const QString& accountId,
+                             const QString& requestedName,
                              int status,
                              const QString& address,
-                             const QString& name);
+                             const QString& registeredName);
     void migrationEnded(const QString& accountId, const QString& result);
     void contactAdded(const QString& accountId, const QString& uri, bool banned);
     void contactRemoved(const QString& accountId, const QString& uri, bool banned);
-- 
GitLab