diff options
author | Nicolas Werner <nicolas.werner@hotmail.de> | 2021-04-24 14:35:21 +0200 |
---|---|---|
committer | Nicolas Werner <nicolas.werner@hotmail.de> | 2021-04-24 14:35:21 +0200 |
commit | 8236f6ba72f677d3572be1eab7d5f71c0150fbf9 (patch) | |
tree | 1f29d71130b640b47dfe4b160ea4ef2801042698 /src/timeline | |
parent | Fix rendering issues with ) in links (diff) | |
parent | fix macos build error (diff) | |
download | nheko-8236f6ba72f677d3572be1eab7d5f71c0150fbf9.tar.xz |
Merge branch 'forward_message_feature' of https://github.com/Jedi18/nheko into Jedi18-forward_message_feature
Diffstat (limited to 'src/timeline')
-rw-r--r-- | src/timeline/TimelineModel.cpp | 10 | ||||
-rw-r--r-- | src/timeline/TimelineModel.h | 2 | ||||
-rw-r--r-- | src/timeline/TimelineViewManager.cpp | 83 | ||||
-rw-r--r-- | src/timeline/TimelineViewManager.h | 49 |
4 files changed, 142 insertions, 2 deletions
diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index bfd95b0d..30ce176e 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -827,6 +827,16 @@ TimelineModel::viewRawMessage(QString id) const } void +TimelineModel::forwardMessage(QString eventId, QString roomId) +{ + auto e = events.get(eventId.toStdString(), ""); + if (!e) + return; + + emit forwardToRoom(e, roomId); +} + +void TimelineModel::viewDecryptedRawMessage(QString id) const { auto e = events.get(id.toStdString(), ""); diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h index 06da95c6..fbe963d2 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,7 @@ signals: void roomNameChanged(); void roomTopicChanged(); void roomAvatarUrlChanged(); + void forwardToRoom(mtx::events::collections::TimelineEvents *e, QString roomId); private: template<typename T> diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp index e9986c7e..518ccaf1 100644 --- a/src/timeline/TimelineViewManager.cpp +++ b/src/timeline/TimelineViewManager.cpp @@ -31,8 +31,6 @@ #include "ui/NhekoCursorShape.h" #include "ui/NhekoDropArea.h" -#include <iostream> //only for debugging - Q_DECLARE_METATYPE(mtx::events::collections::TimelineEvents) Q_DECLARE_METATYPE(std::vector<DeviceInfo>) @@ -329,6 +327,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)); } } @@ -616,3 +618,80 @@ TimelineViewManager::focusTimeline() { getWidget()->setFocus(); } + +void +TimelineViewManager::forwardMessageToRoom(mtx::events::collections::TimelineEvents *e, + QString roomId) +{ + auto room = models.find(roomId); + auto content = mtx::accessors::url(*e); + std::optional<mtx::crypto::EncryptedFile> encryptionInfo = mtx::accessors::file(*e); + + 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) { + if (err) + return; + + 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<int>(err->status_code)); + return; + } + + std::visit( + [this, roomId, 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); + removeReplyFallback(ev); + ev.content.relations.relations.clear(); + 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<decltype(e.content)> == + mtx::events::EventType::RoomMessage) { + e.content.relations.relations.clear(); + removeReplyFallback(e); + room.value()->sendMessageEvent(e.content, + mtx::events::EventType::RoomMessage); + } + }, + *e); +} \ No newline at end of file diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h index 3b405142..809b286e 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,11 +147,59 @@ public slots: void backToRooms() { emit showRoomList(); } QObject *completerFor(QString completerName, QString roomId = ""); + void forwardMessageToRoom(mtx::events::collections::TimelineEvents *e, QString roomId); private slots: void openImageOverlayInternal(QString eventId, QImage img); private: + template<template<class...> class Op, class... Args> + using is_detected = + typename nheko::detail::detector<nheko::nonesuch, void, Op, Args...>::value_t; + + template<class Content> + using file_t = decltype(Content::file); + + template<class Content> + using url_t = decltype(Content::url); + + template<class Content> + using body_t = decltype(Content::body); + + template<class Content> + using formatted_body_t = decltype(Content::formatted_body); + + template<typename T> + static constexpr bool messageWithFileAndUrl(const mtx::events::Event<T> &) + { + return is_detected<file_t, T>::value && is_detected<url_t, T>::value; + } + + template<typename T> + static constexpr void removeReplyFallback(mtx::events::Event<T> &e) + { + if constexpr (is_detected<body_t, T>::value) { + if constexpr (std::is_same_v<std::optional<std::string>, + std::remove_cv_t<decltype(e.content.body)>>) { + if (e.content.body) { + e.content.body = utils::stripReplyFromBody(e.content.body); + } + } else if constexpr (std::is_same_v< + std::string, + std::remove_cv_t<decltype(e.content.body)>>) { + e.content.body = utils::stripReplyFromBody(e.content.body); + } + } + + if constexpr (is_detected<formatted_body_t, T>::value) { + if (e.content.format == "org.matrix.custom.html") { + e.content.formatted_body = + utils::stripReplyFromFormattedBody(e.content.formatted_body); + } + } + } + +private: #ifdef USE_QUICK_VIEW QQuickView *view; #else |