summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Werner <nicolas.werner@hotmail.de>2020-04-13 16:22:30 +0200
committerNicolas Werner <nicolas.werner@hotmail.de>2020-04-13 16:22:30 +0200
commitdcddea6fb89246d63be91a1f1151ce2dbd255a12 (patch)
tree5d3782b9d7763ab83b0d65d183e37dc29fcd40e6
parent82ec022f9c27f68b6328811534a4f70155bd58fe (diff)
Fix reply not closing
fixes #124
-rw-r--r--CMakeLists.txt2
-rw-r--r--resources/qml/TimelineView.qml6
-rw-r--r--src/ChatPage.cpp37
-rw-r--r--src/ChatPage.h6
-rw-r--r--src/TextInputWidget.cpp69
-rw-r--r--src/TextInputWidget.h27
-rw-r--r--src/notifications/ManagerLinux.cpp36
-rw-r--r--src/notifications/ManagerWin.cpp1
-rw-r--r--src/popups/ReplyPopup.cpp103
-rw-r--r--src/popups/ReplyPopup.h44
-rw-r--r--src/timeline/TimelineModel.cpp13
-rw-r--r--src/timeline/TimelineModel.h21
-rw-r--r--src/timeline/TimelineViewManager.cpp76
-rw-r--r--src/timeline/TimelineViewManager.h30
14 files changed, 135 insertions, 336 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9742c48e..6f769a26 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -303,7 +303,6 @@ set(SRC_FILES
src/Utils.cpp
src/WelcomePage.cpp
src/popups/PopupItem.cpp
- src/popups/ReplyPopup.cpp
src/popups/SuggestionsPopup.cpp
src/popups/UserMentions.cpp
src/main.cpp
@@ -501,7 +500,6 @@ qt5_wrap_cpp(MOC_HEADERS
src/UserSettingsPage.h
src/WelcomePage.h
src/popups/PopupItem.h
- src/popups/ReplyPopup.h
src/popups/SuggestionsPopup.h
src/popups/UserMentions.h
)
diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml
index 5b051235..86b511b2 100644
--- a/resources/qml/TimelineView.qml
+++ b/resources/qml/TimelineView.qml
@@ -285,7 +285,7 @@ Page {
id: replyPopup
- visible: timelineManager.replyingEvent && chat.model
+ visible: chat.model && chat.model.reply
// Height of child, plus margins, plus border
height: replyPreview.height + 10
color: colors.base
@@ -300,7 +300,7 @@ Page {
anchors.rightMargin: 20
anchors.bottom: parent.bottom
- modelData: chat.model ? chat.model.getDump(timelineManager.replyingEvent) : {}
+ modelData: chat.model ? chat.model.getDump(chat.model.reply) : {}
userColor: timelineManager.userColor(modelData.userId, colors.window)
}
@@ -318,7 +318,7 @@ Page {
ToolTip.visible: closeReplyButton.hovered
ToolTip.text: qsTr("Close")
- onClicked: timelineManager.closeReply()
+ onClicked: chat.model.reply = undefined
}
}
}
diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp
index d7d11a12..c9afeb75 100644
--- a/src/ChatPage.cpp
+++ b/src/ChatPage.cpp
@@ -303,10 +303,7 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
text_input_,
&TextInputWidget::uploadMedia,
this,
- [this](QSharedPointer<QIODevice> dev,
- QString mimeClass,
- const QString &fn,
- const std::optional<RelatedInfo> &related) {
+ [this](QSharedPointer<QIODevice> dev, QString mimeClass, const QString &fn) {
if (!dev->open(QIODevice::ReadOnly)) {
emit uploadFailed(
QString("Error while reading media: %1").arg(dev->errorString()));
@@ -358,8 +355,7 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
mime = mime.name(),
size = payload.size(),
dimensions,
- blurhash,
- related](const mtx::responses::ContentURI &res, mtx::http::RequestErr err) {
+ blurhash](const mtx::responses::ContentURI &res, mtx::http::RequestErr err) {
if (err) {
emit uploadFailed(
tr("Failed to upload media. Please try again."));
@@ -378,8 +374,7 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
mime,
size,
dimensions,
- blurhash,
- related);
+ blurhash);
});
});
@@ -398,8 +393,7 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
QString mime,
qint64 dsize,
QSize dimensions,
- QString blurhash,
- const std::optional<RelatedInfo> &related) {
+ QString blurhash) {
text_input_->hideUploadSpinner();
if (encryptedFile)
@@ -413,17 +407,16 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
mime,
dsize,
dimensions,
- blurhash,
- related);
+ blurhash);
else if (mimeClass == "audio")
view_manager_->queueAudioMessage(
- roomid, filename, encryptedFile, url, mime, dsize, related);
+ roomid, filename, encryptedFile, url, mime, dsize);
else if (mimeClass == "video")
view_manager_->queueVideoMessage(
- roomid, filename, encryptedFile, url, mime, dsize, related);
+ roomid, filename, encryptedFile, url, mime, dsize);
else
view_manager_->queueFileMessage(
- roomid, filename, encryptedFile, url, mime, dsize, related);
+ roomid, filename, encryptedFile, url, mime, dsize);
});
connect(room_list_, &RoomList::roomAvatarChanged, this, &ChatPage::updateTopBarAvatar);
@@ -548,14 +541,6 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
});
connect(this, &ChatPage::dropToLoginPageCb, this, &ChatPage::dropToLoginPage);
- connect(this, &ChatPage::messageReply, text_input_, &TextInputWidget::addReply);
- connect(this, &ChatPage::messageReply, this, [this](const RelatedInfo &related) {
- view_manager_->updateReplyingEvent(QString::fromStdString(related.related_event));
- });
- connect(view_manager_,
- &TimelineViewManager::replyClosed,
- text_input_,
- &TextInputWidget::closeReplyPopup);
instance_ = this;
}
@@ -597,6 +582,12 @@ ChatPage::resetUI()
}
void
+ChatPage::focusMessageInput()
+{
+ this->text_input_->focusLineEdit();
+}
+
+void
ChatPage::deleteConfigs()
{
QSettings settings;
diff --git a/src/ChatPage.h b/src/ChatPage.h
index 02c19ba7..5182ab99 100644
--- a/src/ChatPage.h
+++ b/src/ChatPage.h
@@ -85,6 +85,7 @@ public:
//! Show the room/group list (if it was visible).
void showSideBars();
void initiateLogout();
+ void focusMessageInput();
public slots:
void leaveRoom(const QString &room_id);
@@ -99,8 +100,6 @@ signals:
void connectionLost();
void connectionRestored();
- void messageReply(const RelatedInfo &related);
-
void notificationsRetrieved(const mtx::responses::Notifications &);
void highlightedNotifsRetrieved(const mtx::responses::Notifications &,
const QPoint widgetPos);
@@ -114,8 +113,7 @@ signals:
const QString &mime,
qint64 dsize,
const QSize &dimensions,
- const QString &blurhash,
- const std::optional<RelatedInfo> &related);
+ const QString &blurhash);
void contentLoaded();
void closing();
diff --git a/src/TextInputWidget.cpp b/src/TextInputWidget.cpp
index 11f7ddda..af5c278e 100644
--- a/src/TextInputWidget.cpp
+++ b/src/TextInputWidget.cpp
@@ -46,7 +46,6 @@ FilteredTextEdit::FilteredTextEdit(QWidget *parent)
: QTextEdit{parent}
, history_index_{0}
, suggestionsPopup_{parent}
- , replyPopup_{parent}
, previewDialog_{parent}
{
setFrameStyle(QFrame::NoFrame);
@@ -73,10 +72,6 @@ FilteredTextEdit::FilteredTextEdit(QWidget *parent)
&FilteredTextEdit::uploadData);
connect(this, &FilteredTextEdit::resultsRetrieved, this, &FilteredTextEdit::showResults);
- connect(&replyPopup_, &ReplyPopup::userSelected, this, [](const QString &text) {
- // TODO: Show user avatar window.
- nhlog::ui()->info("User selected: " + text.toStdString());
- });
connect(
&suggestionsPopup_, &SuggestionsPopup::itemSelected, this, [this](const QString &text) {
suggestionsPopup_.hide();
@@ -90,8 +85,6 @@ FilteredTextEdit::FilteredTextEdit(QWidget *parent)
cursor.insertText(text);
});
- connect(&replyPopup_, &ReplyPopup::cancel, this, [this]() { closeReply(); });
-
// For cycling through the suggestions by hitting tab.
connect(this,
&FilteredTextEdit::selectNextSuggestion,
@@ -174,17 +167,6 @@ FilteredTextEdit::keyPressEvent(QKeyEvent *event)
}
}
- if (replyPopup_.isVisible()) {
- switch (event->key()) {
- case Qt::Key_Escape:
- closeReply();
- return;
-
- default:
- break;
- }
- }
-
switch (event->key()) {
case Qt::Key_At:
atTriggerPosition_ = textCursor().position();
@@ -218,7 +200,6 @@ FilteredTextEdit::keyPressEvent(QKeyEvent *event)
if (!(event->modifiers() & Qt::ShiftModifier)) {
stopTyping();
submit();
- closeReply();
} else {
QTextEdit::keyPressEvent(event);
}
@@ -416,31 +397,18 @@ FilteredTextEdit::submit()
auto name = text.mid(1, command_end - 1);
auto args = text.mid(command_end + 1);
if (name.isEmpty() || name == "/") {
- message(args, related);
+ message(args);
} else {
command(name, args);
}
} else {
- message(std::move(text), std::move(related));
+ message(std::move(text));
}
- related = {};
-
clear();
}
void
-FilteredTextEdit::showReplyPopup(const RelatedInfo &related_)
-{
- QPoint pos = viewport()->mapToGlobal(this->pos());
-
- replyPopup_.setReplyContent(related_);
- replyPopup_.move(pos.x(), pos.y() - replyPopup_.height() - 10);
- replyPopup_.setFixedWidth(this->parentWidget()->width());
- replyPopup_.show();
-}
-
-void
FilteredTextEdit::textChanged()
{
working_history_[history_index_] = toPlainText();
@@ -456,9 +424,7 @@ FilteredTextEdit::uploadData(const QByteArray data,
emit startedUpload();
- emit media(buffer, mediaType, filename, related);
- related = {};
- closeReply();
+ emit media(buffer, mediaType, filename);
}
void
@@ -599,7 +565,7 @@ void
TextInputWidget::command(QString command, QString args)
{
if (command == "me") {
- sendEmoteMessage(args, input_->related);
+ sendEmoteMessage(args);
} else if (command == "join") {
sendJoinRoomRequest(args);
} else if (command == "invite") {
@@ -611,16 +577,14 @@ TextInputWidget::command(QString command, QString args)
} else if (command == "unban") {
sendUnbanRoomRequest(args.section(' ', 0, 0), args.section(' ', 1, -1));
} else if (command == "shrug") {
- sendTextMessage("¯\\_(ツ)_/¯", input_->related);
+ sendTextMessage("¯\\_(ツ)_/¯");
} else if (command == "fliptable") {
- sendTextMessage("(╯°□°)╯︵ ┻━┻", input_->related);
+ sendTextMessage("(╯°□°)╯︵ ┻━┻");
} else if (command == "unfliptable") {
- sendTextMessage(" ┯━┯╭( º _ º╭)", input_->related);
+ sendTextMessage(" ┯━┯╭( º _ º╭)");
} else if (command == "sovietflip") {
- sendTextMessage("ノ┬─┬ノ ︵ ( \\o°o)\\", input_->related);
+ sendTextMessage("ノ┬─┬ノ ︵ ( \\o°o)\\");
}
-
- input_->related = std::nullopt;
}
void
@@ -640,9 +604,7 @@ TextInputWidget::openFileSelection()
QSharedPointer<QFile> file{new QFile{fileName, this}};
- emit uploadMedia(file, format, QFileInfo(fileName).fileName(), input_->related);
- input_->related = {};
- input_->closeReply();
+ emit uploadMedia(file, format, QFileInfo(fileName).fileName());
showUploadSpinner();
}
@@ -687,16 +649,3 @@ TextInputWidget::paintEvent(QPaintEvent *)
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}
-
-void
-TextInputWidget::addReply(const RelatedInfo &related)
-{
- // input_->setText(QString("> %1: %2\n\n").arg(username).arg(msg));
- input_->setFocus();
-
- // input_->showReplyPopup(related);
- auto cursor = input_->textCursor();
- cursor.movePosition(QTextCursor::End);
- input_->setTextCursor(cursor);
- input_->related = related;
-}
diff --git a/src/TextInputWidget.h b/src/TextInputWidget.h
index 77d77e44..addb61ec 100644
--- a/src/TextInputWidget.h
+++ b/src/TextInputWidget.h
@@ -28,7 +28,6 @@
#include "dialogs/PreviewUploadOverlay.h"
#include "emoji/PickButton.h"
-#include "popups/ReplyPopup.h"
#include "popups/SuggestionsPopup.h"
struct SearchResult;
@@ -49,27 +48,15 @@ public:
QSize minimumSizeHint() const override;
void submit();
- void showReplyPopup(const RelatedInfo &related_);
- void closeReply()
- {
- replyPopup_.hide();
- related = {};
- }
-
- // Used for replies
- std::optional<RelatedInfo> related;
signals:
void heightChanged(int height);
void startedTyping();
void stoppedTyping();
void startedUpload();
- void message(QString, const std::optional<RelatedInfo> &);
+ void message(QString msg);
void command(QString name, QString args);
- void media(QSharedPointer<QIODevice> data,
- QString mimeClass,
- const QString &filename,
- const std::optional<RelatedInfo> &related);
+ void media(QSharedPointer<QIODevice> data, QString mimeClass, const QString &filename);
//! Trigger the suggestion popup.
void showSuggestions(const QString &query);
@@ -97,7 +84,6 @@ private:
QTimer *typingTimer_;
SuggestionsPopup suggestionsPopup_;
- ReplyPopup replyPopup_;
enum class AnchorType
{
@@ -163,21 +149,18 @@ public slots:
void openFileSelection();
void hideUploadSpinner();
void focusLineEdit() { input_->setFocus(); }
- void addReply(const RelatedInfo &related);
- void closeReplyPopup() { input_->closeReply(); }
private slots:
void addSelectedEmoji(const QString &emoji);
signals:
- void sendTextMessage(const QString &msg, const std::optional<RelatedInfo> &related);
- void sendEmoteMessage(QString msg, const std::optional<RelatedInfo> &related);
+ void sendTextMessage(const QString &msg);
+ void sendEmoteMessage(QString msg);
void heightChanged(int height);
void uploadMedia(const QSharedPointer<QIODevice> data,
QString mimeClass,
- const QString &filename,
- const std::optional<RelatedInfo> &related);
+ const QString &filename);
void sendJoinRoomRequest(const QString &room);
void sendInviteRoomRequest(const QString &userid, const QString &reason);
diff --git a/src/notifications/ManagerLinux.cpp b/src/notifications/ManagerLinux.cpp
index 8b7b41bb..b9eca1a8 100644
--- a/src/notifications/ManagerLinux.cpp
+++ b/src/notifications/ManagerLinux.cpp
@@ -97,24 +97,24 @@ NotificationsManager::closeNotification(uint id)
void
NotificationsManager::removeNotification(const QString &roomId, const QString &eventId)
-
- roomEventId reId = {roomId, eventId};
-for (auto elem = notificationIds.begin(); elem != notificationIds.end(); ++elem) {
- if (elem.value().roomId != roomId)
- continue;
-
- // close all notifications matching the eventId or having a lower
- // notificationId
- // This relies on the notificationId not wrapping around. This allows for
- // approximately 2,147,483,647 notifications, so it is a bit unlikely.
- // Otherwise we would need to store a 64bit counter instead.
- closeNotification(elem.key());
-
- // FIXME: compare index of event id of the read receipt and the notification instead of just
- // the id to prevent read receipts of events without notification clearing all notifications
- // in that room!
- if (elem.value() == reId)
- break;
+{
+ roomEventId reId = {roomId, eventId};
+ for (auto elem = notificationIds.begin(); elem != notificationIds.end(); ++elem) {
+ if (elem.value().roomId != roomId)
+ continue;
+
+ // close all notifications matching the eventId or having a lower
+ // notificationId
+ // This relies on the notificationId not wrapping around. This allows for
+ // approximately 2,147,483,647 notifications, so it is a bit unlikely.
+ // Otherwise we would need to store a 64bit counter instead.
+ closeNotification(elem.key());
+
+ // FIXME: compare index of event id of the read receipt and the notification instead
+ // of just the id to prevent read receipts of events without notification clearing
+ // all notifications in that room!
+ if (elem.value() == reId)
+ break;
}
}
diff --git a/src/notifications/ManagerWin.cpp b/src/notifications/ManagerWin.cpp
index b00bac2e..5e209ee6 100644
--- a/src/notifications/ManagerWin.cpp
+++ b/src/notifications/ManagerWin.cpp
@@ -67,4 +67,3 @@ void NotificationsManager::notificationClosed(uint, uint) {}
void
NotificationsManager::removeNotification(const QString &roomId, const QString &eventId)
{}
-
diff --git a/src/popups/ReplyPopup.cpp b/src/popups/ReplyPopup.cpp
deleted file mode 100644
index 5058c039..00000000
--- a/src/popups/ReplyPopup.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-#include <QLabel>
-#include <QPaintEvent>
-#include <QPainter>
-#include <QStyleOption>
-
-#include "../Config.h"
-#include "../Utils.h"
-#include "../ui/Avatar.h"
-#include "../ui/DropShadow.h"
-#include "../ui/TextLabel.h"
-#include "PopupItem.h"
-#include "ReplyPopup.h"
-
-ReplyPopup::ReplyPopup(QWidget *parent)
- : QWidget(parent)
- , userItem_{nullptr}
- , msgLabel_{nullptr}
- , eventLabel_{nullptr}
-{
- setAttribute(Qt::WA_ShowWithoutActivating, true);
- setWindowFlags(Qt::ToolTip | Qt::NoDropShadowWindowHint);
-
- mainLayout_ = new QVBoxLayout(this);
- mainLayout_->setMargin(0);
- mainLayout_->setSpacing(0);
-
- topLayout_ = new QHBoxLayout();
- topLayout_->setSpacing(0);
- topLayout_->setContentsMargins(13, 1, 13, 0);
-
- userItem_ = new UserItem(this);
- connect(userItem_, &UserItem::clicked, this, &ReplyPopup::userSelected);
- topLayout_->addWidget(userItem_);
-
- buttonLayout_ = new QHBoxLayout();
- buttonLayout_->setSpacing(0);
- buttonLayout_->setMargin(0);
-
- topLayout_->addLayout(buttonLayout_);
- QFont f;
- f.setPointSizeF(f.pointSizeF());
- const int fontHeight = QFontMetrics(f).height();
- buttonSize_ = std::min(fontHeight, 20);
-
- closeBtn_ = new FlatButton(this);
- closeBtn_->setToolTip(tr("Logout"));
- closeBtn_->setCornerRadius(buttonSize_ / 4);
- closeBtn_->setText("X");
-
- QIcon icon;
- icon.addFile(":/icons/icons/ui/remove-symbol.png");
-
- closeBtn_->setIcon(icon);
- closeBtn_->setIconSize(QSize(buttonSize_, buttonSize_));
- connect(closeBtn_, &FlatButton::clicked, this, [this]() { emit cancel(); });
-
- buttonLayout_->addWidget(closeBtn_);
-
- topLayout_->addLayout(buttonLayout_);
-
- mainLayout_->addLayout(topLayout_);
- msgLabel_ = new TextLabel(this);
- msgLabel_->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::TextBrowserInteraction);
- mainLayout_->addWidget(msgLabel_);
- eventLabel_ = new QLabel(this);
- mainLayout_->addWidget(eventLabel_);
-
- setLayout(mainLayout_);
-}
-
-void
-ReplyPopup::setReplyContent(const RelatedInfo &related)
-{
- // Update the current widget with the new data.
- userItem_->updateItem(related.quoted_user);
-
- msgLabel_->setText(utils::getFormattedQuoteBody(related, "")
- .replace("<mx-reply>", "")
- .replace("</mx-reply>", ""));
-
- // eventLabel_->setText(srcEvent);
-
- adjustSize();
-}
-
-void
-ReplyPopup::paintEvent(QPaintEvent *)
-{
- QStyleOption opt;
- opt.init(this);
- QPainter p(this);
- style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
-}
-
-void
-ReplyPopup::mousePressEvent(QMouseEvent *event)
-{
- if (event->buttons() != Qt::RightButton) {
- emit clicked(eventLabel_->text());
- }
-
- QWidget::mousePressEvent(event);
-}
diff --git a/src/popups/ReplyPopup.h b/src/popups/ReplyPopup.h
deleted file mode 100644
index 1fa3bb83..00000000
--- a/src/popups/ReplyPopup.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#pragma once
-
-#include <QHBoxLayout>
-#include <QLabel>
-#include <QVBoxLayout>
-#include <QWidget>
-
-#include "../ui/FlatButton.h"
-#include "../ui/TextLabel.h"
-
-struct RelatedInfo;
-class UserItem;
-
-class ReplyPopup : public QWidget
-{
- Q_OBJECT
-
-public:
- explicit ReplyPopup(QWidget *parent = nullptr);
-
-public slots:
- void setReplyContent(const RelatedInfo &related);
-
-protected:
- void paintEvent(QPaintEvent *event) override;
- void mousePressEvent(QMouseEvent *event) override;
-
-signals:
- void userSelected(const QString &user);
- void clicked(const QString &text);
- void cancel();
-
-private:
- QHBoxLayout *topLayout_;
- QVBoxLayout *mainLayout_;
- QHBoxLayout *buttonLayout_;
-
- UserItem *userItem_;
- FlatButton *closeBtn_;
- TextLabel *msgLabel_;
- QLabel *eventLabel_;
-
- int buttonSize_;
-};
diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp
index 84dd9885..d54677f7 100644
--- a/src/timeline/TimelineModel.cpp
+++ b/src/timeline/TimelineModel.cpp
@@ -800,6 +800,16 @@ TimelineModel::decryptEvent(const mtx::events::EncryptedEvent<mtx::events::msg::
void
TimelineModel::replyAction(QString id)
{
+ setReply(id);
+ ChatPage::instance()->focusMessageInput();
+}
+
+RelatedInfo
+TimelineModel::relatedInfo(QString id)
+{
+ if (!events.contains(id))
+ return {};
+
auto event = events.value(id);
if (auto e =
std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(&event)) {
@@ -815,10 +825,9 @@ TimelineModel::replyAction(QString id)
related.quoted_formatted_body = mtx::accessors::formattedBodyWithFallback(event);
related.quoted_formatted_body.remove(QRegularExpression(
"<mx-reply>.*</mx-reply>", QRegularExpression::DotMatchesEverythingOption));
- nhlog::ui()->debug("after replacement: {}", related.quoted_body.toStdString());
related.room = room_id_;
- ChatPage::instance()->messageReply(related);
+ return related;
}
void
diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h
index 02f5527a..0b181583 100644
--- a/src/timeline/TimelineModel.h
+++ b/src/timeline/TimelineModel.h
@@ -18,6 +18,7 @@ struct Timeline;
struct Messages;
struct ClaimKeys;
}
+struct RelatedInfo;
namespace qml_mtx_events {
Q_NAMESPACE
@@ -124,6 +125,7 @@ class TimelineModel : public QAbstractListModel
int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
Q_PROPERTY(std::vector<QString> typingUsers READ typingUsers WRITE updateTypingUsers NOTIFY
typingUsersChanged)
+ Q_PROPERTY(QString reply READ reply WRITE setReply NOTIFY replyChanged RESET resetReply)
public:
explicit TimelineModel(TimelineViewManager *manager,
@@ -191,6 +193,7 @@ public:
void addEvents(const mtx::responses::Timeline &events);
template<class T>
void sendMessage(const T &msg);
+ RelatedInfo relatedInfo(QString id);
public slots:
void setCurrentIndex(int index);
@@ -206,6 +209,22 @@ public slots:
}
std::vector<QString> typingUsers() const { return typingUsers_; }
+ QString reply() const { return reply_; }
+ void setReply(QString newReply)
+ {
+ if (reply_ != newReply) {
+ reply_ = newReply;
+ emit replyChanged(reply_);
+ }
+ }
+ void resetReply()
+ {
+ if (!reply_.isEmpty()) {
+ reply_ = "";
+ emit replyChanged(reply_);
+ }
+ }
+
private slots:
// Add old events at the top of the timeline.
void addBackwardsEvents(const mtx::responses::Messages &msgs);
@@ -225,6 +244,7 @@ signals:
void newEncryptedImage(mtx::crypto::EncryptedFile encryptionInfo);
void eventFetched(QString requestingEvent, mtx::events::collections::TimelineEvents event);
void typingUsersChanged(std::vector<QString> users);
+ void replyChanged(QString reply);
private:
DecryptionResult decryptEvent(
@@ -254,6 +274,7 @@ private:
bool isProcessingPending = false;
QString currentId;
+ QString reply_;
std::vector<QString> typingUsers_;
TimelineViewManager *manager_;
diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp
index 794c13aa..0a339825 100644
--- a/src/timeline/TimelineViewManager.cpp
+++ b/src/timeline/TimelineViewManager.cpp
@@ -188,8 +188,11 @@ TimelineViewManager::initWithMessages(const std::map<QString, mtx::responses::Ti
}
void
-TimelineViewManager::queueTextMessage(const QString &msg, const std::optional<RelatedInfo> &related)
+TimelineViewManager::queueTextMessage(const QString &msg)
{
+ if (!timeline_)
+ return;
+
mtx::events::msg::Text text = {};
text.body = msg.trimmed().toStdString();
@@ -203,13 +206,15 @@ TimelineViewManager::queueTextMessage(const QString &msg, const std::optional<Re
text.format = "org.matrix.custom.html";
}
- if (related) {
+ if (!timeline_->reply().isEmpty()) {
+ auto related = timeline_->relatedInfo(timeline_->reply());
+
QString body;
bool firstLine = true;
- for (const auto &line : related->quoted_body.split("\n")) {
+ for (const auto &line : related.quoted_body.split("\n")) {
if (firstLine) {
firstLine = false;
- body = QString("> <%1> %2\n").arg(related->quoted_user).arg(line);
+ body = QString("> <%1> %2\n").arg(related.quoted_user).arg(line);
} else {
body = QString("%1\n> %2\n").arg(body).arg(line);
}
@@ -221,17 +226,17 @@ TimelineViewManager::queueTextMessage(const QString &msg, const std::optional<Re
text.format = "org.matrix.custom.html";
if (settings->isMarkdownEnabled())
text.formatted_body =
- utils::getFormattedQuoteBody(*related, utils::markdownToHtml(msg))
+ utils::getFormattedQuoteBody(related, utils::markdownToHtml(msg))
.toStdString();
else
text.formatted_body =
- utils::getFormattedQuoteBody(*related, msg.toHtmlEscaped()).toStdString();
+ utils::getFormattedQuoteBody(related, msg.toHtmlEscaped()).toStdString();
- text.relates_to.in_reply_to.event_id = related->related_event;
+ text.relates_to.in_reply_to.event_id = related.related_event;
+ timeline_->resetReply();
}
- if (timeline_)
- timeline_->sendMessage(text);
+ timeline_->sendMessage(text);
}
void
@@ -247,6 +252,11 @@ TimelineViewManager::queueEmoteMessage(const QString &msg)
emote.format = "org.matrix.custom.html";
}
+ if (!timeline_->reply().isEmpty()) {
+ emote.relates_to.in_reply_to.event_id = timeline_->reply().toStdString();
+ timeline_->resetReply();
+ }
+
if (timeline_)
timeline_->sendMessage(emote);
}
@@ -259,8 +269,7 @@ TimelineViewManager::queueImageMessage(const QString &roomid,
const QString &mime,
uint64_t dsize,
const QSize &dimensions,
- const QString &blurhash,
- const std::optional<RelatedInfo> &related)
+ const QString &blurhash)
{
mtx::events::msg::Image image;
image.info.mimetype = mime.toStdString();
@@ -272,10 +281,13 @@ TimelineViewManager::queueImageMessage(const QString &roomid,
image.info.w = dimensions.width();
image.file = file;
- if (related)
- image.relates_to.in_reply_to.event_id = related->related_event;
+ auto model = models.value(roomid);
+ if (!model-