diff --git a/src/models/completionmodel.cpp b/src/models/completionmodel.cpp index 789545ef6..fe03263e3 100644 --- a/src/models/completionmodel.cpp +++ b/src/models/completionmodel.cpp @@ -9,18 +9,16 @@ #include "customemojimodel.h" #include "emojimodel.h" #include "neochatroom.h" +#include "roommanager.h" #include "userlistmodel.h" CompletionModel::CompletionModel(QObject *parent) : QAbstractListModel(parent) , m_filterModel(new CompletionProxyModel()) - , m_userListModel(new UserListModel(this)) + , m_userListModel(RoomManager::instance().userListModel()) , m_emojiModel(new QConcatenateTablesProxyModel(this)) { connect(this, &CompletionModel::textChanged, this, &CompletionModel::updateCompletion); - connect(this, &CompletionModel::roomChanged, this, [this]() { - m_userListModel->setRoom(m_room); - }); m_emojiModel->addSourceModel(&CustomEmojiModel::instance()); m_emojiModel->addSourceModel(&EmojiModel::instance()); } diff --git a/src/models/userlistmodel.cpp b/src/models/userlistmodel.cpp index fe3f8f839..ba3a4cbf5 100644 --- a/src/models/userlistmodel.cpp +++ b/src/models/userlistmodel.cpp @@ -33,6 +33,7 @@ void UserListModel::setRoom(NeoChatRoom *room) m_currentRoom->disconnect(this); m_currentRoom->connection()->disconnect(this); m_currentRoom = nullptr; + m_members.clear(); endResetModel(); } @@ -56,7 +57,7 @@ void UserListModel::setRoom(NeoChatRoom *room) }); } - refreshAllMembers(); + m_active = false; Q_EMIT roomChanged(); } @@ -169,7 +170,6 @@ void UserListModel::refreshMember(const Quotient::RoomMember &member, const QLis void UserListModel::refreshAllMembers() { beginResetModel(); - m_members.clear(); if (m_currentRoom != nullptr) { m_members = m_currentRoom->joinedMemberIds(); @@ -179,8 +179,17 @@ void UserListModel::refreshAllMembers() MemberSorter sorter(m_currentRoom); #endif std::sort(m_members.begin(), m_members.end(), [&sorter, this](const auto &left, const auto &right) { + const auto leftPl = m_currentRoom->getUserPowerLevel(left); + const auto rightPl = m_currentRoom->getUserPowerLevel(right); + if (leftPl > rightPl) { + return true; + } else if (rightPl > leftPl) { + return false; + } + return sorter(m_currentRoom->member(left), m_currentRoom->member(right)); }); + } endResetModel(); Q_EMIT usersRefreshed(); @@ -216,4 +225,14 @@ QHash UserListModel::roleNames() const return roles; } +void UserListModel::activate() +{ + if (m_active) { + return; + } + + m_active = true; + refreshAllMembers(); +} + #include "moc_userlistmodel.cpp" diff --git a/src/models/userlistmodel.h b/src/models/userlistmodel.h index e579da0a9..39acd22e3 100644 --- a/src/models/userlistmodel.h +++ b/src/models/userlistmodel.h @@ -77,6 +77,8 @@ public: */ [[nodiscard]] QHash roleNames() const override; + void activate(); + Q_SIGNALS: void roomChanged(); void usersRefreshed(); @@ -94,6 +96,8 @@ private: QPointer m_currentRoom; QList m_members; + bool m_active = false; + int findUserPos(const Quotient::RoomMember &member) const; [[nodiscard]] int findUserPos(const QString &username) const; }; diff --git a/src/neochatroom.cpp b/src/neochatroom.cpp index 62e2fda6c..0d54e0dc4 100644 --- a/src/neochatroom.cpp +++ b/src/neochatroom.cpp @@ -866,11 +866,18 @@ void NeoChatRoom::setUserPowerLevel(const QString &userID, const int &powerLevel int NeoChatRoom::getUserPowerLevel(const QString &userId) const { - auto powerLevelEvent = currentState().get(); - if (!powerLevelEvent) { - return 0; + if (!successorId().isEmpty()) { + return 0; // No one can upgrade a room that's already upgraded } - return powerLevelEvent->powerLevelForUser(userId); + + const auto &mId = userId.isEmpty() ? connection()->userId() : userId; + if (const auto *plEvent = currentState().get()) { + return plEvent->powerLevelForUser(mId); + } + if (const auto *createEvent = creation()) { + return createEvent->senderId() == mId ? 100 : 0; + } + return 0; // That's rather weird but may happen, according to rvdh } QCoro::Task NeoChatRoom::doDeleteMessagesByUser(const QString &user, QString reason) diff --git a/src/qml/RoomInformation.qml b/src/qml/RoomInformation.qml index 23449bad9..653dc5557 100644 --- a/src/qml/RoomInformation.qml +++ b/src/qml/RoomInformation.qml @@ -192,20 +192,7 @@ QQC2.ScrollView { } } - KSortFilterProxyModel { - id: sortedMessageEventModel - - sourceModel: UserListModel { - room: root.room - } - - sortRoleName: "powerLevel" - sortOrder: Qt.DescendingOrder - filterRoleName: "name" - filterCaseSensitivity: Qt.CaseInsensitive - } - - model: root.room.isDirectChat() ? 0 : sortedMessageEventModel + model: root.room.isDirectChat() ? 0 : RoomManager.userListModel clip: true focus: true diff --git a/src/qml/TimelineView.qml b/src/qml/TimelineView.qml index f7689ba89..a3179b4d2 100644 --- a/src/qml/TimelineView.qml +++ b/src/qml/TimelineView.qml @@ -108,6 +108,7 @@ QQC2.ScrollView { onTriggered: { root.roomChanging = false; markReadIfVisibleTimer.reset(); + RoomManager.activateUserModel(); } } onAtYEndChanged: if (!root.roomChanging) { diff --git a/src/roommanager.cpp b/src/roommanager.cpp index 3afd35d85..063799f49 100644 --- a/src/roommanager.cpp +++ b/src/roommanager.cpp @@ -39,6 +39,7 @@ RoomManager::RoomManager(QObject *parent) , m_timelineModel(new TimelineModel(this)) , m_messageFilterModel(new MessageFilterModel(this, m_timelineModel)) , m_mediaMessageFilterModel(new MediaMessageFilterModel(this, m_messageFilterModel)) + , m_userListModel(new UserListModel(this)) { m_lastRoomConfig = m_config->group(QStringLiteral("LastOpenRoom")); m_lastSpaceConfig = m_config->group(QStringLiteral("LastOpenSpace")); @@ -46,6 +47,7 @@ RoomManager::RoomManager(QObject *parent) connect(this, &RoomManager::currentRoomChanged, this, [this]() { m_timelineModel->setRoom(m_currentRoom); + m_userListModel->setRoom(m_currentRoom); }); connect(&Controller::instance(), &Controller::activeConnectionChanged, this, [this](NeoChatConnection *connection) { @@ -113,6 +115,16 @@ MediaMessageFilterModel *RoomManager::mediaMessageFilterModel() const return m_mediaMessageFilterModel; } +UserListModel *RoomManager::userListModel() const +{ + return m_userListModel; +} + +void RoomManager::activateUserModel() +{ + m_userListModel->activate(); +} + UriResolveResult RoomManager::resolveResource(const Uri &uri) { return UriResolverBase::visitResource(m_connection, uri); diff --git a/src/roommanager.h b/src/roommanager.h index 410f42aa1..07de885df 100644 --- a/src/roommanager.h +++ b/src/roommanager.h @@ -22,6 +22,7 @@ #include "models/sortfilterroomtreemodel.h" #include "models/sortfilterspacelistmodel.h" #include "models/timelinemodel.h" +#include "models/userlistmodel.h" class NeoChatRoom; class NeoChatConnection; @@ -120,6 +121,14 @@ class RoomManager : public QObject, public UriResolverBase */ Q_PROPERTY(MediaMessageFilterModel *mediaMessageFilterModel READ mediaMessageFilterModel CONSTANT) + /** + * @brief The UserListModel that should be used for room member visualisation. + * + * @note Available here so that the room page and drawer both have access to the + * same model. + */ + Q_PROPERTY(UserListModel *userListModel READ userListModel CONSTANT) + /** * @brief Whether a room is currently open in NeoChat. * @@ -155,6 +164,9 @@ public: MessageFilterModel *messageFilterModel() const; MediaMessageFilterModel *mediaMessageFilterModel() const; + UserListModel *userListModel() const; + Q_INVOKABLE void activateUserModel(); + /** * @brief Resolve the given URI resource. * @@ -359,6 +371,9 @@ private: TimelineModel *m_timelineModel; MessageFilterModel *m_messageFilterModel; MediaMessageFilterModel *m_mediaMessageFilterModel; + + UserListModel *m_userListModel; + QPointer m_connection; void setCurrentRoom(const QString &roomId); diff --git a/src/settings/Permissions.qml b/src/settings/Permissions.qml index 130f9b45a..2dbcff655 100644 --- a/src/settings/Permissions.qml +++ b/src/settings/Permissions.qml @@ -20,11 +20,6 @@ FormCard.FormCardPage { title: i18nc('@title:window', 'Permissions') - property UserListModel userListModel: UserListModel { - id: userListModel - room: root.room - } - readonly property PowerLevelModel powerLevelModel: PowerLevelModel { showMute: false } @@ -39,7 +34,7 @@ FormCard.FormCardPage { FormCard.FormCard { Repeater { model: KSortFilterProxyModel { - sourceModel: userListModel + sourceModel: RoomManager.userListModel sortRoleName: "powerLevel" sortOrder: Qt.DescendingOrder filterRowCallback: function (source_row, source_parent) { @@ -158,7 +153,7 @@ FormCard.FormCardPage { model: UserFilterModel { id: userListFilterModel - sourceModel: userListModel + sourceModel: RoomManager.userListModel filterText: userListSearchField.text onFilterTextChanged: {