From b9dde957a83c7198e9c5941c657e785577d11ed5 Mon Sep 17 00:00:00 2001 From: Joseph Donofry Date: Sun, 9 Jun 2019 19:03:18 -0400 Subject: [PATCH] Add initial support for rich replies to nheko --- deps/CMakeLists.txt | 4 ++-- src/ChatPage.cpp | 5 +++++ src/ChatPage.h | 2 +- src/TextInputWidget.cpp | 18 +++++++++++++++--- src/TextInputWidget.h | 11 ++++++++++- src/timeline/TimelineItem.cpp | 2 +- src/timeline/TimelineView.cpp | 15 ++++++++++++++- src/timeline/TimelineView.h | 2 ++ src/timeline/TimelineViewManager.cpp | 13 +++++++++++++ src/timeline/TimelineViewManager.h | 2 ++ 10 files changed, 65 insertions(+), 9 deletions(-) diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index 9eb1d840..1a45112e 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -46,10 +46,10 @@ set(BOOST_SHA256 set( MTXCLIENT_URL - https://github.com/Nheko-Reborn/mtxclient/archive/1c31a8072f09a454b9239e11740473c8a7dbee39.tar.gz + https://github.com/Nheko-Reborn/mtxclient/archive/8c6e9ba8fc18ed9dd69d014eebd1ebff08701d6d.tar.gz ) set(MTXCLIENT_HASH - 5cdcd7d6feaefa8df8966bd053ea2d1181eb7e6c0f3b548b2f98f00400e2760e) + b31ec18b9d7d74db1a17b930bfa570fa1cede56cc49b43948b7d86c396f2f3d3) set( TWEENY_URL https://github.com/mobius3/tweeny/archive/b94ce07cfb02a0eb8ac8aaf66137dabdaea857cf.tar.gz diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp index dd23fb80..5b838259 100644 --- a/src/ChatPage.cpp +++ b/src/ChatPage.cpp @@ -264,6 +264,11 @@ ChatPage::ChatPage(QSharedPointer userSettings, QWidget *parent) view_manager_, SLOT(queueTextMessage(const QString &))); + connect(text_input_, + SIGNAL(sendReplyMessage(const QString &, const QString &)), + view_manager_, + SLOT(queueReplyMessage(const QString &, const QString &))); + connect(text_input_, SIGNAL(sendEmoteMessage(const QString &)), view_manager_, diff --git a/src/ChatPage.h b/src/ChatPage.h index 7d3b3273..09e7a2c6 100644 --- a/src/ChatPage.h +++ b/src/ChatPage.h @@ -83,7 +83,7 @@ signals: void connectionLost(); void connectionRestored(); - void messageReply(const QString &username, const QString &msg); + void messageReply(const QString &username, const QString &msg, const QString &related_event); void notificationsRetrieved(const mtx::responses::Notifications &); diff --git a/src/TextInputWidget.cpp b/src/TextInputWidget.cpp index 934f2b2c..340c6f7c 100644 --- a/src/TextInputWidget.cpp +++ b/src/TextInputWidget.cpp @@ -398,14 +398,24 @@ FilteredTextEdit::submit() auto name = text.mid(1, command_end - 1); auto args = text.mid(command_end + 1); if (name.isEmpty() || name == "/") { - message(args); + if (!related_event_.isEmpty()) { + reply(args, related_event_); + } else { + message(args); + } } else { command(name, args); } } else { - message(std::move(text)); + if (!related_event_.isEmpty()) { + reply(std::move(text), std::move(related_event_)); + } else { + message(std::move(text)); + } } + related_event_ = ""; + clear(); } @@ -536,6 +546,7 @@ 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::image, this, &TextInputWidget::uploadImage); connect(input_, &FilteredTextEdit::audio, this, &TextInputWidget::uploadAudio); @@ -653,7 +664,7 @@ TextInputWidget::paintEvent(QPaintEvent *) } void -TextInputWidget::addReply(const QString &username, const QString &msg) +TextInputWidget::addReply(const QString &username, const QString &msg, const QString &replied_event) { input_->setText(QString("> %1: %2\n\n").arg(username).arg(msg)); input_->setFocus(); @@ -661,4 +672,5 @@ TextInputWidget::addReply(const QString &username, const QString &msg) auto cursor = input_->textCursor(); cursor.movePosition(QTextCursor::End); input_->setTextCursor(cursor); + input_->setRelatedEvent(replied_event); } diff --git a/src/TextInputWidget.h b/src/TextInputWidget.h index 8f634f6b..a12183d8 100644 --- a/src/TextInputWidget.h +++ b/src/TextInputWidget.h @@ -54,6 +54,7 @@ public: QSize minimumSizeHint() const override; void submit(); + void setRelatedEvent(const QString &event) { related_event_ = event; } signals: void heightChanged(int height); @@ -61,6 +62,7 @@ signals: void stoppedTyping(); void startedUpload(); void message(QString); + void reply(QString, QString); void command(QString name, QString args); void image(QSharedPointer data, const QString &filename); void audio(QSharedPointer data, const QString &filename); @@ -94,6 +96,9 @@ private: SuggestionsPopup popup_; + // Used for replies + QString related_event_; + enum class AnchorType { Tab = 0, @@ -158,13 +163,14 @@ public slots: void openFileSelection(); void hideUploadSpinner(); void focusLineEdit() { input_->setFocus(); } - void addReply(const QString &username, const QString &msg); + void addReply(const QString &username, const QString &msg, const QString &related_event); private slots: void addSelectedEmoji(const QString &emoji); signals: void sendTextMessage(QString msg); + void sendReplyMessage(QString msg, QString event_id); void sendEmoteMessage(QString msg); void heightChanged(int height); @@ -189,6 +195,9 @@ private: QHBoxLayout *topLayout_; FilteredTextEdit *input_; + // Used for replies + QString related_event_; + LoadingIndicator *spinner_; FlatButton *sendFileBtn_; diff --git a/src/timeline/TimelineItem.cpp b/src/timeline/TimelineItem.cpp index faae1da3..dd09ec78 100644 --- a/src/timeline/TimelineItem.cpp +++ b/src/timeline/TimelineItem.cpp @@ -875,7 +875,7 @@ TimelineItem::replyAction() return; emit ChatPage::instance()->messageReply( - Cache::displayName(room_id_, descriptionMsg_.userid), body_->toPlainText()); + Cache::displayName(room_id_, descriptionMsg_.userid), body_->toPlainText(), eventId()); } void diff --git a/src/timeline/TimelineView.cpp b/src/timeline/TimelineView.cpp index 2b4f979b..ee7021d8 100644 --- a/src/timeline/TimelineView.cpp +++ b/src/timeline/TimelineView.cpp @@ -690,7 +690,7 @@ TimelineView::updatePendingMessage(const std::string &txn_id, const QString &eve } void -TimelineView::addUserMessage(mtx::events::MessageType ty, const QString &body) +TimelineView::addUserMessage(mtx::events::MessageType ty, const QString &body, const QString &related_event) { auto with_sender = (lastSender_ != local_user_) || isDateDifference(lastMsgTimestamp_); @@ -702,6 +702,9 @@ TimelineView::addUserMessage(mtx::events::MessageType ty, const QString &body) message.txn_id = http::client()->generate_txn_id(); message.body = body; message.widget = view_item; + if (!related_event.isEmpty()) { + message.related_event = related_event.toStdString(); + } try { message.is_encrypted = cache::client()->isRoomEncrypted(room_id_.toStdString()); @@ -722,6 +725,12 @@ TimelineView::addUserMessage(mtx::events::MessageType ty, const QString &body) handleNewUserMessage(message); } +void +TimelineView::addUserMessage(mtx::events::MessageType ty, const QString &body) +{ + addUserMessage(ty, body, ""); +} + void TimelineView::handleNewUserMessage(PendingMessage msg) { @@ -1267,6 +1276,10 @@ toRoomMessage(const PendingMessage &m) if (html != m.body.trimmed().toHtmlEscaped()) text.formatted_body = html.toStdString(); + if (!m.related_event.empty()) { + text.relates_to.in_reply_to.event_id = m.related_event; + } + return text; } diff --git a/src/timeline/TimelineView.h b/src/timeline/TimelineView.h index b0909b44..450b5dfa 100644 --- a/src/timeline/TimelineView.h +++ b/src/timeline/TimelineView.h @@ -63,6 +63,7 @@ struct PendingMessage { mtx::events::MessageType ty; std::string txn_id; + std::string related_event; QString body; QString filename; QString mime; @@ -120,6 +121,7 @@ public: // Add new events at the end of the timeline. void addEvents(const mtx::responses::Timeline &timeline); + void addUserMessage(mtx::events::MessageType ty, const QString &body, const QString &related_event); void addUserMessage(mtx::events::MessageType ty, const QString &msg); template diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index feab46a3..10c2d747 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -78,6 +78,19 @@ TimelineViewManager::queueEmoteMessage(const QString &msg) view->addUserMessage(mtx::events::MessageType::Emote, msg); } +void +TimelineViewManager::queueReplyMessage(const QString &reply, + const QString &related_event) +{ + if (active_room_.isEmpty()) + return; + + auto room_id = active_room_; + auto view = views_[room_id]; + + view->addUserMessage(mtx::events::MessageType::Text, reply, related_event); +} + void TimelineViewManager::queueImageMessage(const QString &roomid, const QString &filename, diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h index d23345d3..cc981d9e 100644 --- a/src/timeline/TimelineViewManager.h +++ b/src/timeline/TimelineViewManager.h @@ -63,6 +63,8 @@ public slots: void setHistoryView(const QString &room_id); void queueTextMessage(const QString &msg); + void queueReplyMessage(const QString &reply, + const QString &related_event); void queueEmoteMessage(const QString &msg); void queueImageMessage(const QString &roomid, const QString &filename,