mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-26 13:08:48 +03:00
Add initial support for rich replies to nheko
This commit is contained in:
parent
0840f47f83
commit
b9dde957a8
10 changed files with 65 additions and 9 deletions
4
deps/CMakeLists.txt
vendored
4
deps/CMakeLists.txt
vendored
|
@ -46,10 +46,10 @@ set(BOOST_SHA256
|
||||||
|
|
||||||
set(
|
set(
|
||||||
MTXCLIENT_URL
|
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
|
set(MTXCLIENT_HASH
|
||||||
5cdcd7d6feaefa8df8966bd053ea2d1181eb7e6c0f3b548b2f98f00400e2760e)
|
b31ec18b9d7d74db1a17b930bfa570fa1cede56cc49b43948b7d86c396f2f3d3)
|
||||||
set(
|
set(
|
||||||
TWEENY_URL
|
TWEENY_URL
|
||||||
https://github.com/mobius3/tweeny/archive/b94ce07cfb02a0eb8ac8aaf66137dabdaea857cf.tar.gz
|
https://github.com/mobius3/tweeny/archive/b94ce07cfb02a0eb8ac8aaf66137dabdaea857cf.tar.gz
|
||||||
|
|
|
@ -264,6 +264,11 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
|
||||||
view_manager_,
|
view_manager_,
|
||||||
SLOT(queueTextMessage(const QString &)));
|
SLOT(queueTextMessage(const QString &)));
|
||||||
|
|
||||||
|
connect(text_input_,
|
||||||
|
SIGNAL(sendReplyMessage(const QString &, const QString &)),
|
||||||
|
view_manager_,
|
||||||
|
SLOT(queueReplyMessage(const QString &, const QString &)));
|
||||||
|
|
||||||
connect(text_input_,
|
connect(text_input_,
|
||||||
SIGNAL(sendEmoteMessage(const QString &)),
|
SIGNAL(sendEmoteMessage(const QString &)),
|
||||||
view_manager_,
|
view_manager_,
|
||||||
|
|
|
@ -83,7 +83,7 @@ signals:
|
||||||
void connectionLost();
|
void connectionLost();
|
||||||
void connectionRestored();
|
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 &);
|
void notificationsRetrieved(const mtx::responses::Notifications &);
|
||||||
|
|
||||||
|
|
|
@ -398,13 +398,23 @@ FilteredTextEdit::submit()
|
||||||
auto name = text.mid(1, command_end - 1);
|
auto name = text.mid(1, command_end - 1);
|
||||||
auto args = text.mid(command_end + 1);
|
auto args = text.mid(command_end + 1);
|
||||||
if (name.isEmpty() || name == "/") {
|
if (name.isEmpty() || name == "/") {
|
||||||
|
if (!related_event_.isEmpty()) {
|
||||||
|
reply(args, related_event_);
|
||||||
|
} else {
|
||||||
message(args);
|
message(args);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
command(name, args);
|
command(name, args);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (!related_event_.isEmpty()) {
|
||||||
|
reply(std::move(text), std::move(related_event_));
|
||||||
} else {
|
} else {
|
||||||
message(std::move(text));
|
message(std::move(text));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
related_event_ = "";
|
||||||
|
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
@ -536,6 +546,7 @@ TextInputWidget::TextInputWidget(QWidget *parent)
|
||||||
connect(sendMessageBtn_, &FlatButton::clicked, input_, &FilteredTextEdit::submit);
|
connect(sendMessageBtn_, &FlatButton::clicked, input_, &FilteredTextEdit::submit);
|
||||||
connect(sendFileBtn_, SIGNAL(clicked()), this, SLOT(openFileSelection()));
|
connect(sendFileBtn_, SIGNAL(clicked()), this, SLOT(openFileSelection()));
|
||||||
connect(input_, &FilteredTextEdit::message, this, &TextInputWidget::sendTextMessage);
|
connect(input_, &FilteredTextEdit::message, this, &TextInputWidget::sendTextMessage);
|
||||||
|
connect(input_, &FilteredTextEdit::reply, this, &TextInputWidget::sendReplyMessage);
|
||||||
connect(input_, &FilteredTextEdit::command, this, &TextInputWidget::command);
|
connect(input_, &FilteredTextEdit::command, this, &TextInputWidget::command);
|
||||||
connect(input_, &FilteredTextEdit::image, this, &TextInputWidget::uploadImage);
|
connect(input_, &FilteredTextEdit::image, this, &TextInputWidget::uploadImage);
|
||||||
connect(input_, &FilteredTextEdit::audio, this, &TextInputWidget::uploadAudio);
|
connect(input_, &FilteredTextEdit::audio, this, &TextInputWidget::uploadAudio);
|
||||||
|
@ -653,7 +664,7 @@ TextInputWidget::paintEvent(QPaintEvent *)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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_->setText(QString("> %1: %2\n\n").arg(username).arg(msg));
|
||||||
input_->setFocus();
|
input_->setFocus();
|
||||||
|
@ -661,4 +672,5 @@ TextInputWidget::addReply(const QString &username, const QString &msg)
|
||||||
auto cursor = input_->textCursor();
|
auto cursor = input_->textCursor();
|
||||||
cursor.movePosition(QTextCursor::End);
|
cursor.movePosition(QTextCursor::End);
|
||||||
input_->setTextCursor(cursor);
|
input_->setTextCursor(cursor);
|
||||||
|
input_->setRelatedEvent(replied_event);
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,7 @@ public:
|
||||||
QSize minimumSizeHint() const override;
|
QSize minimumSizeHint() const override;
|
||||||
|
|
||||||
void submit();
|
void submit();
|
||||||
|
void setRelatedEvent(const QString &event) { related_event_ = event; }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void heightChanged(int height);
|
void heightChanged(int height);
|
||||||
|
@ -61,6 +62,7 @@ signals:
|
||||||
void stoppedTyping();
|
void stoppedTyping();
|
||||||
void startedUpload();
|
void startedUpload();
|
||||||
void message(QString);
|
void message(QString);
|
||||||
|
void reply(QString, QString);
|
||||||
void command(QString name, QString args);
|
void command(QString name, QString args);
|
||||||
void image(QSharedPointer<QIODevice> data, const QString &filename);
|
void image(QSharedPointer<QIODevice> data, const QString &filename);
|
||||||
void audio(QSharedPointer<QIODevice> data, const QString &filename);
|
void audio(QSharedPointer<QIODevice> data, const QString &filename);
|
||||||
|
@ -94,6 +96,9 @@ private:
|
||||||
|
|
||||||
SuggestionsPopup popup_;
|
SuggestionsPopup popup_;
|
||||||
|
|
||||||
|
// Used for replies
|
||||||
|
QString related_event_;
|
||||||
|
|
||||||
enum class AnchorType
|
enum class AnchorType
|
||||||
{
|
{
|
||||||
Tab = 0,
|
Tab = 0,
|
||||||
|
@ -158,13 +163,14 @@ public slots:
|
||||||
void openFileSelection();
|
void openFileSelection();
|
||||||
void hideUploadSpinner();
|
void hideUploadSpinner();
|
||||||
void focusLineEdit() { input_->setFocus(); }
|
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:
|
private slots:
|
||||||
void addSelectedEmoji(const QString &emoji);
|
void addSelectedEmoji(const QString &emoji);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void sendTextMessage(QString msg);
|
void sendTextMessage(QString msg);
|
||||||
|
void sendReplyMessage(QString msg, QString event_id);
|
||||||
void sendEmoteMessage(QString msg);
|
void sendEmoteMessage(QString msg);
|
||||||
void heightChanged(int height);
|
void heightChanged(int height);
|
||||||
|
|
||||||
|
@ -189,6 +195,9 @@ private:
|
||||||
QHBoxLayout *topLayout_;
|
QHBoxLayout *topLayout_;
|
||||||
FilteredTextEdit *input_;
|
FilteredTextEdit *input_;
|
||||||
|
|
||||||
|
// Used for replies
|
||||||
|
QString related_event_;
|
||||||
|
|
||||||
LoadingIndicator *spinner_;
|
LoadingIndicator *spinner_;
|
||||||
|
|
||||||
FlatButton *sendFileBtn_;
|
FlatButton *sendFileBtn_;
|
||||||
|
|
|
@ -875,7 +875,7 @@ TimelineItem::replyAction()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
emit ChatPage::instance()->messageReply(
|
emit ChatPage::instance()->messageReply(
|
||||||
Cache::displayName(room_id_, descriptionMsg_.userid), body_->toPlainText());
|
Cache::displayName(room_id_, descriptionMsg_.userid), body_->toPlainText(), eventId());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -690,7 +690,7 @@ TimelineView::updatePendingMessage(const std::string &txn_id, const QString &eve
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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_);
|
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.txn_id = http::client()->generate_txn_id();
|
||||||
message.body = body;
|
message.body = body;
|
||||||
message.widget = view_item;
|
message.widget = view_item;
|
||||||
|
if (!related_event.isEmpty()) {
|
||||||
|
message.related_event = related_event.toStdString();
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
message.is_encrypted = cache::client()->isRoomEncrypted(room_id_.toStdString());
|
message.is_encrypted = cache::client()->isRoomEncrypted(room_id_.toStdString());
|
||||||
|
@ -722,6 +725,12 @@ TimelineView::addUserMessage(mtx::events::MessageType ty, const QString &body)
|
||||||
handleNewUserMessage(message);
|
handleNewUserMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TimelineView::addUserMessage(mtx::events::MessageType ty, const QString &body)
|
||||||
|
{
|
||||||
|
addUserMessage(ty, body, "");
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TimelineView::handleNewUserMessage(PendingMessage msg)
|
TimelineView::handleNewUserMessage(PendingMessage msg)
|
||||||
{
|
{
|
||||||
|
@ -1267,6 +1276,10 @@ toRoomMessage<mtx::events::msg::Text>(const PendingMessage &m)
|
||||||
if (html != m.body.trimmed().toHtmlEscaped())
|
if (html != m.body.trimmed().toHtmlEscaped())
|
||||||
text.formatted_body = html.toStdString();
|
text.formatted_body = html.toStdString();
|
||||||
|
|
||||||
|
if (!m.related_event.empty()) {
|
||||||
|
text.relates_to.in_reply_to.event_id = m.related_event;
|
||||||
|
}
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,7 @@ struct PendingMessage
|
||||||
{
|
{
|
||||||
mtx::events::MessageType ty;
|
mtx::events::MessageType ty;
|
||||||
std::string txn_id;
|
std::string txn_id;
|
||||||
|
std::string related_event;
|
||||||
QString body;
|
QString body;
|
||||||
QString filename;
|
QString filename;
|
||||||
QString mime;
|
QString mime;
|
||||||
|
@ -120,6 +121,7 @@ public:
|
||||||
|
|
||||||
// Add new events at the end of the timeline.
|
// Add new events at the end of the timeline.
|
||||||
void addEvents(const mtx::responses::Timeline &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);
|
void addUserMessage(mtx::events::MessageType ty, const QString &msg);
|
||||||
|
|
||||||
template<class Widget, mtx::events::MessageType MsgType>
|
template<class Widget, mtx::events::MessageType MsgType>
|
||||||
|
|
|
@ -78,6 +78,19 @@ TimelineViewManager::queueEmoteMessage(const QString &msg)
|
||||||
view->addUserMessage(mtx::events::MessageType::Emote, 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
|
void
|
||||||
TimelineViewManager::queueImageMessage(const QString &roomid,
|
TimelineViewManager::queueImageMessage(const QString &roomid,
|
||||||
const QString &filename,
|
const QString &filename,
|
||||||
|
|
|
@ -63,6 +63,8 @@ public slots:
|
||||||
|
|
||||||
void setHistoryView(const QString &room_id);
|
void setHistoryView(const QString &room_id);
|
||||||
void queueTextMessage(const QString &msg);
|
void queueTextMessage(const QString &msg);
|
||||||
|
void queueReplyMessage(const QString &reply,
|
||||||
|
const QString &related_event);
|
||||||
void queueEmoteMessage(const QString &msg);
|
void queueEmoteMessage(const QString &msg);
|
||||||
void queueImageMessage(const QString &roomid,
|
void queueImageMessage(const QString &roomid,
|
||||||
const QString &filename,
|
const QString &filename,
|
||||||
|
|
Loading…
Reference in a new issue