From 603ff33ea68b7c9e06578adf96fb6d824aa465df Mon Sep 17 00:00:00 2001 From: targetakhil Date: Sun, 11 Apr 2021 20:01:49 +0530 Subject: [PATCH 01/10] added basic forwarding --- resources/qml/TimelineView.qml | 81 +++++++++++++++++++++ src/timeline/InputBar.h | 15 ++-- src/timeline/TimelineModel.cpp | 10 +++ src/timeline/TimelineModel.h | 4 ++ src/timeline/TimelineViewManager.cpp | 103 ++++++++++++++++++++++++++- src/timeline/TimelineViewManager.h | 4 ++ 6 files changed, 208 insertions(+), 9 deletions(-) diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index 481561d2..2b6a8f26 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -79,6 +79,78 @@ Page { } + Component { + id: forwardCompleter + + Popup { + id: forwardMessagePopup + x: 400 + y: 400 + + property var mid + + onOpened: { + completerPopup.open(); + roomTextInput.forceActiveFocus(); + } + + background: Rectangle { + border.color: "#444" + } + + function setMessageEventId(mid_in) { + mid = mid_in; + } + + MatrixTextField { + id: roomTextInput + + width: 100 + + color: colors.text + onTextEdited: { + completerPopup.completer.searchString = text; + } + Keys.onPressed: { + if (event.key == Qt.Key_Up && completerPopup.opened) { + event.accepted = true; + completerPopup.up(); + } else if (event.key == Qt.Key_Down && completerPopup.opened) { + event.accepted = true; + completerPopup.down(); + } else if (event.matches(StandardKey.InsertParagraphSeparator)) { + completerPopup.finishCompletion(); + event.accepted = true; + } + } + } + + Completer { + id: completerPopup + + y: 50 + width: 100 + completerName: "room" + avatarHeight: 24 + avatarWidth: 24 + bottomToTop: false + closePolicy: Popup.NoAutoClose + } + + Connections { + onCompletionSelected: { + TimelineManager.timeline.forwardMessage(messageContextMenu.eventId, id); + forwardMessagePopup.close(); + } + onCountChanged: { + if (completerPopup.count > 0 && (completerPopup.currentIndex < 0 || completerPopup.currentIndex >= completerPopup.count)) + completerPopup.currentIndex = 0; + } + target: completerPopup + } + } + } + Shortcut { sequence: "Ctrl+K" onActivated: { @@ -133,6 +205,15 @@ Page { onTriggered: TimelineManager.timeline.readReceiptsAction(messageContextMenu.eventId) } + Platform.MenuItem { + text: qsTr("Forward") + onTriggered: { + var forwardMess = forwardCompleter.createObject(timelineRoot); + forwardMess.open(); + forwardMess.setMessageEventId(messageContextMenu.eventId) + } + } + Platform.MenuItem { text: qsTr("Mark as read") } diff --git a/src/timeline/InputBar.h b/src/timeline/InputBar.h index 9db16bae..d4fcfacf 100644 --- a/src/timeline/InputBar.h +++ b/src/timeline/InputBar.h @@ -41,6 +41,14 @@ public: connect(&typingTimeout_, &QTimer::timeout, this, &InputBar::stopTyping); } + void image(const QString &filename, + const std::optional &file, + const QString &url, + const QString &mime, + uint64_t dsize, + const QSize &dimensions, + const QString &blurhash); + public slots: QString text() const; QString previousText(); @@ -70,13 +78,6 @@ private: void emote(QString body, bool rainbowify); void notice(QString body, bool rainbowify); void command(QString name, QString args); - void image(const QString &filename, - const std::optional &file, - const QString &url, - const QString &mime, - uint64_t dsize, - const QSize &dimensions, - const QString &blurhash); void file(const QString &filename, const std::optional &encryptedFile, const QString &url, diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index 8e96cb3e..e3efe5ad 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -822,6 +822,16 @@ TimelineModel::viewRawMessage(QString id) const Q_UNUSED(dialog); } +void +TimelineModel::forwardMessage(QString eventId, QString roomId) +{ + auto e = events.get(eventId.toStdString(), ""); + if (!e) + return; + + emit forwardToRoom(e, roomId, cache::isRoomEncrypted(room_id_.toStdString())); +} + void TimelineModel::viewDecryptedRawMessage(QString id) const { diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h index 06da95c6..3e6f6f15 100644 --- a/src/timeline/TimelineModel.h +++ b/src/timeline/TimelineModel.h @@ -219,6 +219,7 @@ public: Q_INVOKABLE QString formatPowerLevelEvent(QString id); Q_INVOKABLE void viewRawMessage(QString id) const; + Q_INVOKABLE void forwardMessage(QString eventId, QString roomId); Q_INVOKABLE void viewDecryptedRawMessage(QString id) const; Q_INVOKABLE void openUserProfile(QString userid, bool global = false); Q_INVOKABLE void openRoomSettings(); @@ -322,6 +323,9 @@ signals: void roomNameChanged(); void roomTopicChanged(); void roomAvatarUrlChanged(); + void forwardToRoom(mtx::events::collections::TimelineEvents *e, + QString roomId, + bool sentFromEncrypted); private: template diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index f15b0b14..ae807f2d 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -4,6 +4,7 @@ #include "TimelineViewManager.h" +#include #include #include #include @@ -25,14 +26,13 @@ #include "RoomsModel.h" #include "UserSettingsPage.h" #include "UsersModel.h" +#include "blurhash.hpp" #include "dialogs/ImageOverlay.h" #include "emoji/EmojiModel.h" #include "emoji/Provider.h" #include "ui/NhekoCursorShape.h" #include "ui/NhekoDropArea.h" -#include //only for debugging - Q_DECLARE_METATYPE(mtx::events::collections::TimelineEvents) Q_DECLARE_METATYPE(std::vector) @@ -332,6 +332,10 @@ TimelineViewManager::addRoom(const QString &room_id) &TimelineModel::newEncryptedImage, imgProvider, &MxcImageProvider::addEncryptionInfo); + connect(newRoom.data(), + &TimelineModel::forwardToRoom, + this, + &TimelineViewManager::forwardMessageToRoom); models.insert(room_id, std::move(newRoom)); } } @@ -614,3 +618,98 @@ TimelineViewManager::focusTimeline() { getWidget()->setFocus(); } + +void +TimelineViewManager::forwardMessageToRoom(mtx::events::collections::TimelineEvents *e, + QString roomId, + bool sentFromEncrypted) +{ + auto elem = *e; + auto room = models.find(roomId); + auto messageType = mtx::accessors::msg_type(elem); + + if (sentFromEncrypted && messageType == mtx::events::MessageType::Image) { + auto body = mtx::accessors::body(elem); + auto mimetype = mtx::accessors::mimetype(elem); + auto imageHeight = mtx::accessors::media_height(elem); + auto imageWidth = mtx::accessors::media_height(elem); + + QString mxcUrl = QString::fromStdString(mtx::accessors::url(elem)); + MxcImageProvider::download( + mxcUrl.remove("mxc://"), + QSize(imageWidth, imageHeight), + [this, roomId, body, mimetype](QString, QSize, QImage image, QString) { + QByteArray data = + QByteArray::fromRawData((const char *)image.bits(), image.byteCount()); + + auto payload = std::string(data.data(), data.size()); + std::optional encryptedFile; + + QSize dimensions; + QString blurhash; + auto mimeClass = QString::fromStdString(mimetype).split("/")[0]; + + dimensions = image.size(); + if (image.height() > 200 && image.width() > 360) + image = image.scaled(360, 200, Qt::KeepAspectRatioByExpanding); + std::vector data_; + for (int y = 0; y < image.height(); y++) { + for (int x = 0; x < image.width(); x++) { + auto p = image.pixel(x, y); + data_.push_back(static_cast(qRed(p))); + data_.push_back(static_cast(qGreen(p))); + data_.push_back(static_cast(qBlue(p))); + } + } + blurhash = QString::fromStdString( + blurhash::encode(data_.data(), image.width(), image.height(), 4, 3)); + + http::client()->upload( + payload, + encryptedFile ? "application/octet-stream" : mimetype, + body, + [this, + roomId, + filename = body, + encryptedFile = std::move(encryptedFile), + mimeClass, + mimetype, + size = payload.size(), + dimensions, + blurhash](const mtx::responses::ContentURI &res, + mtx::http::RequestErr err) mutable { + if (err) { + nhlog::net()->warn("failed to upload media: {} {} ({})", + err->matrix_error.error, + to_string(err->matrix_error.errcode), + static_cast(err->status_code)); + return; + } + + auto url = QString::fromStdString(res.content_uri); + if (encryptedFile) + encryptedFile->url = res.content_uri; + + auto r = models.find(roomId); + r.value()->input()->image(QString::fromStdString(filename), + encryptedFile, + url, + QString::fromStdString(mimetype), + size, + dimensions, + blurhash); + }); + }); + return; + }; + + std::visit( + [room](auto e) { + if constexpr (mtx::events::message_content_to_type == + mtx::events::EventType::RoomMessage) { + room.value()->sendMessageEvent(e.content, + mtx::events::EventType::RoomMessage); + } + }, + elem); +} \ No newline at end of file diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h index 3b405142..40bee990 100644 --- a/src/timeline/TimelineViewManager.h +++ b/src/timeline/TimelineViewManager.h @@ -16,6 +16,7 @@ #include "Cache.h" #include "CallManager.h" +#include "EventAccessors.h" #include "Logging.h" #include "TimelineModel.h" #include "Utils.h" @@ -146,6 +147,9 @@ public slots: void backToRooms() { emit showRoomList(); } QObject *completerFor(QString completerName, QString roomId = ""); + void forwardMessageToRoom(mtx::events::collections::TimelineEvents *e, + QString roomId, + bool sentFromEncrypted); private slots: void openImageOverlayInternal(QString eventId, QImage img); From ce8246238ecd16cd29d2d7af290d6f2f7cab5df3 Mon Sep 17 00:00:00 2001 From: targetakhil Date: Tue, 13 Apr 2021 22:31:49 +0530 Subject: [PATCH 02/10] Fix basic UI for forward completer --- resources/qml/ForwardCompleter.qml | 81 ++++++++++++++++++++++++++++++ resources/qml/TimelineView.qml | 71 ++------------------------ resources/res.qrc | 1 + 3 files changed, 85 insertions(+), 68 deletions(-) create mode 100644 resources/qml/ForwardCompleter.qml diff --git a/resources/qml/ForwardCompleter.qml b/resources/qml/ForwardCompleter.qml new file mode 100644 index 00000000..2b5e6dfe --- /dev/null +++ b/resources/qml/ForwardCompleter.qml @@ -0,0 +1,81 @@ +// SPDX-FileCopyrightText: 2021 Nheko Contributors +// +// SPDX-License-Identifier: GPL-3.0-or-later + +import QtQuick 2.9 +import QtQuick.Controls 2.3 +import im.nheko 1.0 + +Popup { + id: forwardMessagePopup + x: 400 + y: 400 + + width: 200 + + property var mid + + onOpened: { + completerPopup.open(); + roomTextInput.forceActiveFocus(); + } + + onClosed: { + completerPopup.close(); + } + + background: Rectangle { + border.color: "#444" + } + + function setMessageEventId(mid_in) { + mid = mid_in; + } + + MatrixTextField { + id: roomTextInput + + width: forwardMessagePopup.width - forwardMessagePopup.leftPadding * 2 + + color: colors.text + onTextEdited: { + completerPopup.completer.searchString = text; + } + Keys.onPressed: { + if (event.key == Qt.Key_Up && completerPopup.opened) { + event.accepted = true; + completerPopup.up(); + } else if (event.key == Qt.Key_Down && completerPopup.opened) { + event.accepted = true; + completerPopup.down(); + } else if (event.matches(StandardKey.InsertParagraphSeparator)) { + completerPopup.finishCompletion(); + event.accepted = true; + } + } + } + + Completer { + id: completerPopup + + y: roomTextInput.height + roomTextInput.bottomPadding + width: forwardMessagePopup.width - forwardMessagePopup.leftPadding * 2 + completerName: "room" + avatarHeight: 24 + avatarWidth: 24 + bottomToTop: false + closePolicy: Popup.NoAutoClose + } + + Connections { + onCompletionSelected: { + TimelineManager.timeline.forwardMessage(messageContextMenu.eventId, id); + forwardMessagePopup.close(); + } + onCountChanged: { + if (completerPopup.count > 0 && (completerPopup.currentIndex < 0 || completerPopup.currentIndex >= completerPopup.count)) + completerPopup.currentIndex = 0; + } + target: completerPopup + } +} \ No newline at end of file diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index 2b6a8f26..6c75eb74 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -80,74 +80,9 @@ Page { } Component { - id: forwardCompleter + id: forwardCompleterComponent - Popup { - id: forwardMessagePopup - x: 400 - y: 400 - - property var mid - - onOpened: { - completerPopup.open(); - roomTextInput.forceActiveFocus(); - } - - background: Rectangle { - border.color: "#444" - } - - function setMessageEventId(mid_in) { - mid = mid_in; - } - - MatrixTextField { - id: roomTextInput - - width: 100 - - color: colors.text - onTextEdited: { - completerPopup.completer.searchString = text; - } - Keys.onPressed: { - if (event.key == Qt.Key_Up && completerPopup.opened) { - event.accepted = true; - completerPopup.up(); - } else if (event.key == Qt.Key_Down && completerPopup.opened) { - event.accepted = true; - completerPopup.down(); - } else if (event.matches(StandardKey.InsertParagraphSeparator)) { - completerPopup.finishCompletion(); - event.accepted = true; - } - } - } - - Completer { - id: completerPopup - - y: 50 - width: 100 - completerName: "room" - avatarHeight: 24 - avatarWidth: 24 - bottomToTop: false - closePolicy: Popup.NoAutoClose - } - - Connections { - onCompletionSelected: { - TimelineManager.timeline.forwardMessage(messageContextMenu.eventId, id); - forwardMessagePopup.close(); - } - onCountChanged: { - if (completerPopup.count > 0 && (completerPopup.currentIndex < 0 || completerPopup.currentIndex >= completerPopup.count)) - completerPopup.currentIndex = 0; - } - target: completerPopup - } + ForwardCompleter { } } @@ -208,7 +143,7 @@ Page { Platform.MenuItem { text: qsTr("Forward") onTriggered: { - var forwardMess = forwardCompleter.createObject(timelineRoot); + var forwardMess = forwardCompleterComponent.createObject(timelineRoot); forwardMess.open(); forwardMess.setMessageEventId(messageContextMenu.eventId) } diff --git a/resources/res.qrc b/resources/res.qrc index 328f65ca..304493b6 100644 --- a/resources/res.qrc +++ b/resources/res.qrc @@ -142,6 +142,7 @@ qml/TimelineRow.qml qml/TopBar.qml qml/QuickSwitcher.qml + qml/ForwardCompleter.qml qml/TypingIndicator.qml qml/RoomSettings.qml qml/emoji/EmojiButton.qml From 6893e3a8d5cd30fc3e29dbf9160f258cb86b0cf0 Mon Sep 17 00:00:00 2001 From: targetakhil Date: Thu, 15 Apr 2021 21:14:58 +0530 Subject: [PATCH 03/10] show forward menu item only for relevant events, changes to ui --- resources/qml/ForwardCompleter.qml | 24 ++++++++++++++++++------ resources/qml/TimelineView.qml | 3 ++- src/timeline/TimelineModel.cpp | 11 +++++++++++ src/timeline/TimelineModel.h | 1 + 4 files changed, 32 insertions(+), 7 deletions(-) diff --git a/resources/qml/ForwardCompleter.qml b/resources/qml/ForwardCompleter.qml index 2b5e6dfe..22d6e5b0 100644 --- a/resources/qml/ForwardCompleter.qml +++ b/resources/qml/ForwardCompleter.qml @@ -2,16 +2,19 @@ // // SPDX-License-Identifier: GPL-3.0-or-later +import "./delegates/" import QtQuick 2.9 import QtQuick.Controls 2.3 import im.nheko 1.0 -Popup { +Dialog { id: forwardMessagePopup + title: qsTr("Forward Message") x: 400 y: 400 width: 200 + height: replyPreview.height + roomTextInput.height + completerPopup.height + implicitFooterHeight + implicitHeaderHeight property var mid @@ -24,19 +27,27 @@ Popup { completerPopup.close(); } - background: Rectangle { - border.color: "#444" - } - function setMessageEventId(mid_in) { mid = mid_in; } + Reply { + id: replyPreview + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + modelData: TimelineManager.timeline ? TimelineManager.timeline.getDump(mid, "") : { + } + userColor: TimelineManager.userColor(modelData.userId, colors.window) + } + MatrixTextField { id: roomTextInput width: forwardMessagePopup.width - forwardMessagePopup.leftPadding * 2 + anchors.top: replyPreview.bottom + color: colors.text onTextEdited: { completerPopup.completer.searchString = text; @@ -58,7 +69,8 @@ Popup { Completer { id: completerPopup - y: roomTextInput.height + roomTextInput.bottomPadding + y: replyPreview.height + roomTextInput.height + roomTextInput.bottomPadding + width: forwardMessagePopup.width - forwardMessagePopup.leftPadding * 2 completerName: "room" avatarHeight: 24 diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index 6c75eb74..e08c8a1e 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -141,11 +141,12 @@ Page { } Platform.MenuItem { + visible: messageContextMenu.eventType == MtxEvent.ImageMessage || messageContextMenu.eventType == MtxEvent.VideoMessage || messageContextMenu.eventType == MtxEvent.AudioMessage || messageContextMenu.eventType == MtxEvent.FileMessage || messageContextMenu.eventType == MtxEvent.Sticker || messageContextMenu.eventType == MtxEvent.TextMessage|| messageContextMenu.eventType == MtxEvent.LocationMessage || messageContextMenu.eventType == MtxEvent.EmoteMessage || messageContextMenu.eventType == MtxEvent.NoticeMessage text: qsTr("Forward") onTriggered: { var forwardMess = forwardCompleterComponent.createObject(timelineRoot); + forwardMess.setMessageEventId(messageContextMenu.eventId); forwardMess.open(); - forwardMess.setMessageEventId(messageContextMenu.eventId) } } diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index e3efe5ad..0edee4aa 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -832,6 +832,17 @@ TimelineModel::forwardMessage(QString eventId, QString roomId) emit forwardToRoom(e, roomId, cache::isRoomEncrypted(room_id_.toStdString())); } +QString +TimelineModel::messageContent(QString eventId) +{ + auto e = events.get(eventId.toStdString(), ""); + if (!e) + return ""; + + auto content = mtx::accessors::body(*e); + return QString::fromStdString(content); +} + void TimelineModel::viewDecryptedRawMessage(QString id) const { diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h index 3e6f6f15..c17280da 100644 --- a/src/timeline/TimelineModel.h +++ b/src/timeline/TimelineModel.h @@ -220,6 +220,7 @@ public: Q_INVOKABLE void viewRawMessage(QString id) const; Q_INVOKABLE void forwardMessage(QString eventId, QString roomId); + Q_INVOKABLE QString messageContent(QString eventId); Q_INVOKABLE void viewDecryptedRawMessage(QString id) const; Q_INVOKABLE void openUserProfile(QString userid, bool global = false); Q_INVOKABLE void openRoomSettings(); From dff5cfc3ba9592900cef5e612f6832258393d8ec Mon Sep 17 00:00:00 2001 From: targetakhil Date: Thu, 15 Apr 2021 22:21:25 +0530 Subject: [PATCH 04/10] Added overlay and UI changes --- resources/qml/ForwardCompleter.qml | 85 ++++++++++++++++++------------ 1 file changed, 50 insertions(+), 35 deletions(-) diff --git a/resources/qml/ForwardCompleter.qml b/resources/qml/ForwardCompleter.qml index 22d6e5b0..4cc2e09d 100644 --- a/resources/qml/ForwardCompleter.qml +++ b/resources/qml/ForwardCompleter.qml @@ -7,14 +7,18 @@ import QtQuick 2.9 import QtQuick.Controls 2.3 import im.nheko 1.0 -Dialog { +Popup { id: forwardMessagePopup - title: qsTr("Forward Message") + palette: colors + parent: Overlay.overlay + modal: true x: 400 - y: 400 + y: 200 - width: 200 - height: replyPreview.height + roomTextInput.height + completerPopup.height + implicitFooterHeight + implicitHeaderHeight + width: implicitWidth >= 300 ? implicitWidth : 300 + height: implicitHeight + completerPopup.height + padding * 2 + leftPadding: 10 + rightPadding: 10 property var mid @@ -31,37 +35,43 @@ Dialog { mid = mid_in; } - Reply { - id: replyPreview - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - modelData: TimelineManager.timeline ? TimelineManager.timeline.getDump(mid, "") : { + Column { + id: forwardColumn + spacing: 5 + + Label { + id: titleLabel + text: qsTr("Forward Message") + font.bold: true + bottomPadding: 10 } - userColor: TimelineManager.userColor(modelData.userId, colors.window) - } - MatrixTextField { - id: roomTextInput - - width: forwardMessagePopup.width - forwardMessagePopup.leftPadding * 2 - - anchors.top: replyPreview.bottom - - color: colors.text - onTextEdited: { - completerPopup.completer.searchString = text; + Reply { + id: replyPreview + modelData: TimelineManager.timeline ? TimelineManager.timeline.getDump(mid, "") : { + } + userColor: TimelineManager.userColor(modelData.userId, colors.window) } - Keys.onPressed: { - if (event.key == Qt.Key_Up && completerPopup.opened) { - event.accepted = true; - completerPopup.up(); - } else if (event.key == Qt.Key_Down && completerPopup.opened) { - event.accepted = true; - completerPopup.down(); - } else if (event.matches(StandardKey.InsertParagraphSeparator)) { - completerPopup.finishCompletion(); - event.accepted = true; + + MatrixTextField { + id: roomTextInput + + width: forwardMessagePopup.width - forwardMessagePopup.leftPadding * 2 + color: colors.text + onTextEdited: { + completerPopup.completer.searchString = text; + } + Keys.onPressed: { + if (event.key == Qt.Key_Up && completerPopup.opened) { + event.accepted = true; + completerPopup.up(); + } else if (event.key == Qt.Key_Down && completerPopup.opened) { + event.accepted = true; + completerPopup.down(); + } else if (event.matches(StandardKey.InsertParagraphSeparator)) { + completerPopup.finishCompletion(); + event.accepted = true; + } } } } @@ -69,10 +79,11 @@ Dialog { Completer { id: completerPopup - y: replyPreview.height + roomTextInput.height + roomTextInput.bottomPadding - + y: titleLabel.height + replyPreview.height + roomTextInput.height + roomTextInput.bottomPadding + forwardColumn.spacing * 3 width: forwardMessagePopup.width - forwardMessagePopup.leftPadding * 2 completerName: "room" + fullWidth: true + centerRowContent: false avatarHeight: 24 avatarWidth: 24 bottomToTop: false @@ -90,4 +101,8 @@ Dialog { } target: completerPopup } + + Overlay.modal: Rectangle { + color: "#aa1E1E1E" + } } \ No newline at end of file From 99340047026b6980c14f83471dfa63369f8eae96 Mon Sep 17 00:00:00 2001 From: targetakhil Date: Thu, 15 Apr 2021 22:32:37 +0530 Subject: [PATCH 05/10] remove unused function and set position to center of timeline view --- resources/qml/ForwardCompleter.qml | 10 +++++++--- src/timeline/TimelineModel.cpp | 11 ----------- src/timeline/TimelineModel.h | 1 - 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/resources/qml/ForwardCompleter.qml b/resources/qml/ForwardCompleter.qml index 4cc2e09d..f85362c1 100644 --- a/resources/qml/ForwardCompleter.qml +++ b/resources/qml/ForwardCompleter.qml @@ -9,11 +9,12 @@ import im.nheko 1.0 Popup { id: forwardMessagePopup + + x: Math.round(parent.width / 2 - width / 2) + y: Math.round(parent.height / 2 - height / 2) + modal: true palette: colors parent: Overlay.overlay - modal: true - x: 400 - y: 200 width: implicitWidth >= 300 ? implicitWidth : 300 height: implicitHeight + completerPopup.height + padding * 2 @@ -37,10 +38,12 @@ Popup { Column { id: forwardColumn + spacing: 5 Label { id: titleLabel + text: qsTr("Forward Message") font.bold: true bottomPadding: 10 @@ -48,6 +51,7 @@ Popup { Reply { id: replyPreview + modelData: TimelineManager.timeline ? TimelineManager.timeline.getDump(mid, "") : { } userColor: TimelineManager.userColor(modelData.userId, colors.window) diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index 0edee4aa..e3efe5ad 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -832,17 +832,6 @@ TimelineModel::forwardMessage(QString eventId, QString roomId) emit forwardToRoom(e, roomId, cache::isRoomEncrypted(room_id_.toStdString())); } -QString -TimelineModel::messageContent(QString eventId) -{ - auto e = events.get(eventId.toStdString(), ""); - if (!e) - return ""; - - auto content = mtx::accessors::body(*e); - return QString::fromStdString(content); -} - void TimelineModel::viewDecryptedRawMessage(QString id) const { diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h index c17280da..3e6f6f15 100644 --- a/src/timeline/TimelineModel.h +++ b/src/timeline/TimelineModel.h @@ -220,7 +220,6 @@ public: Q_INVOKABLE void viewRawMessage(QString id) const; Q_INVOKABLE void forwardMessage(QString eventId, QString roomId); - Q_INVOKABLE QString messageContent(QString eventId); Q_INVOKABLE void viewDecryptedRawMessage(QString id) const; Q_INVOKABLE void openUserProfile(QString userid, bool global = false); Q_INVOKABLE void openRoomSettings(); From eb13f7c16999143e1d885dc2d9280c95adce3f94 Mon Sep 17 00:00:00 2001 From: targetakhil Date: Sat, 17 Apr 2021 22:28:17 +0530 Subject: [PATCH 06/10] directly upload old file object and reuse old message --- src/timeline/InputBar.h | 15 ++-- src/timeline/TimelineViewManager.cpp | 120 ++++++++++++--------------- src/timeline/TimelineViewManager.h | 45 ++++++++++ 3 files changed, 105 insertions(+), 75 deletions(-) diff --git a/src/timeline/InputBar.h b/src/timeline/InputBar.h index d4fcfacf..9db16bae 100644 --- a/src/timeline/InputBar.h +++ b/src/timeline/InputBar.h @@ -41,14 +41,6 @@ public: connect(&typingTimeout_, &QTimer::timeout, this, &InputBar::stopTyping); } - void image(const QString &filename, - const std::optional &file, - const QString &url, - const QString &mime, - uint64_t dsize, - const QSize &dimensions, - const QString &blurhash); - public slots: QString text() const; QString previousText(); @@ -78,6 +70,13 @@ private: void emote(QString body, bool rainbowify); void notice(QString body, bool rainbowify); void command(QString name, QString args); + void image(const QString &filename, + const std::optional &file, + const QString &url, + const QString &mime, + uint64_t dsize, + const QSize &dimensions, + const QString &blurhash); void file(const QString &filename, const std::optional &encryptedFile, const QString &url, diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index ae807f2d..f71fd42b 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -627,86 +627,72 @@ TimelineViewManager::forwardMessageToRoom(mtx::events::collections::TimelineEven auto elem = *e; auto room = models.find(roomId); auto messageType = mtx::accessors::msg_type(elem); + auto content = mtx::accessors::url(elem); - if (sentFromEncrypted && messageType == mtx::events::MessageType::Image) { - auto body = mtx::accessors::body(elem); - auto mimetype = mtx::accessors::mimetype(elem); - auto imageHeight = mtx::accessors::media_height(elem); - auto imageWidth = mtx::accessors::media_height(elem); + if (sentFromEncrypted) { + std::optional encryptionInfo = + mtx::accessors::file(elem); - QString mxcUrl = QString::fromStdString(mtx::accessors::url(elem)); - MxcImageProvider::download( - mxcUrl.remove("mxc://"), - QSize(imageWidth, imageHeight), - [this, roomId, body, mimetype](QString, QSize, QImage image, QString) { - QByteArray data = - QByteArray::fromRawData((const char *)image.bits(), image.byteCount()); - - auto payload = std::string(data.data(), data.size()); - std::optional encryptedFile; - - QSize dimensions; - QString blurhash; - auto mimeClass = QString::fromStdString(mimetype).split("/")[0]; - - dimensions = image.size(); - if (image.height() > 200 && image.width() > 360) - image = image.scaled(360, 200, Qt::KeepAspectRatioByExpanding); - std::vector data_; - for (int y = 0; y < image.height(); y++) { - for (int x = 0; x < image.width(); x++) { - auto p = image.pixel(x, y); - data_.push_back(static_cast(qRed(p))); - data_.push_back(static_cast(qGreen(p))); - data_.push_back(static_cast(qBlue(p))); - } + http::client()->download( + content, + [this, roomId, e, encryptionInfo](const std::string &res, + const std::string &content_type, + const std::string &originalFilename, + mtx::http::RequestErr err) { + if (err) { + return; } - blurhash = QString::fromStdString( - blurhash::encode(data_.data(), image.width(), image.height(), 4, 3)); - http::client()->upload( - payload, - encryptedFile ? "application/octet-stream" : mimetype, - body, - [this, - roomId, - filename = body, - encryptedFile = std::move(encryptedFile), - mimeClass, - mimetype, - size = payload.size(), - dimensions, - blurhash](const mtx::responses::ContentURI &res, - mtx::http::RequestErr err) mutable { - if (err) { - nhlog::net()->warn("failed to upload media: {} {} ({})", - err->matrix_error.error, - to_string(err->matrix_error.errcode), - static_cast(err->status_code)); - return; - } + assert(encryptionInfo); - auto url = QString::fromStdString(res.content_uri); - if (encryptedFile) - encryptedFile->url = res.content_uri; + auto data = mtx::crypto::to_string( + mtx::crypto::decrypt_file(res, encryptionInfo.value())); - auto r = models.find(roomId); - r.value()->input()->image(QString::fromStdString(filename), - encryptedFile, - url, - QString::fromStdString(mimetype), - size, - dimensions, - blurhash); - }); + http::client()->upload( + data, + content_type, + originalFilename, + [this, roomId, e](const mtx::responses::ContentURI &res, + mtx::http::RequestErr err) mutable { + if (err) { + nhlog::net()->warn("failed to upload media: {} {} ({})", + err->matrix_error.error, + to_string(err->matrix_error.errcode), + static_cast(err->status_code)); + return; + } + + std::visit( + [this, roomId, e, url = res.content_uri](auto ev) { + if constexpr (mtx::events::message_content_to_type< + decltype(ev.content)> == + mtx::events::EventType::RoomMessage) { + if constexpr (messageWithFileAndUrl(ev)) { + ev.content.relations.relations.clear(); + ev.content.file.reset(); + ev.content.url = url; + + auto room = models.find(roomId); + room.value()->sendMessageEvent( + ev.content, + mtx::events::EventType::RoomMessage); + } + } + }, + *e); + }); + + return; }); + return; - }; + } std::visit( [room](auto e) { if constexpr (mtx::events::message_content_to_type == mtx::events::EventType::RoomMessage) { + e.content.relations.relations.clear(); room.value()->sendMessageEvent(e.content, mtx::events::EventType::RoomMessage); } diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h index 40bee990..9d1b4b1d 100644 --- a/src/timeline/TimelineViewManager.h +++ b/src/timeline/TimelineViewManager.h @@ -13,6 +13,7 @@ #include #include #include +#include #include "Cache.h" #include "CallManager.h" @@ -31,6 +32,33 @@ class UserSettings; class ChatPage; class DeviceVerificationFlow; +struct nonesuch +{ + ~nonesuch() = delete; + nonesuch(nonesuch const &) = delete; + void operator=(nonesuch const &) = delete; +}; + +namespace detail { +template class Op, class... Args> +struct detector +{ + using value_t = std::false_type; + using type = Default; +}; + +template class Op, class... Args> +struct detector>, Op, Args...> +{ + using value_t = std::true_type; + using type = Op; +}; + +} // namespace detail + +template class Op, class... Args> +using is_detected = typename detail::detector::value_t; + class TimelineViewManager : public QObject { Q_OBJECT @@ -154,6 +182,23 @@ public slots: private slots: void openImageOverlayInternal(QString eventId, QImage img); +private: + template + using f_t = decltype(Content::file); + + template + using u_t = decltype(Content::url); + + template + static constexpr bool messageWithFileAndUrl(const mtx::events::Event &e) + { + if constexpr (is_detected::value && is_detected::value) { + return true; + } + + return false; + } + private: #ifdef USE_QUICK_VIEW QQuickView *view; From 06e12a0a16c8ded7deada5586a4772779f01dbe8 Mon Sep 17 00:00:00 2001 From: targetakhil Date: Sat, 17 Apr 2021 22:58:04 +0530 Subject: [PATCH 07/10] move detection code to nheko namespace and fix a few other bugs --- src/EventAccessors.cpp | 26 +------- src/EventAccessors.h | 26 ++++++++ src/timeline/TimelineModel.cpp | 2 +- src/timeline/TimelineModel.h | 4 +- src/timeline/TimelineViewManager.cpp | 93 +++++++++++++--------------- src/timeline/TimelineViewManager.h | 43 +++---------- 6 files changed, 80 insertions(+), 114 deletions(-) diff --git a/src/EventAccessors.cpp b/src/EventAccessors.cpp index cfc41a98..362bf4e9 100644 --- a/src/EventAccessors.cpp +++ b/src/EventAccessors.cpp @@ -11,32 +11,8 @@ #include namespace { -struct nonesuch -{ - ~nonesuch() = delete; - nonesuch(nonesuch const &) = delete; - void operator=(nonesuch const &) = delete; -}; - -namespace detail { -template class Op, class... Args> -struct detector -{ - using value_t = std::false_type; - using type = Default; -}; - -template class Op, class... Args> -struct detector>, Op, Args...> -{ - using value_t = std::true_type; - using type = Op; -}; - -} // namespace detail - template class Op, class... Args> -using is_detected = typename detail::detector::value_t; +using is_detected = typename nheko::detail::detector::value_t; struct IsStateEvent { diff --git a/src/EventAccessors.h b/src/EventAccessors.h index ced159c1..a58c7de0 100644 --- a/src/EventAccessors.h +++ b/src/EventAccessors.h @@ -11,6 +11,32 @@ #include +namespace nheko { +struct nonesuch +{ + ~nonesuch() = delete; + nonesuch(nonesuch const &) = delete; + void operator=(nonesuch const &) = delete; +}; + +namespace detail { +template class Op, class... Args> +struct detector +{ + using value_t = std::false_type; + using type = Default; +}; + +template class Op, class... Args> +struct detector>, Op, Args...> +{ + using value_t = std::true_type; + using type = Op; +}; + +} // namespace detail +} + namespace mtx::accessors { std::string event_id(const mtx::events::collections::TimelineEvents &event); diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index e3efe5ad..2e83b831 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -829,7 +829,7 @@ TimelineModel::forwardMessage(QString eventId, QString roomId) if (!e) return; - emit forwardToRoom(e, roomId, cache::isRoomEncrypted(room_id_.toStdString())); + emit forwardToRoom(e, roomId); } void diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h index 3e6f6f15..fbe963d2 100644 --- a/src/timeline/TimelineModel.h +++ b/src/timeline/TimelineModel.h @@ -323,9 +323,7 @@ signals: void roomNameChanged(); void roomTopicChanged(); void roomAvatarUrlChanged(); - void forwardToRoom(mtx::events::collections::TimelineEvents *e, - QString roomId, - bool sentFromEncrypted); + void forwardToRoom(mtx::events::collections::TimelineEvents *e, QString roomId); private: template diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index f71fd42b..a3d19950 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -621,68 +621,63 @@ TimelineViewManager::focusTimeline() void TimelineViewManager::forwardMessageToRoom(mtx::events::collections::TimelineEvents *e, - QString roomId, - bool sentFromEncrypted) + QString roomId) { - auto elem = *e; - auto room = models.find(roomId); - auto messageType = mtx::accessors::msg_type(elem); - auto content = mtx::accessors::url(elem); - - if (sentFromEncrypted) { - std::optional encryptionInfo = - mtx::accessors::file(elem); + auto elem = *e; + auto room = models.find(roomId); + auto content = mtx::accessors::url(elem); + std::optional encryptionInfo = mtx::accessors::file(elem); + if (encryptionInfo) { http::client()->download( content, [this, roomId, e, encryptionInfo](const std::string &res, - const std::string &content_type, - const std::string &originalFilename, - mtx::http::RequestErr err) { + const std::string &content_type, + const std::string &originalFilename, + mtx::http::RequestErr err) { if (err) { return; } - assert(encryptionInfo); + auto data = mtx::crypto::to_string( + mtx::crypto::decrypt_file(res, encryptionInfo.value())); - auto data = mtx::crypto::to_string( - mtx::crypto::decrypt_file(res, encryptionInfo.value())); + http::client()->upload( + data, + content_type, + originalFilename, + [this, roomId, e](const mtx::responses::ContentURI &res, + mtx::http::RequestErr err) mutable { + if (err) { + nhlog::net()->warn("failed to upload media: {} {} ({})", + err->matrix_error.error, + to_string(err->matrix_error.errcode), + static_cast(err->status_code)); + return; + } - http::client()->upload( - data, - content_type, - originalFilename, - [this, roomId, e](const mtx::responses::ContentURI &res, - mtx::http::RequestErr err) mutable { - if (err) { - nhlog::net()->warn("failed to upload media: {} {} ({})", - err->matrix_error.error, - to_string(err->matrix_error.errcode), - static_cast(err->status_code)); - return; - } + std::visit( + [this, roomId, e, url = res.content_uri](auto ev) { + if constexpr (mtx::events::message_content_to_type< + decltype(ev.content)> == + mtx::events::EventType::RoomMessage) { + if constexpr (messageWithFileAndUrl(ev)) { + ev.content.relations.relations + .clear(); + ev.content.file.reset(); + ev.content.url = url; + } - std::visit( - [this, roomId, e, url = res.content_uri](auto ev) { - if constexpr (mtx::events::message_content_to_type< - decltype(ev.content)> == - mtx::events::EventType::RoomMessage) { - if constexpr (messageWithFileAndUrl(ev)) { - ev.content.relations.relations.clear(); - ev.content.file.reset(); - ev.content.url = url; + auto room = models.find(roomId); + room.value()->sendMessageEvent( + ev.content, + mtx::events::EventType::RoomMessage); + } + }, + *e); + }); - auto room = models.find(roomId); - room.value()->sendMessageEvent( - ev.content, - mtx::events::EventType::RoomMessage); - } - } - }, - *e); - }); - - return; + return; }); return; diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h index 9d1b4b1d..e5dea7ce 100644 --- a/src/timeline/TimelineViewManager.h +++ b/src/timeline/TimelineViewManager.h @@ -32,33 +32,6 @@ class UserSettings; class ChatPage; class DeviceVerificationFlow; -struct nonesuch -{ - ~nonesuch() = delete; - nonesuch(nonesuch const &) = delete; - void operator=(nonesuch const &) = delete; -}; - -namespace detail { -template class Op, class... Args> -struct detector -{ - using value_t = std::false_type; - using type = Default; -}; - -template class Op, class... Args> -struct detector>, Op, Args...> -{ - using value_t = std::true_type; - using type = Op; -}; - -} // namespace detail - -template class Op, class... Args> -using is_detected = typename detail::detector::value_t; - class TimelineViewManager : public QObject { Q_OBJECT @@ -175,15 +148,17 @@ public slots: void backToRooms() { emit showRoomList(); } QObject *completerFor(QString completerName, QString roomId = ""); - void forwardMessageToRoom(mtx::events::collections::TimelineEvents *e, - QString roomId, - bool sentFromEncrypted); + void forwardMessageToRoom(mtx::events::collections::TimelineEvents *e, QString roomId); private slots: void openImageOverlayInternal(QString eventId, QImage img); private: - template + template class Op, class... Args> + using is_detected = + typename nheko::detail::detector::value_t; + + template using f_t = decltype(Content::file); template @@ -192,11 +167,7 @@ private: template static constexpr bool messageWithFileAndUrl(const mtx::events::Event &e) { - if constexpr (is_detected::value && is_detected::value) { - return true; - } - - return false; + return is_detected::value && is_detected::value; } private: From 2dfa40e017c9880164936b50a0ab698dd83a125b Mon Sep 17 00:00:00 2001 From: targetakhil Date: Sun, 18 Apr 2021 11:22:44 +0530 Subject: [PATCH 08/10] strip reply fallbacks from forwarded message --- src/Utils.cpp | 10 ++----- src/Utils.h | 21 +++++++++++++ src/timeline/TimelineViewManager.cpp | 12 ++++---- src/timeline/TimelineViewManager.h | 45 ++++++++++++++++++++++++---- 4 files changed, 69 insertions(+), 19 deletions(-) diff --git a/src/Utils.cpp b/src/Utils.cpp index ca2d3adc..11e7b1af 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -63,19 +63,13 @@ utils::stripReplyFallbacks(const TimelineEvent &event, std::string id, QString r // get body, strip reply fallback, then transform the event to text, if it is a media event // etc related.quoted_body = QString::fromStdString(mtx::accessors::body(event)); - QRegularExpression plainQuote("^>.*?$\n?", QRegularExpression::MultilineOption); - while (related.quoted_body.startsWith(">")) - related.quoted_body.remove(plainQuote); - if (related.quoted_body.startsWith("\n")) - related.quoted_body.remove(0, 1); + stripReplyFromBody(related.quoted_body); related.quoted_body = utils::getQuoteBody(related); related.quoted_body.replace("@room", QString::fromUtf8("@\u2060room")); // get quoted body and strip reply fallback related.quoted_formatted_body = mtx::accessors::formattedBodyWithFallback(event); - related.quoted_formatted_body.remove(QRegularExpression( - ".*", QRegularExpression::DotMatchesEverythingOption)); - related.quoted_formatted_body.replace("@room", "@\u2060aroom"); + stripReplyFromFormattedBody(related.quoted_formatted_body); related.room = room_id_; return related; diff --git a/src/Utils.h b/src/Utils.h index 7a9eb777..e62b2d34 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -40,6 +41,26 @@ namespace utils { using TimelineEvent = mtx::events::collections::TimelineEvents; +//! Helper function to remove reply fallback from body +static void +stripReplyFromBody(QString &body) +{ + QRegularExpression plainQuote("^>.*?$\n?", QRegularExpression::MultilineOption); + while (body.startsWith(">")) + body.remove(plainQuote); + if (body.startsWith("\n")) + body.remove(0, 1); +} + +//! Helper function to remove reply fallback from formatted body +static void +stripReplyFromFormattedBody(QString &formatted_body) +{ + formatted_body.remove(QRegularExpression(".*", + QRegularExpression::DotMatchesEverythingOption)); + formatted_body.replace("@room", "@\u2060aroom"); +} + RelatedInfo stripReplyFallbacks(const TimelineEvent &event, std::string id, QString room_id_); diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index a3d19950..ff759625 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -4,7 +4,6 @@ #include "TimelineViewManager.h" -#include #include #include #include @@ -26,7 +25,6 @@ #include "RoomsModel.h" #include "UserSettingsPage.h" #include "UsersModel.h" -#include "blurhash.hpp" #include "dialogs/ImageOverlay.h" #include "emoji/EmojiModel.h" #include "emoji/Provider.h" @@ -623,10 +621,9 @@ void TimelineViewManager::forwardMessageToRoom(mtx::events::collections::TimelineEvents *e, QString roomId) { - auto elem = *e; auto room = models.find(roomId); - auto content = mtx::accessors::url(elem); - std::optional encryptionInfo = mtx::accessors::file(elem); + auto content = mtx::accessors::url(*e); + std::optional encryptionInfo = mtx::accessors::file(*e); if (encryptionInfo) { http::client()->download( @@ -669,6 +666,8 @@ TimelineViewManager::forwardMessageToRoom(mtx::events::collections::TimelineEven } auto room = models.find(roomId); + removeReplyFallback(ev); + ev.content.relations.relations.clear(); room.value()->sendMessageEvent( ev.content, mtx::events::EventType::RoomMessage); @@ -688,9 +687,10 @@ TimelineViewManager::forwardMessageToRoom(mtx::events::collections::TimelineEven if constexpr (mtx::events::message_content_to_type == mtx::events::EventType::RoomMessage) { e.content.relations.relations.clear(); + removeReplyFallback(e); room.value()->sendMessageEvent(e.content, mtx::events::EventType::RoomMessage); } }, - elem); + *e); } \ No newline at end of file diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h index e5dea7ce..7e9632de 100644 --- a/src/timeline/TimelineViewManager.h +++ b/src/timeline/TimelineViewManager.h @@ -13,7 +13,6 @@ #include #include #include -#include #include "Cache.h" #include "CallManager.h" @@ -159,15 +158,51 @@ private: typename nheko::detail::detector::value_t; template - using f_t = decltype(Content::file); + using file_t = decltype(Content::file); template - using u_t = decltype(Content::url); + using url_t = decltype(Content::url); + + template + using body_t = decltype(Content::body); + + template + using formatted_body_t = decltype(Content::formatted_body); template - static constexpr bool messageWithFileAndUrl(const mtx::events::Event &e) + static constexpr bool messageWithFileAndUrl(const mtx::events::Event &) { - return is_detected::value && is_detected::value; + return is_detected::value && is_detected::value; + } + + template + static constexpr void removeReplyFallback(mtx::events::Event &e) + { + if constexpr (is_detected::value) { + if constexpr (std::is_same_v, + std::remove_cv_t>) { + if (e.content.body) { + QString body = QString::fromStdString(e.content.body); + utils::stripReplyFromBody(body); + e.content.body = body.toStdString(); + } + } else if constexpr (std::is_same_v< + std::string, + std::remove_cv_t>) { + QString body = QString::fromStdString(e.content.body); + utils::stripReplyFromBody(body); + e.content.body = body.toStdString(); + } + } + + if constexpr (is_detected::value) { + if (e.content.format == "org.matrix.custom.html") { + QString formattedBody = + QString::fromStdString(e.content.formatted_body); + utils::stripReplyFromFormattedBody(formattedBody); + e.content.formatted_body = formattedBody.toStdString(); + } + } } private: From 5a5aba662e21f468733d1ee1bb2023a6ca3d433d Mon Sep 17 00:00:00 2001 From: targetakhil Date: Sun, 18 Apr 2021 12:03:25 +0530 Subject: [PATCH 09/10] make util strip util functions non-static and move definition to cpp file --- src/Utils.cpp | 18 ++++++++++++++++++ src/Utils.h | 20 ++++---------------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/Utils.cpp b/src/Utils.cpp index 11e7b1af..43d94151 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -52,6 +52,24 @@ createDescriptionInfo(const Event &event, const QString &localUser, const QStrin ts}; } +void +utils::stripReplyFromBody(QString &body) +{ + QRegularExpression plainQuote("^>.*?$\n?", QRegularExpression::MultilineOption); + while (body.startsWith(">")) + body.remove(plainQuote); + if (body.startsWith("\n")) + body.remove(0, 1); +} + +void +utils::stripReplyFromFormattedBody(QString &formatted_body) +{ + formatted_body.remove(QRegularExpression(".*", + QRegularExpression::DotMatchesEverythingOption)); + formatted_body.replace("@room", "@\u2060aroom"); +} + RelatedInfo utils::stripReplyFallbacks(const TimelineEvent &event, std::string id, QString room_id_) { diff --git a/src/Utils.h b/src/Utils.h index e62b2d34..f5d02237 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -42,24 +42,12 @@ namespace utils { using TimelineEvent = mtx::events::collections::TimelineEvents; //! Helper function to remove reply fallback from body -static void -stripReplyFromBody(QString &body) -{ - QRegularExpression plainQuote("^>.*?$\n?", QRegularExpression::MultilineOption); - while (body.startsWith(">")) - body.remove(plainQuote); - if (body.startsWith("\n")) - body.remove(0, 1); -} +void +stripReplyFromBody(QString &body); //! Helper function to remove reply fallback from formatted body -static void -stripReplyFromFormattedBody(QString &formatted_body) -{ - formatted_body.remove(QRegularExpression(".*", - QRegularExpression::DotMatchesEverythingOption)); - formatted_body.replace("@room", "@\u2060aroom"); -} +void +stripReplyFromFormattedBody(QString &formatted_body); RelatedInfo stripReplyFallbacks(const TimelineEvent &event, std::string id, QString room_id_); From ddb1983c639be10c7e151ddcb2554076eceb9b78 Mon Sep 17 00:00:00 2001 From: targetakhil Date: Thu, 22 Apr 2021 08:19:27 +0530 Subject: [PATCH 10/10] fix macos build error --- src/Utils.cpp | 18 ++++++++++++------ src/Utils.h | 8 ++++---- src/timeline/TimelineViewManager.cpp | 5 ++--- src/timeline/TimelineViewManager.h | 14 ++++---------- 4 files changed, 22 insertions(+), 23 deletions(-) diff --git a/src/Utils.cpp b/src/Utils.cpp index 43d94151..d6ebc754 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -52,22 +52,26 @@ createDescriptionInfo(const Event &event, const QString &localUser, const QStrin ts}; } -void -utils::stripReplyFromBody(QString &body) +std::string +utils::stripReplyFromBody(const std::string &bodyi) { + QString body = QString::fromStdString(bodyi); QRegularExpression plainQuote("^>.*?$\n?", QRegularExpression::MultilineOption); while (body.startsWith(">")) body.remove(plainQuote); if (body.startsWith("\n")) body.remove(0, 1); + return body.toStdString(); } -void -utils::stripReplyFromFormattedBody(QString &formatted_body) +std::string +utils::stripReplyFromFormattedBody(const std::string &formatted_bodyi) { + QString formatted_body = QString::fromStdString(formatted_bodyi); formatted_body.remove(QRegularExpression(".*", QRegularExpression::DotMatchesEverythingOption)); formatted_body.replace("@room", "@\u2060aroom"); + return formatted_body.toStdString(); } RelatedInfo @@ -81,13 +85,15 @@ utils::stripReplyFallbacks(const TimelineEvent &event, std::string id, QString r // get body, strip reply fallback, then transform the event to text, if it is a media event // etc related.quoted_body = QString::fromStdString(mtx::accessors::body(event)); - stripReplyFromBody(related.quoted_body); + related.quoted_body = + QString::fromStdString(stripReplyFromBody(related.quoted_body.toStdString())); related.quoted_body = utils::getQuoteBody(related); related.quoted_body.replace("@room", QString::fromUtf8("@\u2060room")); // get quoted body and strip reply fallback related.quoted_formatted_body = mtx::accessors::formattedBodyWithFallback(event); - stripReplyFromFormattedBody(related.quoted_formatted_body); + related.quoted_formatted_body = QString::fromStdString( + stripReplyFromFormattedBody(related.quoted_formatted_body.toStdString())); related.room = room_id_; return related; diff --git a/src/Utils.h b/src/Utils.h index f5d02237..e976cf81 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -42,12 +42,12 @@ namespace utils { using TimelineEvent = mtx::events::collections::TimelineEvents; //! Helper function to remove reply fallback from body -void -stripReplyFromBody(QString &body); +std::string +stripReplyFromBody(const std::string &body); //! Helper function to remove reply fallback from formatted body -void -stripReplyFromFormattedBody(QString &formatted_body); +std::string +stripReplyFromFormattedBody(const std::string &formatted_body); RelatedInfo stripReplyFallbacks(const TimelineEvent &event, std::string id, QString room_id_); diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index ff759625..d89f4a1b 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -632,9 +632,8 @@ TimelineViewManager::forwardMessageToRoom(mtx::events::collections::TimelineEven const std::string &content_type, const std::string &originalFilename, mtx::http::RequestErr err) { - if (err) { + if (err) return; - } auto data = mtx::crypto::to_string( mtx::crypto::decrypt_file(res, encryptionInfo.value())); @@ -654,7 +653,7 @@ TimelineViewManager::forwardMessageToRoom(mtx::events::collections::TimelineEven } std::visit( - [this, roomId, e, url = res.content_uri](auto ev) { + [this, roomId, url = res.content_uri](auto ev) { if constexpr (mtx::events::message_content_to_type< decltype(ev.content)> == mtx::events::EventType::RoomMessage) { diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h index 7e9632de..809b286e 100644 --- a/src/timeline/TimelineViewManager.h +++ b/src/timeline/TimelineViewManager.h @@ -182,25 +182,19 @@ private: if constexpr (std::is_same_v, std::remove_cv_t>) { if (e.content.body) { - QString body = QString::fromStdString(e.content.body); - utils::stripReplyFromBody(body); - e.content.body = body.toStdString(); + e.content.body = utils::stripReplyFromBody(e.content.body); } } else if constexpr (std::is_same_v< std::string, std::remove_cv_t>) { - QString body = QString::fromStdString(e.content.body); - utils::stripReplyFromBody(body); - e.content.body = body.toStdString(); + e.content.body = utils::stripReplyFromBody(e.content.body); } } if constexpr (is_detected::value) { if (e.content.format == "org.matrix.custom.html") { - QString formattedBody = - QString::fromStdString(e.content.formatted_body); - utils::stripReplyFromFormattedBody(formattedBody); - e.content.formatted_body = formattedBody.toStdString(); + e.content.formatted_body = + utils::stripReplyFromFormattedBody(e.content.formatted_body); } } }