summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/timeline/InputBar.h15
-rw-r--r--src/timeline/TimelineViewManager.cpp128
-rw-r--r--src/timeline/TimelineViewManager.h45
3 files changed, 109 insertions, 79 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<mtx::crypto::EncryptedFile> &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<mtx::crypto::EncryptedFile> &file,
+                   const QString &url,
+                   const QString &mime,
+                   uint64_t dsize,
+                   const QSize &dimensions,
+                   const QString &blurhash);
         void file(const QString &filename,
                   const std::optional<mtx::crypto::EncryptedFile> &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) {
+                std::optional<mtx::crypto::EncryptedFile> encryptionInfo =
+                  mtx::accessors::file(elem);
+
+                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;
+                          }
 
-        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<mtx::crypto::EncryptedFile> 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<unsigned char> 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<unsigned char>(qRed(p)));
-                                          data_.push_back(static_cast<unsigned char>(qGreen(p)));
-                                          data_.push_back(static_cast<unsigned char>(qBlue(p)));
+                          assert(encryptionInfo);
+
+                        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;
                                   }
-                          }
-                          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<int>(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);
-                            });
+
+                                  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<decltype(e.content)> ==
                                 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 <mtx/common.hpp>
 #include <mtx/responses/messages.hpp>
 #include <mtx/responses/sync.hpp>
+#include <type_traits>
 
 #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 Default, class AlwaysVoid, template<class...> class Op, class... Args>
+struct detector
+{
+        using value_t = std::false_type;
+        using type    = Default;
+};
+
+template<class Default, template<class...> class Op, class... Args>
+struct detector<Default, std::void_t<Op<Args...>>, Op, Args...>
+{
+        using value_t = std::true_type;
+        using type    = Op<Args...>;
+};
+
+} // namespace detail
+
+template<template<class...> class Op, class... Args>
+using is_detected = typename detail::detector<nonesuch, void, Op, Args...>::value_t;
+
 class TimelineViewManager : public QObject
 {
         Q_OBJECT
@@ -155,6 +183,23 @@ private slots:
         void openImageOverlayInternal(QString eventId, QImage img);
 
 private:
+         template<class Content>
+        using f_t = decltype(Content::file);
+
+        template<class Content>
+        using u_t = decltype(Content::url);
+
+        template<typename T>
+        static constexpr bool messageWithFileAndUrl(const mtx::events::Event<T> &e)
+        {
+                if constexpr (is_detected<f_t, T>::value && is_detected<u_t, T>::value) {
+                        return true;
+                }
+
+                return false;
+        }
+
+private:
 #ifdef USE_QUICK_VIEW
         QQuickView *view;
 #else