diff --git a/src/app/accountlistmodel.cpp b/src/app/accountlistmodel.cpp
index ac01bacccc0fae5671d1a6921c4ca5b4cc5d6bb0..2b70f7834235dc4d4d46d6673bbe1acb19b4fa75 100644
--- a/src/app/accountlistmodel.cpp
+++ b/src/app/accountlistmodel.cpp
@@ -29,6 +29,35 @@ AccountListModel::AccountListModel(LRCInstance* instance, QObject* parent)
     : AbstractListModelBase(parent)
 {
     lrcInstance_ = instance;
+
+    // Avoid resetting/redrawing the model when the account status changes.
+    QObject::connect(&lrcInstance_->accountModel(),
+                     &AccountModel::accountStatusChanged,
+                     this,
+                     [&](const QString& accountId) {
+                         auto accountList = lrcInstance_->accountModel().getAccountList();
+                         auto index = accountList.indexOf(accountId);
+                         if (index != -1) {
+                             QModelIndex modelIndex = QAbstractListModel::index(index, 0);
+                             Q_EMIT dataChanged(modelIndex, modelIndex /*, ALL ROLES */);
+                         }
+                     });
+    // If there's a reorder, it's reasonable to reset the model for simplicity, instead
+    // of computing the difference. The same goes for accounts being added and removed.
+    // These operations will only occur when the list is hidden, unless dbus is used while
+    // the list is visible.
+    QObject::connect(&lrcInstance_->accountModel(),
+                     &AccountModel::accountsReordered,
+                     this,
+                     &AccountListModel::reset);
+    QObject::connect(&lrcInstance_->accountModel(),
+                     &AccountModel::accountAdded,
+                     this,
+                     &AccountListModel::reset);
+    QObject::connect(&lrcInstance_->accountModel(),
+                     &AccountModel::accountRemoved,
+                     this,
+                     &AccountListModel::reset);
 }
 
 int
@@ -91,6 +120,7 @@ AccountListModel::roleNames() const
 void
 AccountListModel::reset()
 {
+    // Used to invalidate proxy models.
     beginResetModel();
     endResetModel();
 }
diff --git a/src/app/lrcinstance.cpp b/src/app/lrcinstance.cpp
index af6247934077921b78faecdc38407cccdbb2e9fa..e7c381ad57f349d60431ba78b18767673bdd25b8 100644
--- a/src/app/lrcinstance.cpp
+++ b/src/app/lrcinstance.cpp
@@ -43,9 +43,8 @@ LRCInstance::LRCInstance(const QString& updateUrl,
     muteDaemon_ = muteDaemon;
     threadPool_->setMaxThreadCount(1);
 
-    connect(this, &LRCInstance::currentAccountIdChanged, [this] {
-        // save to config, editing the accountlistmodel's underlying data
-        accountModel().setTopAccount(currentAccountId_);
+    // Update the current account when the account list changes.
+    connect(&accountModel(), &AccountModel::accountsReordered, this, [this] {
         Q_EMIT accountListChanged();
 
         profile::Info profileInfo;
@@ -62,6 +61,11 @@ LRCInstance::LRCInstance(const QString& updateUrl,
         set_currentAccountAvatarSet(!profileInfo.avatar.isEmpty());
     });
 
+    connect(this, &LRCInstance::currentAccountIdChanged, [this] {
+        // This will trigger `AccountModel::accountsReordered`.
+        accountModel().setTopAccount(currentAccountId_);
+    });
+
     connect(&accountModel(), &AccountModel::profileUpdated, this, [this](const QString& id) {
         if (id != currentAccountId_)
             return;
diff --git a/src/app/mainview/components/AccountComboBox.qml b/src/app/mainview/components/AccountComboBox.qml
index ea149f61452ca64444ad299f9937ebe6d7434758..7173cc80d1b94a35fbff4d01c23ff74faf8d3a86 100644
--- a/src/app/mainview/components/AccountComboBox.qml
+++ b/src/app/mainview/components/AccountComboBox.qml
@@ -34,24 +34,6 @@ Label {
 
     property bool inSettings: viewCoordinator.currentViewName === "SettingsView"
 
-    // TODO: remove these refresh hacks use QAbstractItemModels correctly
-    Connections {
-        target: AccountAdapter
-
-        function onAccountStatusChanged(accountId) {
-            AccountListModel.reset();
-        }
-    }
-
-    Connections {
-        target: LRCInstance
-
-        function onAccountListChanged() {
-            root.update();
-            AccountListModel.reset();
-        }
-    }
-
     function togglePopup() {
         if (root.popup.opened) {
             root.popup.close();
diff --git a/src/app/mainview/components/AccountComboBoxPopup.qml b/src/app/mainview/components/AccountComboBoxPopup.qml
index 9bfac5c911da19c4b5e016aed4eb1b0e9e8c2406..35118d23310582c8df9bf93f06fe4c8a5b3fe229 100644
--- a/src/app/mainview/components/AccountComboBoxPopup.qml
+++ b/src/app/mainview/components/AccountComboBoxPopup.qml
@@ -60,23 +60,6 @@ Popup {
 
             property bool inSettings: viewCoordinator.currentViewName === "SettingsView"
 
-            // TODO: remove these refresh hacks use QAbstractItemModels correctly
-            Connections {
-                target: AccountAdapter
-
-                function onAccountStatusChanged(accountId) {
-                    AccountListModel.reset();
-                }
-            }
-
-            Connections {
-                target: LRCInstance
-
-                function onAccountListChanged() {
-                    AccountListModel.reset();
-                }
-            }
-
             RowLayout {
                 id: mainLayout
                 anchors.fill: parent
@@ -257,11 +240,6 @@ Popup {
             color: JamiTheme.smartListHoveredColor
         }
 
-        // fake footer item as workaround for Qt 5.15 bug
-        // https://bugreports.qt.io/browse/QTBUG-85302
-        // don't use the clip trick and footer item overlay
-        // explained here https://stackoverflow.com/a/64625149
-        // as it causes other complexities in handling the drop shadow
         ItemDelegate {
             id: addAccountItem
 
diff --git a/src/libclient/accountmodel.cpp b/src/libclient/accountmodel.cpp
index 45983b970f3ffbf83fdc358e9f27c2d136b20bdb..07af96f4c6fbfdd471cc8fbdb6b7fa2fca0d5069 100644
--- a/src/libclient/accountmodel.cpp
+++ b/src/libclient/accountmodel.cpp
@@ -428,8 +428,9 @@ AccountModelPimpl::updateAccounts()
     const auto previousAccountIdListSize = accountIdList.size();
     accountIdList = configurationManager.getAccountList();
 
-    // If this is just a reordering of the accounts, don't do anything
+    // If this is just a reordering of the accounts, just notify the view.
     if (accountIdList.size() == previousAccountIdListSize) {
+        Q_EMIT linked.accountsReordered();
         return;
     }
 
diff --git a/src/libclient/api/accountmodel.h b/src/libclient/api/accountmodel.h
index 6f199811f731118d9fbbba44b73ef944070dbac7..ba58eddf2709b340e5ef25ce3339109ad5f5f424 100644
--- a/src/libclient/api/accountmodel.h
+++ b/src/libclient/api/accountmodel.h
@@ -288,6 +288,10 @@ Q_SIGNALS:
      * @param accountID
      */
     void accountRemoved(const QString& accountID);
+    /**
+     * Emitted when the account list order has changed.
+     */
+    void accountsReordered();
     /**
      * Connect this signal to know when an account was updated.
      * @param accountID