Make sure that the content model is loaded properly when a new event is set. This fixes seeing an unknown event message for all new events. Instead a loading symbol is briefly seen before switching to the actual content.

This commit is contained in:
James Graham
2024-10-20 14:58:44 +01:00
parent 4b08022075
commit 9874962ee3
6 changed files with 97 additions and 66 deletions

View File

@@ -34,7 +34,7 @@ MessageContentModel::MessageContentModel(NeoChatRoom *room, const QString &event
: QAbstractListModel(parent) : QAbstractListModel(parent)
, m_room(room) , m_room(room)
, m_eventId(eventId) , m_eventId(eventId)
, m_isPending(isPending) , m_currentState(isPending ? Pending : Unknown)
, m_isReply(isReply) , m_isReply(isReply)
{ {
initializeModel(); initializeModel();
@@ -45,19 +45,27 @@ void MessageContentModel::initializeModel()
Q_ASSERT(m_room != nullptr); Q_ASSERT(m_room != nullptr);
Q_ASSERT(!m_eventId.isEmpty()); Q_ASSERT(!m_eventId.isEmpty());
connect(this, &MessageContentModel::eventUnavailable, this, &MessageContentModel::getEvent); connect(m_room, &NeoChatRoom::pendingEventAdded, this, [this]() {
if (m_room != nullptr && m_currentState == Unknown) {
initializeEvent();
updateReplyModel();
resetModel();
}
});
connect(m_room, &NeoChatRoom::pendingEventAboutToMerge, this, [this](Quotient::RoomEvent *serverEvent) { connect(m_room, &NeoChatRoom::pendingEventAboutToMerge, this, [this](Quotient::RoomEvent *serverEvent) {
if (m_room != nullptr) { if (m_room != nullptr) {
if (m_eventId == serverEvent->id() || m_eventId == serverEvent->transactionId()) { if (m_eventId == serverEvent->id() || m_eventId == serverEvent->transactionId()) {
beginResetModel();
m_isPending = false;
m_eventId = serverEvent->id(); m_eventId = serverEvent->id();
initializeEvent();
endResetModel();
} }
} }
}); });
connect(m_room, &NeoChatRoom::pendingEventMerged, this, [this]() {
if (m_room != nullptr && m_currentState == Pending) {
initializeEvent();
updateReplyModel();
resetModel();
}
});
connect(m_room, &NeoChatRoom::addedMessages, this, [this](int fromIndex, int toIndex) { connect(m_room, &NeoChatRoom::addedMessages, this, [this](int fromIndex, int toIndex) {
if (m_room != nullptr) { if (m_room != nullptr) {
for (int i = fromIndex; i <= toIndex; i++) { for (int i = fromIndex; i <= toIndex; i++) {
@@ -143,20 +151,33 @@ void MessageContentModel::initializeModel()
}); });
initializeEvent(); initializeEvent();
updateReplyModel(); if (m_currentState == Available || m_currentState == Pending) {
resetModel(); updateReplyModel();
resetModel();
}
} }
void MessageContentModel::initializeEvent() void MessageContentModel::initializeEvent()
{ {
const auto event = m_room->getEvent(m_eventId); if (m_currentState == UnAvailable) {
if (event == nullptr) {
Q_EMIT eventUnavailable();
return; return;
} }
const auto eventResult = m_room->getEvent(m_eventId);
if (eventResult.first == nullptr) {
if (m_currentState != Pending) {
getEvent();
}
return;
}
if (eventResult.second) {
m_currentState = Pending;
} else {
m_currentState = Available;
}
if (m_eventSenderObject == nullptr) { if (m_eventSenderObject == nullptr) {
auto senderId = event->senderId(); auto senderId = eventResult.first->senderId();
// A pending event might not have a sender ID set yet but in that case it must // A pending event might not have a sender ID set yet but in that case it must
// be the local member. // be the local member.
if (senderId.isEmpty()) { if (senderId.isEmpty()) {
@@ -172,7 +193,6 @@ void MessageContentModel::getEvent()
Quotient::connectUntil(m_room.get(), &NeoChatRoom::extraEventLoaded, this, [this](const QString &eventId) { Quotient::connectUntil(m_room.get(), &NeoChatRoom::extraEventLoaded, this, [this](const QString &eventId) {
if (m_room != nullptr) { if (m_room != nullptr) {
if (eventId == m_eventId) { if (eventId == m_eventId) {
m_notFound = false;
initializeEvent(); initializeEvent();
updateReplyModel(); updateReplyModel();
resetModel(); resetModel();
@@ -184,7 +204,7 @@ void MessageContentModel::getEvent()
Quotient::connectUntil(m_room.get(), &NeoChatRoom::extraEventNotFound, this, [this](const QString &eventId) { Quotient::connectUntil(m_room.get(), &NeoChatRoom::extraEventNotFound, this, [this](const QString &eventId) {
if (m_room != nullptr) { if (m_room != nullptr) {
if (eventId == m_eventId) { if (eventId == m_eventId) {
m_notFound = true; m_currentState = UnAvailable;
resetModel(); resetModel();
return true; return true;
} }
@@ -237,7 +257,7 @@ QVariant MessageContentModel::data(const QModelIndex &index, int role) const
const auto component = m_components[index.row()]; const auto component = m_components[index.row()];
const auto event = m_room->getEvent(m_eventId); const auto event = m_room->getEvent(m_eventId);
if (event == nullptr) { if (event.first == nullptr) {
if (role == DisplayRole) { if (role == DisplayRole) {
if (m_isReply) { if (m_isReply) {
return i18n("Loading reply"); return i18n("Loading reply");
@@ -252,7 +272,7 @@ QVariant MessageContentModel::data(const QModelIndex &index, int role) const
} }
if (role == DisplayRole) { if (role == DisplayRole) {
if (m_notFound || m_room->connection()->isIgnored(m_eventSenderId)) { if (m_currentState == UnAvailable || m_room->connection()->isIgnored(m_eventSenderId)) {
Kirigami::Platform::PlatformTheme *theme = Kirigami::Platform::PlatformTheme *theme =
static_cast<Kirigami::Platform::PlatformTheme *>(qmlAttachedPropertiesObject<Kirigami::Platform::PlatformTheme>(this, true)); static_cast<Kirigami::Platform::PlatformTheme *>(qmlAttachedPropertiesObject<Kirigami::Platform::PlatformTheme>(this, true));
@@ -276,7 +296,7 @@ QVariant MessageContentModel::data(const QModelIndex &index, int role) const
if (!component.content.isEmpty()) { if (!component.content.isEmpty()) {
return component.content; return component.content;
} }
return EventHandler::richBody(m_room, event); return EventHandler::richBody(m_room, event.first);
} }
if (role == ComponentTypeRole) { if (role == ComponentTypeRole) {
return component.type; return component.type;
@@ -285,53 +305,53 @@ QVariant MessageContentModel::data(const QModelIndex &index, int role) const
return component.attributes; return component.attributes;
} }
if (role == EventIdRole) { if (role == EventIdRole) {
return EventHandler::id(event); return EventHandler::id(event.first);
} }
if (role == TimeRole) { if (role == TimeRole) {
const auto pendingIt = std::find_if(m_room->pendingEvents().cbegin(), m_room->pendingEvents().cend(), [event](const PendingEventItem &pendingEvent) { const auto pendingIt = std::find_if(m_room->pendingEvents().cbegin(), m_room->pendingEvents().cend(), [event](const PendingEventItem &pendingEvent) {
return event->transactionId() == pendingEvent->transactionId(); return event.first->transactionId() == pendingEvent->transactionId();
}); });
auto lastUpdated = pendingIt == m_room->pendingEvents().cend() ? QDateTime() : pendingIt->lastUpdated(); auto lastUpdated = pendingIt == m_room->pendingEvents().cend() ? QDateTime() : pendingIt->lastUpdated();
return EventHandler::time(event, m_isPending, lastUpdated); return EventHandler::time(event.first, m_currentState == Pending, lastUpdated);
} }
if (role == TimeStringRole) { if (role == TimeStringRole) {
const auto pendingIt = std::find_if(m_room->pendingEvents().cbegin(), m_room->pendingEvents().cend(), [event](const PendingEventItem &pendingEvent) { const auto pendingIt = std::find_if(m_room->pendingEvents().cbegin(), m_room->pendingEvents().cend(), [event](const PendingEventItem &pendingEvent) {
return event->transactionId() == pendingEvent->transactionId(); return event.first->transactionId() == pendingEvent->transactionId();
}); });
auto lastUpdated = pendingIt == m_room->pendingEvents().cend() ? QDateTime() : pendingIt->lastUpdated(); auto lastUpdated = pendingIt == m_room->pendingEvents().cend() ? QDateTime() : pendingIt->lastUpdated();
return EventHandler::timeString(event, QStringLiteral("hh:mm"), m_isPending, lastUpdated); return EventHandler::timeString(event.first, QStringLiteral("hh:mm"), m_currentState == Pending, lastUpdated);
} }
if (role == AuthorRole) { if (role == AuthorRole) {
return QVariant::fromValue<NeochatRoomMember *>(m_eventSenderObject.get()); return QVariant::fromValue<NeochatRoomMember *>(m_eventSenderObject.get());
} }
if (role == MediaInfoRole) { if (role == MediaInfoRole) {
return EventHandler::mediaInfo(m_room, event); return EventHandler::mediaInfo(m_room, event.first);
} }
if (role == FileTransferInfoRole) { if (role == FileTransferInfoRole) {
return QVariant::fromValue(m_room->cachedFileTransferInfo(event)); return QVariant::fromValue(m_room->cachedFileTransferInfo(event.first));
} }
if (role == ItineraryModelRole) { if (role == ItineraryModelRole) {
return QVariant::fromValue<ItineraryModel *>(m_itineraryModel); return QVariant::fromValue<ItineraryModel *>(m_itineraryModel);
} }
if (role == LatitudeRole) { if (role == LatitudeRole) {
return EventHandler::latitude(event); return EventHandler::latitude(event.first);
} }
if (role == LongitudeRole) { if (role == LongitudeRole) {
return EventHandler::longitude(event); return EventHandler::longitude(event.first);
} }
if (role == AssetRole) { if (role == AssetRole) {
return EventHandler::locationAssetType(event); return EventHandler::locationAssetType(event.first);
} }
if (role == PollHandlerRole) { if (role == PollHandlerRole) {
return QVariant::fromValue<PollHandler *>(m_room->poll(m_eventId)); return QVariant::fromValue<PollHandler *>(m_room->poll(m_eventId));
} }
if (role == ReplyEventIdRole) { if (role == ReplyEventIdRole) {
return EventHandler::replyId(event); return EventHandler::replyId(event.first);
} }
if (role == ReplyAuthorRole) { if (role == ReplyAuthorRole) {
return QVariant::fromValue(EventHandler::replyAuthor(m_room, event)); return QVariant::fromValue(EventHandler::replyAuthor(m_room, event.first));
} }
if (role == ReplyContentModelRole) { if (role == ReplyContentModelRole) {
return QVariant::fromValue<MessageContentModel *>(m_replyModel); return QVariant::fromValue<MessageContentModel *>(m_replyModel);
@@ -387,18 +407,17 @@ QHash<int, QByteArray> MessageContentModel::roleNames() const
void MessageContentModel::resetModel() void MessageContentModel::resetModel()
{ {
const auto event = m_room->getEvent(m_eventId);
beginResetModel(); beginResetModel();
m_components.clear(); m_components.clear();
if (m_room->connection()->isIgnored(m_eventSenderId) || m_notFound) { if (m_room->connection()->isIgnored(m_eventSenderId) || m_currentState == UnAvailable) {
m_components += MessageComponent{MessageComponentType::Text, QString(), {}}; m_components += MessageComponent{MessageComponentType::Text, QString(), {}};
endResetModel(); endResetModel();
return; return;
} }
if (event == nullptr) { const auto event = m_room->getEvent(m_eventId);
if (event.first == nullptr) {
m_components += MessageComponent{MessageComponentType::Loading, QString(), {}}; m_components += MessageComponent{MessageComponentType::Loading, QString(), {}};
endResetModel(); endResetModel();
return; return;
@@ -431,19 +450,19 @@ void MessageContentModel::resetContent(bool isEditing, bool isThreading)
QList<MessageComponent> MessageContentModel::messageContentComponents(bool isEditing, bool isThreading) QList<MessageComponent> MessageContentModel::messageContentComponents(bool isEditing, bool isThreading)
{ {
const auto event = m_room->getEvent(m_eventId); const auto event = m_room->getEvent(m_eventId);
if (event == nullptr) { if (event.first == nullptr) {
return {}; return {};
} }
QList<MessageComponent> newComponents; QList<MessageComponent> newComponents;
if (eventCast<const Quotient::RoomMessageEvent>(event) if (eventCast<const Quotient::RoomMessageEvent>(event.first)
&& eventCast<const Quotient::RoomMessageEvent>(event)->rawMsgtype() == QStringLiteral("m.key.verification.request")) { && eventCast<const Quotient::RoomMessageEvent>(event.first)->rawMsgtype() == QStringLiteral("m.key.verification.request")) {
newComponents += MessageComponent{MessageComponentType::Verification, QString(), {}}; newComponents += MessageComponent{MessageComponentType::Verification, QString(), {}};
return newComponents; return newComponents;
} }
if (event->isRedacted()) { if (event.first->isRedacted()) {
newComponents += MessageComponent{MessageComponentType::Text, QString(), {}}; newComponents += MessageComponent{MessageComponentType::Text, QString(), {}};
return newComponents; return newComponents;
} }
@@ -455,7 +474,7 @@ QList<MessageComponent> MessageContentModel::messageContentComponents(bool isEdi
if (isEditing) { if (isEditing) {
newComponents += MessageComponent{MessageComponentType::ChatBar, QString(), {}}; newComponents += MessageComponent{MessageComponentType::ChatBar, QString(), {}};
} else { } else {
newComponents.append(componentsForType(MessageComponentType::typeForEvent(*event))); newComponents.append(componentsForType(MessageComponentType::typeForEvent(*event.first)));
} }
if (m_room->urlPreviewEnabled()) { if (m_room->urlPreviewEnabled()) {
@@ -463,7 +482,7 @@ QList<MessageComponent> MessageContentModel::messageContentComponents(bool isEdi
} }
// If the event is already threaded the ThreadModel will handle displaying a chat bar. // If the event is already threaded the ThreadModel will handle displaying a chat bar.
if (isThreading && !EventHandler::isThreaded(event)) { if (isThreading && !EventHandler::isThreaded(event.first)) {
newComponents += MessageComponent{MessageComponentType::ChatBar, QString(), {}}; newComponents += MessageComponent{MessageComponentType::ChatBar, QString(), {}};
} }
@@ -473,11 +492,11 @@ QList<MessageComponent> MessageContentModel::messageContentComponents(bool isEdi
void MessageContentModel::updateReplyModel() void MessageContentModel::updateReplyModel()
{ {
const auto event = m_room->getEvent(m_eventId); const auto event = m_room->getEvent(m_eventId);
if (event == nullptr || m_isReply) { if (event.first == nullptr || m_isReply) {
return; return;
} }
if (!EventHandler::hasReply(event) || (EventHandler::isThreaded(event) && NeoChatConfig::self()->threads())) { if (!EventHandler::hasReply(event.first) || (EventHandler::isThreaded(event.first) && NeoChatConfig::self()->threads())) {
if (m_replyModel) { if (m_replyModel) {
delete m_replyModel; delete m_replyModel;
} }
@@ -488,7 +507,7 @@ void MessageContentModel::updateReplyModel()
return; return;
} }
m_replyModel = new MessageContentModel(m_room, EventHandler::replyId(event), true, false, this); m_replyModel = new MessageContentModel(m_room, EventHandler::replyId(event.first), true, false, this);
connect(m_replyModel, &MessageContentModel::eventUpdated, this, [this]() { connect(m_replyModel, &MessageContentModel::eventUpdated, this, [this]() {
Q_EMIT dataChanged(index(0), index(0), {ReplyAuthorRole}); Q_EMIT dataChanged(index(0), index(0), {ReplyAuthorRole});
@@ -498,13 +517,13 @@ void MessageContentModel::updateReplyModel()
QList<MessageComponent> MessageContentModel::componentsForType(MessageComponentType::Type type) QList<MessageComponent> MessageContentModel::componentsForType(MessageComponentType::Type type)
{ {
const auto event = m_room->getEvent(m_eventId); const auto event = m_room->getEvent(m_eventId);
if (event == nullptr) { if (event.first == nullptr) {
return {}; return {};
} }
switch (type) { switch (type) {
case MessageComponentType::Text: { case MessageComponentType::Text: {
const auto roomMessageEvent = eventCast<const Quotient::RoomMessageEvent>(event); const auto roomMessageEvent = eventCast<const Quotient::RoomMessageEvent>(event.first);
auto body = EventHandler::rawMessageBody(*roomMessageEvent); auto body = EventHandler::rawMessageBody(*roomMessageEvent);
return TextHandler().textComponents(body, return TextHandler().textComponents(body,
EventHandler::messageBodyInputFormat(*roomMessageEvent), EventHandler::messageBodyInputFormat(*roomMessageEvent),
@@ -515,11 +534,11 @@ QList<MessageComponent> MessageContentModel::componentsForType(MessageComponentT
case MessageComponentType::File: { case MessageComponentType::File: {
QList<MessageComponent> components; QList<MessageComponent> components;
components += MessageComponent{MessageComponentType::File, QString(), {}}; components += MessageComponent{MessageComponentType::File, QString(), {}};
const auto roomMessageEvent = eventCast<const Quotient::RoomMessageEvent>(event); const auto roomMessageEvent = eventCast<const Quotient::RoomMessageEvent>(event.first);
if (m_emptyItinerary) { if (m_emptyItinerary) {
if (!m_isReply) { if (!m_isReply) {
auto fileTransferInfo = m_room->cachedFileTransferInfo(event); auto fileTransferInfo = m_room->cachedFileTransferInfo(event.first);
#ifndef Q_OS_ANDROID #ifndef Q_OS_ANDROID
Q_ASSERT(roomMessageEvent->content() != nullptr && roomMessageEvent->has<EventContent::FileContent>()); Q_ASSERT(roomMessageEvent->content() != nullptr && roomMessageEvent->has<EventContent::FileContent>());
@@ -567,8 +586,8 @@ QList<MessageComponent> MessageContentModel::componentsForType(MessageComponentT
case MessageComponentType::Image: case MessageComponentType::Image:
case MessageComponentType::Audio: case MessageComponentType::Audio:
case MessageComponentType::Video: { case MessageComponentType::Video: {
if (!event->is<StickerEvent>()) { if (!event.first->is<StickerEvent>()) {
const auto roomMessageEvent = eventCast<const Quotient::RoomMessageEvent>(event); const auto roomMessageEvent = eventCast<const Quotient::RoomMessageEvent>(event.first);
QList<MessageComponent> components; QList<MessageComponent> components;
components += MessageComponent{type, QString(), {}}; components += MessageComponent{type, QString(), {}};
auto body = EventHandler::rawMessageBody(*roomMessageEvent); auto body = EventHandler::rawMessageBody(*roomMessageEvent);
@@ -653,13 +672,13 @@ void MessageContentModel::closeLinkPreview(int row)
void MessageContentModel::updateItineraryModel() void MessageContentModel::updateItineraryModel()
{ {
const auto event = m_room->getEvent(m_eventId); const auto event = m_room->getEvent(m_eventId);
if (m_room == nullptr || event == nullptr) { if (m_room == nullptr || event.first == nullptr) {
return; return;
} }
if (auto roomMessageEvent = eventCast<const Quotient::RoomMessageEvent>(event)) { if (auto roomMessageEvent = eventCast<const Quotient::RoomMessageEvent>(event.first)) {
if (roomMessageEvent->has<EventContent::FileContent>()) { if (roomMessageEvent->has<EventContent::FileContent>()) {
auto filePath = m_room->cachedFileTransferInfo(event).localPath; auto filePath = m_room->cachedFileTransferInfo(event.first).localPath;
if (filePath.isEmpty() && m_itineraryModel != nullptr) { if (filePath.isEmpty() && m_itineraryModel != nullptr) {
delete m_itineraryModel; delete m_itineraryModel;
m_itineraryModel = nullptr; m_itineraryModel = nullptr;

View File

@@ -31,6 +31,14 @@ class MessageContentModel : public QAbstractListModel
Q_PROPERTY(bool showAuthor READ showAuthor WRITE setShowAuthor NOTIFY showAuthorChanged) Q_PROPERTY(bool showAuthor READ showAuthor WRITE setShowAuthor NOTIFY showAuthorChanged)
public: public:
enum MessageState {
Unknown, /**< The message state is unknown. */
Pending, /**< The message is a new pending message which the server has not yet acknowledged. */
Available, /**< The message is available and acknowledged by the server. */
UnAvailable, /**< The message can't be retrieved either because it doesn't exist or is blocked. */
};
Q_ENUM(MessageState)
/** /**
* @brief Defines the model roles. * @brief Defines the model roles.
*/ */
@@ -98,7 +106,6 @@ public:
Q_SIGNALS: Q_SIGNALS:
void showAuthorChanged(); void showAuthorChanged();
void eventUnavailable();
void eventUpdated(); void eventUpdated();
private: private:
@@ -107,10 +114,9 @@ private:
QString m_eventSenderId; QString m_eventSenderId;
std::unique_ptr<NeochatRoomMember> m_eventSenderObject = nullptr; std::unique_ptr<NeochatRoomMember> m_eventSenderObject = nullptr;
bool m_isPending; MessageState m_currentState = Unknown;
bool m_showAuthor = true; bool m_showAuthor = true;
bool m_isReply; bool m_isReply;
bool m_notFound = false;
void initializeModel(); void initializeModel();
void initializeEvent(); void initializeEvent();

View File

@@ -162,7 +162,7 @@ void MessageEventModel::setRoom(NeoChatRoom *room)
}); });
connect(m_currentRoom, &Room::pendingEventAboutToAdd, this, [this](Quotient::RoomEvent *event) { connect(m_currentRoom, &Room::pendingEventAboutToAdd, this, [this](Quotient::RoomEvent *event) {
m_initialized = true; m_initialized = true;
createEventObjects(event); createEventObjects(event, true);
beginInsertRows({}, 0, 0); beginInsertRows({}, 0, 0);
}); });
connect(m_currentRoom, &Room::pendingEventAdded, this, &MessageEventModel::endInsertRows); connect(m_currentRoom, &Room::pendingEventAdded, this, &MessageEventModel::endInsertRows);
@@ -618,7 +618,7 @@ int MessageEventModel::eventIdToRow(const QString &eventID) const
return it - m_currentRoom->messageEvents().rbegin() + timelineBaseIndex(); return it - m_currentRoom->messageEvents().rbegin() + timelineBaseIndex();
} }
void MessageEventModel::createEventObjects(const Quotient::RoomEvent *event) void MessageEventModel::createEventObjects(const Quotient::RoomEvent *event, bool isPending)
{ {
if (event == nullptr) { if (event == nullptr) {
return; return;
@@ -641,7 +641,7 @@ void MessageEventModel::createEventObjects(const Quotient::RoomEvent *event)
if (!m_contentModels.contains(eventId) && !m_contentModels.contains(event->transactionId())) { if (!m_contentModels.contains(eventId) && !m_contentModels.contains(event->transactionId())) {
if (!event->isStateEvent() || event->matrixType() == QStringLiteral("org.matrix.msc3672.beacon_info")) { if (!event->isStateEvent() || event->matrixType() == QStringLiteral("org.matrix.msc3672.beacon_info")) {
m_contentModels[eventId] = std::unique_ptr<MessageContentModel>(new MessageContentModel(m_currentRoom, eventId)); m_contentModels[eventId] = std::unique_ptr<MessageContentModel>(new MessageContentModel(m_currentRoom, eventId, false, isPending));
} }
} }

View File

@@ -136,7 +136,7 @@ private:
int refreshEventRoles(const QString &eventId, const QList<int> &roles = {}); int refreshEventRoles(const QString &eventId, const QList<int> &roles = {});
void moveReadMarker(const QString &toEventId); void moveReadMarker(const QString &toEventId);
void createEventObjects(const Quotient::RoomEvent *event); void createEventObjects(const Quotient::RoomEvent *event, bool isPending = false);
// Hack to ensure that we don't call endInsertRows when we haven't called beginInsertRows // Hack to ensure that we don't call endInsertRows when we haven't called beginInsertRows
bool m_initialized = false; bool m_initialized = false;

View File

@@ -1749,25 +1749,31 @@ void NeoChatRoom::downloadEventFromServer(const QString &eventId)
}); });
} }
const RoomEvent *NeoChatRoom::getEvent(const QString &eventId) const std::pair<const Quotient::RoomEvent *, bool> NeoChatRoom::getEvent(const QString &eventId) const
{ {
if (eventId.isEmpty()) { if (eventId.isEmpty()) {
return nullptr; return {};
} }
const auto timelineIt = findInTimeline(eventId); const auto timelineIt = findInTimeline(eventId);
if (timelineIt != historyEdge()) { if (timelineIt != historyEdge()) {
return timelineIt->get(); return std::make_pair(timelineIt->get(), false);
} }
const auto pendingIt = findPendingEvent(eventId); auto pendingIt = findPendingEvent(eventId);
if (pendingIt != pendingEvents().end()) { if (pendingIt != pendingEvents().end()) {
return pendingIt->event(); return std::make_pair(pendingIt->event(), true);
}
// findPendingEvent() searches by transaction ID, we also need to check event ID.
for (const auto &event : pendingEvents()) {
if (event->id() == eventId || event->transactionId() == eventId) {
return std::make_pair(event.event(), true);
}
} }
auto extraIt = std::find_if(m_extraEvents.begin(), m_extraEvents.end(), [eventId](const Quotient::event_ptr_tt<Quotient::RoomEvent> &event) { auto extraIt = std::find_if(m_extraEvents.begin(), m_extraEvents.end(), [eventId](const Quotient::event_ptr_tt<Quotient::RoomEvent> &event) {
return event->id() == eventId; return event->id() == eventId;
}); });
return extraIt != m_extraEvents.end() ? extraIt->get() : nullptr; return std::make_pair(extraIt != m_extraEvents.end() ? extraIt->get() : nullptr, false);
} }
const RoomEvent *NeoChatRoom::getReplyForEvent(const RoomEvent &event) const const RoomEvent *NeoChatRoom::getReplyForEvent(const RoomEvent &event) const

View File

@@ -570,7 +570,7 @@ public:
* *
* The result will be nullptr if not found so needs to be managed. * The result will be nullptr if not found so needs to be managed.
*/ */
const Quotient::RoomEvent *getEvent(const QString &eventId) const; std::pair<const Quotient::RoomEvent *, bool> getEvent(const QString &eventId) const;
/** /**
* @brief Returns the event that is being replied to. This includes events that were manually loaded using NeoChatRoom::loadReply. * @brief Returns the event that is being replied to. This includes events that were manually loaded using NeoChatRoom::loadReply.