From ae9b2abdc7aa73d2734179c2b6f62606e29e681d Mon Sep 17 00:00:00 2001 From: Joshua Goins Date: Thu, 19 Feb 2026 18:08:18 -0500 Subject: [PATCH] Reduce layout shift when loading mutual rooms in user profiles Instead of making the visibility of this section in user profiles dependent on the model, its now checking if you can check mutual rooms and using a busy indicator. There's also a label for when you have no rooms in common, which is a rare case (for example, banned or left users.) --- src/app/models/commonroomsmodel.cpp | 34 +++++++++++++++++++++-------- src/app/models/commonroomsmodel.h | 5 +++++ src/app/qml/UserDetailDialog.qml | 22 +++++++++++++++++-- 3 files changed, 50 insertions(+), 11 deletions(-) diff --git a/src/app/models/commonroomsmodel.cpp b/src/app/models/commonroomsmodel.cpp index 1fe05853d..be5e98905 100644 --- a/src/app/models/commonroomsmodel.cpp +++ b/src/app/models/commonroomsmodel.cpp @@ -74,6 +74,11 @@ QHash CommonRoomsModel::roleNames() const }; } +bool CommonRoomsModel::loading() const +{ + return m_loading; +} + void CommonRoomsModel::reload() { if (!m_connection || m_userId.isEmpty()) { @@ -89,15 +94,26 @@ void CommonRoomsModel::reload() return; } - m_connection->callApi(m_userId).then([this](const auto job) { - const auto &replyData = job->jsonData(); - beginResetModel(); - for (const auto &roomId : replyData[u"joined"_s].toArray()) { - m_commonRooms.push_back(roomId.toString()); - } - endResetModel(); - Q_EMIT countChanged(); - }); + m_loading = true; + Q_EMIT loadingChanged(); + + m_connection->callApi(m_userId) + .then([this](const auto job) { + const auto &replyData = job->jsonData(); + beginResetModel(); + for (const auto &roomId : replyData[u"joined"_s].toArray()) { + m_commonRooms.push_back(roomId.toString()); + } + endResetModel(); + Q_EMIT countChanged(); + + m_loading = false; + Q_EMIT loadingChanged(); + }) + .onFailure([this] { + m_loading = false; + Q_EMIT loadingChanged(); + }); } #include "moc_commonroomsmodel.cpp" diff --git a/src/app/models/commonroomsmodel.h b/src/app/models/commonroomsmodel.h index b6afc060a..bb3634317 100644 --- a/src/app/models/commonroomsmodel.h +++ b/src/app/models/commonroomsmodel.h @@ -21,6 +21,7 @@ class CommonRoomsModel : public QAbstractListModel Q_PROPERTY(NeoChatConnection *connection WRITE setConnection READ connection NOTIFY connectionChanged REQUIRED) Q_PROPERTY(QString userId WRITE setUserId READ userId NOTIFY userIdChanged REQUIRED) Q_PROPERTY(int count READ rowCount NOTIFY countChanged) + Q_PROPERTY(bool loading READ loading NOTIFY loadingChanged) public: enum Roles { @@ -43,10 +44,13 @@ public: QHash roleNames() const override; + bool loading() const; + Q_SIGNALS: void connectionChanged(); void userIdChanged(); void countChanged(); + void loadingChanged(); private: void reload(); @@ -54,4 +58,5 @@ private: QPointer m_connection; QString m_userId; QList m_commonRooms; + bool m_loading = false; }; diff --git a/src/app/qml/UserDetailDialog.qml b/src/app/qml/UserDetailDialog.qml index 9c0e88d32..c422a31cf 100644 --- a/src/app/qml/UserDetailDialog.qml +++ b/src/app/qml/UserDetailDialog.qml @@ -401,18 +401,36 @@ Kirigami.Dialog { Kirigami.Heading { text: i18nc("@title The set of common rooms between your current user and the one shown", "Mutual Rooms") level: 4 - visible: !root.isSelf && root.hasMutualRooms + visible: !root.isSelf && root.connection.canCheckMutualRooms Layout.topMargin: Kirigami.Units.largeSpacing } RowLayout { spacing: Kirigami.Units.smallSpacing - visible: !root.isSelf && root.hasMutualRooms + visible: !root.isSelf && root.connection.canCheckMutualRooms Layout.topMargin: Kirigami.Units.smallSpacing + QQC2.BusyIndicator { + visible: roomRepeater.count === 0 && root.model.loading + + Layout.preferredWidth: Kirigami.Units.iconSizes.medium + Layout.preferredHeight: Kirigami.Units.iconSizes.medium + } + + QQC2.Label { + visible: roomRepeater.count === 0 && !root.model.loading + text: i18nc("@info:label", "No rooms in common") + verticalAlignment: Text.AlignVCenter + + Layout.preferredHeight: Kirigami.Units.iconSizes.medium + Layout.fillHeight: true + } + Repeater { + id: roomRepeater + model: root.limiterModel delegate: KirigamiComponents.AvatarButton {