feat: add a quick reply workflow using the Ctrl+Up arrow key

neochat now supports a quick reply shortcut, which helps to reply to
the last event in a room.
This commit is contained in:
Srevin Saju
2021-04-04 21:50:30 +03:00
committed by Carl Schwan
parent e4ab2e565f
commit 78f7f815ca
7 changed files with 67 additions and 1 deletions

View File

@@ -29,6 +29,7 @@ ToolBar {
signal messageSent()
signal pasteImageTriggered()
signal editLastUserMessage()
signal replyPreviousUserMessage()
property alias isCompleting: completionMenu.visible
@@ -142,7 +143,9 @@ ToolBar {
switchRoomUp();
} else if (event.key === Qt.Key_V && event.modifiers & Qt.ControlModifier) {
chatBar.pasteImage();
} else if (event.key === Qt.Key_Up && !(event.modifiers & Qt.ControlModifier)) {
} else if (event.key === Qt.Key_Up && event.modifiers & Qt.ControlModifier) {
replyPreviousUserMessage();
} else if (event.key === Qt.Key_Up) {
editLastUserMessage();
}
}

View File

@@ -18,6 +18,7 @@ Item {
signal fancyEffectsReasonFound(string fancyEffect)
signal messageSent()
signal editLastUserMessage()
signal replyPreviousUserMessage()
Kirigami.Theme.colorSet: Kirigami.Theme.View
@@ -157,6 +158,9 @@ Item {
onEditLastUserMessage: {
root.editLastUserMessage();
}
onReplyPreviousUserMessage: {
root.replyPreviousUserMessage();
}
}
function checkForFancyEffectsReason() {

View File

@@ -657,6 +657,12 @@ Kirigami.ScrollablePage {
ChatBoxHelper.edit(targetMessage["body"], targetMessage["body"], targetMessage["event_id"]);
}
}
onReplyPreviousUserMessage: {
const replyResponse = messageEventModel.getLatestMessageFromIndex(0);
if (replyResponse && replyResponse["event_id"]) {
ChatBoxHelper.replyToMessage(replyResponse["event_id"], replyResponse["event"], replyResponse["sender_id"]);
}
}
}
background: FancyEffectsContainer {

View File

@@ -672,3 +672,43 @@ QVariant MessageEventModel::getLastLocalUserMessageEventId()
}
return targetMessage;
}
QVariant MessageEventModel::getLatestMessageFromIndex(const int baseline)
{
QVariantMap replyResponse;
const auto &timelineBottom = m_currentRoom->messageEvents().rbegin() + baseline;
// set a cap limit of baseline + 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(baseline + 35, m_currentRoom->timelineSize());
for (auto it = timelineBottom; it != limit; ++it) {
auto evt = it->event();
auto e = eventCast<const RoomMessageEvent>(evt);
auto content = (*it)->contentJson();
if (content.contains("m.relates_to")) {
auto relatedContent = content["m.relates_to"].toObject();
if (!relatedContent.contains("m.in_reply_to")) {
// the message has been edited once
// so we have to return the id of the related' message instead
replyResponse.insert("event_id", relatedContent["event_id"].toString());
replyResponse.insert("event", content["m.formatted_body"].toString());
replyResponse.insert("sender_id", QVariant::fromValue(m_currentRoom->getUser((*it)->senderId())));
replyResponse.insert("at", -it->index());
return replyResponse;
}
}
if (e->msgtype() != MessageEventType::Unknown) {
replyResponse.insert("event_id", (*it)->id());
replyResponse.insert("event", content["body"].toString());
replyResponse.insert("sender_id", QVariant::fromValue(m_currentRoom->getUser((*it)->senderId())));
replyResponse.insert("at", -it->index());
return replyResponse;
}
}
return replyResponse;
}

View File

@@ -70,6 +70,7 @@ public:
Q_INVOKABLE [[nodiscard]] int eventIDToIndex(const QString &eventID) const;
Q_INVOKABLE [[nodiscard]] QVariant getLastLocalUserMessageEventId();
Q_INVOKABLE [[nodiscard]] QVariant getLatestMessageFromIndex(const int baseline);
private Q_SLOTS:
int refreshEvent(const QString &eventId);

View File

@@ -265,6 +265,17 @@ QVariantList NeoChatRoom::getUsers(const QString &keyword) const
return matchedList;
}
QVariantMap NeoChatRoom::getUser(const QString& userID) const
{
NeoChatUser user(userID, connection());
return QVariantMap {
{ QStringLiteral("id"), user.id() },
{ QStringLiteral("displayName"), user.displayname(this) },
{ QStringLiteral("avatarMediaId"), user.avatarMediaId(this) },
{ QStringLiteral("color"), user.color() }
};
}
QUrl NeoChatRoom::urlToMxcUrl(const QUrl &mxcUrl)
{
return DownloadFileJob::makeRequestUrl(connection()->homeserver(), mxcUrl);

View File

@@ -92,6 +92,7 @@ public:
Q_INVOKABLE void saveViewport(int topIndex, int bottomIndex);
Q_INVOKABLE [[nodiscard]] QVariantList getUsers(const QString &keyword) const;
Q_INVOKABLE [[nodiscard]] QVariantMap getUser(const QString &userID) const;
Q_INVOKABLE QUrl urlToMxcUrl(const QUrl &mxcUrl);