From 9ab8f796d8180ffec0bc3b6209ec46605e96a698 Mon Sep 17 00:00:00 2001 From: Tobias Fella Date: Thu, 27 Jun 2024 23:05:55 +0200 Subject: [PATCH] Port away from remove things in libquotient Mostly the User class and Omittable --- autotests/chatbarcachetest.cpp | 8 +-- autotests/eventhandlertest.cpp | 30 ++++---- autotests/reactionmodeltest.cpp | 2 +- src/actionshandler.cpp | 2 +- src/chatbarcache.cpp | 4 +- src/definitions.h | 5 +- src/eventhandler.cpp | 41 ++++++----- src/events/imagepackevent.cpp | 4 +- src/models/actionsmodel.cpp | 20 +++--- src/models/locationsmodel.cpp | 2 +- src/models/locationsmodel.h | 2 +- src/models/messageeventmodel.cpp | 4 +- src/models/notificationsmodel.cpp | 6 +- src/models/reactionmodel.cpp | 6 +- src/models/spacechildrenmodel.cpp | 4 +- src/models/userlistmodel.cpp | 106 +++++++++++++--------------- src/models/userlistmodel.h | 19 ++--- src/neochatconnection.cpp | 42 +++++------ src/neochatconnection.h | 7 -- src/neochatroom.cpp | 91 ++++++++++++------------ src/neochatroom.h | 10 +-- src/notificationsmanager.cpp | 24 +++---- src/pollhandler.cpp | 4 +- src/qml/Main.qml | 6 +- src/qml/UserDetailDialog.qml | 36 +++++----- src/registration.cpp | 4 +- src/roommanager.cpp | 9 ++- src/roommanager.h | 2 +- src/settings/IgnoredUsersDialog.qml | 2 +- src/spacehierarchycache.cpp | 6 +- src/texthandler.cpp | 6 +- src/utils.cpp | 42 ++--------- src/utils.h | 2 +- 33 files changed, 253 insertions(+), 305 deletions(-) diff --git a/autotests/chatbarcachetest.cpp b/autotests/chatbarcachetest.cpp index b34856879..78b49b8f5 100644 --- a/autotests/chatbarcachetest.cpp +++ b/autotests/chatbarcachetest.cpp @@ -50,7 +50,7 @@ void ChatBarCacheTest::empty() QCOMPARE(chatBarCache->replyId(), QString()); QCOMPARE(chatBarCache->isEditing(), false); QCOMPARE(chatBarCache->editId(), QString()); - QCOMPARE(chatBarCache->relationUser(), room->getUser(nullptr)); + QCOMPARE(chatBarCache->relationUser(), room->getUser(QString())); QCOMPARE(chatBarCache->relationMessage(), QString()); QCOMPARE(chatBarCache->attachmentPath(), QString()); } @@ -98,7 +98,7 @@ void ChatBarCacheTest::reply() QCOMPARE(chatBarCache->replyId(), QLatin1String("$153456789:example.org")); QCOMPARE(chatBarCache->isEditing(), false); QCOMPARE(chatBarCache->editId(), QString()); - QCOMPARE(chatBarCache->relationUser(), room->getUser(room->user(QLatin1String("@example:example.org")))); + QCOMPARE(chatBarCache->relationUser(), room->getUser(QLatin1String("@example:example.org"))); QCOMPARE(chatBarCache->relationMessage(), QLatin1String("This is an example\ntext message")); QCOMPARE(chatBarCache->attachmentPath(), QString()); } @@ -115,7 +115,7 @@ void ChatBarCacheTest::edit() QCOMPARE(chatBarCache->replyId(), QString()); QCOMPARE(chatBarCache->isEditing(), true); QCOMPARE(chatBarCache->editId(), QLatin1String("$153456789:example.org")); - QCOMPARE(chatBarCache->relationUser(), room->getUser(room->user(QLatin1String("@example:example.org")))); + QCOMPARE(chatBarCache->relationUser(), room->getUser(QLatin1String("@example:example.org"))); QCOMPARE(chatBarCache->relationMessage(), QLatin1String("This is an example\ntext message")); QCOMPARE(chatBarCache->attachmentPath(), QString()); } @@ -132,7 +132,7 @@ void ChatBarCacheTest::attachment() QCOMPARE(chatBarCache->replyId(), QString()); QCOMPARE(chatBarCache->isEditing(), false); QCOMPARE(chatBarCache->editId(), QString()); - QCOMPARE(chatBarCache->relationUser(), room->getUser(nullptr)); + QCOMPARE(chatBarCache->relationUser(), room->getUser(QString())); QCOMPARE(chatBarCache->relationMessage(), QString()); QCOMPARE(chatBarCache->attachmentPath(), QLatin1String("some/path")); } diff --git a/autotests/eventhandlertest.cpp b/autotests/eventhandlertest.cpp index cb3dde831..b37f24d55 100644 --- a/autotests/eventhandlertest.cpp +++ b/autotests/eventhandlertest.cpp @@ -101,17 +101,17 @@ void EventHandlerTest::nullEventId() void EventHandlerTest::author() { auto event = room->messageEvents().at(0).get(); - auto author = room->user(event->senderId()); + auto author = room->member(event->senderId()); EventHandler eventHandler(room, event); auto eventHandlerAuthor = eventHandler.getAuthor(); - QCOMPARE(eventHandlerAuthor["isLocalUser"_ls], author->id() == room->localUser()->id()); - QCOMPARE(eventHandlerAuthor["id"_ls], author->id()); - QCOMPARE(eventHandlerAuthor["displayName"_ls], author->displayname(room)); + QCOMPARE(eventHandlerAuthor["isLocalUser"_ls], author.id() == room->localMember().id()); + QCOMPARE(eventHandlerAuthor["id"_ls], author.id()); + QCOMPARE(eventHandlerAuthor["displayName"_ls], author.displayName()); QCOMPARE(eventHandlerAuthor["avatarSource"_ls], room->avatarForMember(author)); - QCOMPARE(eventHandlerAuthor["avatarMediaId"_ls], author->avatarMediaId(room)); - QCOMPARE(eventHandlerAuthor["color"_ls], Utils::getUserColor(author->hueF())); + QCOMPARE(eventHandlerAuthor["avatarMediaId"_ls], author.avatarMediaId()); + QCOMPARE(eventHandlerAuthor["color"_ls], Utils::getUserColor(author.hueF())); QCOMPARE(eventHandlerAuthor["object"_ls], QVariant::fromValue(author)); } @@ -122,7 +122,7 @@ void EventHandlerTest::nullAuthor() EventHandler noEventHandler(room, nullptr); QTest::ignoreMessage(QtWarningMsg, "getAuthor called with m_event set to nullptr. Returning empty user."); - QCOMPARE(noEventHandler.getAuthor(), room->getUser(nullptr)); + QCOMPARE(noEventHandler.getAuthor(), room->getUser(QString())); } void EventHandlerTest::authorDisplayName() @@ -393,21 +393,21 @@ void EventHandlerTest::nullReplyId() void EventHandlerTest::replyAuthor() { auto replyEvent = room->messageEvents().at(0).get(); - auto replyAuthor = room->user(replyEvent->senderId()); + auto replyAuthor = room->member(replyEvent->senderId()); EventHandler eventHandler(room, room->messageEvents().at(5).get()); auto eventHandlerReplyAuthor = eventHandler.getReplyAuthor(); - QCOMPARE(eventHandlerReplyAuthor["isLocalUser"_ls], replyAuthor->id() == room->localUser()->id()); - QCOMPARE(eventHandlerReplyAuthor["id"_ls], replyAuthor->id()); - QCOMPARE(eventHandlerReplyAuthor["displayName"_ls], replyAuthor->displayname(room)); + QCOMPARE(eventHandlerReplyAuthor["isLocalUser"_ls], replyAuthor.id() == room->localMember().id()); + QCOMPARE(eventHandlerReplyAuthor["id"_ls], replyAuthor.id()); + QCOMPARE(eventHandlerReplyAuthor["displayName"_ls], replyAuthor.displayName()); QCOMPARE(eventHandlerReplyAuthor["avatarSource"_ls], room->avatarForMember(replyAuthor)); - QCOMPARE(eventHandlerReplyAuthor["avatarMediaId"_ls], replyAuthor->avatarMediaId(room)); - QCOMPARE(eventHandlerReplyAuthor["color"_ls], Utils::getUserColor(replyAuthor->hueF())); + QCOMPARE(eventHandlerReplyAuthor["avatarMediaId"_ls], replyAuthor.avatarMediaId()); + QCOMPARE(eventHandlerReplyAuthor["color"_ls], Utils::getUserColor(replyAuthor.hueF())); QCOMPARE(eventHandlerReplyAuthor["object"_ls], QVariant::fromValue(replyAuthor)); EventHandler eventHandlerNoAuthor(room, room->messageEvents().at(0).get()); - QCOMPARE(eventHandlerNoAuthor.getReplyAuthor(), room->getUser(nullptr)); + QCOMPARE(eventHandlerNoAuthor.getReplyAuthor(), room->getUser(QString())); } void EventHandlerTest::nullReplyAuthor() @@ -417,7 +417,7 @@ void EventHandlerTest::nullReplyAuthor() EventHandler noEventHandler(room, nullptr); QTest::ignoreMessage(QtWarningMsg, "getReplyAuthor called with m_event set to nullptr. Returning empty user."); - QCOMPARE(noEventHandler.getReplyAuthor(), room->getUser(nullptr)); + QCOMPARE(noEventHandler.getReplyAuthor(), room->getUser(QString())); } void EventHandlerTest::replyBody() diff --git a/autotests/reactionmodeltest.cpp b/autotests/reactionmodeltest.cpp index e807ae783..be2078c3d 100644 --- a/autotests/reactionmodeltest.cpp +++ b/autotests/reactionmodeltest.cpp @@ -53,7 +53,7 @@ void ReactionModelTest::basicReaction() QCOMPARE(model.data(model.index(0), ReactionModel::ReactionRole), QStringLiteral("👍")); QCOMPARE(model.data(model.index(0), ReactionModel::ToolTipRole), QStringLiteral("@alice:matrix.org reacted with 👍")); - auto authorList = QVariantList{room->getUser(room->user(QStringLiteral("@alice:matrix.org")))}; + auto authorList = QVariantList{room->getUser(QStringLiteral("@alice:matrix.org"))}; QCOMPARE(model.data(model.index(0), ReactionModel::AuthorsRole), authorList); QCOMPARE(model.data(model.index(0), ReactionModel::HasLocalUser), false); } diff --git a/src/actionshandler.cpp b/src/actionshandler.cpp index 8fd3cf535..e5ddaadbd 100644 --- a/src/actionshandler.cpp +++ b/src/actionshandler.cpp @@ -91,7 +91,7 @@ void ActionsHandler::handleMessage(const QString &text, QString handledText, Cha for (auto it = m_room->messageEvents().crbegin(); it != m_room->messageEvents().crend(); it++) { if (const auto event = eventCast(&**it)) { - if (event->senderId() == m_room->localUser()->id() && event->hasTextContent()) { + if (event->senderId() == m_room->localMember().id() && event->hasTextContent()) { QString originalString; if (event->content()) { originalString = static_cast(event->content())->body; diff --git a/src/chatbarcache.cpp b/src/chatbarcache.cpp index d123db5f3..277d9cb9e 100644 --- a/src/chatbarcache.cpp +++ b/src/chatbarcache.cpp @@ -96,9 +96,9 @@ QVariantMap ChatBarCache::relationUser() const return {}; } if (m_relationId.isEmpty()) { - return room->getUser(nullptr); + return room->getUser(QString()); } - return room->getUser(room->user((*room->findInTimeline(m_relationId))->senderId())); + return room->getUser((*room->findInTimeline(m_relationId))->senderId()); } QString ChatBarCache::relationMessage() const diff --git a/src/definitions.h b/src/definitions.h index eae8c3149..cd505e27e 100644 --- a/src/definitions.h +++ b/src/definitions.h @@ -3,8 +3,9 @@ #if Quotient_VERSION_MINOR > 8 #define Omittable std::optional -#define none Quotient::none +#define quotientNone std::nullopt #else +#include #define Omittable Quotient::Omittable -#define none std::nullopt +#define quotientNone Quotient::none #endif diff --git a/src/eventhandler.cpp b/src/eventhandler.cpp index ca42438b1..ab2f6bac4 100644 --- a/src/eventhandler.cpp +++ b/src/eventhandler.cpp @@ -70,10 +70,10 @@ QVariantMap EventHandler::getAuthor(bool isPending) const // If we have a room we can return an empty user by handing nullptr to m_room->getUser. if (m_event == nullptr) { qCWarning(EventHandling) << "getAuthor called with m_event set to nullptr. Returning empty user."; - return m_room->getUser(nullptr); + return m_room->getUser(QString()); } - const auto author = isPending ? m_room->localUser() : m_room->user(m_event->senderId()); + const auto author = isPending ? m_room->localMember() : m_room->member(m_event->senderId()); return m_room->getUser(author); } @@ -96,8 +96,8 @@ QString EventHandler::getAuthorDisplayName(bool isPending) const } return previousDisplayName; } else { - const auto author = isPending ? m_room->localUser() : m_room->user(m_event->senderId()); - return m_room->htmlSafeMemberName(author->id()); + const auto author = isPending ? m_room->localMember() : m_room->member(m_event->senderId()); + return author.htmlSafeDisplayName(); } } @@ -112,8 +112,8 @@ QString EventHandler::singleLineAuthorDisplayname(bool isPending) const return {}; } - const auto author = isPending ? m_room->localUser() : m_room->user(m_event->senderId()); - auto displayName = m_room->safeMemberName(author->id()); + const auto author = isPending ? m_room->localMember() : m_room->member(m_event->senderId()); + auto displayName = author.displayName(); displayName.replace(QStringLiteral("
\n"), QStringLiteral(" ")); displayName.replace(QStringLiteral("
"), QStringLiteral(" ")); displayName.replace(QStringLiteral("
\n"), QStringLiteral(" ")); @@ -220,7 +220,7 @@ bool EventHandler::isHidden() } } - if (m_room->connection()->isIgnored(m_room->user(m_event->senderId()))) { + if (m_room->connection()->isIgnored(m_event->senderId())) { return true; } @@ -255,7 +255,7 @@ QString EventHandler::rawMessageBody(const Quotient::RoomMessageEvent &event) QString body; if (event.hasTextContent() && event.content()) { - body = static_cast(event.content())->body; + body = static_cast(event.content())->body; } else { body = event.plainBody(); } @@ -318,7 +318,7 @@ QString EventHandler::getBody(const Quotient::RoomEvent *event, Qt::TextFormat f }, [this, prettyPrint](const RoomMemberEvent &e) { // FIXME: Rewind to the name that was at the time of this event - auto subjectName = m_room->htmlSafeMemberName(e.userId()); + auto subjectName = m_room->member(e.userId()).htmlSafeDisplayName(); if (e.membership() == Membership::Leave) { if (e.prevContent() && e.prevContent()->displayName) { subjectName = sanitized(*e.prevContent()->displayName).toHtmlEscaped(); @@ -479,7 +479,7 @@ QString EventHandler::getMessageBody(const RoomMessageEvent &event, Qt::TextForm QString body; if (event.hasTextContent() && event.content()) { - body = static_cast(event.content())->body; + body = static_cast(event.content())->body; } else { body = event.plainBody(); } @@ -809,16 +809,15 @@ QVariantMap EventHandler::getReplyAuthor() const // If we have a room we can return an empty user by handing nullptr to m_room->getUser. if (m_event == nullptr) { qCWarning(EventHandling) << "getReplyAuthor called with m_event set to nullptr. Returning empty user."; - return m_room->getUser(nullptr); + return m_room->getUser(QString()); } auto replyPtr = m_room->getReplyForEvent(*m_event); if (replyPtr) { - auto replyUser = m_room->user(replyPtr->senderId()); - return m_room->getUser(replyUser); + return m_room->getUser(replyPtr->senderId()); } else { - return m_room->getUser(nullptr); + return m_room->getUser(QString()); } } @@ -966,7 +965,7 @@ bool EventHandler::hasReadMarkers() const } auto userIds = m_room->userIdsAtEvent(m_event->id()); - userIds.remove(m_room->localUser()->id()); + userIds.remove(m_room->localMember().id()); return userIds.size() > 0; } @@ -982,7 +981,7 @@ QVariantList EventHandler::getReadMarkers(int maxMarkers) const } auto userIds_temp = m_room->userIdsAtEvent(m_event->id()); - userIds_temp.remove(m_room->localUser()->id()); + userIds_temp.remove(m_room->localMember().id()); auto userIds = userIds_temp.values(); if (userIds.count() > maxMarkers) { @@ -992,7 +991,7 @@ QVariantList EventHandler::getReadMarkers(int maxMarkers) const QVariantList users; users.reserve(userIds.size()); for (const auto &userId : userIds) { - auto user = m_room->user(userId); + auto user = m_room->member(userId); users += m_room->getUser(user); } @@ -1011,7 +1010,7 @@ QString EventHandler::getNumberExcessReadMarkers(int maxMarkers) const } auto userIds = m_room->userIdsAtEvent(m_event->id()); - userIds.remove(m_room->localUser()->id()); + userIds.remove(m_room->localMember().id()); if (userIds.count() > maxMarkers) { return QStringLiteral("+ ") + QString::number(userIds.count() - maxMarkers); @@ -1032,7 +1031,7 @@ QString EventHandler::getReadMarkersString() const } auto userIds = m_room->userIdsAtEvent(m_event->id()); - userIds.remove(m_room->localUser()->id()); + userIds.remove(m_room->localMember().id()); /** * The string ends up in the form @@ -1040,8 +1039,8 @@ QString EventHandler::getReadMarkersString() const */ QString readMarkersString = i18np("1 user: ", "%1 users: ", userIds.size()); for (const auto &userId : userIds) { - auto user = m_room->user(userId); - auto displayName = user->displayname(m_room); + auto user = m_room->member(userId); + auto displayName = user.displayName(); if (displayName.isEmpty()) { displayName = userId; } diff --git a/src/events/imagepackevent.cpp b/src/events/imagepackevent.cpp index 6a909bd21..34ff5c512 100644 --- a/src/events/imagepackevent.cpp +++ b/src/events/imagepackevent.cpp @@ -16,7 +16,7 @@ ImagePackEventContent::ImagePackEventContent(const QJsonObject &json) fromJson>(json["pack"_ls].toObject()["attribution"_ls]), }; } else { - pack = none; + pack = quotientNone; } const auto &keys = json["images"_ls].toObject().keys(); @@ -25,7 +25,7 @@ ImagePackEventContent::ImagePackEventContent(const QJsonObject &json) if (json["images"_ls][k].toObject().contains(QStringLiteral("info"))) { info = EventContent::ImageInfo(QUrl(json["images"_ls][k]["url"_ls].toString()), json["images"_ls][k]["info"_ls].toObject(), k); } else { - info = none; + info = quotientNone; } images += ImagePackImage{ k, diff --git a/src/models/actionsmodel.cpp b/src/models/actionsmodel.cpp index e0d66df72..757f63f81 100644 --- a/src/models/actionsmodel.cpp +++ b/src/models/actionsmodel.cpp @@ -202,11 +202,11 @@ QList actions{ Q_EMIT room->showMessage(NeoChatRoom::Info, i18nc(" is banned from this room.", "%1 is banned from this room.", text)); return QString(); } - if (room->localUser()->id() == text) { + if (room->localMember().id() == text) { Q_EMIT room->showMessage(NeoChatRoom::Positive, i18n("You are already in this room.")); return QString(); } - if (room->users().contains(room->user(text))) { + if (room->memberIds().contains(text)) { Q_EMIT room->showMessage(NeoChatRoom::Info, i18nc(" is already in this room.", "%1 is already in this room.", text)); return QString(); } @@ -359,7 +359,7 @@ QList actions{ Q_EMIT room->showMessage(NeoChatRoom::Info, i18nc(" is already ignored.", "%1 is already ignored.", text)); return QString(); } - room->connection()->addToIgnoredUsers(room->connection()->user(text)); + room->connection()->addToIgnoredUsers(text); Q_EMIT room->showMessage(NeoChatRoom::Positive, i18nc(" is now ignored", "%1 is now ignored.", text)); return QString(); }, @@ -382,7 +382,7 @@ QList actions{ Q_EMIT room->showMessage(NeoChatRoom::Info, i18nc(" is not ignored.", "%1 is not ignored.", text)); return QString(); } - room->connection()->removeFromIgnoredUsers(room->connection()->user(text)); + room->connection()->removeFromIgnoredUsers(text); Q_EMIT room->showMessage(NeoChatRoom::Positive, i18nc(" is no longer ignored.", "%1 is no longer ignored.", text)); return QString(); }, @@ -431,11 +431,11 @@ QList actions{ if (!plEvent) { return QString(); } - if (plEvent->ban() > plEvent->powerLevelForUser(room->localUser()->id())) { + if (plEvent->ban() > plEvent->powerLevelForUser(room->localMember().id())) { Q_EMIT room->showMessage(NeoChatRoom::Error, i18n("You are not allowed to ban users from this room.")); return QString(); } - if (plEvent->powerLevelForUser(room->localUser()->id()) <= plEvent->powerLevelForUser(parts[0])) { + if (plEvent->powerLevelForUser(room->localMember().id()) <= plEvent->powerLevelForUser(parts[0])) { Q_EMIT room->showMessage( NeoChatRoom::Error, i18nc("You are not allowed to ban from this room.", "You are not allowed to ban %1 from this room.", parts[0])); @@ -464,7 +464,7 @@ QList actions{ if (!plEvent) { return QString(); } - if (plEvent->ban() > plEvent->powerLevelForUser(room->localUser()->id())) { + if (plEvent->ban() > plEvent->powerLevelForUser(room->localMember().id())) { Q_EMIT room->showMessage(NeoChatRoom::Error, i18n("You are not allowed to unban users from this room.")); return QString(); } @@ -495,7 +495,7 @@ QList actions{ i18nc("'' does not look like a matrix id.", "'%1' does not look like a matrix id.", parts[0])); return QString(); } - if (parts[0] == room->localUser()->id()) { + if (parts[0] == room->localMember().id()) { Q_EMIT room->showMessage(NeoChatRoom::Error, i18n("You cannot kick yourself from the room.")); return QString(); } @@ -508,11 +508,11 @@ QList actions{ return QString(); } auto kick = plEvent->kick(); - if (plEvent->powerLevelForUser(room->localUser()->id()) < kick) { + if (plEvent->powerLevelForUser(room->localMember().id()) < kick) { Q_EMIT room->showMessage(NeoChatRoom::Error, i18n("You are not allowed to kick users from this room.")); return QString(); } - if (plEvent->powerLevelForUser(room->localUser()->id()) <= plEvent->powerLevelForUser(parts[0])) { + if (plEvent->powerLevelForUser(room->localMember().id()) <= plEvent->powerLevelForUser(parts[0])) { Q_EMIT room->showMessage( NeoChatRoom::Error, i18nc("You are not allowed to kick from this room", "You are not allowed to kick %1 from this room.", parts[0])); diff --git a/src/models/locationsmodel.cpp b/src/models/locationsmodel.cpp index 1f15f12bd..4229e1213 100644 --- a/src/models/locationsmodel.cpp +++ b/src/models/locationsmodel.cpp @@ -63,7 +63,7 @@ void LocationsModel::addLocation(const RoomMessageEvent *event) .latitude = latitude, .longitude = longitude, .content = event->contentJson(), - .author = m_room->user(event->senderId()), + .author = event->senderId(), }; endInsertRows(); } diff --git a/src/models/locationsmodel.h b/src/models/locationsmodel.h index 7f7b1fb97..0016906dc 100644 --- a/src/models/locationsmodel.h +++ b/src/models/locationsmodel.h @@ -57,7 +57,7 @@ private: float latitude; float longitude; QJsonObject content; - Quotient::User *author; + QString author; }; QList m_locations; void addLocation(const Quotient::RoomMessageEvent *event); diff --git a/src/models/messageeventmodel.cpp b/src/models/messageeventmodel.cpp index 77cc4ce69..2211f7c80 100644 --- a/src/models/messageeventmodel.cpp +++ b/src/models/messageeventmodel.cpp @@ -222,7 +222,7 @@ void MessageEventModel::setRoom(NeoChatRoom *room) beginResetModel(); endResetModel(); }); - qCDebug(MessageEvent) << "Connected to room" << room->id() << "as" << room->localUser()->id(); + qCDebug(MessageEvent) << "Connected to room" << room->id() << "as" << room->localMember().id(); } else { lastReadEventId.clear(); } @@ -592,7 +592,7 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const } if (role == IsEditableRole) { - return eventHandler.messageComponentType() == MessageComponentType::Text && evt.senderId() == m_currentRoom->localUser()->id(); + return eventHandler.messageComponentType() == MessageComponentType::Text && evt.senderId() == m_currentRoom->localMember().id(); } return {}; diff --git a/src/models/notificationsmodel.cpp b/src/models/notificationsmodel.cpp index 9cd573d3c..b3bfed5f6 100644 --- a/src/models/notificationsmodel.cpp +++ b/src/models/notificationsmodel.cpp @@ -116,7 +116,7 @@ void NotificationsModel::loadData() if (!room) { continue; } - auto u = room->memberAvatarUrl(authorId); + auto u = room->member(authorId).avatarUrl(); auto avatar = u.isEmpty() ? QUrl() : connection()->makeMediaUrl(u); const auto &authorAvatar = avatar.isValid() && avatar.scheme() == QStringLiteral("mxc") ? avatar : QUrl(); @@ -125,9 +125,9 @@ void NotificationsModel::loadData() beginInsertRows({}, m_notifications.length(), m_notifications.length()); m_notifications += Notification{ .roomId = notification.roomId, - .text = room->htmlSafeMemberName(authorId) + (roomEvent->is() ? QStringLiteral(" ") : QStringLiteral(": ")) + .text = room->member(authorId).htmlSafeDisplayName() + (roomEvent->is() ? QStringLiteral(" ") : QStringLiteral(": ")) + eventHandler.getPlainBody(true), - .authorName = room->htmlSafeMemberName(authorId), + .authorName = room->member(authorId).htmlSafeDisplayName(), .authorAvatar = authorAvatar, .eventId = roomEvent->id(), .roomDisplayName = room->displayName(), diff --git a/src/models/reactionmodel.cpp b/src/models/reactionmodel.cpp index d2793eecb..a1209c364 100644 --- a/src/models/reactionmodel.cpp +++ b/src/models/reactionmodel.cpp @@ -92,7 +92,7 @@ QVariant ReactionModel::data(const QModelIndex &index, int role) const if (role == HasLocalUser) { for (auto author : reaction.authors) { - if (author.toMap()[QStringLiteral("id")] == m_room->localUser()->id()) { + if (author.toMap()[QStringLiteral("id")] == m_room->localMember().id()) { return true; } } @@ -121,13 +121,13 @@ void ReactionModel::updateReactions() return; }; - QMap> reactions = {}; + QMap> reactions = {}; for (const auto &a : annotations) { if (a->isRedacted()) { // Just in case? continue; } if (const auto &e = eventCast(a)) { - reactions[e->key()].append(m_room->user(e->senderId())); + reactions[e->key()].append(m_room->member(e->senderId())); if (e->contentJson()[QStringLiteral("shortcode")].toString().length()) { m_shortcodes[e->key()] = e->contentJson()[QStringLiteral("shortcode")].toString().toHtmlEscaped(); } diff --git a/src/models/spacechildrenmodel.cpp b/src/models/spacechildrenmodel.cpp index 849f994cb..7a04e63f8 100644 --- a/src/models/spacechildrenmodel.cpp +++ b/src/models/spacechildrenmodel.cpp @@ -88,7 +88,7 @@ void SpaceChildrenModel::refreshModel() m_rootItem = new SpaceTreeItem(dynamic_cast(m_space->connection()), nullptr, m_space->id(), m_space->displayName(), m_space->canonicalAlias()); endResetModel(); - auto job = m_space->connection()->callApi(m_space->id(), none, none, 1); + auto job = m_space->connection()->callApi(m_space->id(), quotientNone, quotientNone, 1); m_currentJobs.append(job); connect(job, &Quotient::BaseJob::success, this, [this, job]() { insertChildren(job->rooms()); @@ -137,7 +137,7 @@ void SpaceChildrenModel::insertChildren(std::vector 0) { - auto job = m_space->connection()->callApi(children[i].roomId, none, none, 1); + auto job = m_space->connection()->callApi(children[i].roomId, quotientNone, quotientNone, 1); m_currentJobs.append(job); connect(job, &Quotient::BaseJob::success, this, [this, parent, insertRow, job]() { insertChildren(job->rooms(), index(insertRow, 0, parent)); diff --git a/src/models/userlistmodel.cpp b/src/models/userlistmodel.cpp index fca7e6abc..e87d84c2f 100644 --- a/src/models/userlistmodel.cpp +++ b/src/models/userlistmodel.cpp @@ -5,7 +5,9 @@ #include +#include #include +#include #include "enums/powerlevel.h" #include "neochatroom.h" @@ -26,18 +28,26 @@ void UserListModel::setRoom(NeoChatRoom *room) if (m_currentRoom) { m_currentRoom->disconnect(this); + m_currentRoom->connection()->disconnect(this); } m_currentRoom = room; if (m_currentRoom) { - connect(m_currentRoom, &Room::userAdded, this, &UserListModel::userAdded); - connect(m_currentRoom, &Room::userRemoved, this, &UserListModel::userRemoved); - connect(m_currentRoom, &Room::memberAboutToRename, this, &UserListModel::userRemoved); - connect(m_currentRoom, &Room::memberRenamed, this, &UserListModel::userAdded); - connect(m_currentRoom, &Room::changed, this, &UserListModel::refreshAllUsers); + connect(m_currentRoom, &Room::memberJoined, this, &UserListModel::memberJoined); + connect(m_currentRoom, &Room::memberLeft, this, &UserListModel::memberLeft); + connect(m_currentRoom, &Room::memberNameUpdated, this, [this](RoomMember member) { + refreshMember(member, {DisplayNameRole}); + }); + connect(m_currentRoom, &Room::memberAvatarUpdated, this, [this](RoomMember member) { + refreshMember(member, {AvatarRole}); + }); + connect(m_currentRoom, &Room::changed, this, &UserListModel::refreshAllMembers); + connect(m_currentRoom->connection(), &Connection::loggedOut, this, [this]() { + setRoom(nullptr); + }); } - refreshAllUsers(); + refreshAllMembers(); Q_EMIT roomChanged(); } @@ -46,44 +56,36 @@ NeoChatRoom *UserListModel::room() const return m_currentRoom; } -Quotient::User *UserListModel::userAt(QModelIndex index) const -{ - if (index.row() < 0 || index.row() >= m_users.size()) { - return nullptr; - } - return m_users.at(index.row()); -} - QVariant UserListModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) { return QVariant(); } - if (index.row() >= m_users.count()) { + if (index.row() >= m_members.count()) { qDebug() << "UserListModel, something's wrong: index.row() >= " "users.count()"; return {}; } - auto user = m_users.at(index.row()); + auto member = m_members.at(index.row()); if (role == DisplayNameRole) { - return user->displayname(m_currentRoom); + return m_currentRoom->member(member).disambiguatedName(); } if (role == UserIdRole) { - return user->id(); + return member; } if (role == AvatarRole) { - return m_currentRoom->avatarForMember(user); + return m_currentRoom->memberAvatar(member).url(); } if (role == ObjectRole) { - return QVariant::fromValue(user); + return QVariant::fromValue(member); } if (role == PowerLevelRole) { auto plEvent = m_currentRoom->currentState().get(); if (!plEvent) { return 0; } - return plEvent->powerLevelForUser(user->id()); + return plEvent->powerLevelForUser(member); } if (role == PowerLevelStringRole) { auto pl = m_currentRoom->currentState().get(); @@ -93,7 +95,7 @@ QVariant UserListModel::data(const QModelIndex &index, int role) const return QStringLiteral("Not Available"); } - auto userPl = pl->powerLevelForUser(user->id()); + auto userPl = pl->powerLevelForUser(member); return i18nc("%1 is the name of the power level, e.g. admin and %2 is the value that represents.", "%1 (%2)", @@ -109,87 +111,77 @@ int UserListModel::rowCount(const QModelIndex &parent) const if (parent.isValid()) { return 0; } - return m_users.count(); + return m_members.count(); } bool UserListModel::event(QEvent *event) { if (event->type() == QEvent::ApplicationPaletteChange) { - refreshAllUsers(); + refreshAllMembers(); } return QObject::event(event); } -void UserListModel::userAdded(Quotient::User *user) +void UserListModel::memberJoined(const Quotient::RoomMember &member) { - auto pos = findUserPos(user); + auto pos = findUserPos(member); beginInsertRows(QModelIndex(), pos, pos); - m_users.insert(pos, user); + m_members.insert(pos, member.id()); endInsertRows(); - connect(user, &User::defaultAvatarChanged, this, [this, user]() { - refreshUser(user, {AvatarRole}); - }); } -void UserListModel::userRemoved(Quotient::User *user) +void UserListModel::memberLeft(const Quotient::RoomMember &member) { - auto pos = findUserPos(user); - if (pos != m_users.size()) { + auto pos = findUserPos(member); + if (pos != m_members.size()) { beginRemoveRows(QModelIndex(), pos, pos); - m_users.removeAt(pos); + m_members.removeAt(pos); endRemoveRows(); - user->disconnect(this); } else { qWarning() << "Trying to remove a room member not in the user list"; } } -void UserListModel::refreshUser(Quotient::User *user, const QList &roles) +void UserListModel::refreshMember(const Quotient::RoomMember &member, const QList &roles) { - auto pos = findUserPos(user); - if (pos != m_users.size()) { + auto pos = findUserPos(member); + if (pos != m_members.size()) { Q_EMIT dataChanged(index(pos), index(pos), roles); } else { qWarning() << "Trying to access a room member not in the user list"; } } -void UserListModel::refreshAllUsers() +void UserListModel::refreshAllMembers() { beginResetModel(); - for (User *user : std::as_const(m_users)) { - user->disconnect(this); - } - m_users.clear(); + m_members.clear(); if (m_currentRoom != nullptr) { - m_users = m_currentRoom->users(); - std::sort(m_users.begin(), m_users.end(), m_currentRoom->memberSorter()); - - for (User *user : std::as_const(m_users)) { - connect(user, &User::defaultAvatarChanged, this, [this, user]() { - refreshUser(user, {AvatarRole}); - }); - } - connect(m_currentRoom->connection(), &Connection::loggedOut, this, [this]() { - setRoom(nullptr); + m_members = m_currentRoom->joinedMemberIds(); + std::sort(m_members.begin(), m_members.end(), [this](const auto &left, const auto &right) { + return m_currentRoom->member(left).displayName() < m_currentRoom->member(right).displayName(); }); } endResetModel(); Q_EMIT usersRefreshed(); } -int UserListModel::findUserPos(Quotient::User *user) const +int UserListModel::findUserPos(const RoomMember &member) const { - return findUserPos(m_currentRoom->safeMemberName(user->id())); + return findUserPos(member.id()); } -int UserListModel::findUserPos(const QString &username) const +int UserListModel::findUserPos(const QString &userId) const { if (!m_currentRoom) { return 0; } - return m_currentRoom->memberSorter().lowerBoundIndex(m_users, username); +#if Quotient_VERSION_MINOR > 8 + return Quotient::lowerBoundMemberIndex(m_members, m_currentRoom->member(userId).displayName(), m_currentRoom); +#else + return m_currentRoom->memberSorter().lowerBoundIndex(m_currentRoom->members(), m_currentRoom->member(userId)); +#endif } QHash UserListModel::roleNames() const diff --git a/src/models/userlistmodel.h b/src/models/userlistmodel.h index cc0fd73f4..799261285 100644 --- a/src/models/userlistmodel.h +++ b/src/models/userlistmodel.h @@ -56,11 +56,6 @@ public: [[nodiscard]] NeoChatRoom *room() const; void setRoom(NeoChatRoom *room); - /** - * @brief The user at the given index of the model. - */ - [[nodiscard]] Quotient::User *userAt(QModelIndex index) const; - /** * @brief Get the given role value at the given index. * @@ -90,15 +85,15 @@ protected: bool event(QEvent *event) override; private Q_SLOTS: - void userAdded(Quotient::User *user); - void userRemoved(Quotient::User *user); - void refreshUser(Quotient::User *user, const QList &roles = {}); - void refreshAllUsers(); + void memberJoined(const Quotient::RoomMember &member); + void memberLeft(const Quotient::RoomMember &member); + void refreshMember(const Quotient::RoomMember &member, const QList &roles = {}); + void refreshAllMembers(); private: QPointer m_currentRoom; - QList m_users; + QList m_members; - int findUserPos(Quotient::User *user) const; - [[nodiscard]] int findUserPos(const QString &username) const; + int findUserPos(const Quotient::RoomMember &member) const; + [[nodiscard]] int findUserPos(const QString &userId) const; }; diff --git a/src/neochatconnection.cpp b/src/neochatconnection.cpp index 0b8c0ce52..24fbbcd94 100644 --- a/src/neochatconnection.cpp +++ b/src/neochatconnection.cpp @@ -381,34 +381,30 @@ bool NeoChatConnection::directChatExists(Quotient::User *user) void NeoChatConnection::openOrCreateDirectChat(const QString &userId) { if (auto user = this->user(userId)) { - openOrCreateDirectChat(user); + const auto existing = directChats(); + + if (existing.contains(user)) { + const auto room = this->room(existing.value(user)); + if (room) { + RoomManager::instance().resolveResource(room->id()); + return; + } + } + requestDirectChat(userId); + connect( + this, + &Connection::directChatAvailable, + this, + [=](auto room) { + room->activateEncryption(); + }, + Qt::SingleShotConnection); + } else { qWarning() << "openOrCreateDirectChat: Couldn't get user object for ID " << userId << ", unable to open/request direct chat."; } } -void NeoChatConnection::openOrCreateDirectChat(User *user) -{ - const auto existing = directChats(); - - if (existing.contains(user)) { - const auto room = this->room(existing.value(user)); - if (room) { - RoomManager::instance().resolveResource(room->id()); - return; - } - } - requestDirectChat(user); - connect( - this, - &Connection::directChatAvailable, - this, - [=](auto room) { - room->activateEncryption(); - }, - Qt::SingleShotConnection); -} - qsizetype NeoChatConnection::directChatNotifications() const { qsizetype notifications = 0; diff --git a/src/neochatconnection.h b/src/neochatconnection.h index 4c57766ee..4b55ef9df 100644 --- a/src/neochatconnection.h +++ b/src/neochatconnection.h @@ -151,13 +151,6 @@ public: */ Q_INVOKABLE void openOrCreateDirectChat(const QString &userId); - /** - * @brief Join a direct chat with the given user object. - * - * If a direct chat with the user doesn't exist one is created and then joined. - */ - Q_INVOKABLE void openOrCreateDirectChat(Quotient::User *user); - /** * @brief Get the account data with \param type as a formatted JSON string. */ diff --git a/src/neochatroom.cpp b/src/neochatroom.cpp index 05a194f42..017cbb19f 100644 --- a/src/neochatroom.cpp +++ b/src/neochatroom.cpp @@ -100,22 +100,25 @@ NeoChatRoom::NeoChatRoom(Connection *connection, QString roomId, JoinState joinS this, &Room::baseStateLoaded, this, - [this]() { + [this, connection]() { updatePushNotificationState(QStringLiteral("m.push_rules")); Q_EMIT canEncryptRoomChanged(); if (this->joinState() != JoinState::Invite) { return; } - auto roomMemberEvent = currentState().get(localUser()->id()); + auto roomMemberEvent = currentState().get(localMember().id()); QImage avatar_image; - if (roomMemberEvent && !user(roomMemberEvent->senderId())->avatarUrl(this).isEmpty()) { - avatar_image = user(roomMemberEvent->senderId())->avatar(128, this); + if (roomMemberEvent && !member(roomMemberEvent->senderId()).avatarUrl().isEmpty()) { + avatar_image = memberAvatar(roomMemberEvent->senderId()).get(connection, 128, {}); } else { qWarning() << "using this room's avatar"; avatar_image = avatar(128); } - NotificationsManager::instance().postInviteNotification(this, displayName(), htmlSafeMemberName(roomMemberEvent->senderId()), avatar_image); + NotificationsManager::instance().postInviteNotification(this, + displayName(), + member(roomMemberEvent->senderId()).htmlSafeDisplayName(), + avatar_image); }, Qt::SingleShotConnection); connect(this, &Room::changed, this, [this] { @@ -264,18 +267,18 @@ void NeoChatRoom::forget() QVariantList NeoChatRoom::getUsersTyping() const { - auto users = usersTyping(); - users.removeAll(localUser()); + auto users = membersTyping(); + users.removeAll(localMember()); QVariantList userVariants; for (const auto &user : users) { - if (connection()->isIgnored(user->id())) { + if (connection()->isIgnored(user.id())) { continue; } userVariants.append(QVariantMap{ - {"id"_ls, user->id()}, - {"avatarMediaId"_ls, user->avatarMediaId(this)}, - {"displayName"_ls, user->displayname(this)}, - {"display"_ls, user->name()}, + {"id"_ls, user.id()}, + {"avatarMediaId"_ls, user.avatarMediaId()}, + {"displayName"_ls, user.displayName()}, + {"display"_ls, user.name()}, }); } return userVariants; @@ -283,7 +286,7 @@ QVariantList NeoChatRoom::getUsersTyping() const void NeoChatRoom::sendTypingNotification(bool isTyping) { - connection()->callApi(BackgroundRequest, localUser()->id(), id(), isTyping, 10000); + connection()->callApi(BackgroundRequest, localMember().id(), id(), isTyping, 10000); } const RoomEvent *NeoChatRoom::lastEvent() const @@ -321,7 +324,7 @@ const RoomEvent *NeoChatRoom::lastEvent() const } } - if (connection()->isIgnored(user(event->senderId()))) { + if (connection()->isIgnored(event->senderId())) { continue; } @@ -381,13 +384,13 @@ bool NeoChatRoom::isEventHighlighted(const RoomEvent *e) const void NeoChatRoom::checkForHighlights(const Quotient::TimelineItem &ti) { - auto localUserId = localUser()->id(); + auto localUserId = localMember().id(); if (ti->senderId() == localUserId) { return; } if (auto *e = ti.viewAs()) { const auto &text = e->plainBody(); - if (text.contains(localUserId) || text.contains(safeMemberName(localUserId))) { + if (text.contains(localUserId) || text.contains(localUserId)) { highlights.insert(e); } } @@ -446,24 +449,20 @@ static const QVariantMap emptyUser = { QVariantMap NeoChatRoom::getUser(const QString &userID) const { - return getUser(user(userID)); + return getUser(member(userID)); } -QVariantMap NeoChatRoom::getUser(User *user) const +QVariantMap NeoChatRoom::getUser(RoomMember member) const { - if (user == nullptr) { - return emptyUser; - } - return QVariantMap{ - {QStringLiteral("isLocalUser"), user->id() == localUser()->id()}, - {QStringLiteral("id"), user->id()}, - {QStringLiteral("displayName"), user->displayname(this)}, - {QStringLiteral("escapedDisplayName"), htmlSafeMemberName(user->id())}, - {QStringLiteral("avatarSource"), avatarForMember(user)}, - {QStringLiteral("avatarMediaId"), user->avatarMediaId(this)}, - {QStringLiteral("color"), Utils::getUserColor(user->hueF())}, - {QStringLiteral("object"), QVariant::fromValue(user)}, + {QStringLiteral("isLocalUser"), member.id() == localMember().id()}, + {QStringLiteral("id"), member.id()}, + {QStringLiteral("displayName"), member.displayName()}, + {QStringLiteral("escapedDisplayName"), member.htmlSafeDisplayName()}, + {QStringLiteral("avatarSource"), member.avatarUrl()}, + {QStringLiteral("avatarMediaId"), member.avatarMediaId()}, + {QStringLiteral("color"), Utils::getUserColor(member.hueF())}, + {QStringLiteral("object"), QVariant::fromValue(member)}, }; } @@ -474,10 +473,10 @@ QString NeoChatRoom::avatarMediaId() const } // Use the first (excluding self) user's avatar for direct chats - const auto dcUsers = directChatUsers(); + const auto dcUsers = directChatMembers(); for (const auto u : dcUsers) { - if (u != localUser()) { - return u->avatarMediaId(this); + if (u != localMember()) { + return u.avatarMediaId().mid(6); } } @@ -644,7 +643,7 @@ void NeoChatRoom::toggleReaction(const QString &eventId, const QString &reaction continue; } - if (e->senderId() == localUser()->id()) { + if (e->senderId() == localMember().id()) { redactEventIds.push_back(e->id()); break; } @@ -673,7 +672,7 @@ bool NeoChatRoom::canSendEvent(const QString &eventType) const return false; } auto pl = plEvent->powerLevelForEvent(eventType); - auto currentPl = plEvent->powerLevelForUser(localUser()->id()); + auto currentPl = plEvent->powerLevelForUser(localMember().id()); return currentPl >= pl; } @@ -685,7 +684,7 @@ bool NeoChatRoom::canSendState(const QString &eventType) const return false; } auto pl = plEvent->powerLevelForState(eventType); - auto currentPl = plEvent->powerLevelForUser(localUser()->id()); + auto currentPl = plEvent->powerLevelForUser(localMember().id()); return currentPl >= pl; } @@ -863,7 +862,7 @@ void NeoChatRoom::setUrlPreviewEnabled(const bool &urlPreviewEnabled) * "type": "org.matrix.room.preview_urls", * } */ - connection()->callApi(localUser()->id(), + connection()->callApi(localMember().id(), id(), "org.matrix.room.preview_urls"_ls, QJsonObject{{"disable"_ls, !urlPreviewEnabled}}); @@ -1531,7 +1530,7 @@ void NeoChatRoom::editLastMessage() } // check if the current message's sender's id is same as the user's id - if ((*it)->senderId() == localUser()->id()) { + if ((*it)->senderId() == localMember().id()) { auto content = (*it)->contentJson(); if (e->msgtype() != MessageEventType::Unknown) { @@ -1656,13 +1655,13 @@ int NeoChatRoom::maxRoomVersion() const return maxVersion; } -Quotient::User *NeoChatRoom::directChatRemoteUser() const +RoomMember NeoChatRoom::directChatRemoteUser() const { - auto users = connection()->directChatUsers(this); + auto users = connection()->directChatMemberIds(this); if (users.isEmpty()) { - return nullptr; + return {}; } - return users[0]; + return member(users[0]); } void NeoChatRoom::sendLocation(float lat, float lon, const QString &description) @@ -1694,9 +1693,9 @@ QByteArray NeoChatRoom::roomAcountDataJson(const QString &eventType) return QJsonDocument(accountData(eventType)->fullJson()).toJson(); } -QUrl NeoChatRoom::avatarForMember(Quotient::User *user) const +QUrl NeoChatRoom::avatarForMember(RoomMember member) const { - const auto &url = memberAvatarUrl(user->id()); + const auto &url = member.avatarUrl(); if (url.isEmpty() || url.scheme() != "mxc"_ls) { return {}; } @@ -1780,9 +1779,9 @@ void NeoChatRoom::cleanupExtraEvent(const QString &eventId) } } -User *NeoChatRoom::invitingUser() const +QString NeoChatRoom::invitingUserId() const { - return connection()->user(currentState().get(connection()->userId())->senderId()); + return currentState().get(connection()->userId())->senderId(); } void NeoChatRoom::setRoomState(const QString &type, const QString &stateKey, const QByteArray &content) diff --git a/src/neochatroom.h b/src/neochatroom.h index 417741a6e..640ad23ed 100644 --- a/src/neochatroom.h +++ b/src/neochatroom.h @@ -95,7 +95,7 @@ class NeoChatRoom : public Quotient::Room /** * @brief Get a user object for the other person in a direct chat. */ - Q_PROPERTY(Quotient::User *directChatRemoteUser READ directChatRemoteUser CONSTANT) + Q_PROPERTY(Quotient::RoomMember directChatRemoteUser READ directChatRemoteUser CONSTANT) /** * @brief The Matrix IDs of this room's parents. @@ -285,7 +285,7 @@ public: * * @sa Quotient::User */ - Q_INVOKABLE [[nodiscard]] QVariantMap getUser(Quotient::User *user) const; + Q_INVOKABLE [[nodiscard]] QVariantMap getUser(Quotient::RoomMember member) const; [[nodiscard]] QVariantList getUsersTyping() const; @@ -400,7 +400,7 @@ public: [[nodiscard]] QString avatarMediaId() const; - Quotient::User *directChatRemoteUser() const; + Quotient::RoomMember directChatRemoteUser() const; /** * @brief Whether this room has one or more parent spaces set. @@ -630,7 +630,7 @@ public: */ Q_INVOKABLE QByteArray roomAcountDataJson(const QString &eventType); - Q_INVOKABLE [[nodiscard]] QUrl avatarForMember(Quotient::User *user) const; + Q_INVOKABLE [[nodiscard]] QUrl avatarForMember(Quotient::RoomMember member) const; /** * @brief Loads the event with the given id from the server and saves it locally. @@ -660,7 +660,7 @@ public: /** * If we're invited to this room, the user that invited us. Undefined in other cases. */ - Q_INVOKABLE Quotient::User *invitingUser() const; + Q_INVOKABLE QString invitingUserId() const; private: QSet highlights; diff --git a/src/notificationsmanager.cpp b/src/notificationsmanager.cpp index ebb7c9c39..4491207d3 100644 --- a/src/notificationsmanager.cpp +++ b/src/notificationsmanager.cpp @@ -42,12 +42,12 @@ NotificationsManager::NotificationsManager(QObject *parent) void NotificationsManager::handleNotifications(QPointer connection) { - if (!m_connActiveJob.contains(connection->user()->id())) { + if (!m_connActiveJob.contains(connection->userId())) { auto job = connection->callApi(); m_connActiveJob.append(connection->user()->id()); connect(job, &BaseJob::success, this, [this, job, connection]() { - m_connActiveJob.removeAll(connection->user()->id()); - processNotificationJob(connection, job, !m_oldNotifications.contains(connection->user()->id())); + m_connActiveJob.removeAll(connection->userId()); + processNotificationJob(connection, job, !m_oldNotifications.contains(connection->userId())); }); } } @@ -58,7 +58,7 @@ void NotificationsManager::processNotificationJob(QPointer co return; } - const auto connectionId = connection->user()->id(); + const auto connectionId = connection->userId(); const auto notifications = job->jsonData()["notifications"_ls].toArray(); if (initialization) { @@ -108,7 +108,7 @@ void NotificationsManager::processNotificationJob(QPointer co if (!room) { continue; } - auto sender = room->user(notification["event"_ls]["sender"_ls].toString()); + auto sender = room->member(notification["event"_ls]["sender"_ls].toString()); QString body; if (notification["event"_ls]["type"_ls].toString() == "org.matrix.msc3381.poll.start"_ls) { @@ -124,13 +124,13 @@ void NotificationsManager::processNotificationJob(QPointer co } QImage avatar_image; - if (!sender->avatarUrl(room).isEmpty()) { - avatar_image = sender->avatar(128, room); + if (!sender.avatarUrl().isEmpty()) { + avatar_image = room->memberAvatar(sender.id()).get(connection, 128, {}); } else { avatar_image = room->avatar(128); } postNotification(dynamic_cast(room), - sender->displayname(room), + sender.displayName(), body, avatar_image, notification["event"_ls].toObject()["event_id"_ls].toString(), @@ -213,7 +213,7 @@ void NotificationsManager::postNotification(NeoChatRoom *room, if (!room) { return; } - auto connection = dynamic_cast(Controller::instance().accounts().get(room->localUser()->id())); + auto connection = dynamic_cast(Controller::instance().accounts().get(room->localMember().id())); Controller::instance().setActiveConnection(connection); RoomManager::instance().setConnection(connection); RoomManager::instance().resolveResource(room->id()); @@ -230,7 +230,7 @@ void NotificationsManager::postNotification(NeoChatRoom *room, notification->setReplyAction(std::move(replyAction)); } - notification->setHint(QStringLiteral("x-kde-origin-name"), room->localUser()->id()); + notification->setHint(QStringLiteral("x-kde-origin-name"), room->localMember().id()); notification->sendEvent(); } @@ -276,7 +276,7 @@ void NotificationsManager::postInviteNotification(NeoChatRoom *rawRoom, const QS return; } RoomManager::instance().leaveRoom(room); - room->connection()->addToIgnoredUsers(room->invitingUser()); + room->connection()->addToIgnoredUsers(room->invitingUserId()); notification->close(); }); connect(notification, &KNotification::closed, this, [this, room]() { @@ -286,7 +286,7 @@ void NotificationsManager::postInviteNotification(NeoChatRoom *rawRoom, const QS m_invitations.remove(room->id()); }); - notification->setHint(QStringLiteral("x-kde-origin-name"), room->localUser()->id()); + notification->setHint(QStringLiteral("x-kde-origin-name"), room->localMember().id()); notification->sendEvent(); } diff --git a/src/pollhandler.cpp b/src/pollhandler.cpp index 463cbc5fb..30911e220 100644 --- a/src/pollhandler.cpp +++ b/src/pollhandler.cpp @@ -154,7 +154,7 @@ void PollHandler::sendPollAnswer(const QString &eventId, const QString &answerId return; } QStringList ownAnswers; - for (const auto &answer : m_answers[room->localUser()->id()].toArray()) { + for (const auto &answer : m_answers[room->localMember().id()].toArray()) { ownAnswers += answer.toString(); } if (ownAnswers.contains(answerId)) { @@ -169,7 +169,7 @@ void PollHandler::sendPollAnswer(const QString &eventId, const QString &answerId } auto response = new PollResponseEvent(eventId, ownAnswers); - handleAnswer(response->contentJson(), room->localUser()->id(), QDateTime::currentDateTime()); + handleAnswer(response->contentJson(), room->localMember().id(), QDateTime::currentDateTime()); room->postEvent(response); } diff --git a/src/qml/Main.qml b/src/qml/Main.qml index 5311fd986..ce3857d19 100644 --- a/src/qml/Main.qml +++ b/src/qml/Main.qml @@ -351,10 +351,10 @@ Kirigami.ApplicationWindow { dialog.closeDialog() }) } - function showUserDetail(user) { + function showUserDetail(user, room) { Qt.createComponent("org.kde.neochat", "UserDetailDialog").createObject(root.QQC2.ApplicationWindow.window, { - room: RoomManager.currentRoom ? RoomManager.currentRoom : null, - user: RoomManager.currentRoom ? RoomManager.currentRoom.getUser(user.id) : QmlUtils.getUser(user), + room: room, + user: user, connection: root.connection }).open(); } diff --git a/src/qml/UserDetailDialog.qml b/src/qml/UserDetailDialog.qml index 0f3e89072..08bc89947 100644 --- a/src/qml/UserDetailDialog.qml +++ b/src/qml/UserDetailDialog.qml @@ -48,9 +48,9 @@ Kirigami.Dialog { Layout.preferredWidth: Kirigami.Units.iconSizes.huge Layout.preferredHeight: Kirigami.Units.iconSizes.huge - name: root.user.displayName - source: root.user.avatarSource - color: root.user.color + name: root.room ? root.room.member(root.user.id).displayName : root.user.displayName + source: root.room ? root.room.member(root.user.id).avatarUrl : root.user.avatarUrl + color: root.room ? root.room.member(root.user.id).color : undefined } ColumnLayout { @@ -63,7 +63,7 @@ Kirigami.Dialog { elide: Text.ElideRight wrapMode: Text.NoWrap - text: root.user.displayName + text: root.room ? root.room.member(root.user.id).displayName : root.user.displayName textFormat: Text.PlainText } @@ -84,10 +84,10 @@ Kirigami.Dialog { onClicked: { let map = qrMaximizeComponent.createObject(parent, { text: barcode.content, - title: root.user.displayName, + title: root.room ? root.room.member(root.user.id).displayName : root.user.displayName, subtitle: root.user.id, - avatarColor: root.user.color, - avatarSource: root.user.avatarSource + avatarColor: root.room?.member(root.user.id).color, + avatarSource: root.room? root.room.member(root.user.id).avatarUrl : root.user.avatarUrl }); root.close(); map.open(); @@ -104,19 +104,19 @@ Kirigami.Dialog { } FormCard.FormButtonDelegate { - visible: !root.user.isLocalUser && !!root.user.object + visible: root.user.id !== root.connection.localUserId && !!root.user action: Kirigami.Action { - text: !!root.user.object && root.connection.isIgnored(root.user.object) ? i18n("Unignore this user") : i18n("Ignore this user") + text: !!root.user && root.connection.isIgnored(root.user.id) ? i18n("Unignore this user") : i18n("Ignore this user") icon.name: "im-invisible-user" onTriggered: { root.close(); - root.connection.isIgnored(root.user.object) ? root.connection.removeFromIgnoredUsers(root.user.object) : root.connection.addToIgnoredUsers(root.user.object); + root.connection.isIgnored(root.user.id) ? root.connection.removeFromIgnoredUsers(root.user.id) : root.connection.addToIgnoredUsers(root.user.id); } } } FormCard.FormButtonDelegate { - visible: root.room && !root.user.isLocalUser && room.canSendState("kick") && room.containsUser(root.user.id) && room.getUserPowerLevel(root.user.id) < room.getUserPowerLevel(root.connection.localUser.id) + visible: root.room && root.user.id !== root.connection.localUserId && room.canSendState("kick") && room.containsUser(root.user.id) && room.getUserPowerLevel(root.user.id) < room.getUserPowerLevel(root.connection.localUserId) action: Kirigami.Action { text: i18n("Kick this user") @@ -129,7 +129,7 @@ Kirigami.Dialog { } FormCard.FormButtonDelegate { - visible: root.room && !root.user.isLocalUser && room.canSendState("invite") && !room.containsUser(root.user.id) + visible: root.room && root.user.id !== root.connection.localUserId && room.canSendState("invite") && !room.containsUser(root.user.id) action: Kirigami.Action { enabled: root.room && !root.room.isUserBanned(root.user.id) @@ -143,7 +143,7 @@ Kirigami.Dialog { } FormCard.FormButtonDelegate { - visible: root.room && !root.user.isLocalUser && room.canSendState("ban") && !room.isUserBanned(root.user.id) && room.getUserPowerLevel(root.user.id) < room.getUserPowerLevel(root.room.connection.localUser.id) + visible: root.room && root.user.id !== root.connection.localUserId && room.canSendState("ban") && !room.isUserBanned(root.user.id) && room.getUserPowerLevel(root.user.id) < room.getUserPowerLevel(root.connection.localUserId) action: Kirigami.Action { text: i18n("Ban this user") @@ -163,7 +163,7 @@ Kirigami.Dialog { } FormCard.FormButtonDelegate { - visible: root.room && !root.user.isLocalUser && room.canSendState("ban") && room.isUserBanned(root.user.id) + visible: root.room && root.user.id !== root.connection.localUserId && room.canSendState("ban") && room.isUserBanned(root.user.id) action: Kirigami.Action { text: i18n("Unban this user") @@ -201,7 +201,7 @@ Kirigami.Dialog { } FormCard.FormButtonDelegate { - visible: root.room && (root.user.isLocalUser || room.canSendState("redact")) + visible: root.room && (root.user.id === root.connection.localUserId || room.canSendState("redact")) action: Kirigami.Action { text: i18n("Remove recent messages by this user") @@ -221,12 +221,12 @@ Kirigami.Dialog { } FormCard.FormButtonDelegate { - visible: !root.user.isLocalUser + visible: root.user.id !== root.connection.localUserId action: Kirigami.Action { - text: root.connection.directChatExists(root.user.object) ? i18nc("%1 is the name of the user.", "Chat with %1", root.user.escapedDisplayName) : i18n("Invite to private chat") + text: root.connection.directChatExists(root.user) ? i18nc("%1 is the name of the user.", "Chat with %1", root.room ? root.room.member(root.user.id).htmlSafeDisplayName : QmlUtils.escapeString(root.user.displayName)) : i18n("Invite to private chat") icon.name: "document-send" onTriggered: { - root.connection.openOrCreateDirectChat(root.user.object); + root.connection.openOrCreateDirectChat(root.user.id); root.close(); } } diff --git a/src/registration.cpp b/src/registration.cpp index d4692f48f..206da2d77 100644 --- a/src/registration.cpp +++ b/src/registration.cpp @@ -63,7 +63,7 @@ QString Registration::recaptchaSiteKey() const void Registration::registerAccount() { setStatus(Working); - Omittable authData = none; + Omittable authData; if (nextStep() == "m.login.recaptcha"_ls) { authData = QJsonObject{ {"type"_ls, "m.login.recaptcha"_ls}, @@ -185,7 +185,7 @@ void Registration::testHomeserver() if (m_testServerJob) { delete m_testServerJob; } - m_testServerJob = m_connection->callApi("user"_ls, none, "user"_ls, QString(), QString(), QString(), false); + m_testServerJob = m_connection->callApi("user"_ls, quotientNone, "user"_ls, QString(), QString(), QString(), false); connect(m_testServerJob.data(), &BaseJob::finished, this, [this]() { if (m_testServerJob->error() == BaseJob::StatusCode::ContentAccessError) { setStatus(ServerNoRegistration); diff --git a/src/roommanager.cpp b/src/roommanager.cpp index 5d8a41b1a..e25de5ba5 100644 --- a/src/roommanager.cpp +++ b/src/roommanager.cpp @@ -147,7 +147,10 @@ void RoomManager::resolveResource(const QString &idOrUri, const QString &action) Q_EMIT askJoinRoom(uri.primaryId()); } } else { // Invalid cases should have been eliminated earlier - Q_ASSERT(result == Quotient::UriResolved); + if (result == Quotient::UriResolved) { + // we used to assert here, but we shouldn't assert based on invalid user data + return; + } if (uri.type() == Uri::RoomAlias || uri.type() == Uri::RoomId) { connect( @@ -255,10 +258,10 @@ void RoomManager::openRoomForActiveConnection() UriResolveResult RoomManager::visitUser(User *user, const QString &action) { - if (action == "mention"_ls || action.isEmpty()) { + if (action == "mention"_ls || action == "qr"_ls || action.isEmpty()) { // send it has QVariantMap because the properties in the user->load(); - Q_EMIT showUserDetail(user); + Q_EMIT showUserDetail(user, action == "qr"_ls ? nullptr : currentRoom()); } else if (action == "_interactive"_ls) { user->requestDirectChat(); } else if (action == "chat"_ls) { diff --git a/src/roommanager.h b/src/roommanager.h index 7c4e9264f..e67d31b80 100644 --- a/src/roommanager.h +++ b/src/roommanager.h @@ -260,7 +260,7 @@ Q_SIGNALS: * Ask current room to open the user's details for the give user. * This assumes the user is loaded. */ - void showUserDetail(const Quotient::User *user); + void showUserDetail(const Quotient::User *user, NeoChatRoom *room); /** * @brief Request a media item is shown maximized. diff --git a/src/settings/IgnoredUsersDialog.qml b/src/settings/IgnoredUsersDialog.qml index 8e2e7505f..d1ff18ded 100644 --- a/src/settings/IgnoredUsersDialog.qml +++ b/src/settings/IgnoredUsersDialog.qml @@ -50,7 +50,7 @@ FormCard.FormCardPage { QQC2.ToolButton { text: i18nc("@action:button", "Unignore this user") icon.name: "list-remove-symbolic" - onClicked: root.connection.removeFromIgnoredUsers(root.connection.user(modelData)) + onClicked: root.connection.removeFromIgnoredUsers(modelData) display: QQC2.Button.IconOnly QQC2.ToolTip.text: text QQC2.ToolTip.visible: hovered diff --git a/src/spacehierarchycache.cpp b/src/spacehierarchycache.cpp index d8089a962..d9719857c 100644 --- a/src/spacehierarchycache.cpp +++ b/src/spacehierarchycache.cpp @@ -13,6 +13,8 @@ #include "neochatroom.h" #include "roomlistmodel.h" +#include "definitions.h" + using namespace Quotient; SpaceHierarchyCache::SpaceHierarchyCache(QObject *parent) @@ -62,7 +64,7 @@ void SpaceHierarchyCache::populateSpaceHierarchy(const QString &spaceId) } m_nextBatchTokens[spaceId] = QString(); - auto job = m_connection->callApi(spaceId, none, none, none, *m_nextBatchTokens[spaceId]); + auto job = m_connection->callApi(spaceId, quotientNone, quotientNone, quotientNone, *m_nextBatchTokens[spaceId]); auto group = KConfigGroup(KSharedConfig::openStateConfig("SpaceHierarchy"_ls), "Cache"_ls); m_spaceHierarchy.insert(spaceId, group.readEntry(spaceId, QStringList())); @@ -91,7 +93,7 @@ void SpaceHierarchyCache::addBatch(const QString &spaceId, Quotient::GetSpaceHie const auto nextBatchToken = job->nextBatch(); if (!nextBatchToken.isEmpty() && nextBatchToken != *m_nextBatchTokens[spaceId]) { *m_nextBatchTokens[spaceId] = nextBatchToken; - auto nextJob = m_connection->callApi(spaceId, none, none, none, *m_nextBatchTokens[spaceId]); + auto nextJob = m_connection->callApi(spaceId, quotientNone, quotientNone, quotientNone, *m_nextBatchTokens[spaceId]); connect(nextJob, &BaseJob::success, this, [this, nextJob, spaceId]() { addBatch(spaceId, nextJob); }); diff --git a/src/texthandler.cpp b/src/texthandler.cpp index f2c706e46..967a36854 100644 --- a/src/texthandler.cpp +++ b/src/texthandler.cpp @@ -691,9 +691,9 @@ QString TextHandler::emoteString(const NeoChatRoom *room, const Quotient::RoomEv } auto e = eventCast(event); - auto author = room->user(e->senderId()); - return QStringLiteral("* senderId() + QStringLiteral("\" style=\"color:") + Utils::getUserColor(author->hueF()).name() - + QStringLiteral("\">") + author->displayname(room) + QStringLiteral(" "); + auto author = room->member(e->senderId()); + return QStringLiteral("* senderId() + QStringLiteral("\" style=\"color:") + Utils::getUserColor(author.hueF()).name() + + QStringLiteral("\">") + author.displayName() + QStringLiteral(" "); } QString TextHandler::convertCodeLanguageString(const QString &languageString) diff --git a/src/utils.cpp b/src/utils.cpp index b07922230..d10915f6a 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -9,46 +9,14 @@ using namespace Quotient; -static const QVariantMap emptyUser = { - {"isLocalUser"_ls, false}, - {"id"_ls, QString()}, - {"displayName"_ls, QString()}, - {"avatarSource"_ls, QUrl()}, - {"avatarMediaId"_ls, QString()}, - {"color"_ls, QColor()}, - {"object"_ls, QVariant()}, -}; - -QVariantMap QmlUtils::getUser(User *user) const -{ - if (user == nullptr) { - return emptyUser; - } - - const auto &url = user->avatarUrl(); - if (url.isEmpty() || url.scheme() != "mxc"_ls) { - return {}; - } - auto avatarSource = user->connection()->makeMediaUrl(url); - if (!avatarSource.isValid() || avatarSource.scheme() != QStringLiteral("mxc")) { - avatarSource = {}; - } - - return QVariantMap{ - {QStringLiteral("isLocalUser"), user->id() == user->connection()->user()->id()}, - {QStringLiteral("id"), user->id()}, - {QStringLiteral("displayName"), user->displayname()}, - {QStringLiteral("escapedDisplayName"), user->displayname().toHtmlEscaped()}, - {QStringLiteral("avatarSource"), avatarSource}, - {QStringLiteral("avatarMediaId"), user->avatarMediaId()}, - {QStringLiteral("color"), Utils::getUserColor(user->hueF())}, - {QStringLiteral("object"), QVariant::fromValue(user)}, - }; -} - bool QmlUtils::isValidJson(const QByteArray &json) { return !QJsonDocument::fromJson(json).isNull(); } +QString QmlUtils::escapeString(const QString &string) +{ + return string.toHtmlEscaped(); +} + #include "moc_utils.cpp" diff --git a/src/utils.h b/src/utils.h index 1fc0e3e78..646665772 100644 --- a/src/utils.h +++ b/src/utils.h @@ -30,8 +30,8 @@ public: return _instance; } - Q_INVOKABLE QVariantMap getUser(Quotient::User *user) const; Q_INVOKABLE bool isValidJson(const QByteArray &json); + Q_INVOKABLE QString escapeString(const QString &string); private: QmlUtils() = default;