Create a list model for read markers. The primary reason is to stop `RoomMembers` being accessed after their state event is deleted. With this the read marker doesn't pass and `RoomMember` objects to qml.
137 lines
3.8 KiB
C++
137 lines
3.8 KiB
C++
// SPDX-FileCopyrightText: 2024 James Graham <james.h.graham@protonmail.com>
|
|
// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
|
|
|
#include "readmarkermodel.h"
|
|
|
|
#include <KLocalizedString>
|
|
|
|
#include <Quotient/roommember.h>
|
|
|
|
#define MAXMARKERS 5
|
|
|
|
ReadMarkerModel::ReadMarkerModel(const QString &eventId, NeoChatRoom *room)
|
|
: QAbstractListModel(nullptr)
|
|
, m_room(room)
|
|
, m_eventId(eventId)
|
|
{
|
|
Q_ASSERT(!m_eventId.isEmpty());
|
|
Q_ASSERT(m_room != nullptr);
|
|
|
|
connect(m_room, &NeoChatRoom::changed, this, [this](Quotient::Room::Changes changes) {
|
|
if (m_room != nullptr && changes.testFlag(Quotient::Room::Change::Other)) {
|
|
auto memberIds = m_room->userIdsAtEvent(m_eventId).values();
|
|
if (memberIds == m_markerIds) {
|
|
return;
|
|
}
|
|
|
|
beginResetModel();
|
|
m_markerIds.clear();
|
|
endResetModel();
|
|
|
|
beginResetModel();
|
|
memberIds.removeAll(m_room->localMember().id());
|
|
m_markerIds = memberIds;
|
|
endResetModel();
|
|
|
|
Q_EMIT reactionUpdated();
|
|
}
|
|
});
|
|
connect(m_room, &NeoChatRoom::memberNameUpdated, this, [this](Quotient::RoomMember member) {
|
|
if (m_markerIds.contains(member.id())) {
|
|
const auto memberIndex = index(m_markerIds.indexOf(member.id()));
|
|
Q_EMIT dataChanged(memberIndex, memberIndex);
|
|
}
|
|
});
|
|
connect(m_room, &NeoChatRoom::memberAvatarUpdated, this, [this](Quotient::RoomMember member) {
|
|
if (m_markerIds.contains(member.id())) {
|
|
const auto memberIndex = index(m_markerIds.indexOf(member.id()));
|
|
Q_EMIT dataChanged(memberIndex, memberIndex);
|
|
}
|
|
});
|
|
|
|
beginResetModel();
|
|
auto userIds = m_room->userIdsAtEvent(m_eventId);
|
|
userIds.remove(m_room->localMember().id());
|
|
m_markerIds = userIds.values();
|
|
endResetModel();
|
|
|
|
Q_EMIT reactionUpdated();
|
|
}
|
|
|
|
QVariant ReadMarkerModel::data(const QModelIndex &index, int role) const
|
|
{
|
|
if (!index.isValid()) {
|
|
return {};
|
|
}
|
|
|
|
if (index.row() >= rowCount()) {
|
|
qDebug() << "ReactionModel, something's wrong: index.row() >= rowCount()";
|
|
return {};
|
|
}
|
|
|
|
const auto member = m_room->member(m_markerIds.value(index.row()));
|
|
|
|
if (role == DisplayNameRole) {
|
|
return member.htmlSafeDisplayName();
|
|
}
|
|
|
|
if (role == AvatarUrlRole) {
|
|
return member.avatarUrl();
|
|
}
|
|
|
|
if (role == ColorRole) {
|
|
return member.color();
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
int ReadMarkerModel::rowCount(const QModelIndex &parent) const
|
|
{
|
|
Q_UNUSED(parent)
|
|
return std::min(int(m_markerIds.size()), MAXMARKERS);
|
|
}
|
|
|
|
QHash<int, QByteArray> ReadMarkerModel::roleNames() const
|
|
{
|
|
return {
|
|
{DisplayNameRole, "displayName"},
|
|
{AvatarUrlRole, "avatarUrl"},
|
|
{ColorRole, "memberColor"},
|
|
};
|
|
}
|
|
|
|
QString ReadMarkerModel::readMarkersString()
|
|
{
|
|
/**
|
|
* The string ends up in the form
|
|
* "x users: user1DisplayName, user2DisplayName, etc."
|
|
*/
|
|
QString readMarkersString = i18np("1 user: ", "%1 users: ", m_markerIds.size());
|
|
for (const auto &memberId : m_markerIds) {
|
|
auto member = m_room->member(memberId);
|
|
QString displayName = member.htmlSafeDisambiguatedName();
|
|
if (displayName.isEmpty()) {
|
|
displayName = i18nc("A member who is not in the room has been requested.", "unknown member");
|
|
}
|
|
readMarkersString += displayName + i18nc("list separator", ", ");
|
|
}
|
|
readMarkersString.chop(2);
|
|
return readMarkersString;
|
|
}
|
|
|
|
QString ReadMarkerModel::excessReadMarkersString()
|
|
{
|
|
if (m_room == nullptr) {
|
|
return {};
|
|
}
|
|
|
|
if (m_markerIds.size() > MAXMARKERS) {
|
|
return QStringLiteral("+ ") + QString::number(m_markerIds.size() - MAXMARKERS);
|
|
} else {
|
|
return QString();
|
|
}
|
|
}
|
|
|
|
#include "moc_readmarkermodel.cpp"
|