From 28e40f88da676e563dfb183e6cc443f382424674 Mon Sep 17 00:00:00 2001
From: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com>
Date: Thu, 8 Oct 2020 19:18:53 -0400
Subject: [PATCH] smartlist: select top item when return is pressed during a
 search

- fixes index change on re-filtering

Change-Id: I08c32857600c5f3930967a98756a3c4b8b63fe64
---
 src/conversationsadapter.cpp                  | 24 ++++++++-------
 src/conversationsadapter.h                    |  3 +-
 src/mainview/components/ContactSearchBar.qml  | 13 +++++++-
 .../components/ConversationSmartListView.qml  | 30 ++++++++++++-------
 .../ConversationSmartListViewItemDelegate.qml |  5 ++++
 src/mainview/components/SidePanel.qml         | 13 ++++----
 6 files changed, 60 insertions(+), 28 deletions(-)

diff --git a/src/conversationsadapter.cpp b/src/conversationsadapter.cpp
index dd90dbc38..ed7e51416 100644
--- a/src/conversationsadapter.cpp
+++ b/src/conversationsadapter.cpp
@@ -61,9 +61,8 @@ ConversationsAdapter::safeInit()
 
     connectConversationModel();
 
-    setProperty("currentTypeFilter", QVariant::fromValue(
-                    LRCInstance::getCurrentAccountInfo().profileInfo.type));
-
+    setProperty("currentTypeFilter",
+                QVariant::fromValue(LRCInstance::getCurrentAccountInfo().profileInfo.type));
 }
 
 void
@@ -129,8 +128,8 @@ ConversationsAdapter::onCurrentAccountIdChanged()
     disconnectConversationModel();
     connectConversationModel();
 
-    setProperty("currentTypeFilter", QVariant::fromValue(
-                    LRCInstance::getCurrentAccountInfo().profileInfo.type));
+    setProperty("currentTypeFilter",
+                QVariant::fromValue(LRCInstance::getCurrentAccountInfo().profileInfo.type));
 }
 
 void
@@ -146,10 +145,7 @@ ConversationsAdapter::onNewUnreadInteraction(const QString& accountId,
         auto& accInfo = LRCInstance::getAccountInfo(accountId);
         auto& contact = accInfo.contactModel->getContact(interaction.authorUri);
         auto from = Utils::bestNameForContact(contact);
-        auto onClicked = [this,
-                          accountId,
-                          convUid,
-                          uri = interaction.authorUri] {
+        auto onClicked = [this, accountId, convUid, uri = interaction.authorUri] {
 #ifdef Q_OS_WINDOWS
             emit LRCInstance::instance().notificationClicked();
 #else
@@ -159,7 +155,7 @@ ConversationsAdapter::onNewUnreadInteraction(const QString& accountId,
             if (!convInfo.uid.isEmpty()) {
                 selectConversation(accountId, convInfo.uid);
                 emit LRCInstance::instance().updateSmartList();
-                emit modelSorted(uri);
+                emit modelSorted(convInfo.uid);
             }
         };
 
@@ -210,7 +206,7 @@ ConversationsAdapter::connectConversationModel(bool updateFilter)
                        == lrc::api::profile::Type::TEMPORARY) {
                 return;
             }
-            emit modelSorted(QVariant::fromValue(contactURI));
+            emit modelSorted(QVariant::fromValue(conversation.uid));
         });
 
     modelUpdatedConnection_ = QObject::connect(currentConversationModel,
@@ -228,6 +224,7 @@ ConversationsAdapter::connectConversationModel(bool updateFilter)
                                                     conversationSmartListModel_
                                                         ->fillConversationsList();
                                                     updateConversationsFilterWidget();
+                                                    emit indexRepositionRequested();
                                                     emit updateListViewRequested();
                                                 });
 
@@ -264,6 +261,11 @@ ConversationsAdapter::connectConversationModel(bool updateFilter)
                            &lrc::api::ConversationModel::searchStatusChanged,
                            [this](const QString& status) { emit showSearchStatus(status); });
 
+    // This connection is ideal when  separated search results list.
+    // This signal is guaranteed to fire just after filterChanged during a search if results are
+    // changed, and once before filterChanged when calling setFilter.
+    // NOTE: Currently, when searching, the entire conversation list will be copied 2-3 times each
+    // keystroke :/.
     searchResultUpdatedConnection_
         = QObject::connect(currentConversationModel,
                            &lrc::api::ConversationModel::searchResultUpdated,
diff --git a/src/conversationsadapter.h b/src/conversationsadapter.h
index ec7aac4c6..abd97368a 100644
--- a/src/conversationsadapter.h
+++ b/src/conversationsadapter.h
@@ -52,10 +52,11 @@ signals:
     void showSearchStatus(const QString& status);
 
     void modelChanged(const QVariant& model);
-    void modelSorted(const QVariant& uri);
+    void modelSorted(const QVariant& uid);
     void updateListViewRequested();
     void navigateToWelcomePageRequested();
     void currentTypeFilterChanged();
+    void indexRepositionRequested();
 
 private slots:
     void onCurrentAccountIdChanged();
diff --git a/src/mainview/components/ContactSearchBar.qml b/src/mainview/components/ContactSearchBar.qml
index 6db304f70..f0ef89083 100644
--- a/src/mainview/components/ContactSearchBar.qml
+++ b/src/mainview/components/ContactSearchBar.qml
@@ -26,13 +26,14 @@ Rectangle {
     id: contactSearchBarRect
 
     signal contactSearchBarTextChanged(string text)
+    signal returnPressedWhileSearching
 
     function clearText() {
         contactSearchBar.clear()
         fakeFocus.forceActiveFocus()
     }
 
-    radius: height/2
+    radius: height / 2
     color: "white"
 
     FocusScope {
@@ -93,4 +94,14 @@ Rectangle {
         context: Qt.ApplicationShortcut
         onActivated: contactSearchBar.forceActiveFocus()
     }
+
+    Shortcut {
+        sequence: "Return"
+        context: Qt.ApplicationShortcut
+        onActivated: {
+            if (contactSearchBar.text !== "") {
+                returnPressedWhileSearching()
+            }
+        }
+    }
 }
diff --git a/src/mainview/components/ConversationSmartListView.qml b/src/mainview/components/ConversationSmartListView.qml
index 0a21df47b..109f6918f 100644
--- a/src/mainview/components/ConversationSmartListView.qml
+++ b/src/mainview/components/ConversationSmartListView.qml
@@ -40,6 +40,20 @@ ListView {
         root.forceUpdatePotentialInvalidItem()
     }
 
+    function repositionIndex(uid = "") {
+        if (uid === "")
+            uid = mainViewWindow.currentConvUID
+        root.currentIndex = -1
+        updateListView()
+        for (var i = 0; i < count; i++) {
+            if (root.model.data(
+                root.model.index(i, 0), SmartListModel.UID) === uid) {
+                root.currentIndex = i
+                break
+            }
+        }
+    }
+
     ConversationSmartListContextMenu {
         id: smartListContextMenu
     }
@@ -53,21 +67,17 @@ ListView {
 
         // When the model has been sorted, we need to adjust the focus (currentIndex)
         // to the previously focused conversation item.
-        function onModelSorted(uri) {
-            root.currentIndex = -1
-            updateListView()
-            for (var i = 0; i < count; i++) {
-                if (root.model.data(
-                    root.model.index(i, 0), SmartListModel.URI) === uri) {
-                    root.currentIndex = i
-                    break
-                }
-            }
+        function onModelSorted(uid) {
+            repositionIndex(uid)
         }
 
         function onUpdateListViewRequested() {
             updateListView()
         }
+
+        function onIndexRepositionRequested() {
+            repositionIndex()
+        }
     }
 
     Connections {
diff --git a/src/mainview/components/ConversationSmartListViewItemDelegate.qml b/src/mainview/components/ConversationSmartListViewItemDelegate.qml
index bf25a2bf7..f2489e5a4 100644
--- a/src/mainview/components/ConversationSmartListViewItemDelegate.qml
+++ b/src/mainview/components/ConversationSmartListViewItemDelegate.qml
@@ -29,6 +29,11 @@ ItemDelegate {
     height: 72
 
     property int lastInteractionPreferredWidth: 80
+
+    function convUid() {
+        return UID
+    }
+
     Connections {
         target: conversationSmartListView
 
diff --git a/src/mainview/components/SidePanel.qml b/src/mainview/components/SidePanel.qml
index c36f54562..ee9f0fada 100644
--- a/src/mainview/components/SidePanel.qml
+++ b/src/mainview/components/SidePanel.qml
@@ -59,13 +59,9 @@ Rectangle {
         contactSearchBar.clearText()
     }
 
-    function accountChangedUIReset() {
-        contactSearchBar.clearText()
-    }
-
     function refreshAccountComboBox(index) {
         accountComboBox.update()
-        accountChangedUIReset()
+        clearContactSearchBar()
         accountComboBox.resetAccountListModel()
     }
 
@@ -99,6 +95,13 @@ Rectangle {
         onContactSearchBarTextChanged: {
             UtilsAdapter.setConversationFilter(text)
         }
+
+        onReturnPressedWhileSearching: {
+            var convUid = conversationSmartListView.itemAtIndex(0).convUid()
+            var currentAccountId = AccountAdapter.currentAccountId
+            ConversationsAdapter.selectConversation(currentAccountId, convUid)
+            conversationSmartListView.repositionIndex(convUid)
+        }
     }
 
     SidePanelTabBar {
-- 
GitLab