Allow opening message menus for out-of-room events
These are more common than we thought, good examples are pinned or searched messages - which are not going to be in the room's history unless you happen to have them loaded. But currently our message menu infrastructure expects them to be, since its looked up by the room + event ID. To fix this is simple, we now move the job of finding the event to the caller which may use a model instead. I didn't fix all existing call-sites yet, mainly the message menu opening one since that was the most obvious bug. But this opens up the door for other assumptions about room history to be fixed too. I had to do a bit of C++ re-jiggering in order to expose useful functions to QML.
This commit is contained in:
@@ -152,6 +152,23 @@ QModelIndex MessageFilterModel::indexForEventId(const QString &eventId) const
|
||||
return mapFromSource(eventIndex);
|
||||
}
|
||||
|
||||
const Quotient::RoomEvent *MessageFilterModel::findEvent(const QString &eventId) const
|
||||
{
|
||||
// Check if sourceModel is a message model.
|
||||
auto messageModel = dynamic_cast<MessageModel *>(sourceModel());
|
||||
// See if it's a timeline model.
|
||||
if (!messageModel) {
|
||||
if (const auto timelineModel = dynamic_cast<TimelineModel *>(sourceModel())) {
|
||||
messageModel = timelineModel->timelineMessageModel();
|
||||
if (!messageModel) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return messageModel->findEvent(eventId);
|
||||
}
|
||||
|
||||
bool MessageFilterModel::showAuthor(QModelIndex index) const
|
||||
{
|
||||
for (auto r = index.row() + 1; r < rowCount(); ++r) {
|
||||
|
||||
@@ -67,9 +67,13 @@ public:
|
||||
/**
|
||||
* @brief Get the QModelIndex the given event ID in the model.
|
||||
*/
|
||||
Q_INVOKABLE QModelIndex indexforEventId(const QString &eventId) const;
|
||||
Q_INVOKABLE QModelIndex indexForEventId(const QString &eventId) const;
|
||||
|
||||
/**
|
||||
* @brief Finds the event of the given event ID in the model, returning nullptr if no matches were found.
|
||||
*/
|
||||
Q_INVOKABLE const Quotient::RoomEvent *findEvent(const QString &eventId) const;
|
||||
|
||||
static void setShowAllEvents(bool enabled);
|
||||
static void setShowDeletedMessages(bool enabled);
|
||||
|
||||
|
||||
@@ -351,16 +351,21 @@ QHash<int, QByteArray> MessageModel::roleNames() const
|
||||
|
||||
QModelIndex MessageModel::indexForEventId(const QString &eventId) const
|
||||
{
|
||||
if (m_room == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto it = m_room->findInTimeline(eventId);
|
||||
if (it == m_room->historyEdge()) {
|
||||
const auto matches = match(index(0, 0), EventIdRole, eventId);
|
||||
if (matches.isEmpty()) {
|
||||
qWarning() << "Trying to find non-existent event:" << eventId;
|
||||
return {};
|
||||
}
|
||||
return index(it - m_room->messageEvents().rbegin() + timelineServerIndex());
|
||||
return matches.constFirst();
|
||||
}
|
||||
|
||||
const RoomEvent *MessageModel::findEvent(const QString &eventId) const
|
||||
{
|
||||
const auto index = indexForEventId(eventId);
|
||||
if (const auto event = getEventForIndex(index)) {
|
||||
return &event.value().get();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void MessageModel::fullEventRefresh(int row)
|
||||
|
||||
@@ -115,9 +115,13 @@ public:
|
||||
/**
|
||||
* @brief Get the QModelIndex of the given event ID in the model, returning an invalid QModelIndex if no matches were found.
|
||||
*/
|
||||
Q_INVOKABLE QModelIndex indexforEventId(const QString &eventId) const;
|
||||
Q_INVOKABLE QModelIndex indexForEventId(const QString &eventId) const;
|
||||
|
||||
/**
|
||||
* @brief Finds the event of the given event ID in the model, returning nullptr if no matches were found.
|
||||
*/
|
||||
Q_INVOKABLE const Quotient::RoomEvent *findEvent(const QString &eventId) const;
|
||||
|
||||
static void setHiddenFilter(std::function<bool(const Quotient::RoomEvent *)> hiddenFilter);
|
||||
|
||||
static void setThreadsEnabled(bool enableThreads);
|
||||
|
||||
Reference in New Issue
Block a user