diff --git a/CMakeLists.txt b/CMakeLists.txt
index 05436a37..86a4a656 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -287,6 +287,7 @@ qt5_wrap_cpp(MOC_HEADERS
src/dialogs/LeaveRoom.h
src/dialogs/Logout.h
src/dialogs/UserProfile.h
+ src/dialogs/RawMessage.h
src/dialogs/ReadReceipts.h
src/dialogs/ReCaptcha.h
src/dialogs/RoomSettings.h
diff --git a/src/MatrixClient.cpp b/src/MatrixClient.cpp
index 8d9361af..12d7ac91 100644
--- a/src/MatrixClient.cpp
+++ b/src/MatrixClient.cpp
@@ -31,6 +31,7 @@ init()
qRegisterMetaType<mtx::responses::JoinedGroups>();
qRegisterMetaType<mtx::responses::GroupProfile>();
qRegisterMetaType<std::string>();
+ qRegisterMetaType<nlohmann::json>();
qRegisterMetaType<std::vector<std::string>>();
qRegisterMetaType<std::vector<QString>>();
qRegisterMetaType<std::map<QString, bool>>("std::map<QString, bool>");
diff --git a/src/MatrixClient.h b/src/MatrixClient.h
index f0aca5c4..981c6b1c 100644
--- a/src/MatrixClient.h
+++ b/src/MatrixClient.h
@@ -4,6 +4,7 @@
#include <QObject>
#include <QString>
+#include "json.hpp"
#include <mtx/responses.hpp>
#include <mtxclient/http/client.hpp>
@@ -15,6 +16,7 @@ Q_DECLARE_METATYPE(mtx::responses::Sync)
Q_DECLARE_METATYPE(mtx::responses::JoinedGroups)
Q_DECLARE_METATYPE(mtx::responses::GroupProfile)
Q_DECLARE_METATYPE(std::string)
+Q_DECLARE_METATYPE(nlohmann::json)
Q_DECLARE_METATYPE(std::vector<std::string>)
Q_DECLARE_METATYPE(std::vector<QString>)
diff --git a/src/dialogs/RawMessage.h b/src/dialogs/RawMessage.h
new file mode 100644
index 00000000..5a7335f4
--- /dev/null
+++ b/src/dialogs/RawMessage.h
@@ -0,0 +1,56 @@
+#pragma once
+
+#include <QFont>
+#include <QFontDatabase>
+#include <QTextBrowser>
+#include <QVBoxLayout>
+#include <QWidget>
+
+#include "json.hpp"
+
+#include "Logging.h"
+#include "MainWindow.h"
+#include "ui/FlatButton.h"
+
+namespace dialogs {
+
+class RawMessage : public QWidget
+{
+ Q_OBJECT
+public:
+ RawMessage(QString msg, QWidget *parent = nullptr)
+ : QWidget{parent}
+ {
+ QFont monospaceFont = QFontDatabase::systemFont(QFontDatabase::FixedFont);
+
+ auto layout = new QVBoxLayout{this};
+ auto viewer = new QTextBrowser{this};
+ viewer->setFont(monospaceFont);
+ viewer->setText(msg);
+
+ layout->setSpacing(0);
+ layout->setMargin(0);
+ layout->addWidget(viewer);
+
+ setAutoFillBackground(true);
+ setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
+ setAttribute(Qt::WA_DeleteOnClose, true);
+
+ QSize winsize;
+ QPoint center;
+
+ auto window = MainWindow::instance();
+ if (window) {
+ winsize = window->frameGeometry().size();
+ center = window->frameGeometry().center();
+
+ move(center.x() - (width() * 0.5), center.y() - (height() * 0.5));
+ } else {
+ nhlog::ui()->warn("unable to retrieve MainWindow's size");
+ }
+
+ raise();
+ show();
+ }
+};
+} // namespace dialogs
diff --git a/src/dialogs/RoomSettings.cpp b/src/dialogs/RoomSettings.cpp
index a9739f3e..7409c5bd 100644
--- a/src/dialogs/RoomSettings.cpp
+++ b/src/dialogs/RoomSettings.cpp
@@ -1,6 +1,7 @@
#include <QApplication>
#include <QComboBox>
#include <QFileDialog>
+#include <QFontDatabase>
#include <QImageReader>
#include <QLabel>
#include <QMessageBox>
@@ -190,9 +191,7 @@ RoomSettings::RoomSettings(const QString &room_id, QWidget *parent)
auto infoLabel = new QLabel(tr("Info").toUpper(), this);
infoLabel->setFont(font);
- QFont monospaceFont;
- monospaceFont.setFamily("Courier New");
- monospaceFont.setStyleHint(QFont::Courier);
+ QFont monospaceFont = QFontDatabase::systemFont(QFontDatabase::FixedFont);
auto roomIdLabel = new QLabel(room_id, this);
roomIdLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
diff --git a/src/timeline/TimelineItem.cpp b/src/timeline/TimelineItem.cpp
index 8f44b7e8..5bec4458 100644
--- a/src/timeline/TimelineItem.cpp
+++ b/src/timeline/TimelineItem.cpp
@@ -34,6 +34,8 @@
#include "timeline/widgets/ImageItem.h"
#include "timeline/widgets/VideoItem.h"
+#include "dialogs/RawMessage.h"
+
constexpr int MSG_RIGHT_MARGIN = 7;
constexpr int MSG_PADDING = 20;
@@ -185,8 +187,10 @@ TimelineItem::init()
contextMenu_ = new QMenu(this);
showReadReceipts_ = new QAction("Read receipts", this);
markAsRead_ = new QAction("Mark as read", this);
+ viewRawMessage_ = new QAction("View raw message", this);
redactMsg_ = new QAction("Redact message", this);
contextMenu_->addAction(showReadReceipts_);
+ contextMenu_->addAction(viewRawMessage_);
contextMenu_->addAction(markAsRead_);
contextMenu_->addAction(redactMsg_);
@@ -218,7 +222,8 @@ TimelineItem::init()
});
});
- connect(markAsRead_, &QAction::triggered, this, [this]() { sendReadReceipt(); });
+ connect(markAsRead_, &QAction::triggered, this, &TimelineItem::sendReadReceipt);
+ connect(viewRawMessage_, &QAction::triggered, this, &TimelineItem::openRawMessageViewer);
topLayout_ = new QHBoxLayout(this);
mainLayout_ = new QVBoxLayout;
@@ -816,3 +821,37 @@ TimelineItem::sendReadReceipt() const
}
});
}
+
+void
+TimelineItem::openRawMessageViewer() const
+{
+ const auto event_id = event_id_.toStdString();
+ const auto room_id = room_id_.toStdString();
+
+ auto proxy = std::make_shared<EventProxy>();
+ connect(proxy.get(), &EventProxy::eventRetrieved, this, [](const nlohmann::json &obj) {
+ auto dialog = new dialogs::RawMessage{QString::fromStdString(obj.dump(4))};
+ Q_UNUSED(dialog);
+ });
+
+ http::client()->get_event(
+ room_id,
+ event_id,
+ [event_id, room_id, proxy = std::move(proxy)](
+ const mtx::events::collections::TimelineEvents &res, mtx::http::RequestErr err) {
+ using namespace mtx::events;
+
+ if (err) {
+ nhlog::net()->warn(
+ "failed to retrieve event {} from {}", event_id, room_id);
+ return;
+ }
+
+ try {
+ emit proxy->eventRetrieved(utils::serialize_event(res));
+ } catch (const nlohmann::json::exception &e) {
+ nhlog::net()->warn(
+ "failed to serialize event ({}, {})", room_id, event_id);
+ }
+ });
+}
diff --git a/src/timeline/TimelineItem.h b/src/timeline/TimelineItem.h
index 26bcfbae..fb961b6c 100644
--- a/src/timeline/TimelineItem.h
+++ b/src/timeline/TimelineItem.h
@@ -88,6 +88,14 @@ private:
static constexpr int MaxWidth = 24;
};
+class EventProxy : public QObject
+{
+ Q_OBJECT
+
+signals:
+ void eventRetrieved(const nlohmann::json &);
+};
+
class TextLabel : public QTextBrowser
{
Q_OBJECT
@@ -220,6 +228,7 @@ public:
bool isReceived() { return isReceived_; };
void setRoomId(QString room_id) { room_id_ = room_id; }
void sendReadReceipt() const;
+ void openRawMessageViewer() const;
//! Add a user avatar for this event.
void addAvatar();
@@ -273,6 +282,7 @@ private:
QAction *showReadReceipts_;
QAction *markAsRead_;
QAction *redactMsg_;
+ QAction *viewRawMessage_;
QAction *replyMsg_;
QHBoxLayout *topLayout_ = nullptr;
|