diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp
index ad07efdd..777709be 100644
--- a/src/ChatPage.cpp
+++ b/src/ChatPage.cpp
@@ -56,6 +56,7 @@ constexpr int RETRY_TIMEOUT = 5'000;
constexpr size_t MAX_ONETIME_KEYS = 50;
Q_DECLARE_METATYPE(std::optional<mtx::crypto::EncryptedFile>)
+Q_DECLARE_METATYPE(std::optional<RelatedInfo>)
ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
: QWidget(parent)
@@ -65,8 +66,8 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
{
setObjectName("chatPage");
- qRegisterMetaType<std::optional<mtx::crypto::EncryptedFile>>(
- "std::optional<mtx::crypto::EncryptedFile>");
+ qRegisterMetaType<std::optional<mtx::crypto::EncryptedFile>>();
+ qRegisterMetaType<std::optional<RelatedInfo>>();
topLayout_ = new QHBoxLayout(this);
topLayout_->setSpacing(0);
@@ -287,19 +288,14 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
SLOT(showUnreadMessageNotification(int)));
connect(text_input_,
- SIGNAL(sendTextMessage(const QString &)),
+ &TextInputWidget::sendTextMessage,
view_manager_,
- SLOT(queueTextMessage(const QString &)));
+ &TimelineViewManager::queueTextMessage);
connect(text_input_,
- SIGNAL(sendReplyMessage(const QString &, const RelatedInfo &)),
+ &TextInputWidget::sendEmoteMessage,
view_manager_,
- SLOT(queueReplyMessage(const QString &, const RelatedInfo &)));
-
- connect(text_input_,
- SIGNAL(sendEmoteMessage(const QString &)),
- view_manager_,
- SLOT(queueEmoteMessage(const QString &)));
+ &TimelineViewManager::queueEmoteMessage);
connect(text_input_, &TextInputWidget::sendJoinRoomRequest, this, &ChatPage::joinRoom);
@@ -307,7 +303,10 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
text_input_,
&TextInputWidget::uploadMedia,
this,
- [this](QSharedPointer<QIODevice> dev, QString mimeClass, const QString &fn) {
+ [this](QSharedPointer<QIODevice> dev,
+ QString mimeClass,
+ const QString &fn,
+ const std::optional<RelatedInfo> &related) {
QMimeDatabase db;
QMimeType mime = db.mimeTypeForData(dev.data());
@@ -341,7 +340,8 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
mimeClass,
mime = mime.name(),
size = payload.size(),
- dimensions](const mtx::responses::ContentURI &res, mtx::http::RequestErr err) {
+ dimensions,
+ related](const mtx::responses::ContentURI &res, mtx::http::RequestErr err) {
if (err) {
emit uploadFailed(
tr("Failed to upload media. Please try again."));
@@ -359,7 +359,8 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
mimeClass,
mime,
size,
- dimensions);
+ dimensions,
+ related);
});
});
@@ -367,35 +368,37 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
text_input_->hideUploadSpinner();
emit showNotification(msg);
});
- connect(this,
- &ChatPage::mediaUploaded,
- this,
- [this](QString roomid,
- QString filename,
- std::optional<mtx::crypto::EncryptedFile> encryptedFile,
- QString url,
- QString mimeClass,
- QString mime,
- qint64 dsize,
- QSize dimensions) {
- text_input_->hideUploadSpinner();
+ connect(
+ this,
+ &ChatPage::mediaUploaded,
+ this,
+ [this](QString roomid,
+ QString filename,
+ std::optional<mtx::crypto::EncryptedFile> encryptedFile,
+ QString url,
+ QString mimeClass,
+ QString mime,
+ qint64 dsize,
+ QSize dimensions,
+ const std::optional<RelatedInfo> &related) {
+ text_input_->hideUploadSpinner();
- if (encryptedFile)
- encryptedFile->url = url.toStdString();
+ if (encryptedFile)
+ encryptedFile->url = url.toStdString();
- if (mimeClass == "image")
- view_manager_->queueImageMessage(
- roomid, filename, encryptedFile, url, mime, dsize, dimensions);
- else if (mimeClass == "audio")
- view_manager_->queueAudioMessage(
- roomid, filename, encryptedFile, url, mime, dsize);
- else if (mimeClass == "video")
- view_manager_->queueVideoMessage(
- roomid, filename, encryptedFile, url, mime, dsize);
- else
- view_manager_->queueFileMessage(
- roomid, filename, encryptedFile, url, mime, dsize);
- });
+ if (mimeClass == "image")
+ view_manager_->queueImageMessage(
+ roomid, filename, encryptedFile, url, mime, dsize, dimensions, related);
+ else if (mimeClass == "audio")
+ view_manager_->queueAudioMessage(
+ roomid, filename, encryptedFile, url, mime, dsize, related);
+ else if (mimeClass == "video")
+ view_manager_->queueVideoMessage(
+ roomid, filename, encryptedFile, url, mime, dsize, related);
+ else
+ view_manager_->queueFileMessage(
+ roomid, filename, encryptedFile, url, mime, dsize, related);
+ });
connect(room_list_, &RoomList::roomAvatarChanged, this, &ChatPage::updateTopBarAvatar);
diff --git a/src/ChatPage.h b/src/ChatPage.h
index 9e88dcc6..e4c0ef16 100644
--- a/src/ChatPage.h
+++ b/src/ChatPage.h
@@ -109,7 +109,8 @@ signals:
const QString &mimeClass,
const QString &mime,
qint64 dsize,
- const QSize &dimensions);
+ const QSize &dimensions,
+ const std::optional<RelatedInfo> &related);
void contentLoaded();
void closing();
diff --git a/src/TextInputWidget.cpp b/src/TextInputWidget.cpp
index b481a57c..b6b51980 100644
--- a/src/TextInputWidget.cpp
+++ b/src/TextInputWidget.cpp
@@ -419,33 +419,25 @@ FilteredTextEdit::submit()
auto name = text.mid(1, command_end - 1);
auto args = text.mid(command_end + 1);
if (name.isEmpty() || name == "/") {
- if (!related_.related_event.empty()) {
- reply(args, related_);
- } else {
- message(args);
- }
+ message(args, related);
} else {
command(name, args);
}
} else {
- if (!related_.related_event.empty()) {
- reply(std::move(text), std::move(related_));
- } else {
- message(std::move(text));
- }
+ message(std::move(text), std::move(related));
}
- related_ = {};
+ related = {};
clear();
}
void
-FilteredTextEdit::showReplyPopup(const RelatedInfo &related)
+FilteredTextEdit::showReplyPopup(const RelatedInfo &related_)
{
QPoint pos = viewport()->mapToGlobal(this->pos());
- replyPopup_.setReplyContent(related);
+ replyPopup_.setReplyContent(related_);
replyPopup_.move(pos.x(), pos.y() - replyPopup_.height() - 10);
replyPopup_.setFixedWidth(this->parentWidget()->width());
replyPopup_.show();
@@ -467,7 +459,9 @@ FilteredTextEdit::uploadData(const QByteArray data,
emit startedUpload();
- emit media(buffer, mediaType, filename);
+ emit media(buffer, mediaType, filename, related);
+ related = {};
+ closeReply();
}
void
@@ -573,7 +567,6 @@ TextInputWidget::TextInputWidget(QWidget *parent)
connect(sendMessageBtn_, &FlatButton::clicked, input_, &FilteredTextEdit::submit);
connect(sendFileBtn_, SIGNAL(clicked()), this, SLOT(openFileSelection()));
connect(input_, &FilteredTextEdit::message, this, &TextInputWidget::sendTextMessage);
- connect(input_, &FilteredTextEdit::reply, this, &TextInputWidget::sendReplyMessage);
connect(input_, &FilteredTextEdit::command, this, &TextInputWidget::command);
connect(input_, &FilteredTextEdit::media, this, &TextInputWidget::uploadMedia);
connect(emojiBtn_,
@@ -609,14 +602,16 @@ void
TextInputWidget::command(QString command, QString args)
{
if (command == "me") {
- sendEmoteMessage(args);
+ sendEmoteMessage(args, input_->related);
} else if (command == "join") {
sendJoinRoomRequest(args);
} else if (command == "shrug") {
- sendTextMessage("¯\\_(ツ)_/¯");
+ sendTextMessage("¯\\_(ツ)_/¯", input_->related);
} else if (command == "fliptable") {
- sendTextMessage("(╯°□°)╯︵ ┻━┻");
+ sendTextMessage("(╯°□°)╯︵ ┻━┻", input_->related);
}
+
+ input_->related = std::nullopt;
}
void
@@ -635,7 +630,9 @@ TextInputWidget::openFileSelection()
QSharedPointer<QFile> file{new QFile{fileName, this}};
- emit uploadMedia(file, format, fileName);
+ emit uploadMedia(file, format, fileName, input_->related);
+ input_->related = {};
+ input_->closeReply();
showUploadSpinner();
}
@@ -691,5 +688,5 @@ TextInputWidget::addReply(const RelatedInfo &related)
auto cursor = input_->textCursor();
cursor.movePosition(QTextCursor::End);
input_->setTextCursor(cursor);
- input_->setRelated(related);
+ input_->related = related;
}
diff --git a/src/TextInputWidget.h b/src/TextInputWidget.h
index d498be72..6641d97c 100644
--- a/src/TextInputWidget.h
+++ b/src/TextInputWidget.h
@@ -20,6 +20,7 @@
#include <deque>
#include <iterator>
#include <map>
+#include <optional>
#include <QApplication>
#include <QDebug>
@@ -52,18 +53,27 @@ public:
QSize minimumSizeHint() const override;
void submit();
- void setRelated(const RelatedInfo &related) { related_ = related; }
- void showReplyPopup(const RelatedInfo &related);
+ 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);
- void reply(QString, const RelatedInfo &);
+ void message(QString, const std::optional<RelatedInfo> &);
void command(QString name, QString args);
- void media(QSharedPointer<QIODevice> data, QString mimeClass, const QString &filename);
+ void media(QSharedPointer<QIODevice> data,
+ QString mimeClass,
+ const QString &filename,
+ const std::optional<RelatedInfo> &related);
//! Trigger the suggestion popup.
void showSuggestions(const QString &query);
@@ -93,9 +103,6 @@ private:
SuggestionsPopup suggestionsPopup_;
ReplyPopup replyPopup_;
- // Used for replies
- RelatedInfo related_;
-
enum class AnchorType
{
Tab = 0,
@@ -107,11 +114,6 @@ private:
int anchorWidth(AnchorType anchor) { return static_cast<int>(anchor); }
void closeSuggestions() { suggestionsPopup_.hide(); }
- void closeReply()
- {
- replyPopup_.hide();
- related_ = {};
- }
void resetAnchor() { atTriggerPosition_ = -1; }
bool isAnchorValid() { return atTriggerPosition_ != -1; }
bool hasAnchor(int pos, AnchorType anchor)
@@ -171,14 +173,14 @@ private slots:
void addSelectedEmoji(const QString &emoji);
signals:
- void sendTextMessage(QString msg);
- void sendReplyMessage(QString msg, const RelatedInfo &related);
- void sendEmoteMessage(QString msg);
+ void sendTextMessage(const QString &msg, const std::optional<RelatedInfo> &related);
+ void sendEmoteMessage(QString msg, const std::optional<RelatedInfo> &related);
void heightChanged(int height);
void uploadMedia(const QSharedPointer<QIODevice> data,
QString mimeClass,
- const QString &filename);
+ const QString &filename,
+ const std::optional<RelatedInfo> &related);
void sendJoinRoomRequest(const QString &room);
@@ -196,9 +198,6 @@ private:
QHBoxLayout *topLayout_;
FilteredTextEdit *input_;
- // Used for replies
- QString related_event_;
-
LoadingIndicator *spinner_;
FlatButton *sendFileBtn_;
diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp
index 8cb204a6..cd2b4a7b 100644
--- a/src/timeline/TimelineViewManager.cpp
+++ b/src/timeline/TimelineViewManager.cpp
@@ -170,38 +170,30 @@ TimelineViewManager::initWithMessages(const std::map<QString, mtx::responses::Ti
}
void
-TimelineViewManager::queueTextMessage(const QString &msg)
+TimelineViewManager::queueTextMessage(const QString &msg, const std::optional<RelatedInfo> &related)
{
mtx::events::msg::Text text = {};
text.body = msg.trimmed().toStdString();
text.format = "org.matrix.custom.html";
text.formatted_body = utils::markdownToHtml(msg).toStdString();
- if (timeline_)
- timeline_->sendMessage(text);
-}
-
-void
-TimelineViewManager::queueReplyMessage(const QString &reply, const RelatedInfo &related)
-{
- mtx::events::msg::Text text = {};
-
- QString body;
- bool firstLine = true;
- for (const auto &line : related.quoted_body.split("\n")) {
- if (firstLine) {
- firstLine = false;
- body = QString("> <%1> %2\n").arg(related.quoted_user).arg(line);
- } else {
- body = QString("%1\n> %2\n").arg(body).arg(line);
+ if (related) {
+ QString body;
+ bool firstLine = true;
+ for (const auto &line : related->quoted_body.split("\n")) {
+ if (firstLine) {
+ firstLine = false;
+ body = QString("> <%1> %2\n").arg(related->quoted_user).arg(line);
+ } else {
+ body = QString("%1\n> %2\n").arg(body).arg(line);
+ }
}
- }
- text.body = QString("%1\n%2").arg(body).arg(reply).toStdString();
- text.format = "org.matrix.custom.html";
- text.formatted_body =
- utils::getFormattedQuoteBody(related, utils::markdownToHtml(reply)).toStdString();
- text.relates_to.in_reply_to.event_id = related.related_event;
+ text.body = QString("%1\n%2").arg(body).arg(msg).toStdString();
+ text.formatted_body =
+ utils::getFormattedQuoteBody(*related, utils::markdownToHtml(msg)).toStdString();
+ text.relates_to.in_reply_to.event_id = related->related_event;
+ }
if (timeline_)
timeline_->sendMessage(text);
@@ -229,7 +221,8 @@ TimelineViewManager::queueImageMessage(const QString &roomid,
const QString &url,
const QString &mime,
uint64_t dsize,
- const QSize &dimensions)
+ const QSize &dimensions,
+ const std::optional<RelatedInfo> &related)
{
mtx::events::msg::Image image;
image.info.mimetype = mime.toStdString();
@@ -239,6 +232,10 @@ TimelineViewManager::queueImageMessage(const QString &roomid,
image.info.h = dimensions.height();
image.info.w = dimensions.width();
image.file = file;
+
+ if (related)
+ image.relates_to.in_reply_to.event_id = related->related_event;
+
models.value(roomid)->sendMessage(image);
}
@@ -249,7 +246,8 @@ TimelineViewManager::queueFileMessage(
const std::optional<mtx::crypto::EncryptedFile> &encryptedFile,
const QString &url,
const QString &mime,
- uint64_t dsize)
+ uint64_t dsize,
+ const std::optional<RelatedInfo> &related)
{
mtx::events::msg::File file;
file.info.mimetype = mime.toStdString();
@@ -257,6 +255,10 @@ TimelineViewManager::queueFileMessage(
file.body = filename.toStdString();
file.url = url.toStdString();
file.file = encryptedFile;
+
+ if (related)
+ file.relates_to.in_reply_to.event_id = related->related_event;
+
models.value(roomid)->sendMessage(file);
}
@@ -266,7 +268,8 @@ TimelineViewManager::queueAudioMessage(const QString &roomid,
const std::optional<mtx::crypto::EncryptedFile> &file,
const QString &url,
const QString &mime,
- uint64_t dsize)
+ uint64_t dsize,
+ const std::optional<RelatedInfo> &related)
{
mtx::events::msg::Audio audio;
audio.info.mimetype = mime.toStdString();
@@ -274,6 +277,10 @@ TimelineViewManager::queueAudioMessage(const QString &roomid,
audio.body = filename.toStdString();
audio.url = url.toStdString();
audio.file = file;
+
+ if (related)
+ audio.relates_to.in_reply_to.event_id = related->related_event;
+
models.value(roomid)->sendMessage(audio);
}
@@ -283,7 +290,8 @@ TimelineViewManager::queueVideoMessage(const QString &roomid,
const std::optional<mtx::crypto::EncryptedFile> &file,
const QString &url,
const QString &mime,
- uint64_t dsize)
+ uint64_t dsize,
+ const std::optional<RelatedInfo> &related)
{
mtx::events::msg::Video video;
video.info.mimetype = mime.toStdString();
@@ -291,5 +299,9 @@ TimelineViewManager::queueVideoMessage(const QString &roomid,
video.body = filename.toStdString();
video.url = url.toStdString();
video.file = file;
+
+ if (related)
+ video.relates_to.in_reply_to.event_id = related->related_event;
+
models.value(roomid)->sendMessage(video);
}
diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h
index 587aa14e..63075649 100644
--- a/src/timeline/TimelineViewManager.h
+++ b/src/timeline/TimelineViewManager.h
@@ -51,8 +51,7 @@ public slots:
void setHistoryView(const QString &room_id);
void updateColorPalette();
- void queueTextMessage(const QString &msg);
- void queueReplyMessage(const QString &reply, const RelatedInfo &related);
+ void queueTextMessage(const QString &msg, const std::optional<RelatedInfo> &related);
void queueEmoteMessage(const QString &msg);
void queueImageMessage(const QString &roomid,
const QString &filename,
@@ -60,25 +59,29 @@ public slots:
const QString &url,
const QString &mime,
uint64_t dsize,
- const QSize &dimensions);
+ const QSize &dimensions,
+ const std::optional<RelatedInfo> &related);
void queueFileMessage(const QString &roomid,
const QString &filename,
const std::optional<mtx::crypto::EncryptedFile> &file,
const QString &url,
const QString &mime,
- uint64_t dsize);
+ uint64_t dsize,
+ const std::optional<RelatedInfo> &related);
void queueAudioMessage(const QString &roomid,
const QString &filename,
const std::optional<mtx::crypto::EncryptedFile> &file,
const QString &url,
const QString &mime,
- uint64_t dsize);
+ uint64_t dsize,
+ const std::optional<RelatedInfo> &related);
void queueVideoMessage(const QString &roomid,
const QString &filename,
const std::optional<mtx::crypto::EncryptedFile> &file,
const QString &url,
const QString &mime,
- uint64_t dsize);
+ uint64_t dsize,
+ const std::optional<RelatedInfo> &related);
private:
#ifdef USE_QUICK_VIEW
|