Fix reply not closing

fixes #124
master
Nicolas Werner 5 years ago
parent 82ec022f9c
commit dcddea6fb8
  1. 2
      CMakeLists.txt
  2. 6
      resources/qml/TimelineView.qml
  3. 37
      src/ChatPage.cpp
  4. 6
      src/ChatPage.h
  5. 69
      src/TextInputWidget.cpp
  6. 27
      src/TextInputWidget.h
  7. 36
      src/notifications/ManagerLinux.cpp
  8. 1
      src/notifications/ManagerWin.cpp
  9. 103
      src/popups/ReplyPopup.cpp
  10. 44
      src/popups/ReplyPopup.h
  11. 13
      src/timeline/TimelineModel.cpp
  12. 21
      src/timeline/TimelineModel.h
  13. 76
      src/timeline/TimelineViewManager.cpp
  14. 30
      src/timeline/TimelineViewManager.h

@ -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
)

@ -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
}
}
}

@ -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;
}
@ -596,6 +581,12 @@ ChatPage::resetUI()
showUnreadMessageNotification(0);
}
void
ChatPage::focusMessageInput()
{
this->text_input_->focusLineEdit();
}
void
ChatPage::deleteConfigs()
{

@ -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();

@ -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,30 +397,17 @@ 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()
{
@ -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;
}

@ -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);

@ -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;
}
}

@ -67,4 +67,3 @@ void NotificationsManager::notificationClosed(uint, uint) {}
void
NotificationsManager::removeNotification(const QString &roomId, const QString &eventId)
{}

@ -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);
}

@ -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_;
};

@ -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

@ -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_;

@ -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->reply().isEmpty()) {
image.relates_to.in_reply_to.event_id = model->reply().toStdString();
model->resetReply();
}
models.value(roomid)->sendMessage(image);
model->sendMessage(image);
}
void
@ -285,8 +297,7 @@ TimelineViewManager::queueFileMessage(
const std::optional<mtx::crypto::EncryptedFile> &encryptedFile,
const QString &url,
const QString &mime,
uint64_t dsize,
const std::optional<RelatedInfo> &related)
uint64_t dsize)
{
mtx::events::msg::File file;
file.info.mimetype = mime.toStdString();
@ -295,10 +306,13 @@ TimelineViewManager::queueFileMessage(
file.url = url.toStdString();
file.file = encryptedFile;
if (related)
file.relates_to.in_reply_to.event_id = related->related_event;
auto model = models.value(roomid);
if (!model->reply().isEmpty()) {
file.relates_to.in_reply_to.event_id = model->reply().toStdString();
model->resetReply();
}
models.value(roomid)->sendMessage(file);
model->sendMessage(file);
}
void
@ -307,8 +321,7 @@ TimelineViewManager::queueAudioMessage(const QString &roomid,
const std::optional<mtx::crypto::EncryptedFile> &file,
const QString &url,
const QString &mime,
uint64_t dsize,
const std::optional<RelatedInfo> &related)
uint64_t dsize)
{
mtx::events::msg::Audio audio;
audio.info.mimetype = mime.toStdString();
@ -317,10 +330,13 @@ TimelineViewManager::queueAudioMessage(const QString &roomid,
audio.url = url.toStdString();
audio.file = file;
if (related)
audio.relates_to.in_reply_to.event_id = related->related_event;
auto model = models.value(roomid);
if (!model->reply().isEmpty()) {
audio.relates_to.in_reply_to.event_id = model->reply().toStdString();
model->resetReply();
}
models.value(roomid)->sendMessage(audio);
model->sendMessage(audio);
}
void
@ -329,8 +345,7 @@ TimelineViewManager::queueVideoMessage(const QString &roomid,
const std::optional<mtx::crypto::EncryptedFile> &file,
const QString &url,
const QString &mime,
uint64_t dsize,
const std::optional<RelatedInfo> &related)
uint64_t dsize)
{
mtx::events::msg::Video video;
video.info.mimetype = mime.toStdString();
@ -339,8 +354,11 @@ TimelineViewManager::queueVideoMessage(const QString &roomid,
video.url = url.toStdString();
video.file = file;
if (related)
video.relates_to.in_reply_to.event_id = related->related_event;
auto model = models.value(roomid);
if (!model->reply().isEmpty()) {
video.relates_to.in_reply_to.event_id = model->reply().toStdString();
model->resetReply();
}
models.value(roomid)->sendMessage(video);
model->sendMessage(video);
}

@ -26,8 +26,6 @@ class TimelineViewManager : public QObject
TimelineModel *timeline MEMBER timeline_ READ activeTimeline NOTIFY activeTimelineChanged)
Q_PROPERTY(
bool isInitialSync MEMBER isInitialSync_ READ isInitialSync NOTIFY initialSyncChanged)
Q_PROPERTY(QString replyingEvent READ getReplyingEvent WRITE updateReplyingEvent NOTIFY
replyingEventChanged)
public:
TimelineViewManager(QSharedPointer<UserSettings> userSettings, QWidget *parent = nullptr);
@ -52,26 +50,13 @@ signals:
void replyClosed();
public slots:
void updateReplyingEvent(const QString &replyingEvent)
{
if (this->replyingEvent_ != replyingEvent) {
this->replyingEvent_ = replyingEvent;
emit replyingEventChanged(replyingEvent_);
}
}
void closeReply()
{
this->updateReplyingEvent(nullptr);
emit replyClosed();
}
QString getReplyingEvent() const { return replyingEvent_; }
void updateReadReceipts(const QString &room_id, const std::vector<QString> &event_ids);
void initWithMessages(const std::map<QString, mtx::responses::Timeline> &msgs);
void setHistoryView(const QString &room_id);
void updateColorPalette();
void queueTextMessage(const QString &msg, const std::optional<RelatedInfo> &related);
void queueTextMessage(const QString &msg);
void queueEmoteMessage(const QString &msg);
void queueImageMessage(const QString &roomid,
const QString &filename,
@ -80,29 +65,25 @@ public slots:
const QString &mime,
uint64_t dsize,
const QSize &dimensions,
const QString &blurhash,
const std::optional<RelatedInfo> &related);
const QString &blurhash);
void queueFileMessage(const QString &roomid,
const QString &filename,
const std::optional<mtx::crypto::EncryptedFile> &file,
const QString &url,
const QString &mime,
uint64_t dsize,
const std::optional<RelatedInfo> &related);
uint64_t dsize);
void queueAudioMessage(const QString &roomid,
const QString &filename,
const std::optional<mtx::crypto::EncryptedFile> &file,
const QString &url,
const QString &mime,
uint64_t dsize,
const std::optional<RelatedInfo> &related);
uint64_t dsize);
void queueVideoMessage(const QString &roomid,
const QString &filename,
const std::optional<mtx::crypto::EncryptedFile> &file,
const QString &url,
const QString &mime,
uint64_t dsize,
const std::optional<RelatedInfo> &related);
uint64_t dsize);
private:
#ifdef USE_QUICK_VIEW
@ -119,7 +100,6 @@ private:
QHash<QString, QSharedPointer<TimelineModel>> models;
TimelineModel *timeline_ = nullptr;
bool isInitialSync_ = true;
QString replyingEvent_;
QSharedPointer<UserSettings> settings;
QHash<QString, QColor> userColors;

Loading…
Cancel
Save