Create NeochatRoomMember as a shim for RoomMember
The intention is that NeochatRoomMember can be created passed to QML and then be fully managed by it. It effectively just grabs the current RoomMember, calls the correct function then discards it so that we don't end up trying to access an already deleted state event.
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "messagecontentmodel.h"
|
||||
#include "neochatconfig.h"
|
||||
#include "neochatroommember.h"
|
||||
|
||||
#include <QImageReader>
|
||||
|
||||
@@ -35,10 +36,10 @@ MessageContentModel::MessageContentModel(NeoChatRoom *room, const Quotient::Room
|
||||
, m_room(room)
|
||||
, m_eventId(event != nullptr ? event->id() : QString())
|
||||
, m_eventSenderId(event != nullptr ? event->senderId() : QString())
|
||||
, m_event(loadEvent<RoomEvent>(event->fullJson()))
|
||||
, m_isPending(isPending)
|
||||
, m_isReply(isReply)
|
||||
{
|
||||
intiializeEvent(event);
|
||||
initializeModel();
|
||||
}
|
||||
|
||||
@@ -81,8 +82,7 @@ void MessageContentModel::initializeModel()
|
||||
if (m_eventId == serverEvent->id()) {
|
||||
beginResetModel();
|
||||
m_isPending = false;
|
||||
m_event = loadEvent<RoomEvent>(serverEvent->fullJson());
|
||||
Q_EMIT eventUpdated();
|
||||
intiializeEvent(serverEvent);
|
||||
endResetModel();
|
||||
}
|
||||
}
|
||||
@@ -91,8 +91,7 @@ void MessageContentModel::initializeModel()
|
||||
if (m_room != nullptr && m_event != nullptr) {
|
||||
if (m_eventId == newEvent->id()) {
|
||||
beginResetModel();
|
||||
m_event = loadEvent<RoomEvent>(newEvent->fullJson());
|
||||
Q_EMIT eventUpdated();
|
||||
intiializeEvent(newEvent);
|
||||
endResetModel();
|
||||
}
|
||||
}
|
||||
@@ -154,6 +153,29 @@ void MessageContentModel::initializeModel()
|
||||
resetModel();
|
||||
}
|
||||
|
||||
void MessageContentModel::intiializeEvent(const QString &eventId)
|
||||
{
|
||||
const auto newEvent = m_room->getEvent(eventId);
|
||||
if (newEvent != nullptr) {
|
||||
intiializeEvent(newEvent);
|
||||
}
|
||||
}
|
||||
|
||||
void MessageContentModel::intiializeEvent(const Quotient::RoomEvent *event)
|
||||
{
|
||||
m_event = loadEvent<RoomEvent>(event->fullJson());
|
||||
auto senderId = event->senderId();
|
||||
// A pending event might not have a sender ID set yet but in that case it must
|
||||
// be the local member.
|
||||
if (senderId.isEmpty()) {
|
||||
senderId = m_room->localMember().id();
|
||||
}
|
||||
if (m_eventSenderObject == nullptr) {
|
||||
m_eventSenderObject = std::unique_ptr<NeochatRoomMember>(new NeochatRoomMember(m_room, senderId));
|
||||
}
|
||||
Q_EMIT eventUpdated();
|
||||
}
|
||||
|
||||
bool MessageContentModel::showAuthor() const
|
||||
{
|
||||
return m_showAuthor;
|
||||
@@ -239,7 +261,7 @@ QVariant MessageContentModel::data(const QModelIndex &index, int role) const
|
||||
return eventHandler.getTimeString(false, QLocale::ShortFormat, m_isPending, lastUpdated);
|
||||
}
|
||||
if (role == AuthorRole) {
|
||||
return QVariant::fromValue(eventHandler.getAuthor(m_isPending));
|
||||
return QVariant::fromValue<NeochatRoomMember *>(m_eventSenderObject.get());
|
||||
}
|
||||
if (role == MediaInfoRole) {
|
||||
return eventHandler.getMediaInfo();
|
||||
|
||||
@@ -6,11 +6,13 @@
|
||||
#include <QAbstractListModel>
|
||||
#include <QQmlEngine>
|
||||
|
||||
#include <Quotient/events/roomevent.h>
|
||||
#include <Quotient/room.h>
|
||||
|
||||
#include "enums/messagecomponenttype.h"
|
||||
#include "eventhandler.h"
|
||||
#include "itinerarymodel.h"
|
||||
#include "neochatroommember.h"
|
||||
|
||||
struct MessageComponent {
|
||||
MessageComponentType::Type type = MessageComponentType::Other;
|
||||
@@ -115,6 +117,7 @@ private:
|
||||
QPointer<NeoChatRoom> m_room;
|
||||
QString m_eventId;
|
||||
QString m_eventSenderId;
|
||||
std::unique_ptr<NeochatRoomMember> m_eventSenderObject = nullptr;
|
||||
Quotient::RoomEventPtr m_event;
|
||||
|
||||
bool m_isPending;
|
||||
@@ -122,6 +125,8 @@ private:
|
||||
bool m_isReply;
|
||||
|
||||
void initializeModel();
|
||||
void intiializeEvent(const QString &eventId);
|
||||
void intiializeEvent(const Quotient::RoomEvent *event);
|
||||
|
||||
QList<MessageComponent> m_components;
|
||||
void resetModel();
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#include "messagecontentmodel.h"
|
||||
#include "models/messagefiltermodel.h"
|
||||
#include "models/reactionmodel.h"
|
||||
#include "neochatroom.h"
|
||||
#include "neochatroommember.h"
|
||||
#include "readmarkermodel.h"
|
||||
#include "texthandler.h"
|
||||
|
||||
@@ -90,6 +92,10 @@ void MessageEventModel::setRoom(NeoChatRoom *room)
|
||||
m_currentRoom->disconnect(this);
|
||||
m_currentRoom = nullptr;
|
||||
endResetModel();
|
||||
|
||||
// Don't clear the member objects until the model has been fully reset and all
|
||||
// refs cleared.
|
||||
m_memberObjects.clear();
|
||||
}
|
||||
|
||||
beginResetModel();
|
||||
@@ -150,8 +156,9 @@ void MessageEventModel::setRoom(NeoChatRoom *room)
|
||||
refreshLastUserEvents(i);
|
||||
}
|
||||
});
|
||||
connect(m_currentRoom, &Room::pendingEventAboutToAdd, this, [this] {
|
||||
connect(m_currentRoom, &Room::pendingEventAboutToAdd, this, [this](Quotient::RoomEvent *event) {
|
||||
m_initialized = true;
|
||||
createEventObjects(event);
|
||||
beginInsertRows({}, 0, 0);
|
||||
});
|
||||
connect(m_currentRoom, &Room::pendingEventAdded, this, &MessageEventModel::endInsertRows);
|
||||
@@ -214,22 +221,6 @@ void MessageEventModel::setRoom(NeoChatRoom *room)
|
||||
beginResetModel();
|
||||
endResetModel();
|
||||
});
|
||||
connect(m_currentRoom, &Room::memberNameUpdated, this, [this](RoomMember member) {
|
||||
for (auto it = m_currentRoom->messageEvents().rbegin(); it != m_currentRoom->messageEvents().rend(); ++it) {
|
||||
auto event = it->event();
|
||||
if (event->senderId() == member.id()) {
|
||||
refreshEventRoles(event->id(), {AuthorRole});
|
||||
}
|
||||
}
|
||||
});
|
||||
connect(m_currentRoom, &Room::memberAvatarUpdated, this, [this](RoomMember member) {
|
||||
for (auto it = m_currentRoom->messageEvents().rbegin(); it != m_currentRoom->messageEvents().rend(); ++it) {
|
||||
auto event = it->event();
|
||||
if (event->senderId() == member.id()) {
|
||||
refreshEventRoles(event->id(), {AuthorRole});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
qCDebug(MessageEvent) << "Connected to room" << room->id() << "as" << room->localMember().id();
|
||||
} else {
|
||||
@@ -397,6 +388,8 @@ void MessageEventModel::fetchMore(const QModelIndex &parent)
|
||||
}
|
||||
}
|
||||
|
||||
static NeochatRoomMember *emptyNeochatRoomMember = new NeochatRoomMember;
|
||||
|
||||
QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
|
||||
{
|
||||
if (!checkIndex(idx, QAbstractItemModel::CheckIndexOption::IndexIsValid)) {
|
||||
@@ -469,7 +462,18 @@ QVariant MessageEventModel::data(const QModelIndex &idx, int role) const
|
||||
}
|
||||
|
||||
if (role == AuthorRole) {
|
||||
return QVariant::fromValue(eventHandler.getAuthor(isPending));
|
||||
QString mId;
|
||||
if (isPending) {
|
||||
mId = m_currentRoom->localMember().id();
|
||||
} else {
|
||||
mId = evt.senderId();
|
||||
}
|
||||
|
||||
if (!m_memberObjects.contains(mId)) {
|
||||
return QVariant::fromValue<NeochatRoomMember *>(emptyNeochatRoomMember);
|
||||
}
|
||||
|
||||
return QVariant::fromValue<NeochatRoomMember *>(m_memberObjects.at(mId).get());
|
||||
}
|
||||
|
||||
if (role == HighlightRole) {
|
||||
@@ -619,6 +623,16 @@ void MessageEventModel::createEventObjects(const Quotient::RoomEvent *event)
|
||||
}
|
||||
|
||||
auto eventId = event->id();
|
||||
auto senderId = event->senderId();
|
||||
// A pending event might not have a sender ID set yet but in that case it must
|
||||
// be the local member.
|
||||
if (senderId.isEmpty()) {
|
||||
senderId = m_currentRoom->localMember().id();
|
||||
}
|
||||
|
||||
if (!m_memberObjects.contains(senderId)) {
|
||||
m_memberObjects[senderId] = std::unique_ptr<NeochatRoomMember>(new NeochatRoomMember(m_currentRoom, senderId));
|
||||
}
|
||||
|
||||
// ReadMarkerModel handles updates to add and remove markers, we only need to
|
||||
// handle adding and removing whole models here.
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "linkpreviewer.h"
|
||||
#include "neochatroom.h"
|
||||
#include "neochatroommember.h"
|
||||
#include "pollhandler.h"
|
||||
#include "readmarkermodel.h"
|
||||
|
||||
@@ -115,6 +116,7 @@ private:
|
||||
bool movingEvent = false;
|
||||
KFormat m_format;
|
||||
|
||||
std::map<QString, std::unique_ptr<NeochatRoomMember>> m_memberObjects;
|
||||
QMap<QString, QSharedPointer<ReadMarkerModel>> m_readMarkerModels;
|
||||
QMap<QString, QSharedPointer<ReactionModel>> m_reactionModels;
|
||||
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
#include "messagefiltermodel.h"
|
||||
|
||||
#include <KLocalizedString>
|
||||
#include <QVariant>
|
||||
|
||||
#include "enums/delegatetype.h"
|
||||
#include "messagecontentmodel.h"
|
||||
#include "messageeventmodel.h"
|
||||
#include "neochatconfig.h"
|
||||
#include "neochatroommember.h"
|
||||
#include "timelinemodel.h"
|
||||
|
||||
using namespace Quotient;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "eventhandler.h"
|
||||
#include "models/messagecontentmodel.h"
|
||||
#include "neochatroom.h"
|
||||
#include "neochatroommember.h"
|
||||
|
||||
#include <QGuiApplication>
|
||||
|
||||
@@ -66,7 +67,17 @@ void SearchModel::search()
|
||||
m_job = job;
|
||||
connect(job, &BaseJob::finished, this, [this, job] {
|
||||
beginResetModel();
|
||||
m_memberObjects.clear();
|
||||
m_result = job->searchCategories().roomEvents;
|
||||
|
||||
if (m_result.has_value()) {
|
||||
for (const auto &result : m_result.value().results) {
|
||||
if (!m_memberObjects.contains(result.result->senderId())) {
|
||||
m_memberObjects[result.result->senderId()] = std::unique_ptr<NeochatRoomMember>(new NeochatRoomMember(m_room, result.result->senderId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
setSearching(false);
|
||||
m_job = nullptr;
|
||||
@@ -83,7 +94,7 @@ QVariant SearchModel::data(const QModelIndex &index, int role) const
|
||||
|
||||
switch (role) {
|
||||
case AuthorRole:
|
||||
return QVariant::fromValue(eventHandler.getAuthor());
|
||||
return QVariant::fromValue<NeochatRoomMember *>(m_memberObjects.at(event.senderId()).get());
|
||||
case ShowSectionRole:
|
||||
if (row == 0) {
|
||||
return true;
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
#include <Quotient/csapi/search.h>
|
||||
|
||||
#include "neochatroommember.h"
|
||||
|
||||
namespace Quotient
|
||||
{
|
||||
class Connection;
|
||||
@@ -123,4 +125,6 @@ private:
|
||||
std::optional<Quotient::SearchJob::ResultRoomEvents> m_result = std::nullopt;
|
||||
Quotient::SearchJob *m_job = nullptr;
|
||||
bool m_searching = false;
|
||||
|
||||
std::map<QString, std::unique_ptr<NeochatRoomMember>> m_memberObjects;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user