summary refs log tree commit diff
path: root/src/timeline
diff options
context:
space:
mode:
Diffstat (limited to 'src/timeline')
-rw-r--r--src/timeline/InputBar.h15
-rw-r--r--src/timeline/TimelineModel.cpp10
-rw-r--r--src/timeline/TimelineModel.h4
-rw-r--r--src/timeline/TimelineViewManager.cpp103
-rw-r--r--src/timeline/TimelineViewManager.h4
5 files changed, 127 insertions, 9 deletions
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<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();
@@ -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<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/TimelineModel.cpp b/src/timeline/TimelineModel.cpp
index 8e96cb3e..e3efe5ad 100644
--- a/src/timeline/TimelineModel.cpp
+++ b/src/timeline/TimelineModel.cpp
@@ -823,6 +823,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, cache::isRoomEncrypted(room_id_.toStdString()));
+}
+
+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..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<typename T>
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 <QBuffer>
 #include <QDesktopServices>
 #include <QDropEvent>
 #include <QMetaType>
@@ -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 <iostream> //only for debugging
-
 Q_DECLARE_METATYPE(mtx::events::collections::TimelineEvents)
 Q_DECLARE_METATYPE(std::vector<DeviceInfo>)
 
@@ -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<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)));
+                                  }
+                          }
+                          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);
+                            });
+                  });
+                return;
+        };
+
+        std::visit(
+          [room](auto e) {
+                  if constexpr (mtx::events::message_content_to_type<decltype(e.content)> ==
+                                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);