From 8751f6fea7ea1dc7dc3fbd1d92b516434b37c2d1 Mon Sep 17 00:00:00 2001 From: James Graham Date: Sun, 7 Jul 2024 14:02:43 +0100 Subject: [PATCH] Never refresh the author role except when a member updated signal is generated. This should remove a potential source of crashes where a RoomMember object tries to access an already deleted room member state event --- src/models/messageeventmodel.cpp | 22 +++++++++++----------- src/models/messageeventmodel.h | 5 +---- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/models/messageeventmodel.cpp b/src/models/messageeventmodel.cpp index 5ec27111c..c13462e3e 100644 --- a/src/models/messageeventmodel.cpp +++ b/src/models/messageeventmodel.cpp @@ -179,13 +179,13 @@ void MessageEventModel::setRoom(NeoChatRoom *room) endMoveRows(); movingEvent = false; } - refreshRow(timelineBaseIndex()); // Refresh the looks + fullEventRefresh(timelineBaseIndex()); refreshLastUserEvents(0); if (timelineBaseIndex() > 0) { // Refresh below, see #312 refreshEventRoles(timelineBaseIndex() - 1, {ContentModelRole}); } }); - connect(m_currentRoom, &Room::pendingEventChanged, this, &MessageEventModel::refreshRow); + connect(m_currentRoom, &Room::pendingEventChanged, this, &MessageEventModel::fullEventRefresh); connect(m_currentRoom, &Room::pendingEventAboutToDiscard, this, [this](int i) { beginRemoveRows({}, i, i); }); @@ -255,14 +255,15 @@ void MessageEventModel::setRoom(NeoChatRoom *room) } } -int MessageEventModel::refreshEvent(const QString &eventId) +void MessageEventModel::fullEventRefresh(int row) { - return refreshEventRoles(eventId); -} - -void MessageEventModel::refreshRow(int row) -{ - refreshEventRoles(row); + auto roles = roleNames().keys(); + // The author of an event never changes so should only be updated when a member + // changed signal is emitted. + // This also avoids any race conditions where a member is updating and this refresh + // tries to access a member event that has already been deleted. + roles.removeAll(AuthorRole); + refreshEventRoles(row, roles); } int MessageEventModel::timelineBaseIndex() const @@ -378,8 +379,7 @@ void MessageEventModel::refreshLastUserEvents(int baseTimelineRow) const auto limit = timelineBottom + std::min(baseTimelineRow + 10, m_currentRoom->timelineSize()); for (auto it = timelineBottom + std::max(baseTimelineRow - 10, 0); it != limit; ++it) { if ((*it)->senderId() == lastSender) { - auto idx = index(it - timelineBottom); - Q_EMIT dataChanged(idx, idx); + fullEventRefresh(it - timelineBottom); } } } diff --git a/src/models/messageeventmodel.h b/src/models/messageeventmodel.h index e86ad1349..deab8fd65 100644 --- a/src/models/messageeventmodel.h +++ b/src/models/messageeventmodel.h @@ -107,10 +107,6 @@ public: protected: bool event(QEvent *event) override; -private Q_SLOTS: - int refreshEvent(const QString &eventId); - void refreshRow(int row); - private: QPointer m_currentRoom = nullptr; QString lastReadEventId; @@ -128,6 +124,7 @@ private: bool canFetchMore(const QModelIndex &parent) const override; void fetchMore(const QModelIndex &parent) override; + void fullEventRefresh(int row); void refreshLastUserEvents(int baseTimelineRow); void refreshEventRoles(int row, const QList &roles = {}); int refreshEventRoles(const QString &eventId, const QList &roles = {});