diff --git a/src/models/messagemodel.cpp b/src/models/messagemodel.cpp index 5295f83e0..566e310d0 100644 --- a/src/models/messagemodel.cpp +++ b/src/models/messagemodel.cpp @@ -120,11 +120,7 @@ QVariant MessageModel::data(const QModelIndex &idx, int role) const } if (role == ContentModelRole) { - auto evtOrTxnId = event->get().id(); - if (evtOrTxnId.isEmpty()) { - evtOrTxnId = event->get().transactionId(); - } - return QVariant::fromValue(m_room->contentModelForEvent(evtOrTxnId)); + return QVariant::fromValue(m_room->contentModelForEvent(&event->get())); } if (role == GenericDisplayRole) { diff --git a/src/neochatroom.cpp b/src/neochatroom.cpp index 56bdcdbe2..733b0d547 100644 --- a/src/neochatroom.cpp +++ b/src/neochatroom.cpp @@ -1740,28 +1740,42 @@ NeochatRoomMember *NeoChatRoom::qmlSafeMember(const QString &memberId) return m_memberObjects[memberId].get(); } -MessageContentModel *NeoChatRoom::contentModelForEvent(const QString &evtOrTxnId) +MessageContentModel *NeoChatRoom::contentModelForEvent(const QString &eventId) { - const auto event = getEvent(evtOrTxnId); - if (event.first == nullptr) { + if (eventId.isEmpty()) { + return nullptr; + } + + if (!m_eventContentModels.contains(eventId)) { + return m_eventContentModels.emplace(eventId, std::make_unique(this, eventId)).first->second.get(); + } + + return m_eventContentModels[eventId].get(); +} + +MessageContentModel *NeoChatRoom::contentModelForEvent(const Quotient::RoomEvent *event) +{ + const auto roomMessageEvent = eventCast(event); + if (roomMessageEvent == nullptr) { // If for some reason a model is there remove. - if (m_eventContentModels.contains(evtOrTxnId)) { - m_eventContentModels.erase(evtOrTxnId); + if (m_eventContentModels.contains(event->id())) { + m_eventContentModels.erase(event->id()); + } + if (m_eventContentModels.contains(event->transactionId())) { + m_eventContentModels.erase(event->transactionId()); } return nullptr; } - if (event.first->isStateEvent() || event.first->matrixType() == u"org.matrix.msc3672.beacon_info"_s) { + if (event->isStateEvent() || event->matrixType() == u"org.matrix.msc3672.beacon_info"_s) { return nullptr; } - auto eventId = event.first->id(); - const auto txnId = event.first->transactionId(); + auto eventId = event->id(); + const auto txnId = event->transactionId(); if (!m_eventContentModels.contains(eventId) && !m_eventContentModels.contains(txnId)) { - if (eventId.isEmpty()) { - eventId = txnId; - } - return m_eventContentModels.emplace(eventId, std::make_unique(this, eventId, false, event.second)).first->second.get(); + return m_eventContentModels.emplace(eventId, std::make_unique(this, eventId.isEmpty() ? txnId : eventId, false, eventId.isEmpty())) + .first->second.get(); } if (!eventId.isEmpty() && m_eventContentModels.contains(eventId)) { diff --git a/src/neochatroom.h b/src/neochatroom.h index 69d262cb1..97367f488 100644 --- a/src/neochatroom.h +++ b/src/neochatroom.h @@ -3,6 +3,7 @@ #pragma once +#include #include #include @@ -589,8 +590,35 @@ public: NeochatRoomMember *qmlSafeMember(const QString &memberId); + /** + * @brief Returns the content model for the given event ID. + * + * A model is created is one doesn't exist. Will return nullptr if evtOrTxnId + * is empty. + * + * @warning If a non-empty ID is given it is assumed to be a valid Quotient::RoomMessageEvent + * event ID. The caller must ensure that the ID is a real event. A model will be + * returned unconditionally. + * + * @warning Do NOT use for pending events as this function has no way to differentiate. + */ MessageContentModel *contentModelForEvent(const QString &evtOrTxnId); + /** + * @brief Returns the content model for the given event. + * + * A model is created is one doesn't exist. Will return nullptr if event is: + * - nullptr + * - not a Quotient::RoomMessageEvent (e.g a state event) + * + * @note This method is preferred to the version using just an event ID as it + * can perform some basic checks. If a copy of the event is not available, + * you may have to use the version that takes an event ID. + * + * @note This version must be used for pending events as it can differentiate. + */ + MessageContentModel *contentModelForEvent(const Quotient::RoomEvent *event); + /** * @brief Returns the thread model for the given thread root event ID. *