Fix replying and editing from chatbox
Restore the functionality to edit or reply to the last message in the `chatbar`. This is achieved be moving the functions `getLastLocalUserMessageEventId` and `getLatestMessageFromRow` to `NeoChatRoom` as `editLastMessage` and `replyLastMessage` as `chatbar` no longer has access to `messageEventModel`. The functions are also simplified as they only need to find the `eventId` and always from row 0 as this was the only use of the functions. BUG: 469733
This commit is contained in:
@@ -979,87 +979,6 @@ int MessageEventModel::eventIdToRow(const QString &eventID) const
|
|||||||
return it - m_currentRoom->messageEvents().rbegin() + timelineBaseIndex();
|
return it - m_currentRoom->messageEvents().rbegin() + timelineBaseIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant MessageEventModel::getLastLocalUserMessageEventId()
|
|
||||||
{
|
|
||||||
QVariantMap targetMessage;
|
|
||||||
const auto &timelineBottom = m_currentRoom->messageEvents().rbegin();
|
|
||||||
|
|
||||||
// set a cap limit of 35 messages, to prevent loading a lot of messages
|
|
||||||
// in rooms where the user has not sent many messages
|
|
||||||
const auto limit = timelineBottom + std::min(35, m_currentRoom->timelineSize());
|
|
||||||
|
|
||||||
for (auto it = timelineBottom; it != limit; ++it) {
|
|
||||||
auto evt = it->event();
|
|
||||||
auto e = eventCast<const RoomMessageEvent>(evt);
|
|
||||||
if (!e) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if the current message's sender's id is same as the user's id
|
|
||||||
if ((*it)->senderId() == m_currentRoom->localUser()->id()) {
|
|
||||||
auto content = (*it)->contentJson();
|
|
||||||
|
|
||||||
if (e->msgtype() != MessageEventType::Unknown) {
|
|
||||||
QString eventId;
|
|
||||||
if (content.contains("m.new_content")) {
|
|
||||||
// The message has been edited so we have to return the id of the original message instead of the replacement
|
|
||||||
eventId = content["m.relates_to"].toObject()["event_id"].toString();
|
|
||||||
} else {
|
|
||||||
// For any message that isn't an edit return the id of the current message
|
|
||||||
eventId = (*it)->id();
|
|
||||||
}
|
|
||||||
targetMessage.insert("event_id", eventId);
|
|
||||||
targetMessage.insert("formattedBody", content["formatted_body"].toString());
|
|
||||||
// Need to get the message from the original eventId or body will have * on the front
|
|
||||||
QModelIndex idx = index(eventIdToRow(eventId), 0);
|
|
||||||
targetMessage.insert("message", idx.data(Qt::UserRole + 2));
|
|
||||||
|
|
||||||
return targetMessage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return targetMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant MessageEventModel::getLatestMessageFromRow(const int startRow)
|
|
||||||
{
|
|
||||||
QVariantMap replyResponse;
|
|
||||||
const auto &timelineBottom = m_currentRoom->messageEvents().rbegin() + startRow;
|
|
||||||
|
|
||||||
// set a cap limit of startRow + 35 messages, to prevent loading a lot of messages
|
|
||||||
// in rooms where the user has not sent many messages
|
|
||||||
const auto limit = timelineBottom + std::min(startRow + 35, m_currentRoom->timelineSize());
|
|
||||||
|
|
||||||
for (auto it = timelineBottom; it != limit; ++it) {
|
|
||||||
auto evt = it->event();
|
|
||||||
auto e = eventCast<const RoomMessageEvent>(evt);
|
|
||||||
if (!e) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto content = (*it)->contentJson();
|
|
||||||
|
|
||||||
if (e->msgtype() != MessageEventType::Unknown) {
|
|
||||||
QString eventId;
|
|
||||||
if (content.contains("m.new_content")) {
|
|
||||||
// The message has been edited so we have to return the id of the original message instead of the replacement
|
|
||||||
eventId = content["m.relates_to"].toObject()["event_id"].toString();
|
|
||||||
} else {
|
|
||||||
// For any message that isn't an edit return the id of the current message
|
|
||||||
eventId = (*it)->id();
|
|
||||||
}
|
|
||||||
replyResponse.insert("event_id", eventId);
|
|
||||||
// Need to get the message from the original eventId or body will have * on the front
|
|
||||||
QModelIndex idx = index(eventIdToRow(eventId), 0);
|
|
||||||
replyResponse.insert("message", idx.data(Qt::UserRole + 2));
|
|
||||||
replyResponse.insert("sender_id", QVariant::fromValue(m_currentRoom->getUser((*it)->senderId())));
|
|
||||||
replyResponse.insert("at", -it->index());
|
|
||||||
return replyResponse;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return replyResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MessageEventModel::loadReply(const QModelIndex &index)
|
void MessageEventModel::loadReply(const QModelIndex &index)
|
||||||
{
|
{
|
||||||
auto job = m_currentRoom->connection()->callApi<GetOneRoomEventJob>(m_currentRoom->id(), data(index, ReplyIdRole).toString());
|
auto job = m_currentRoom->connection()->callApi<GetOneRoomEventJob>(m_currentRoom->id(), data(index, ReplyIdRole).toString());
|
||||||
|
|||||||
@@ -142,31 +142,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
Q_INVOKABLE [[nodiscard]] int eventIdToRow(const QString &eventID) const;
|
Q_INVOKABLE [[nodiscard]] int eventIdToRow(const QString &eventID) const;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the last message sent by the local user.
|
|
||||||
*
|
|
||||||
* @note This checks a maximum of the previous 35 message for performance reasons.
|
|
||||||
*
|
|
||||||
* @return a QVariantMap for the event with the following parameters:
|
|
||||||
* - eventId - The event ID.
|
|
||||||
* - formattedBody - The message text formatted as Qt::RichText.
|
|
||||||
* - message - The message text formatted as Qt::PlainText.
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE [[nodiscard]] QVariant getLastLocalUserMessageEventId();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the last message sent earlier than the given row.
|
|
||||||
*
|
|
||||||
* @note This checks a maximum of the previous 35 message for performance reasons.
|
|
||||||
*
|
|
||||||
* @return a QVariantMap for the event with the following parameters:
|
|
||||||
* - eventId - The event ID.
|
|
||||||
* - message - The message text formatted as Qt::PlainText.
|
|
||||||
* - sender_id - The matrix ID of the sender.
|
|
||||||
* - at - The QModelIndex of the message.
|
|
||||||
*/
|
|
||||||
Q_INVOKABLE [[nodiscard]] QVariant getLatestMessageFromRow(const int startRow);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Load the event that the item at the given index replied to.
|
* @brief Load the event that the item at the given index replied to.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1831,6 +1831,73 @@ void NeoChatRoom::setSavedText(const QString &savedText)
|
|||||||
m_savedText = savedText;
|
m_savedText = savedText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NeoChatRoom::replyLastMessage()
|
||||||
|
{
|
||||||
|
const auto &timelineBottom = messageEvents().rbegin();
|
||||||
|
|
||||||
|
// set a cap limit of startRow + 35 messages, to prevent loading a lot of messages
|
||||||
|
// in rooms where the user has not sent many messages
|
||||||
|
const auto limit = timelineBottom + std::min(35, timelineSize());
|
||||||
|
|
||||||
|
for (auto it = timelineBottom; it != limit; ++it) {
|
||||||
|
auto evt = it->event();
|
||||||
|
auto e = eventCast<const RoomMessageEvent>(evt);
|
||||||
|
if (!e) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto content = (*it)->contentJson();
|
||||||
|
|
||||||
|
if (e->msgtype() != MessageEventType::Unknown) {
|
||||||
|
QString eventId;
|
||||||
|
if (content.contains("m.new_content")) {
|
||||||
|
// The message has been edited so we have to return the id of the original message instead of the replacement
|
||||||
|
eventId = content["m.relates_to"].toObject()["event_id"].toString();
|
||||||
|
} else {
|
||||||
|
// For any message that isn't an edit return the id of the current message
|
||||||
|
eventId = (*it)->id();
|
||||||
|
}
|
||||||
|
setChatBoxReplyId(eventId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NeoChatRoom::editLastMessage()
|
||||||
|
{
|
||||||
|
const auto &timelineBottom = messageEvents().rbegin();
|
||||||
|
|
||||||
|
// set a cap limit of 35 messages, to prevent loading a lot of messages
|
||||||
|
// in rooms where the user has not sent many messages
|
||||||
|
const auto limit = timelineBottom + std::min(35, timelineSize());
|
||||||
|
|
||||||
|
for (auto it = timelineBottom; it != limit; ++it) {
|
||||||
|
auto evt = it->event();
|
||||||
|
auto e = eventCast<const RoomMessageEvent>(evt);
|
||||||
|
if (!e) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if the current message's sender's id is same as the user's id
|
||||||
|
if ((*it)->senderId() == localUser()->id()) {
|
||||||
|
auto content = (*it)->contentJson();
|
||||||
|
|
||||||
|
if (e->msgtype() != MessageEventType::Unknown) {
|
||||||
|
QString eventId;
|
||||||
|
if (content.contains("m.new_content")) {
|
||||||
|
// The message has been edited so we have to return the id of the original message instead of the replacement
|
||||||
|
eventId = content["m.relates_to"].toObject()["event_id"].toString();
|
||||||
|
} else {
|
||||||
|
// For any message that isn't an edit return the id of the current message
|
||||||
|
eventId = (*it)->id();
|
||||||
|
}
|
||||||
|
setChatBoxEditId(eventId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool NeoChatRoom::canEncryptRoom() const
|
bool NeoChatRoom::canEncryptRoom() const
|
||||||
{
|
{
|
||||||
#ifdef QUOTIENT_07
|
#ifdef QUOTIENT_07
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <qobjectdefs.h>
|
||||||
#include <room.h>
|
#include <room.h>
|
||||||
|
|
||||||
#include <QCache>
|
#include <QCache>
|
||||||
@@ -735,6 +736,20 @@ public:
|
|||||||
*/
|
*/
|
||||||
void setSavedText(const QString &savedText);
|
void setSavedText(const QString &savedText);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reply to the last message sent in the timeline.
|
||||||
|
*
|
||||||
|
* @note This checks a maximum of the previous 35 message for performance reasons.
|
||||||
|
*/
|
||||||
|
Q_INVOKABLE void replyLastMessage();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Edit the last message sent by the local user.
|
||||||
|
*
|
||||||
|
* @note This checks a maximum of the previous 35 message for performance reasons.
|
||||||
|
*/
|
||||||
|
Q_INVOKABLE void editLastMessage();
|
||||||
|
|
||||||
#ifdef QUOTIENT_07
|
#ifdef QUOTIENT_07
|
||||||
/**
|
/**
|
||||||
* @brief Get a PollHandler object for the given event Id.
|
* @brief Get a PollHandler object for the given event Id.
|
||||||
|
|||||||
@@ -203,15 +203,9 @@ QQC2.Control {
|
|||||||
if (event.key === Qt.Key_V && event.modifiers & Qt.ControlModifier) {
|
if (event.key === Qt.Key_V && event.modifiers & Qt.ControlModifier) {
|
||||||
chatBar.pasteImage();
|
chatBar.pasteImage();
|
||||||
} else if (event.key === Qt.Key_Up && event.modifiers & Qt.ControlModifier) {
|
} else if (event.key === Qt.Key_Up && event.modifiers & Qt.ControlModifier) {
|
||||||
let replyEvent = messageEventModel.getLatestMessageFromRow(0)
|
currentRoom.replyLastMessage();
|
||||||
if (replyEvent && replyEvent["event_id"]) {
|
|
||||||
currentRoom.chatBoxReplyId = replyEvent["event_id"]
|
|
||||||
}
|
|
||||||
} else if (event.key === Qt.Key_Up && textField.text.length === 0) {
|
} else if (event.key === Qt.Key_Up && textField.text.length === 0) {
|
||||||
let editEvent = messageEventModel.getLastLocalUserMessageEventId()
|
currentRoom.editLastMessage();
|
||||||
if (editEvent) {
|
|
||||||
currentRoom.chatBoxEditId = editEvent["event_id"]
|
|
||||||
}
|
|
||||||
} else if (event.key === Qt.Key_Up && completionMenu.visible) {
|
} else if (event.key === Qt.Key_Up && completionMenu.visible) {
|
||||||
completionMenu.decrementIndex()
|
completionMenu.decrementIndex()
|
||||||
} else if (event.key === Qt.Key_Down && completionMenu.visible) {
|
} else if (event.key === Qt.Key_Down && completionMenu.visible) {
|
||||||
|
|||||||
Reference in New Issue
Block a user