summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--im.nheko.Nheko.yaml2
-rw-r--r--src/Cache.cpp30
-rw-r--r--src/Cache.h7
-rw-r--r--src/Cache_p.h6
-rw-r--r--src/ChatPage.cpp8
-rw-r--r--src/ChatPage.h3
-rw-r--r--src/CombinedImagePackModel.cpp4
-rw-r--r--src/EventAccessors.cpp2
-rw-r--r--src/EventAccessors.h8
-rw-r--r--src/GridImagePackModel.cpp3
-rw-r--r--src/ImagePackListModel.cpp4
-rw-r--r--src/MainWindow.cpp52
-rw-r--r--src/Utils.cpp137
-rw-r--r--src/Utils.h145
-rw-r--r--src/encryption/DeviceVerificationFlow.cpp30
-rw-r--r--src/encryption/DeviceVerificationFlow.h32
-rw-r--r--src/encryption/Olm.cpp16
-rw-r--r--src/encryption/SelfVerificationStatus.cpp2
-rw-r--r--src/timeline/InputBar.h2
20 files changed, 226 insertions, 269 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3eb45168..52e7b56d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -595,7 +595,7 @@ if(USE_BUNDLED_MTXCLIENT)
     FetchContent_Declare(
         MatrixClient
             GIT_REPOSITORY https://github.com/Nheko-Reborn/mtxclient.git
-            GIT_TAG        9876a75f46cc829beaa630d49dc8c5279a940b0d
+            GIT_TAG        f7734a6f26eddc74fb59c4e4bd0be28b632af9fd
     )
     set(BUILD_LIB_EXAMPLES OFF CACHE INTERNAL "")
     set(BUILD_LIB_TESTS OFF CACHE INTERNAL "")
diff --git a/im.nheko.Nheko.yaml b/im.nheko.Nheko.yaml
index 4a610735..de24976b 100644
--- a/im.nheko.Nheko.yaml
+++ b/im.nheko.Nheko.yaml
@@ -214,7 +214,7 @@ modules:
     buildsystem: cmake-ninja
     name: mtxclient
     sources:
-      - commit: 9876a75f46cc829beaa630d49dc8c5279a940b0d
+      - commit: f7734a6f26eddc74fb59c4e4bd0be28b632af9fd
         #tag: v0.9.2
         type: git
         url: https://github.com/Nheko-Reborn/mtxclient.git
diff --git a/src/Cache.cpp b/src/Cache.cpp
index 5367ee22..e6b7313e 100644
--- a/src/Cache.cpp
+++ b/src/Cache.cpp
@@ -463,14 +463,14 @@ fatalSecretError()
 }
 
 static QString
-secretName(std::string name, bool internal)
+secretName(std::string_view name, bool internal)
 {
     auto settings = UserSettings::instance();
     return (internal ? "nheko." : "matrix.") +
            QString(
              QCryptographicHash::hash(settings->profile().toUtf8(), QCryptographicHash::Sha256)
                .toBase64()) +
-           "." + QString::fromStdString(name);
+           "." + QString::fromUtf8(name);
 }
 
 void
@@ -560,7 +560,7 @@ Cache::loadSecretsFromStore(
 }
 
 std::optional<std::string>
-Cache::secret(const std::string &name_, bool internal)
+Cache::secret(std::string_view name_, bool internal)
 {
     auto name = secretName(name_, internal);
 
@@ -580,7 +580,7 @@ Cache::secret(const std::string &name_, bool internal)
 }
 
 void
-Cache::storeSecret(const std::string &name_, const std::string &secret, bool internal)
+Cache::storeSecret(std::string_view name_, const std::string &secret, bool internal)
 {
     auto name = secretName(name_, internal);
 
@@ -592,11 +592,11 @@ Cache::storeSecret(const std::string &name_, const std::string &secret, bool int
     auto db_name = "secret." + name.toStdString();
     syncStateDb_.put(txn, db_name, nlohmann::json(encrypted).dump());
     txn.commit();
-    emit secretChanged(name_);
+    emit secretChanged(std::string(name_));
 }
 
 void
-Cache::deleteSecret(const std::string &name_, bool internal)
+Cache::deleteSecret(std::string_view name_, bool internal)
 {
     auto name = secretName(name_, internal);
 
@@ -1631,10 +1631,10 @@ Cache::runMigrations()
            this->databaseReady_ = false;
            loadSecretsFromStore(
              {
-               {mtx::secret_storage::secrets::cross_signing_master, false},
-               {mtx::secret_storage::secrets::cross_signing_self_signing, false},
-               {mtx::secret_storage::secrets::cross_signing_user_signing, false},
-               {mtx::secret_storage::secrets::megolm_backup_v1, false},
+               {std::string(mtx::secret_storage::secrets::cross_signing_master), false},
+               {std::string(mtx::secret_storage::secrets::cross_signing_self_signing), false},
+               {std::string(mtx::secret_storage::secrets::cross_signing_user_signing), false},
+               {std::string(mtx::secret_storage::secrets::megolm_backup_v1), false},
              },
              [this,
               count = 1](const std::string &name, bool internal, const std::string &value) mutable {
@@ -6147,15 +6147,21 @@ restoreOlmAccount()
 }
 
 void
-storeSecret(const std::string &name, const std::string &secret)
+storeSecret(std::string_view name, const std::string &secret)
 {
     instance_->storeSecret(name, secret);
 }
 std::optional<std::string>
-secret(const std::string &name)
+secret(std::string_view name)
 {
     return instance_->secret(name);
 }
+
+std::vector<ImagePackInfo>
+getImagePacks(const std::string &room_id, std::optional<bool> stickers)
+{
+    return instance_->getImagePacks(room_id, stickers);
+}
 } // namespace cache
 
 #define NHEKO_CACHE_GET_STATE_EVENT_DEFINITION(Content)                                            \
diff --git a/src/Cache.h b/src/Cache.h
index bed4938c..7c79881c 100644
--- a/src/Cache.h
+++ b/src/Cache.h
@@ -253,7 +253,10 @@ std::string
 restoreOlmAccount();
 
 void
-storeSecret(const std::string &name, const std::string &secret);
+storeSecret(std::string_view name, const std::string &secret);
 std::optional<std::string>
-secret(const std::string &name);
+secret(std::string_view name);
+
+std::vector<ImagePackInfo>
+getImagePacks(const std::string &room_id, std::optional<bool> stickers);
 }
diff --git a/src/Cache_p.h b/src/Cache_p.h
index d1316ae5..24ea2939 100644
--- a/src/Cache_p.h
+++ b/src/Cache_p.h
@@ -291,9 +291,9 @@ public:
     void deleteBackupVersion();
     std::optional<OnlineBackupVersion> backupVersion();
 
-    void storeSecret(const std::string &name, const std::string &secret, bool internal = false);
-    void deleteSecret(const std::string &name, bool internal = false);
-    std::optional<std::string> secret(const std::string &name, bool internal = false);
+    void storeSecret(std::string_view name, const std::string &secret, bool internal = false);
+    void deleteSecret(std::string_view name, bool internal = false);
+    std::optional<std::string> secret(std::string_view name, bool internal = false);
 
     std::string pickleSecret();
 
diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp
index 03144faf..b756f486 100644
--- a/src/ChatPage.cpp
+++ b/src/ChatPage.cpp
@@ -778,7 +778,9 @@ ChatPage::handleSyncResponse(const mtx::responses::Sync &res, const std::string
     nhlog::net()->debug("sync completed: {}", res.next_batch);
 
     // Ensure that we have enough one-time keys available.
-    ensureOneTimeKeyCount(res.device_one_time_keys_count, res.device_unused_fallback_key_types);
+    std::map<std::string_view, std::uint16_t> counts{res.device_one_time_keys_count.begin(),
+                                                     res.device_one_time_keys_count.end()};
+    ensureOneTimeKeyCount(counts, res.device_unused_fallback_key_types);
 
     std::optional<mtx::events::account_data::IgnoredUsers> oldIgnoredUsers;
     if (auto ignoreEv = std::ranges::find_if(
@@ -1194,7 +1196,7 @@ ChatPage::verifyOneTimeKeyCountAfterStartup()
                   return;
           }
 
-          std::map<std::string, uint16_t> key_counts;
+          std::map<std::string_view, uint16_t> key_counts;
           std::uint64_t count = 0;
           if (auto c = res.one_time_key_counts.find(mtx::crypto::SIGNED_CURVE25519);
               c == res.one_time_key_counts.end()) {
@@ -1215,7 +1217,7 @@ ChatPage::verifyOneTimeKeyCountAfterStartup()
 }
 
 void
-ChatPage::ensureOneTimeKeyCount(const std::map<std::string, uint16_t> &counts,
+ChatPage::ensureOneTimeKeyCount(const std::map<std::string_view, uint16_t> &counts,
                                 const std::optional<std::vector<std::string>> &unused_fallback_keys)
 {
     if (auto count = counts.find(mtx::crypto::SIGNED_CURVE25519); count != counts.end()) {
diff --git a/src/ChatPage.h b/src/ChatPage.h
index 1e1da049..13621b23 100644
--- a/src/ChatPage.h
+++ b/src/ChatPage.h
@@ -6,7 +6,6 @@
 
 #include <atomic>
 #include <optional>
-#include <variant>
 
 #include <mtx/common.hpp>
 #include <mtx/events.hpp>
@@ -191,7 +190,7 @@ private:
     void tryInitialSync();
     void trySync();
     void verifyOneTimeKeyCountAfterStartup();
-    void ensureOneTimeKeyCount(const std::map<std::string, uint16_t> &counts,
+    void ensureOneTimeKeyCount(const std::map<std::string_view, uint16_t> &counts,
                                const std::optional<std::vector<std::string>> &fallback_keys);
     void removeOldFallbackKey();
     void getProfileInfo();
diff --git a/src/CombinedImagePackModel.cpp b/src/CombinedImagePackModel.cpp
index 23fb50f1..c4a09847 100644
--- a/src/CombinedImagePackModel.cpp
+++ b/src/CombinedImagePackModel.cpp
@@ -4,7 +4,7 @@
 
 #include "CombinedImagePackModel.h"
 
-#include "Cache_p.h"
+#include "Cache.h"
 #include "CompletionModelRoles.h"
 #include "emoji/Provider.h"
 
@@ -12,7 +12,7 @@ CombinedImagePackModel::CombinedImagePackModel(const std::string &roomId, QObjec
   : QAbstractListModel(parent)
   , room_id(roomId)
 {
-    auto packs = cache::client()->getImagePacks(room_id, false);
+    auto packs = cache::getImagePacks(room_id, false);
 
     for (const auto &pack : packs) {
         QString packname =
diff --git a/src/EventAccessors.cpp b/src/EventAccessors.cpp
index 8cb09a1d..ca730a75 100644
--- a/src/EventAccessors.cpp
+++ b/src/EventAccessors.cpp
@@ -10,6 +10,8 @@
 #include <cctype>
 #include <type_traits>
 
+#include <mtx/events/collections.hpp>
+
 namespace {
 
 struct IsStateEvent
diff --git a/src/EventAccessors.h b/src/EventAccessors.h
index 78484e91..4128f681 100644
--- a/src/EventAccessors.h
+++ b/src/EventAccessors.h
@@ -9,7 +9,13 @@
 #include <QDateTime>
 #include <QString>
 
-#include <mtx/events/collections.hpp>
+#include <mtx/common.hpp>
+#include <mtx/events.hpp>
+
+namespace mtx::events::collections {
+struct TimelineEvents;
+struct StateEvents;
+}
 
 namespace nheko {
 struct nonesuch
diff --git a/src/GridImagePackModel.cpp b/src/GridImagePackModel.cpp
index cfd014f0..4dbe6af3 100644
--- a/src/GridImagePackModel.cpp
+++ b/src/GridImagePackModel.cpp
@@ -10,7 +10,6 @@
 #include <algorithm>
 
 #include "Cache.h"
-#include "Cache_p.h"
 #include "emoji/Provider.h"
 
 QString
@@ -102,7 +101,7 @@ GridImagePackModel::GridImagePackModel(const std::string &roomId, bool stickers,
         }
     }
 
-    auto originalPacks = cache::client()->getImagePacks(room_id, stickers);
+    auto originalPacks = cache::getImagePacks(room_id, stickers);
 
     for (auto &pack : originalPacks) {
         PackDesc newPack{};
diff --git a/src/ImagePackListModel.cpp b/src/ImagePackListModel.cpp
index 4cf807a9..94b319f2 100644
--- a/src/ImagePackListModel.cpp
+++ b/src/ImagePackListModel.cpp
@@ -6,14 +6,14 @@
 
 #include <QQmlEngine>
 
-#include "Cache_p.h"
+#include "Cache.h"
 #include "SingleImagePackModel.h"
 
 ImagePackListModel::ImagePackListModel(const std::string &roomId, QObject *parent)
   : QAbstractListModel(parent)
   , room_id(roomId)
 {
-    auto packs_ = cache::client()->getImagePacks(room_id, std::nullopt);
+    auto packs_ = cache::getImagePacks(room_id, std::nullopt);
 
     packs.reserve(packs_.size());
     for (const auto &pack : packs_) {
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index 1a0b1e96..e25619cd 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -101,58 +101,6 @@ MainWindow::MainWindow(QWindow *parent)
 void
 MainWindow::registerQmlTypes()
 {
-    // qmlRegisterUncreatableType<DeviceVerificationFlow>(
-    //   "im.nheko",
-    //   1,
-    //   0,
-    //   "DeviceVerificationFlow",
-    //   QStringLiteral("Can't create verification flow from QML!"));
-    // qmlRegisterUncreatableType<UserProfile>(
-    //   "im.nheko",
-    //   1,
-    //   0,
-    //   "UserProfileModel",
-    //   QStringLiteral("UserProfile needs to be instantiated on the C++ side"));
-    // qmlRegisterUncreatableType<MemberList>(
-    //   "im.nheko",
-    //   1,
-    //   0,
-    //   "MemberList",
-    //   QStringLiteral("MemberList needs to be instantiated on the C++ side"));
-    // qmlRegisterUncreatableType<RoomSettings>(
-    //   "im.nheko",
-    //   1,
-    //   0,
-    //   "RoomSettingsModel",
-    //   QStringLiteral("Room Settings needs to be instantiated on the C++ side"));
-    // qmlRegisterUncreatableType<TimelineModel>(
-    //   "im.nheko", 1, 0, "Room", QStringLiteral("Room needs to be instantiated on the C++ side"));
-    // qmlRegisterUncreatableType<ImagePackListModel>(
-    //   "im.nheko",
-    //   1,
-    //   0,
-    //   "ImagePackListModel",
-    //   QStringLiteral("ImagePackListModel needs to be instantiated on the C++ side"));
-    // qmlRegisterUncreatableType<SingleImagePackModel>(
-    //   "im.nheko",
-    //   1,
-    //   0,
-    //   "SingleImagePackModel",
-    //   QStringLiteral("SingleImagePackModel needs to be instantiated on the C++ side"));
-    // qmlRegisterUncreatableType<InviteesModel>(
-    //   "im.nheko",
-    //   1,
-    //   0,
-    //   "InviteesModel",
-    //   QStringLiteral("InviteesModel needs to be instantiated on the C++ side"));
-
-    // qmlRegisterUncreatableMetaObject(emoji::staticMetaObject,
-    //                                  "im.nheko.EmojiModel",
-    //                                  1,
-    //                                  0,
-    //                                  "EmojiCategory",
-    //                                  QStringLiteral("Error: Only enums"));
-
     imgProvider = new MxcImageProvider();
     engine()->addImageProvider(QStringLiteral("MxcImage"), imgProvider);
     engine()->addImageProvider(QStringLiteral("colorimage"), new ColorImageProvider());
diff --git a/src/Utils.cpp b/src/Utils.cpp
index 7a487101..8d372763 100644
--- a/src/Utils.cpp
+++ b/src/Utils.cpp
@@ -40,6 +40,133 @@
 #include "MatrixClient.h"
 #include "UserSettingsPage.h"
 
+//! Match widgets/events with a description message.
+namespace {
+template<class T>
+QString
+messageDescription(const QString &username = QString(),
+                   const QString &body     = QString(),
+                   const bool isLocal      = false)
+{
+    using Audio         = mtx::events::RoomEvent<mtx::events::msg::Audio>;
+    using Emote         = mtx::events::RoomEvent<mtx::events::msg::Emote>;
+    using File          = mtx::events::RoomEvent<mtx::events::msg::File>;
+    using Image         = mtx::events::RoomEvent<mtx::events::msg::Image>;
+    using Notice        = mtx::events::RoomEvent<mtx::events::msg::Notice>;
+    using Sticker       = mtx::events::Sticker;
+    using Text          = mtx::events::RoomEvent<mtx::events::msg::Text>;
+    using Unknown       = mtx::events::RoomEvent<mtx::events::msg::Unknown>;
+    using Video         = mtx::events::RoomEvent<mtx::events::msg::Video>;
+    using ElementEffect = mtx::events::RoomEvent<mtx::events::msg::ElementEffect>;
+    using CallInvite    = mtx::events::RoomEvent<mtx::events::voip::CallInvite>;
+    using CallAnswer    = mtx::events::RoomEvent<mtx::events::voip::CallAnswer>;
+    using CallHangUp    = mtx::events::RoomEvent<mtx::events::voip::CallHangUp>;
+    using CallReject    = mtx::events::RoomEvent<mtx::events::voip::CallReject>;
+    using Encrypted     = mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>;
+
+    if (std::is_same<T, Audio>::value) {
+        if (isLocal)
+            return QCoreApplication::translate("message-description sent:",
+                                               "You sent an audio clip");
+        else
+            return QCoreApplication::translate("message-description sent:", "%1 sent an audio clip")
+              .arg(username);
+    } else if (std::is_same<T, Image>::value) {
+        if (isLocal)
+            return QCoreApplication::translate("message-description sent:", "You sent an image");
+        else
+            return QCoreApplication::translate("message-description sent:", "%1 sent an image")
+              .arg(username);
+    } else if (std::is_same<T, File>::value) {
+        if (isLocal)
+            return QCoreApplication::translate("message-description sent:", "You sent a file");
+        else
+            return QCoreApplication::translate("message-description sent:", "%1 sent a file")
+              .arg(username);
+    } else if (std::is_same<T, Video>::value) {
+        if (isLocal)
+            return QCoreApplication::translate("message-description sent:", "You sent a video");
+        else
+            return QCoreApplication::translate("message-description sent:", "%1 sent a video")
+              .arg(username);
+    } else if (std::is_same<T, Sticker>::value) {
+        if (isLocal)
+            return QCoreApplication::translate("message-description sent:", "You sent a sticker");
+        else
+            return QCoreApplication::translate("message-description sent:", "%1 sent a sticker")
+              .arg(username);
+    } else if (std::is_same<T, Notice>::value) {
+        if (isLocal)
+            return QCoreApplication::translate("message-description sent:",
+                                               "You sent a notification");
+        else
+            return QCoreApplication::translate("message-description sent:",
+                                               "%1 sent a notification")
+              .arg(username);
+    } else if (std::is_same<T, Text>::value || std::is_same<T, Unknown>::value) {
+        if (isLocal)
+            return QCoreApplication::translate("message-description sent:", "You: %1").arg(body);
+        else
+            return QCoreApplication::translate("message-description sent:", "%1: %2")
+              .arg(username, body);
+    } else if (std::is_same<T, ElementEffect>::value) {
+        if (body.isEmpty()) {
+            // TODO: what is the best way to handle this?
+            if (isLocal)
+                return QCoreApplication::translate("message-description sent:",
+                                                   "You sent a chat effect");
+            else
+                return QCoreApplication::translate("message-description sent:",
+                                                   "%1 sent a chat effect")
+                  .arg(username);
+        } else {
+            if (isLocal)
+                return QCoreApplication::translate("message-description sent:", "You: %1")
+                  .arg(body);
+            else
+                return QCoreApplication::translate("message-description sent:", "%1: %2")
+                  .arg(username, body);
+        }
+    } else if (std::is_same<T, Emote>::value) {
+        return QStringLiteral("* %1 %2").arg(username, body);
+    } else if (std::is_same<T, Encrypted>::value) {
+        if (isLocal)
+            return QCoreApplication::translate("message-description sent:",
+                                               "You sent an encrypted message");
+        else
+            return QCoreApplication::translate("message-description sent:",
+                                               "%1 sent an encrypted message")
+              .arg(username);
+    } else if (std::is_same<T, CallInvite>::value) {
+        if (isLocal)
+            return QCoreApplication::translate("message-description sent:", "You placed a call");
+        else
+            return QCoreApplication::translate("message-description sent:", "%1 placed a call")
+              .arg(username);
+    } else if (std::is_same<T, CallAnswer>::value) {
+        if (isLocal)
+            return QCoreApplication::translate("message-description sent:", "You answered a call");
+        else
+            return QCoreApplication::translate("message-description sent:", "%1 answered a call")
+              .arg(username);
+    } else if (std::is_same<T, CallHangUp>::value) {
+        if (isLocal)
+            return QCoreApplication::translate("message-description sent:", "You ended a call");
+        else
+            return QCoreApplication::translate("message-description sent:", "%1 ended a call")
+              .arg(username);
+    } else if (std::is_same<T, CallReject>::value) {
+        if (isLocal)
+            return QCoreApplication::translate("message-description sent:", "You rejected a call");
+        else
+            return QCoreApplication::translate("message-description sent:", "%1 rejected a call")
+              .arg(username);
+    } else {
+        return QCoreApplication::translate("utils", "Unknown Message Type");
+    }
+}
+}
+
 template<class T, class Event>
 static DescInfo
 createDescriptionInfo(const Event &event, const QString &localUser, const QString &displayName)
@@ -56,7 +183,7 @@ createDescriptionInfo(const Event &event, const QString &localUser, const QStrin
     return DescInfo{
       QString::fromStdString(msg.event_id),
       sender,
-      utils::messageDescription<T>(username, QString::fromStdString(body), sender == localUser),
+      messageDescription<T>(username, QString::fromStdString(body), sender == localUser),
       utils::descriptiveTime(ts),
       msg.origin_server_ts,
       ts};
@@ -389,13 +516,9 @@ utils::mxcToHttp(const QUrl &url, const QString &server, int port)
 }
 
 QString
-utils::humanReadableFingerprint(const std::string &ed25519)
-{
-    return humanReadableFingerprint(QString::fromStdString(ed25519));
-}
-QString
-utils::humanReadableFingerprint(const QString &ed25519)
+utils::humanReadableFingerprint(const std::string &ed25519_)
 {
+    auto ed25519 = QString::fromStdString(ed25519_);
     QString fingerprint;
     for (int i = 0; i < ed25519.length(); i = i + 4) {
         fingerprint.append(QStringView(ed25519).mid(i, 4));
diff --git a/src/Utils.h b/src/Utils.h
index 2c75cb5c..7f844627 100644
--- a/src/Utils.h
+++ b/src/Utils.h
@@ -5,14 +5,14 @@
 #pragma once
 
 #include <CacheStructs.h>
-#include <QCoreApplication>
 #include <QDateTime>
 #include <QPixmap>
-#include <QRegularExpression>
-#include <mtx/events/collections.hpp>
-#include <mtx/events/common.hpp>
+#include <mtx/events.hpp>
 
-#include <qmath.h>
+namespace mtx::events::collections {
+struct TimelineEvents;
+struct StateEvents;
+}
 
 struct DescInfo;
 
@@ -85,131 +85,6 @@ firstChar(const QString &input);
 QString
 humanReadableFileSize(uint64_t bytes);
 
-//! Match widgets/events with a description message.
-template<class T>
-QString
-messageDescription(const QString &username = QString(),
-                   const QString &body     = QString(),
-                   const bool isLocal      = false)
-{
-    using Audio         = mtx::events::RoomEvent<mtx::events::msg::Audio>;
-    using Emote         = mtx::events::RoomEvent<mtx::events::msg::Emote>;
-    using File          = mtx::events::RoomEvent<mtx::events::msg::File>;
-    using Image         = mtx::events::RoomEvent<mtx::events::msg::Image>;
-    using Notice        = mtx::events::RoomEvent<mtx::events::msg::Notice>;
-    using Sticker       = mtx::events::Sticker;
-    using Text          = mtx::events::RoomEvent<mtx::events::msg::Text>;
-    using Unknown       = mtx::events::RoomEvent<mtx::events::msg::Unknown>;
-    using Video         = mtx::events::RoomEvent<mtx::events::msg::Video>;
-    using ElementEffect = mtx::events::RoomEvent<mtx::events::msg::ElementEffect>;
-    using CallInvite    = mtx::events::RoomEvent<mtx::events::voip::CallInvite>;
-    using CallAnswer    = mtx::events::RoomEvent<mtx::events::voip::CallAnswer>;
-    using CallHangUp    = mtx::events::RoomEvent<mtx::events::voip::CallHangUp>;
-    using CallReject    = mtx::events::RoomEvent<mtx::events::voip::CallReject>;
-    using Encrypted     = mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>;
-
-    if (std::is_same<T, Audio>::value) {
-        if (isLocal)
-            return QCoreApplication::translate("message-description sent:",
-                                               "You sent an audio clip");
-        else
-            return QCoreApplication::translate("message-description sent:", "%1 sent an audio clip")
-              .arg(username);
-    } else if (std::is_same<T, Image>::value) {
-        if (isLocal)
-            return QCoreApplication::translate("message-description sent:", "You sent an image");
-        else
-            return QCoreApplication::translate("message-description sent:", "%1 sent an image")
-              .arg(username);
-    } else if (std::is_same<T, File>::value) {
-        if (isLocal)
-            return QCoreApplication::translate("message-description sent:", "You sent a file");
-        else
-            return QCoreApplication::translate("message-description sent:", "%1 sent a file")
-              .arg(username);
-    } else if (std::is_same<T, Video>::value) {
-        if (isLocal)
-            return QCoreApplication::translate("message-description sent:", "You sent a video");
-        else
-            return QCoreApplication::translate("message-description sent:", "%1 sent a video")
-              .arg(username);
-    } else if (std::is_same<T, Sticker>::value) {
-        if (isLocal)
-            return QCoreApplication::translate("message-description sent:", "You sent a sticker");
-        else
-            return QCoreApplication::translate("message-description sent:", "%1 sent a sticker")
-              .arg(username);
-    } else if (std::is_same<T, Notice>::value) {
-        if (isLocal)
-            return QCoreApplication::translate("message-description sent:",
-                                               "You sent a notification");
-        else
-            return QCoreApplication::translate("message-description sent:",
-                                               "%1 sent a notification")
-              .arg(username);
-    } else if (std::is_same<T, Text>::value || std::is_same<T, Unknown>::value) {
-        if (isLocal)
-            return QCoreApplication::translate("message-description sent:", "You: %1").arg(body);
-        else
-            return QCoreApplication::translate("message-description sent:", "%1: %2")
-              .arg(username, body);
-    } else if (std::is_same<T, ElementEffect>::value) {
-        if (body.isEmpty()) {
-            // TODO: what is the best way to handle this?
-            if (isLocal)
-                return QCoreApplication::translate("message-description sent:",
-                                                   "You sent a chat effect");
-            else
-                return QCoreApplication::translate("message-description sent:",
-                                                   "%1 sent a chat effect")
-                  .arg(username);
-        } else {
-            if (isLocal)
-                return QCoreApplication::translate("message-description sent:", "You: %1")
-                  .arg(body);
-            else
-                return QCoreApplication::translate("message-description sent:", "%1: %2")
-                  .arg(username, body);
-        }
-    } else if (std::is_same<T, Emote>::value) {
-        return QStringLiteral("* %1 %2").arg(username, body);
-    } else if (std::is_same<T, Encrypted>::value) {
-        if (isLocal)
-            return QCoreApplication::translate("message-description sent:",
-                                               "You sent an encrypted message");
-        else
-            return QCoreApplication::translate("message-description sent:",
-                                               "%1 sent an encrypted message")
-              .arg(username);
-    } else if (std::is_same<T, CallInvite>::value) {
-        if (isLocal)
-            return QCoreApplication::translate("message-description sent:", "You placed a call");
-        else
-            return QCoreApplication::translate("message-description sent:", "%1 placed a call")
-              .arg(username);
-    } else if (std::is_same<T, CallAnswer>::value) {
-        if (isLocal)
-            return QCoreApplication::translate("message-description sent:", "You answered a call");
-        else
-            return QCoreApplication::translate("message-description sent:", "%1 answered a call")
-              .arg(username);
-    } else if (std::is_same<T, CallHangUp>::value) {
-        if (isLocal)
-            return QCoreApplication::translate("message-description sent:", "You ended a call");
-        else
-            return QCoreApplication::translate("message-description sent:", "%1 ended a call")
-              .arg(username);
-    } else if (std::is_same<T, CallReject>::value) {
-        if (isLocal)
-            return QCoreApplication::translate("message-description sent:", "You rejected a call");
-        else
-            return QCoreApplication::translate("message-description sent:", "%1 rejected a call")
-              .arg(username);
-    } else {
-        return QCoreApplication::translate("utils", "Unknown Message Type");
-    }
-}
-
 //! Scale down an image to fit to the given width & height limitations.
 QPixmap
 scaleDown(uint64_t maxWidth, uint64_t maxHeight, const QPixmap &source);
@@ -227,13 +102,6 @@ erase_if(ContainerT &items, const PredicateT &predicate)
     }
 }
 
-template<class T>
-QString
-message_body(const mtx::events::collections::TimelineEvents &event)
-{
-    return QString::fromStdString(std::get<T>(event).content.body);
-}
-
 //! Calculate the Levenshtein distance between two strings with character skipping.
 int
 levenshtein_distance(const std::string &s1, const std::string &s2);
@@ -249,9 +117,6 @@ mxcToHttp(const QUrl &url, const QString &server, int port);
 QString
 humanReadableFingerprint(const std::string &ed25519);
 
-QString
-humanReadableFingerprint(const QString &ed25519);
-
 //! Retrieve the message body taking into account the `formatted_body` field.
 //! If the `format` of the message is not supported we fallback to `body`.
 template<typename RoomMessageT>
diff --git a/src/encryption/DeviceVerificationFlow.cpp b/src/encryption/DeviceVerificationFlow.cpp
index f0c7ed52..8c7204be 100644
--- a/src/encryption/DeviceVerificationFlow.cpp
+++ b/src/encryption/DeviceVerificationFlow.cpp
@@ -944,3 +944,33 @@ DeviceVerificationFlow::InitiateDeviceVerification(QObject *parent_,
 
     return flow;
 }
+template<typename T>
+void
+DeviceVerificationFlow::send(T msg)
+{
+    if (this->type == DeviceVerificationFlow::Type::ToDevice) {
+        mtx::requests::ToDeviceMessages<T> body;
+        msg.transaction_id = this->transaction_id;
+        for (const auto &d : deviceIds)
+            body[this->toClient][d.toStdString()] = msg;
+
+        http::client()->send_to_device<T>(
+          http::client()->generate_txn_id(), body, [](mtx::http::RequestErr err) {
+              if (err)
+                  nhlog::net()->warn("failed to send verification to_device message: {} {}",
+                                     err->matrix_error.error,
+                                     static_cast<int>(err->status_code));
+          });
+    } else if (this->type == DeviceVerificationFlow::Type::RoomMsg && model_) {
+        if constexpr (!std::is_same_v<T, mtx::events::msg::KeyVerificationRequest>) {
+            msg.relations.relations.push_back(this->relation);
+            // Set synthesized to surpress the nheko relation extensions
+            msg.relations.synthesized = true;
+        }
+        (model_)->sendMessageEvent(msg, mtx::events::to_device_content_to_type<T>);
+    }
+
+    nhlog::net()->debug("Sent verification step: {} in state: {}",
+                        mtx::events::to_string(mtx::events::to_device_content_to_type<T>),
+                        state().toStdString());
+}
diff --git a/src/encryption/DeviceVerificationFlow.h b/src/encryption/DeviceVerificationFlow.h
index 6b1776e0..e64eab96 100644
--- a/src/encryption/DeviceVerificationFlow.h
+++ b/src/encryption/DeviceVerificationFlow.h
@@ -7,13 +7,14 @@
 #include <QObject>
 
 #include <mtx/responses/crypto.hpp>
+#include <mtxclient/crypto/client.hpp>
 
 #include "CacheCryptoStructs.h"
 #include "Logging.h"
 #include "MatrixClient.h"
-#include "timeline/TimelineModel.h"
 
 class QTimer;
+class TimelineModel;
 
 using sas_ptr = std::unique_ptr<mtx::crypto::SAS>;
 
@@ -230,32 +231,5 @@ private:
     bool keySent = false, macSent = false, acceptSent = false, startSent = false;
 
     template<typename T>
-    void send(T msg)
-    {
-        if (this->type == DeviceVerificationFlow::Type::ToDevice) {
-            mtx::requests::ToDeviceMessages<T> body;
-            msg.transaction_id = this->transaction_id;
-            for (const auto &d : deviceIds)
-                body[this->toClient][d.toStdString()] = msg;
-
-            http::client()->send_to_device<T>(
-              http::client()->generate_txn_id(), body, [](mtx::http::RequestErr err) {
-                  if (err)
-                      nhlog::net()->warn("failed to send verification to_device message: {} {}",
-                                         err->matrix_error.error,
-                                         static_cast<int>(err->status_code));
-              });
-        } else if (this->type == DeviceVerificationFlow::Type::RoomMsg && model_) {
-            if constexpr (!std::is_same_v<T, mtx::events::msg::KeyVerificationRequest>) {
-                msg.relations.relations.push_back(this->relation);
-                // Set synthesized to surpress the nheko relation extensions
-                msg.relations.synthesized = true;
-            }
-            (model_)->sendMessageEvent(msg, mtx::events::to_device_content_to_type<T>);
-        }
-
-        nhlog::net()->debug("Sent verification step: {} in state: {}",
-                            mtx::events::to_string(mtx::events::to_device_content_to_type<T>),
-                            state().toStdString());
-    }
+    void send(T msg);
 };
diff --git a/src/encryption/Olm.cpp b/src/encryption/Olm.cpp
index aaa7e43f..0352d8d3 100644
--- a/src/encryption/Olm.cpp
+++ b/src/encryption/Olm.cpp
@@ -1665,10 +1665,10 @@ request_cross_signing_keys()
         });
     };
 
-    request(mtx::secret_storage::secrets::cross_signing_master);
-    request(mtx::secret_storage::secrets::cross_signing_self_signing);
-    request(mtx::secret_storage::secrets::cross_signing_user_signing);
-    request(mtx::secret_storage::secrets::megolm_backup_v1);
+    request(std::string(mtx::secret_storage::secrets::cross_signing_master));
+    request(std::string(mtx::secret_storage::secrets::cross_signing_self_signing));
+    request(std::string(mtx::secret_storage::secrets::cross_signing_user_signing));
+    request(std::string(mtx::secret_storage::secrets::megolm_backup_v1));
 }
 
 namespace {
@@ -1725,22 +1725,22 @@ download_cross_signing_keys()
 
                             if (backup_key && !backup_key->encrypted.empty())
                                 secrets[backup_key->encrypted.begin()->first]
-                                       [secrets::megolm_backup_v1] =
+                                       [std::string(secrets::megolm_backup_v1)] =
                                          backup_key->encrypted.begin()->second;
 
                             if (master_key && !master_key->encrypted.empty())
                                 secrets[master_key->encrypted.begin()->first]
-                                       [secrets::cross_signing_master] =
+                                       [std::string(secrets::cross_signing_master)] =
                                          master_key->encrypted.begin()->second;
 
                             if (self_signing_key && !self_signing_key->encrypted.empty())
                                 secrets[self_signing_key->encrypted.begin()->first]
-                                       [secrets::cross_signing_self_signing] =
+                                       [std::string(secrets::cross_signing_self_signing)] =
                                          self_signing_key->encrypted.begin()->second;
 
                             if (user_signing_key && !user_signing_key->encrypted.empty())
                                 secrets[user_signing_key->encrypted.begin()->first]
-                                       [secrets::cross_signing_user_signing] =
+                                       [std::string(secrets::cross_signing_user_signing)] =
                                          user_signing_key->encrypted.begin()->second;
 
                             for (const auto &[key, secret_] : secrets)
diff --git a/src/encryption/SelfVerificationStatus.cpp b/src/encryption/SelfVerificationStatus.cpp
index 8981244d..29711716 100644
--- a/src/encryption/SelfVerificationStatus.cpp
+++ b/src/encryption/SelfVerificationStatus.cpp
@@ -110,7 +110,7 @@ SelfVerificationStatus::setupCrosssigning(bool useSSSS,
         http::client()->set_secret_storage_default_key(ssss->keyDescription.name,
                                                        [](mtx::http::RequestErr) {});
 
-        auto uploadSecret = [ssss](const std::string &key_name, const std::string &secret) {
+        auto uploadSecret = [ssss](std::string_view key_name, const std::string &secret) {
             mtx::secret_storage::Secret s;
             s.encrypted[ssss->keyDescription.name] =
               mtx::crypto::encrypt(secret, ssss->privateKey, key_name);
diff --git a/src/timeline/InputBar.h b/src/timeline/InputBar.h
index 3cd65524..b15377fc 100644
--- a/src/timeline/InputBar.h
+++ b/src/timeline/InputBar.h
@@ -18,7 +18,7 @@
 #include <memory>
 
 #include <mtx/common.hpp>
-#include <mtx/responses/messages.hpp>
+#include <mtx/events/common.hpp>
 
 class TimelineModel;
 class CombinedImagePackModel;