summary refs log tree commit diff
diff options
context:
space:
mode:
authorNicolas Werner <nicolas.werner@hotmail.de>2021-09-18 00:22:33 +0200
committerNicolas Werner <nicolas.werner@hotmail.de>2021-09-18 00:45:50 +0200
commitcfca7157b98c9dc8e0852fe6484bc3f75008af7d (patch)
tree32b92340908a9374214ec7b84c1fac7ea338f56d
parentMerge pull request #728 from Thulinma/goto (diff)
downloadnheko-cfca7157b98c9dc8e0852fe6484bc3f75008af7d.tar.xz
Change indentation to 4 spaces
-rw-r--r--.clang-format6
-rw-r--r--src/AvatarProvider.cpp69
-rw-r--r--src/AvatarProvider.h4
-rw-r--r--src/BlurhashProvider.cpp56
-rw-r--r--src/BlurhashProvider.h48
-rw-r--r--src/Cache.cpp6424
-rw-r--r--src/CacheCryptoStructs.h154
-rw-r--r--src/CacheStructs.h86
-rw-r--r--src/Cache_p.h1286
-rw-r--r--src/CallDevices.cpp443
-rw-r--r--src/CallDevices.h43
-rw-r--r--src/CallManager.cpp918
-rw-r--r--src/CallManager.h151
-rw-r--r--src/ChatPage.cpp2081
-rw-r--r--src/ChatPage.h281
-rw-r--r--src/Clipboard.cpp7
-rw-r--r--src/Clipboard.h12
-rw-r--r--src/ColorImageProvider.cpp26
-rw-r--r--src/ColorImageProvider.h8
-rw-r--r--src/CombinedImagePackModel.cpp84
-rw-r--r--src/CombinedImagePackModel.h58
-rw-r--r--src/CompletionModelRoles.h6
-rw-r--r--src/CompletionProxyModel.cpp188
-rw-r--r--src/CompletionProxyModel.h283
-rw-r--r--src/DeviceVerificationFlow.cpp1279
-rw-r--r--src/DeviceVerificationFlow.h353
-rw-r--r--src/EventAccessors.cpp489
-rw-r--r--src/EventAccessors.h14
-rw-r--r--src/ImagePackListModel.cpp91
-rw-r--r--src/ImagePackListModel.h46
-rw-r--r--src/InviteesModel.cpp75
-rw-r--r--src/InviteesModel.h54
-rw-r--r--src/JdenticonProvider.cpp104
-rw-r--r--src/JdenticonProvider.h75
-rw-r--r--src/Logging.cpp117
-rw-r--r--src/LoginPage.cpp795
-rw-r--r--src/LoginPage.h128
-rw-r--r--src/MainWindow.cpp540
-rw-r--r--src/MainWindow.h135
-rw-r--r--src/MatrixClient.cpp30
-rw-r--r--src/MemberList.cpp122
-rw-r--r--src/MemberList.h84
-rw-r--r--src/MxcImageProvider.cpp420
-rw-r--r--src/MxcImageProvider.h58
-rw-r--r--src/Olm.cpp2792
-rw-r--r--src/Olm.h32
-rw-r--r--src/ReadReceiptsModel.cpp147
-rw-r--r--src/ReadReceiptsModel.h74
-rw-r--r--src/RegisterPage.cpp791
-rw-r--r--src/RegisterPage.h118
-rw-r--r--src/RoomDirectoryModel.cpp280
-rw-r--r--src/RoomDirectoryModel.h94
-rw-r--r--src/RoomsModel.cpp102
-rw-r--r--src/RoomsModel.h38
-rw-r--r--src/SSOHandler.cpp64
-rw-r--r--src/SSOHandler.h16
-rw-r--r--src/SingleImagePackModel.cpp478
-rw-r--r--src/SingleImagePackModel.h131
-rw-r--r--src/TrayIcon.cpp148
-rw-r--r--src/TrayIcon.h28
-rw-r--r--src/UserSettingsPage.cpp2301
-rw-r--r--src/UserSettingsPage.h731
-rw-r--r--src/UsersModel.cpp72
-rw-r--r--src/UsersModel.h36
-rw-r--r--src/Utils.cpp1085
-rw-r--r--src/Utils.h232
-rw-r--r--src/WebRTCSession.cpp1622
-rw-r--r--src/WebRTCSession.h144
-rw-r--r--src/WelcomePage.cpp98
-rw-r--r--src/WelcomePage.h14
-rw-r--r--src/dialogs/CreateRoom.cpp254
-rw-r--r--src/dialogs/CreateRoom.h28
-rw-r--r--src/dialogs/FallbackAuth.cpp84
-rw-r--r--src/dialogs/FallbackAuth.h14
-rw-r--r--src/dialogs/ImageOverlay.cpp107
-rw-r--r--src/dialogs/ImageOverlay.h24
-rw-r--r--src/dialogs/JoinRoom.cpp66
-rw-r--r--src/dialogs/JoinRoom.h16
-rw-r--r--src/dialogs/LeaveRoom.cpp54
-rw-r--r--src/dialogs/LeaveRoom.h10
-rw-r--r--src/dialogs/Logout.cpp72
-rw-r--r--src/dialogs/Logout.h10
-rw-r--r--src/dialogs/PreviewUploadOverlay.cpp283
-rw-r--r--src/dialogs/PreviewUploadOverlay.h40
-rw-r--r--src/dialogs/ReCaptcha.cpp80
-rw-r--r--src/dialogs/ReCaptcha.h14
-rw-r--r--src/emoji/EmojiModel.cpp69
-rw-r--r--src/emoji/EmojiModel.h26
-rw-r--r--src/emoji/MacHelper.h4
-rw-r--r--src/emoji/Provider.h46
-rw-r--r--src/main.cpp403
-rw-r--r--src/notifications/Manager.cpp48
-rw-r--r--src/notifications/Manager.h82
-rw-r--r--src/notifications/ManagerLinux.cpp357
-rw-r--r--src/notifications/ManagerMac.cpp70
-rw-r--r--src/notifications/ManagerWin.cpp100
-rw-r--r--src/timeline/CommunitiesModel.cpp373
-rw-r--r--src/timeline/CommunitiesModel.h102
-rw-r--r--src/timeline/DelegateChooser.cpp115
-rw-r--r--src/timeline/DelegateChooser.h94
-rw-r--r--src/timeline/EventStore.cpp1389
-rw-r--r--src/timeline/EventStore.h230
-rw-r--r--src/timeline/InputBar.cpp1224
-rw-r--r--src/timeline/InputBar.h172
-rw-r--r--src/timeline/Permissions.cpp34
-rw-r--r--src/timeline/Permissions.h24
-rw-r--r--src/timeline/Reaction.h26
-rw-r--r--src/timeline/RoomlistModel.cpp1595
-rw-r--r--src/timeline/RoomlistModel.h310
-rw-r--r--src/timeline/TimelineModel.cpp3135
-rw-r--r--src/timeline/TimelineModel.h727
-rw-r--r--src/timeline/TimelineViewManager.cpp967
-rw-r--r--src/timeline/TimelineViewManager.h174
-rw-r--r--src/ui/Badge.cpp168
-rw-r--r--src/ui/Badge.h72
-rw-r--r--src/ui/DropShadow.cpp155
-rw-r--r--src/ui/DropShadow.h20
-rw-r--r--src/ui/FlatButton.cpp653
-rw-r--r--src/ui/FlatButton.h255
-rw-r--r--src/ui/FloatingButton.cpp106
-rw-r--r--src/ui/FloatingButton.h14
-rw-r--r--src/ui/InfoMessage.cpp58
-rw-r--r--src/ui/InfoMessage.h52
-rw-r--r--src/ui/Label.cpp14
-rw-r--r--src/ui/Label.h22
-rw-r--r--src/ui/LoadingIndicator.cpp64
-rw-r--r--src/ui/LoadingIndicator.h30
-rw-r--r--src/ui/Menu.h16
-rw-r--r--src/ui/MxcAnimatedImage.cpp279
-rw-r--r--src/ui/MxcAnimatedImage.h124
-rw-r--r--src/ui/MxcMediaProxy.cpp209
-rw-r--r--src/ui/MxcMediaProxy.h95
-rw-r--r--src/ui/NhekoCursorShape.cpp12
-rw-r--r--src/ui/NhekoCursorShape.h16
-rw-r--r--src/ui/NhekoDropArea.cpp16
-rw-r--r--src/ui/NhekoDropArea.h30
-rw-r--r--src/ui/NhekoGlobalObject.cpp58
-rw-r--r--src/ui/NhekoGlobalObject.h66
-rw-r--r--src/ui/OverlayModal.cpp46
-rw-r--r--src/ui/OverlayModal.h26
-rw-r--r--src/ui/OverlayWidget.cpp78
-rw-r--r--src/ui/OverlayWidget.h12
-rw-r--r--src/ui/Painter.h260
-rw-r--r--src/ui/RaisedButton.cpp96
-rw-r--r--src/ui/RaisedButton.h20
-rw-r--r--src/ui/Ripple.cpp72
-rw-r--r--src/ui/Ripple.h98
-rw-r--r--src/ui/RippleOverlay.cpp46
-rw-r--r--src/ui/RippleOverlay.h38
-rw-r--r--src/ui/RoomSettings.cpp893
-rw-r--r--src/ui/RoomSettings.h168
-rw-r--r--src/ui/SnackBar.cpp128
-rw-r--r--src/ui/SnackBar.h100
-rw-r--r--src/ui/TextField.cpp416
-rw-r--r--src/ui/TextField.h168
-rw-r--r--src/ui/TextLabel.cpp128
-rw-r--r--src/ui/TextLabel.h40
-rw-r--r--src/ui/Theme.cpp116
-rw-r--r--src/ui/Theme.h56
-rw-r--r--src/ui/ThemeManager.cpp56
-rw-r--r--src/ui/ThemeManager.h16
-rw-r--r--src/ui/ToggleButton.cpp178
-rw-r--r--src/ui/ToggleButton.h110
-rw-r--r--src/ui/UserProfile.cpp512
-rw-r--r--src/ui/UserProfile.h201
165 files changed, 24152 insertions, 24981 deletions
diff --git a/.clang-format b/.clang-format
index 059aee19..b5e2f017 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1,14 +1,14 @@
 ---
 Language: Cpp
-Standard: Cpp11
-AccessModifierOffset: -8
+Standard: c++17
+AccessModifierOffset: -4
 AlignAfterOpenBracket: Align
 AlignConsecutiveAssignments: true
 AllowShortFunctionsOnASingleLine: true
 BasedOnStyle: Mozilla
 ColumnLimit: 100
 IndentCaseLabels: false
-IndentWidth: 8
+IndentWidth: 4
 KeepEmptyLinesAtTheStartOfBlocks: false
 PointerAlignment: Right
 Cpp11BracedListStyle: true
diff --git a/src/AvatarProvider.cpp b/src/AvatarProvider.cpp
index b9962cef..177bf903 100644
--- a/src/AvatarProvider.cpp
+++ b/src/AvatarProvider.cpp
@@ -22,45 +22,44 @@ namespace AvatarProvider {
 void
 resolve(QString avatarUrl, int size, QObject *receiver, AvatarCallback callback)
 {
-        const auto cacheKey = QString("%1_size_%2").arg(avatarUrl).arg(size);
+    const auto cacheKey = QString("%1_size_%2").arg(avatarUrl).arg(size);
 
-        QPixmap pixmap;
-        if (avatarUrl.isEmpty()) {
-                callback(pixmap);
-                return;
-        }
+    QPixmap pixmap;
+    if (avatarUrl.isEmpty()) {
+        callback(pixmap);
+        return;
+    }
 
-        if (avatar_cache.find(cacheKey, &pixmap)) {
-                callback(pixmap);
-                return;
-        }
+    if (avatar_cache.find(cacheKey, &pixmap)) {
+        callback(pixmap);
+        return;
+    }
 
-        MxcImageProvider::download(avatarUrl.remove(QStringLiteral("mxc://")),
-                                   QSize(size, size),
-                                   [callback, cacheKey, recv = QPointer<QObject>(receiver)](
-                                     QString, QSize, QImage img, QString) {
-                                           if (!recv)
-                                                   return;
+    MxcImageProvider::download(avatarUrl.remove(QStringLiteral("mxc://")),
+                               QSize(size, size),
+                               [callback, cacheKey, recv = QPointer<QObject>(receiver)](
+                                 QString, QSize, QImage img, QString) {
+                                   if (!recv)
+                                       return;
 
-                                           auto proxy = std::make_shared<AvatarProxy>();
-                                           QObject::connect(proxy.get(),
-                                                            &AvatarProxy::avatarDownloaded,
-                                                            recv,
-                                                            [callback, cacheKey](QPixmap pm) {
-                                                                    if (!pm.isNull())
-                                                                            avatar_cache.insert(
-                                                                              cacheKey, pm);
-                                                                    callback(pm);
-                                                            });
+                                   auto proxy = std::make_shared<AvatarProxy>();
+                                   QObject::connect(proxy.get(),
+                                                    &AvatarProxy::avatarDownloaded,
+                                                    recv,
+                                                    [callback, cacheKey](QPixmap pm) {
+                                                        if (!pm.isNull())
+                                                            avatar_cache.insert(cacheKey, pm);
+                                                        callback(pm);
+                                                    });
 
-                                           if (img.isNull()) {
-                                                   emit proxy->avatarDownloaded(QPixmap{});
-                                                   return;
-                                           }
+                                   if (img.isNull()) {
+                                       emit proxy->avatarDownloaded(QPixmap{});
+                                       return;
+                                   }
 
-                                           auto pm = QPixmap::fromImage(std::move(img));
-                                           emit proxy->avatarDownloaded(pm);
-                                   });
+                                   auto pm = QPixmap::fromImage(std::move(img));
+                                   emit proxy->avatarDownloaded(pm);
+                               });
 }
 
 void
@@ -70,8 +69,8 @@ resolve(const QString &room_id,
         QObject *receiver,
         AvatarCallback callback)
 {
-        auto avatarUrl = cache::avatarUrl(room_id, user_id);
+    auto avatarUrl = cache::avatarUrl(room_id, user_id);
 
-        resolve(std::move(avatarUrl), size, receiver, callback);
+    resolve(std::move(avatarUrl), size, receiver, callback);
 }
 }
diff --git a/src/AvatarProvider.h b/src/AvatarProvider.h
index 173a2fba..efd0f330 100644
--- a/src/AvatarProvider.h
+++ b/src/AvatarProvider.h
@@ -12,10 +12,10 @@ using AvatarCallback = std::function<void(QPixmap)>;
 
 class AvatarProxy : public QObject
 {
-        Q_OBJECT
+    Q_OBJECT
 
 signals:
-        void avatarDownloaded(QPixmap pm);
+    void avatarDownloaded(QPixmap pm);
 };
 
 namespace AvatarProvider {
diff --git a/src/BlurhashProvider.cpp b/src/BlurhashProvider.cpp
index aef618a2..e905474a 100644
--- a/src/BlurhashProvider.cpp
+++ b/src/BlurhashProvider.cpp
@@ -13,33 +13,33 @@
 void
 BlurhashResponse::run()
 {
-        if (m_requestedSize.width() < 0 || m_requestedSize.height() < 0) {
-                m_error = QStringLiteral("Blurhash needs size request");
-                emit finished();
-                return;
-        }
-        if (m_requestedSize.width() == 0 || m_requestedSize.height() == 0) {
-                m_image = QImage(m_requestedSize, QImage::Format_RGB32);
-                m_image.fill(QColor(0, 0, 0));
-                emit finished();
-                return;
-        }
-
-        auto decoded = blurhash::decode(QUrl::fromPercentEncoding(m_id.toUtf8()).toStdString(),
-                                        m_requestedSize.width(),
-                                        m_requestedSize.height());
-        if (decoded.image.empty()) {
-                m_error = QStringLiteral("Failed decode!");
-                emit finished();
-                return;
-        }
-
-        QImage image(decoded.image.data(),
-                     (int)decoded.width,
-                     (int)decoded.height,
-                     (int)decoded.width * 3,
-                     QImage::Format_RGB888);
-
-        m_image = image.copy();
+    if (m_requestedSize.width() < 0 || m_requestedSize.height() < 0) {
+        m_error = QStringLiteral("Blurhash needs size request");
         emit finished();
+        return;
+    }
+    if (m_requestedSize.width() == 0 || m_requestedSize.height() == 0) {
+        m_image = QImage(m_requestedSize, QImage::Format_RGB32);
+        m_image.fill(QColor(0, 0, 0));
+        emit finished();
+        return;
+    }
+
+    auto decoded = blurhash::decode(QUrl::fromPercentEncoding(m_id.toUtf8()).toStdString(),
+                                    m_requestedSize.width(),
+                                    m_requestedSize.height());
+    if (decoded.image.empty()) {
+        m_error = QStringLiteral("Failed decode!");
+        emit finished();
+        return;
+    }
+
+    QImage image(decoded.image.data(),
+                 (int)decoded.width,
+                 (int)decoded.height,
+                 (int)decoded.width * 3,
+                 QImage::Format_RGB888);
+
+    m_image = image.copy();
+    emit finished();
 }
diff --git a/src/BlurhashProvider.h b/src/BlurhashProvider.h
index ee89302c..1c8351f2 100644
--- a/src/BlurhashProvider.h
+++ b/src/BlurhashProvider.h
@@ -15,41 +15,41 @@ class BlurhashResponse
   , public QRunnable
 {
 public:
-        BlurhashResponse(const QString &id, const QSize &requestedSize)
+    BlurhashResponse(const QString &id, const QSize &requestedSize)
 
-          : m_id(id)
-          , m_requestedSize(requestedSize)
-        {
-                setAutoDelete(false);
-        }
+      : m_id(id)
+      , m_requestedSize(requestedSize)
+    {
+        setAutoDelete(false);
+    }
 
-        QQuickTextureFactory *textureFactory() const override
-        {
-                return QQuickTextureFactory::textureFactoryForImage(m_image);
-        }
-        QString errorString() const override { return m_error; }
+    QQuickTextureFactory *textureFactory() const override
+    {
+        return QQuickTextureFactory::textureFactoryForImage(m_image);
+    }
+    QString errorString() const override { return m_error; }
 
-        void run() override;
+    void run() override;
 
-        QString m_id, m_error;
-        QSize m_requestedSize;
-        QImage m_image;
+    QString m_id, m_error;
+    QSize m_requestedSize;
+    QImage m_image;
 };
 
 class BlurhashProvider
   : public QObject
   , public QQuickAsyncImageProvider
 {
-        Q_OBJECT
+    Q_OBJECT
 public slots:
-        QQuickImageResponse *requestImageResponse(const QString &id,
-                                                  const QSize &requestedSize) override
-        {
-                BlurhashResponse *response = new BlurhashResponse(id, requestedSize);
-                pool.start(response);
-                return response;
-        }
+    QQuickImageResponse *requestImageResponse(const QString &id,
+                                              const QSize &requestedSize) override
+    {
+        BlurhashResponse *response = new BlurhashResponse(id, requestedSize);
+        pool.start(response);
+        return response;
+    }
 
 private:
-        QThreadPool pool;
+    QThreadPool pool;
 };
diff --git a/src/Cache.cpp b/src/Cache.cpp
index 9ebc61b9..b124fe5e 100644
--- a/src/Cache.cpp
+++ b/src/Cache.cpp
@@ -97,55 +97,55 @@ std::unique_ptr<Cache> instance_ = nullptr;
 
 struct RO_txn
 {
-        ~RO_txn() { txn.reset(); }
-        operator MDB_txn *() const noexcept { return txn.handle(); }
-        operator lmdb::txn &() noexcept { return txn; }
+    ~RO_txn() { txn.reset(); }
+    operator MDB_txn *() const noexcept { return txn.handle(); }
+    operator lmdb::txn &() noexcept { return txn; }
 
-        lmdb::txn &txn;
+    lmdb::txn &txn;
 };
 
 RO_txn
 ro_txn(lmdb::env &env)
 {
-        thread_local lmdb::txn txn     = lmdb::txn::begin(env, nullptr, MDB_RDONLY);
-        thread_local int reuse_counter = 0;
+    thread_local lmdb::txn txn     = lmdb::txn::begin(env, nullptr, MDB_RDONLY);
+    thread_local int reuse_counter = 0;
 
-        if (reuse_counter >= 100 || txn.env() != env.handle()) {
-                txn.abort();
-                txn           = lmdb::txn::begin(env, nullptr, MDB_RDONLY);
-                reuse_counter = 0;
-        } else if (reuse_counter > 0) {
-                try {
-                        txn.renew();
-                } catch (...) {
-                        txn.abort();
-                        txn           = lmdb::txn::begin(env, nullptr, MDB_RDONLY);
-                        reuse_counter = 0;
-                }
+    if (reuse_counter >= 100 || txn.env() != env.handle()) {
+        txn.abort();
+        txn           = lmdb::txn::begin(env, nullptr, MDB_RDONLY);
+        reuse_counter = 0;
+    } else if (reuse_counter > 0) {
+        try {
+            txn.renew();
+        } catch (...) {
+            txn.abort();
+            txn           = lmdb::txn::begin(env, nullptr, MDB_RDONLY);
+            reuse_counter = 0;
         }
-        reuse_counter++;
+    }
+    reuse_counter++;
 
-        return RO_txn{txn};
+    return RO_txn{txn};
 }
 
 template<class T>
 bool
 containsStateUpdates(const T &e)
 {
-        return std::visit([](const auto &ev) { return Cache::isStateEvent_<decltype(ev)>; }, e);
+    return std::visit([](const auto &ev) { return Cache::isStateEvent_<decltype(ev)>; }, e);
 }
 
 bool
 containsStateUpdates(const mtx::events::collections::StrippedEvents &e)
 {
-        using namespace mtx::events;
-        using namespace mtx::events::state;
+    using namespace mtx::events;
+    using namespace mtx::events::state;
 
-        return std::holds_alternative<StrippedEvent<state::Avatar>>(e) ||
-               std::holds_alternative<StrippedEvent<CanonicalAlias>>(e) ||
-               std::holds_alternative<StrippedEvent<Name>>(e) ||
-               std::holds_alternative<StrippedEvent<Member>>(e) ||
-               std::holds_alternative<StrippedEvent<Topic>>(e);
+    return std::holds_alternative<StrippedEvent<state::Avatar>>(e) ||
+           std::holds_alternative<StrippedEvent<CanonicalAlias>>(e) ||
+           std::holds_alternative<StrippedEvent<Name>>(e) ||
+           std::holds_alternative<StrippedEvent<Member>>(e) ||
+           std::holds_alternative<StrippedEvent<Topic>>(e);
 }
 
 bool
@@ -153,45 +153,45 @@ Cache::isHiddenEvent(lmdb::txn &txn,
                      mtx::events::collections::TimelineEvents e,
                      const std::string &room_id)
 {
-        using namespace mtx::events;
-
-        // Always hide edits
-        if (mtx::accessors::relations(e).replaces())
-                return true;
-
-        if (auto encryptedEvent = std::get_if<EncryptedEvent<msg::Encrypted>>(&e)) {
-                MegolmSessionIndex index;
-                index.room_id    = room_id;
-                index.session_id = encryptedEvent->content.session_id;
-                index.sender_key = encryptedEvent->content.sender_key;
+    using namespace mtx::events;
 
-                auto result = olm::decryptEvent(index, *encryptedEvent, true);
-                if (!result.error)
-                        e = result.event.value();
-        }
+    // Always hide edits
+    if (mtx::accessors::relations(e).replaces())
+        return true;
 
-        mtx::events::account_data::nheko_extensions::HiddenEvents hiddenEvents;
-        hiddenEvents.hidden_event_types = {
-          EventType::Reaction, EventType::CallCandidates, EventType::Unsupported};
-
-        if (auto temp = getAccountData(txn, mtx::events::EventType::NhekoHiddenEvents, ""))
-                hiddenEvents =
-                  std::move(std::get<mtx::events::AccountDataEvent<
-                              mtx::events::account_data::nheko_extensions::HiddenEvents>>(*temp)
-                              .content);
-        if (auto temp = getAccountData(txn, mtx::events::EventType::NhekoHiddenEvents, room_id))
-                hiddenEvents =
-                  std::move(std::get<mtx::events::AccountDataEvent<
-                              mtx::events::account_data::nheko_extensions::HiddenEvents>>(*temp)
-                              .content);
-
-        return std::visit(
-          [hiddenEvents](const auto &ev) {
-                  return std::any_of(hiddenEvents.hidden_event_types.begin(),
-                                     hiddenEvents.hidden_event_types.end(),
-                                     [ev](EventType type) { return type == ev.type; });
-          },
-          e);
+    if (auto encryptedEvent = std::get_if<EncryptedEvent<msg::Encrypted>>(&e)) {
+        MegolmSessionIndex index;
+        index.room_id    = room_id;
+        index.session_id = encryptedEvent->content.session_id;
+        index.sender_key = encryptedEvent->content.sender_key;
+
+        auto result = olm::decryptEvent(index, *encryptedEvent, true);
+        if (!result.error)
+            e = result.event.value();
+    }
+
+    mtx::events::account_data::nheko_extensions::HiddenEvents hiddenEvents;
+    hiddenEvents.hidden_event_types = {
+      EventType::Reaction, EventType::CallCandidates, EventType::Unsupported};
+
+    if (auto temp = getAccountData(txn, mtx::events::EventType::NhekoHiddenEvents, ""))
+        hiddenEvents =
+          std::move(std::get<mtx::events::AccountDataEvent<
+                      mtx::events::account_data::nheko_extensions::HiddenEvents>>(*temp)
+                      .content);
+    if (auto temp = getAccountData(txn, mtx::events::EventType::NhekoHiddenEvents, room_id))
+        hiddenEvents =
+          std::move(std::get<mtx::events::AccountDataEvent<
+                      mtx::events::account_data::nheko_extensions::HiddenEvents>>(*temp)
+                      .content);
+
+    return std::visit(
+      [hiddenEvents](const auto &ev) {
+          return std::any_of(hiddenEvents.hidden_event_types.begin(),
+                             hiddenEvents.hidden_event_types.end(),
+                             [ev](EventType type) { return type == ev.type; });
+      },
+      e);
 }
 
 Cache::Cache(const QString &userId, QObject *parent)
@@ -199,218 +199,210 @@ Cache::Cache(const QString &userId, QObject *parent)
   , env_{nullptr}
   , localUserId_{userId}
 {
-        setup();
-        connect(this, &Cache::userKeysUpdate, this, &Cache::updateUserKeys, Qt::QueuedConnection);
+    setup();
+    connect(this, &Cache::userKeysUpdate, this, &Cache::updateUserKeys, Qt::QueuedConnection);
 }
 
 void
 Cache::setup()
 {
-        auto settings = UserSettings::instance();
+    auto settings = UserSettings::instance();
 
-        nhlog::db()->debug("setting up cache");
+    nhlog::db()->debug("setting up cache");
 
-        // Previous location of the cache directory
-        auto oldCache = QString("%1/%2%3")
-                          .arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))
-                          .arg(QString::fromUtf8(localUserId_.toUtf8().toHex()))
-                          .arg(QString::fromUtf8(settings->profile().toUtf8().toHex()));
+    // Previous location of the cache directory
+    auto oldCache = QString("%1/%2%3")
+                      .arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))
+                      .arg(QString::fromUtf8(localUserId_.toUtf8().toHex()))
+                      .arg(QString::fromUtf8(settings->profile().toUtf8().toHex()));
 
-        cacheDirectory_ = QString("%1/%2%3")
-                            .arg(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation))
-                            .arg(QString::fromUtf8(localUserId_.toUtf8().toHex()))
-                            .arg(QString::fromUtf8(settings->profile().toUtf8().toHex()));
+    cacheDirectory_ = QString("%1/%2%3")
+                        .arg(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation))
+                        .arg(QString::fromUtf8(localUserId_.toUtf8().toHex()))
+                        .arg(QString::fromUtf8(settings->profile().toUtf8().toHex()));
 
-        bool isInitial = !QFile::exists(cacheDirectory_);
+    bool isInitial = !QFile::exists(cacheDirectory_);
 
-        // NOTE: If both cache directories exist it's better to do nothing: it
-        // could mean a previous migration failed or was interrupted.
-        bool needsMigration = isInitial && QFile::exists(oldCache);
+    // NOTE: If both cache directories exist it's better to do nothing: it
+    // could mean a previous migration failed or was interrupted.
+    bool needsMigration = isInitial && QFile::exists(oldCache);
 
-        if (needsMigration) {
-                nhlog::db()->info("found old state directory, migrating");
-                if (!QDir().rename(oldCache, cacheDirectory_)) {
-                        throw std::runtime_error(("Unable to migrate the old state directory (" +
-                                                  oldCache + ") to the new location (" +
-                                                  cacheDirectory_ + ")")
-                                                   .toStdString()
-                                                   .c_str());
-                }
-                nhlog::db()->info("completed state migration");
+    if (needsMigration) {
+        nhlog::db()->info("found old state directory, migrating");
+        if (!QDir().rename(oldCache, cacheDirectory_)) {
+            throw std::runtime_error(("Unable to migrate the old state directory (" + oldCache +
+                                      ") to the new location (" + cacheDirectory_ + ")")
+                                       .toStdString()
+                                       .c_str());
         }
+        nhlog::db()->info("completed state migration");
+    }
 
-        env_ = lmdb::env::create();
-        env_.set_mapsize(DB_SIZE);
-        env_.set_max_dbs(MAX_DBS);
+    env_ = lmdb::env::create();
+    env_.set_mapsize(DB_SIZE);
+    env_.set_max_dbs(MAX_DBS);
 
-        if (isInitial) {
-                nhlog::db()->info("initializing LMDB");
+    if (isInitial) {
+        nhlog::db()->info("initializing LMDB");
 
-                if (!QDir().mkpath(cacheDirectory_)) {
-                        throw std::runtime_error(
-                          ("Unable to create state directory:" + cacheDirectory_)
-                            .toStdString()
-                            .c_str());
-                }
+        if (!QDir().mkpath(cacheDirectory_)) {
+            throw std::runtime_error(
+              ("Unable to create state directory:" + cacheDirectory_).toStdString().c_str());
         }
+    }
 
-        try {
-                // NOTE(Nico): We may want to use (MDB_MAPASYNC | MDB_WRITEMAP) in the future, but
-                // it can really mess up our database, so we shouldn't. For now, hopefully
-                // NOMETASYNC is fast enough.
-                env_.open(cacheDirectory_.toStdString().c_str(), MDB_NOMETASYNC | MDB_NOSYNC);
-        } catch (const lmdb::error &e) {
-                if (e.code() != MDB_VERSION_MISMATCH && e.code() != MDB_INVALID) {
-                        throw std::runtime_error("LMDB initialization failed" +
-                                                 std::string(e.what()));
-                }
+    try {
+        // NOTE(Nico): We may want to use (MDB_MAPASYNC | MDB_WRITEMAP) in the future, but
+        // it can really mess up our database, so we shouldn't. For now, hopefully
+        // NOMETASYNC is fast enough.
+        env_.open(cacheDirectory_.toStdString().c_str(), MDB_NOMETASYNC | MDB_NOSYNC);
+    } catch (const lmdb::error &e) {
+        if (e.code() != MDB_VERSION_MISMATCH && e.code() != MDB_INVALID) {
+            throw std::runtime_error("LMDB initialization failed" + std::string(e.what()));
+        }
 
-                nhlog::db()->warn("resetting cache due to LMDB version mismatch: {}", e.what());
+        nhlog::db()->warn("resetting cache due to LMDB version mismatch: {}", e.what());
 
-                QDir stateDir(cacheDirectory_);
+        QDir stateDir(cacheDirectory_);
 
-                for (const auto &file : stateDir.entryList(QDir::NoDotAndDotDot)) {
-                        if (!stateDir.remove(file))
-                                throw std::runtime_error(
-                                  ("Unable to delete file " + file).toStdString().c_str());
-                }
-                env_.open(cacheDirectory_.toStdString().c_str());
+        for (const auto &file : stateDir.entryList(QDir::NoDotAndDotDot)) {
+            if (!stateDir.remove(file))
+                throw std::runtime_error(("Unable to delete file " + file).toStdString().c_str());
         }
+        env_.open(cacheDirectory_.toStdString().c_str());
+    }
 
-        auto txn          = lmdb::txn::begin(env_);
-        syncStateDb_      = lmdb::dbi::open(txn, SYNC_STATE_DB, MDB_CREATE);
-        roomsDb_          = lmdb::dbi::open(txn, ROOMS_DB, MDB_CREATE);
-        spacesChildrenDb_ = lmdb::dbi::open(txn, SPACES_CHILDREN_DB, MDB_CREATE | MDB_DUPSORT);
-        spacesParentsDb_  = lmdb::dbi::open(txn, SPACES_PARENTS_DB, MDB_CREATE | MDB_DUPSORT);
-        invitesDb_        = lmdb::dbi::open(txn, INVITES_DB, MDB_CREATE);
-        readReceiptsDb_   = lmdb::dbi::open(txn, READ_RECEIPTS_DB, MDB_CREATE);
-        notificationsDb_  = lmdb::dbi::open(txn, NOTIFICATIONS_DB, MDB_CREATE);
-
-        // Device management
-        devicesDb_    = lmdb::dbi::open(txn, DEVICES_DB, MDB_CREATE);
-        deviceKeysDb_ = lmdb::dbi::open(txn, DEVICE_KEYS_DB, MDB_CREATE);
-
-        // Session management
-        inboundMegolmSessionDb_  = lmdb::dbi::open(txn, INBOUND_MEGOLM_SESSIONS_DB, MDB_CREATE);
-        outboundMegolmSessionDb_ = lmdb::dbi::open(txn, OUTBOUND_MEGOLM_SESSIONS_DB, MDB_CREATE);
-        megolmSessionDataDb_     = lmdb::dbi::open(txn, MEGOLM_SESSIONS_DATA_DB, MDB_CREATE);
-
-        // What rooms are encrypted
-        encryptedRooms_                      = lmdb::dbi::open(txn, ENCRYPTED_ROOMS_DB, MDB_CREATE);
-        [[maybe_unused]] auto verificationDb = getVerificationDb(txn);
-        [[maybe_unused]] auto userKeysDb     = getUserKeysDb(txn);
+    auto txn          = lmdb::txn::begin(env_);
+    syncStateDb_      = lmdb::dbi::open(txn, SYNC_STATE_DB, MDB_CREATE);
+    roomsDb_          = lmdb::dbi::open(txn, ROOMS_DB, MDB_CREATE);
+    spacesChildrenDb_ = lmdb::dbi::open(txn, SPACES_CHILDREN_DB, MDB_CREATE | MDB_DUPSORT);
+    spacesParentsDb_  = lmdb::dbi::open(txn, SPACES_PARENTS_DB, MDB_CREATE | MDB_DUPSORT);
+    invitesDb_        = lmdb::dbi::open(txn, INVITES_DB, MDB_CREATE);
+    readReceiptsDb_   = lmdb::dbi::open(txn, READ_RECEIPTS_DB, MDB_CREATE);
+    notificationsDb_  = lmdb::dbi::open(txn, NOTIFICATIONS_DB, MDB_CREATE);
 
-        txn.commit();
+    // Device management
+    devicesDb_    = lmdb::dbi::open(txn, DEVICES_DB, MDB_CREATE);
+    deviceKeysDb_ = lmdb::dbi::open(txn, DEVICE_KEYS_DB, MDB_CREATE);
+
+    // Session management
+    inboundMegolmSessionDb_  = lmdb::dbi::open(txn, INBOUND_MEGOLM_SESSIONS_DB, MDB_CREATE);
+    outboundMegolmSessionDb_ = lmdb::dbi::open(txn, OUTBOUND_MEGOLM_SESSIONS_DB, MDB_CREATE);
+    megolmSessionDataDb_     = lmdb::dbi::open(txn, MEGOLM_SESSIONS_DATA_DB, MDB_CREATE);
+
+    // What rooms are encrypted
+    encryptedRooms_                      = lmdb::dbi::open(txn, ENCRYPTED_ROOMS_DB, MDB_CREATE);
+    [[maybe_unused]] auto verificationDb = getVerificationDb(txn);
+    [[maybe_unused]] auto userKeysDb     = getUserKeysDb(txn);
 
-        databaseReady_ = true;
+    txn.commit();
+
+    databaseReady_ = true;
 }
 
 void
 Cache::setEncryptedRoom(lmdb::txn &txn, const std::string &room_id)
 {
-        nhlog::db()->info("mark room {} as encrypted", room_id);
+    nhlog::db()->info("mark room {} as encrypted", room_id);
 
-        encryptedRooms_.put(txn, room_id, "0");
+    encryptedRooms_.put(txn, room_id, "0");
 }
 
 bool
 Cache::isRoomEncrypted(const std::string &room_id)
 {
-        std::string_view unused;
+    std::string_view unused;
 
-        auto txn = ro_txn(env_);
-        auto res = encryptedRooms_.get(txn, room_id, unused);
+    auto txn = ro_txn(env_);
+    auto res = encryptedRooms_.get(txn, room_id, unused);
 
-        return res;
+    return res;
 }
 
 std::optional<mtx::events::state::Encryption>
 Cache::roomEncryptionSettings(const std::string &room_id)
 {
-        using namespace mtx::events;
-        using namespace mtx::events::state;
+    using namespace mtx::events;
+    using namespace mtx::events::state;
 
-        try {
-                auto txn      = ro_txn(env_);
-                auto statesdb = getStatesDb(txn, room_id);
-                std::string_view event;
-                bool res =
-                  statesdb.get(txn, to_string(mtx::events::EventType::RoomEncryption), event);
-
-                if (res) {
-                        try {
-                                StateEvent<Encryption> msg = json::parse(event);
-
-                                return msg.content;
-                        } catch (const json::exception &e) {
-                                nhlog::db()->warn("failed to parse m.room.encryption event: {}",
-                                                  e.what());
-                                return Encryption{};
-                        }
-                }
-        } catch (lmdb::error &) {
+    try {
+        auto txn      = ro_txn(env_);
+        auto statesdb = getStatesDb(txn, room_id);
+        std::string_view event;
+        bool res = statesdb.get(txn, to_string(mtx::events::EventType::RoomEncryption), event);
+
+        if (res) {
+            try {
+                StateEvent<Encryption> msg = json::parse(event);
+
+                return msg.content;
+            } catch (const json::exception &e) {
+                nhlog::db()->warn("failed to parse m.room.encryption event: {}", e.what());
+                return Encryption{};
+            }
         }
+    } catch (lmdb::error &) {
+    }
 
-        return std::nullopt;
+    return std::nullopt;
 }
 
 mtx::crypto::ExportedSessionKeys
 Cache::exportSessionKeys()
 {
-        using namespace mtx::crypto;
+    using namespace mtx::crypto;
 
-        ExportedSessionKeys keys;
+    ExportedSessionKeys keys;
 
-        auto txn    = ro_txn(env_);
-        auto cursor = lmdb::cursor::open(txn, inboundMegolmSessionDb_);
+    auto txn    = ro_txn(env_);
+    auto cursor = lmdb::cursor::open(txn, inboundMegolmSessionDb_);
 
-        std::string_view key, value;
-        while (cursor.get(key, value, MDB_NEXT)) {
-                ExportedSession exported;
-                MegolmSessionIndex index;
+    std::string_view key, value;
+    while (cursor.get(key, value, MDB_NEXT)) {
+        ExportedSession exported;
+        MegolmSessionIndex index;
 
-                auto saved_session =
-                  unpickle<InboundSessionObject>(std::string(value), pickle_secret_);
+        auto saved_session = unpickle<InboundSessionObject>(std::string(value), pickle_secret_);
 
-                try {
-                        index = nlohmann::json::parse(key).get<MegolmSessionIndex>();
-                } catch (const nlohmann::json::exception &e) {
-                        nhlog::db()->critical("failed to export megolm session: {}", e.what());
-                        continue;
-                }
+        try {
+            index = nlohmann::json::parse(key).get<MegolmSessionIndex>();
+        } catch (const nlohmann::json::exception &e) {
+            nhlog::db()->critical("failed to export megolm session: {}", e.what());
+            continue;
+        }
 
-                exported.room_id     = index.room_id;
-                exported.sender_key  = index.sender_key;
-                exported.session_id  = index.session_id;
-                exported.session_key = export_session(saved_session.get(), -1);
+        exported.room_id     = index.room_id;
+        exported.sender_key  = index.sender_key;
+        exported.session_id  = index.session_id;
+        exported.session_key = export_session(saved_session.get(), -1);
 
-                keys.sessions.push_back(exported);
-        }
+        keys.sessions.push_back(exported);
+    }
 
-        cursor.close();
+    cursor.close();
 
-        return keys;
+    return keys;
 }
 
 void
 Cache::importSessionKeys(const mtx::crypto::ExportedSessionKeys &keys)
 {
-        for (const auto &s : keys.sessions) {
-                MegolmSessionIndex index;
-                index.room_id    = s.room_id;
-                index.session_id = s.session_id;
-                index.sender_key = s.sender_key;
+    for (const auto &s : keys.sessions) {
+        MegolmSessionIndex index;
+        index.room_id    = s.room_id;
+        index.session_id = s.session_id;
+        index.sender_key = s.sender_key;
 
-                GroupSessionData data{};
-                data.forwarding_curve25519_key_chain = s.forwarding_curve25519_key_chain;
-                if (s.sender_claimed_keys.count("ed25519"))
-                        data.sender_claimed_ed25519_key = s.sender_claimed_keys.at("ed25519");
+        GroupSessionData data{};
+        data.forwarding_curve25519_key_chain = s.forwarding_curve25519_key_chain;
+        if (s.sender_claimed_keys.count("ed25519"))
+            data.sender_claimed_ed25519_key = s.sender_claimed_keys.at("ed25519");
 
-                auto exported_session = mtx::crypto::import_session(s.session_key);
+        auto exported_session = mtx::crypto::import_session(s.session_key);
 
-                saveInboundMegolmSession(index, std::move(exported_session), data);
-                ChatPage::instance()->receivedSessionKey(index.room_id, index.session_id);
-        }
+        saveInboundMegolmSession(index, std::move(exported_session), data);
+        ChatPage::instance()->receivedSessionKey(index.room_id, index.session_id);
+    }
 }
 
 //
@@ -422,67 +414,64 @@ Cache::saveInboundMegolmSession(const MegolmSessionIndex &index,
                                 mtx::crypto::InboundGroupSessionPtr session,
                                 const GroupSessionData &data)
 {
-        using namespace mtx::crypto;
-        const auto key     = json(index).dump();
-        const auto pickled = pickle<InboundSessionObject>(session.get(), pickle_secret_);
+    using namespace mtx::crypto;
+    const auto key     = json(index).dump();
+    const auto pickled = pickle<InboundSessionObject>(session.get(), pickle_secret_);
 
-        auto txn = lmdb::txn::begin(env_);
+    auto txn = lmdb::txn::begin(env_);
 
-        std::string_view value;
-        if (inboundMegolmSessionDb_.get(txn, key, value)) {
-                auto oldSession =
-                  unpickle<InboundSessionObject>(std::string(value), pickle_secret_);
-                if (olm_inbound_group_session_first_known_index(session.get()) >
-                    olm_inbound_group_session_first_known_index(oldSession.get())) {
-                        nhlog::crypto()->warn(
-                          "Not storing inbound session with newer first known index");
-                        return;
-                }
+    std::string_view value;
+    if (inboundMegolmSessionDb_.get(txn, key, value)) {
+        auto oldSession = unpickle<InboundSessionObject>(std::string(value), pickle_secret_);
+        if (olm_inbound_group_session_first_known_index(session.get()) >
+            olm_inbound_group_session_first_known_index(oldSession.get())) {
+            nhlog::crypto()->warn("Not storing inbound session with newer first known index");
+            return;
         }
+    }
 
-        inboundMegolmSessionDb_.put(txn, key, pickled);
-        megolmSessionDataDb_.put(txn, key, json(data).dump());
-        txn.commit();
+    inboundMegolmSessionDb_.put(txn, key, pickled);
+    megolmSessionDataDb_.put(txn, key, json(data).dump());
+    txn.commit();
 }
 
 mtx::crypto::InboundGroupSessionPtr
 Cache::getInboundMegolmSession(const MegolmSessionIndex &index)
 {
-        using namespace mtx::crypto;
+    using namespace mtx::crypto;
 
-        try {
-                auto txn        = ro_txn(env_);
-                std::string key = json(index).dump();
-                std::string_view value;
-
-                if (inboundMegolmSessionDb_.get(txn, key, value)) {
-                        auto session =
-                          unpickle<InboundSessionObject>(std::string(value), pickle_secret_);
-                        return session;
-                }
-        } catch (std::exception &e) {
-                nhlog::db()->error("Failed to get inbound megolm session {}", e.what());
+    try {
+        auto txn        = ro_txn(env_);
+        std::string key = json(index).dump();
+        std::string_view value;
+
+        if (inboundMegolmSessionDb_.get(txn, key, value)) {
+            auto session = unpickle<InboundSessionObject>(std::string(value), pickle_secret_);
+            return session;
         }
+    } catch (std::exception &e) {
+        nhlog::db()->error("Failed to get inbound megolm session {}", e.what());
+    }
 
-        return nullptr;
+    return nullptr;
 }
 
 bool
 Cache::inboundMegolmSessionExists(const MegolmSessionIndex &index)
 {
-        using namespace mtx::crypto;
+    using namespace mtx::crypto;
 
-        try {
-                auto txn        = ro_txn(env_);
-                std::string key = json(index).dump();
-                std::string_view value;
+    try {
+        auto txn        = ro_txn(env_);
+        std::string key = json(index).dump();
+        std::string_view value;
 
-                return inboundMegolmSessionDb_.get(txn, key, value);
-        } catch (std::exception &e) {
-                nhlog::db()->error("Failed to get inbound megolm session {}", e.what());
-        }
+        return inboundMegolmSessionDb_.get(txn, key, value);
+    } catch (std::exception &e) {
+        nhlog::db()->error("Failed to get inbound megolm session {}", e.what());
+    }
 
-        return false;
+    return false;
 }
 
 void
@@ -490,42 +479,42 @@ Cache::updateOutboundMegolmSession(const std::string &room_id,
                                    const GroupSessionData &data_,
                                    mtx::crypto::OutboundGroupSessionPtr &ptr)
 {
-        using namespace mtx::crypto;
+    using namespace mtx::crypto;
 
-        if (!outboundMegolmSessionExists(room_id))
-                return;
+    if (!outboundMegolmSessionExists(room_id))
+        return;
 
-        GroupSessionData data = data_;
-        data.message_index    = olm_outbound_group_session_message_index(ptr.get());
-        MegolmSessionIndex index;
-        index.room_id    = room_id;
-        index.sender_key = olm::client()->identity_keys().ed25519;
-        index.session_id = mtx::crypto::session_id(ptr.get());
+    GroupSessionData data = data_;
+    data.message_index    = olm_outbound_group_session_message_index(ptr.get());
+    MegolmSessionIndex index;
+    index.room_id    = room_id;
+    index.sender_key = olm::client()->identity_keys().ed25519;
+    index.session_id = mtx::crypto::session_id(ptr.get());
 
-        // Save the updated pickled data for the session.
-        json j;
-        j["session"] = pickle<OutboundSessionObject>(ptr.get(), pickle_secret_);
+    // Save the updated pickled data for the session.
+    json j;
+    j["session"] = pickle<OutboundSessionObject>(ptr.get(), pickle_secret_);
 
-        auto txn = lmdb::txn::begin(env_);
-        outboundMegolmSessionDb_.put(txn, room_id, j.dump());
-        megolmSessionDataDb_.put(txn, json(index).dump(), json(data).dump());
-        txn.commit();
+    auto txn = lmdb::txn::begin(env_);
+    outboundMegolmSessionDb_.put(txn, room_id, j.dump());
+    megolmSessionDataDb_.put(txn, json(index).dump(), json(data).dump());
+    txn.commit();
 }
 
 void
 Cache::dropOutboundMegolmSession(const std::string &room_id)
 {
-        using namespace mtx::crypto;
+    using namespace mtx::crypto;
 
-        if (!outboundMegolmSessionExists(room_id))
-                return;
+    if (!outboundMegolmSessionExists(room_id))
+        return;
 
-        {
-                auto txn = lmdb::txn::begin(env_);
-                outboundMegolmSessionDb_.del(txn, room_id);
-                // don't delete session data, so that we can still share the session.
-                txn.commit();
-        }
+    {
+        auto txn = lmdb::txn::begin(env_);
+        outboundMegolmSessionDb_.del(txn, room_id);
+        // don't delete session data, so that we can still share the session.
+        txn.commit();
+    }
 }
 
 void
@@ -533,86 +522,86 @@ Cache::saveOutboundMegolmSession(const std::string &room_id,
                                  const GroupSessionData &data_,
                                  mtx::crypto::OutboundGroupSessionPtr &session)
 {
-        using namespace mtx::crypto;
-        const auto pickled = pickle<OutboundSessionObject>(session.get(), pickle_secret_);
+    using namespace mtx::crypto;
+    const auto pickled = pickle<OutboundSessionObject>(session.get(), pickle_secret_);
 
-        GroupSessionData data = data_;
-        data.message_index    = olm_outbound_group_session_message_index(session.get());
-        MegolmSessionIndex index;
-        index.room_id    = room_id;
-        index.sender_key = olm::client()->identity_keys().ed25519;
-        index.session_id = mtx::crypto::session_id(session.get());
+    GroupSessionData data = data_;
+    data.message_index    = olm_outbound_group_session_message_index(session.get());
+    MegolmSessionIndex index;
+    index.room_id    = room_id;
+    index.sender_key = olm::client()->identity_keys().ed25519;
+    index.session_id = mtx::crypto::session_id(session.get());
 
-        json j;
-        j["session"] = pickled;
+    json j;
+    j["session"] = pickled;
 
-        auto txn = lmdb::txn::begin(env_);
-        outboundMegolmSessionDb_.put(txn, room_id, j.dump());
-        megolmSessionDataDb_.put(txn, json(index).dump(), json(data).dump());
-        txn.commit();
+    auto txn = lmdb::txn::begin(env_);
+    outboundMegolmSessionDb_.put(txn, room_id, j.dump());
+    megolmSessionDataDb_.put(txn, json(index).dump(), json(data).dump());
+    txn.commit();
 }
 
 bool
 Cache::outboundMegolmSessionExists(const std::string &room_id) noexcept
 {
-        try {
-                auto txn = ro_txn(env_);
-                std::string_view value;
-                return outboundMegolmSessionDb_.get(txn, room_id, value);
-        } catch (std::exception &e) {
-                nhlog::db()->error("Failed to retrieve outbound Megolm Session: {}", e.what());
-                return false;
-        }
+    try {
+        auto txn = ro_txn(env_);
+        std::string_view value;
+        return outboundMegolmSessionDb_.get(txn, room_id, value);
+    } catch (std::exception &e) {
+        nhlog::db()->error("Failed to retrieve outbound Megolm Session: {}", e.what());
+        return false;
+    }
 }
 
 OutboundGroupSessionDataRef
 Cache::getOutboundMegolmSession(const std::string &room_id)
 {
-        try {
-                using namespace mtx::crypto;
-
-                auto txn = ro_txn(env_);
-                std::string_view value;
-                outboundMegolmSessionDb_.get(txn, room_id, value);
-                auto obj = json::parse(value);
+    try {
+        using namespace mtx::crypto;
 
-                OutboundGroupSessionDataRef ref{};
-                ref.session = unpickle<OutboundSessionObject>(obj.at("session"), pickle_secret_);
+        auto txn = ro_txn(env_);
+        std::string_view value;
+        outboundMegolmSessionDb_.get(txn, room_id, value);
+        auto obj = json::parse(value);
 
-                MegolmSessionIndex index;
-                index.room_id    = room_id;
-                index.sender_key = olm::client()->identity_keys().ed25519;
-                index.session_id = mtx::crypto::session_id(ref.session.get());
+        OutboundGroupSessionDataRef ref{};
+        ref.session = unpickle<OutboundSessionObject>(obj.at("session"), pickle_secret_);
 
-                if (megolmSessionDataDb_.get(txn, json(index).dump(), value)) {
-                        ref.data = nlohmann::json::parse(value).get<GroupSessionData>();
-                }
+        MegolmSessionIndex index;
+        index.room_id    = room_id;
+        index.sender_key = olm::client()->identity_keys().ed25519;
+        index.session_id = mtx::crypto::session_id(ref.session.get());
 
-                return ref;
-        } catch (std::exception &e) {
-                nhlog::db()->error("Failed to retrieve outbound Megolm Session: {}", e.what());
-                return {};
+        if (megolmSessionDataDb_.get(txn, json(index).dump(), value)) {
+            ref.data = nlohmann::json::parse(value).get<GroupSessionData>();
         }
+
+        return ref;
+    } catch (std::exception &e) {
+        nhlog::db()->error("Failed to retrieve outbound Megolm Session: {}", e.what());
+        return {};
+    }
 }
 
 std::optional<GroupSessionData>
 Cache::getMegolmSessionData(const MegolmSessionIndex &index)
 {
-        try {
-                using namespace mtx::crypto;
-
-                auto txn = ro_txn(env_);
+    try {
+        using namespace mtx::crypto;
 
-                std::string_view value;
-                if (megolmSessionDataDb_.get(txn, json(index).dump(), value)) {
-                        return nlohmann::json::parse(value).get<GroupSessionData>();
-                }
+        auto txn = ro_txn(env_);
 
-                return std::nullopt;
-        } catch (std::exception &e) {
-                nhlog::db()->error("Failed to retrieve Megolm Session Data: {}", e.what());
-                return std::nullopt;
+        std::string_view value;
+        if (megolmSessionDataDb_.get(txn, json(index).dump(), value)) {
+            return nlohmann::json::parse(value).get<GroupSessionData>();
         }
+
+        return std::nullopt;
+    } catch (std::exception &e) {
+        nhlog::db()->error("Failed to retrieve Megolm Session Data: {}", e.what());
+        return std::nullopt;
+    }
 }
 //
 // OLM sessions.
@@ -623,1013 +612,972 @@ Cache::saveOlmSession(const std::string &curve25519,
                       mtx::crypto::OlmSessionPtr session,
                       uint64_t timestamp)
 {
-        using namespace mtx::crypto;
+    using namespace mtx::crypto;
 
-        auto txn = lmdb::txn::begin(env_);
-        auto db  = getOlmSessionsDb(txn, curve25519);
+    auto txn = lmdb::txn::begin(env_);
+    auto db  = getOlmSessionsDb(txn, curve25519);
 
-        const auto pickled    = pickle<SessionObject>(session.get(), pickle_secret_);
-        const auto session_id = mtx::crypto::session_id(session.get());
+    const auto pickled    = pickle<SessionObject>(session.get(), pickle_secret_);
+    const auto session_id = mtx::crypto::session_id(session.get());
 
-        StoredOlmSession stored_session;
-        stored_session.pickled_session = pickled;
-        stored_session.last_message_ts = timestamp;
+    StoredOlmSession stored_session;
+    stored_session.pickled_session = pickled;
+    stored_session.last_message_ts = timestamp;
 
-        db.put(txn, session_id, json(stored_session).dump());
+    db.put(txn, session_id, json(stored_session).dump());
 
-        txn.commit();
+    txn.commit();
 }
 
 std::optional<mtx::crypto::OlmSessionPtr>
 Cache::getOlmSession(const std::string &curve25519, const std::string &session_id)
 {
-        using namespace mtx::crypto;
+    using namespace mtx::crypto;
 
-        auto txn = lmdb::txn::begin(env_);
-        auto db  = getOlmSessionsDb(txn, curve25519);
+    auto txn = lmdb::txn::begin(env_);
+    auto db  = getOlmSessionsDb(txn, curve25519);
 
-        std::string_view pickled;
-        bool found = db.get(txn, session_id, pickled);
+    std::string_view pickled;
+    bool found = db.get(txn, session_id, pickled);
 
-        txn.commit();
+    txn.commit();
 
-        if (found) {
-                auto data = json::parse(pickled).get<StoredOlmSession>();
-                return unpickle<SessionObject>(data.pickled_session, pickle_secret_);
-        }
+    if (found) {
+        auto data = json::parse(pickled).get<StoredOlmSession>();
+        return unpickle<SessionObject>(data.pickled_session, pickle_secret_);
+    }
 
-        return std::nullopt;
+    return std::nullopt;
 }
 
 std::optional<mtx::crypto::OlmSessionPtr>
 Cache::getLatestOlmSession(const std::string &curve25519)
 {
-        using namespace mtx::crypto;
+    using namespace mtx::crypto;
 
-        auto txn = lmdb::txn::begin(env_);
-        auto db  = getOlmSessionsDb(txn, curve25519);
+    auto txn = lmdb::txn::begin(env_);
+    auto db  = getOlmSessionsDb(txn, curve25519);
 
-        std::string_view session_id, pickled_session;
+    std::string_view session_id, pickled_session;
 
-        std::optional<StoredOlmSession> currentNewest;
+    std::optional<StoredOlmSession> currentNewest;
 
-        auto cursor = lmdb::cursor::open(txn, db);
-        while (cursor.get(session_id, pickled_session, MDB_NEXT)) {
-                auto data = json::parse(pickled_session).get<StoredOlmSession>();
-                if (!currentNewest || currentNewest->last_message_ts < data.last_message_ts)
-                        currentNewest = data;
-        }
-        cursor.close();
+    auto cursor = lmdb::cursor::open(txn, db);
+    while (cursor.get(session_id, pickled_session, MDB_NEXT)) {
+        auto data = json::parse(pickled_session).get<StoredOlmSession>();
+        if (!currentNewest || currentNewest->last_message_ts < data.last_message_ts)
+            currentNewest = data;
+    }
+    cursor.close();
 
-        txn.commit();
+    txn.commit();
 
-        return currentNewest ? std::optional(unpickle<SessionObject>(currentNewest->pickled_session,
-                                                                     pickle_secret_))
-                             : std::nullopt;
+    return currentNewest ? std::optional(unpickle<SessionObject>(currentNewest->pickled_session,
+                                                                 pickle_secret_))
+                         : std::nullopt;
 }
 
 std::vector<std::string>
 Cache::getOlmSessions(const std::string &curve25519)
 {
-        using namespace mtx::crypto;
+    using namespace mtx::crypto;
 
-        auto txn = lmdb::txn::begin(env_);
-        auto db  = getOlmSessionsDb(txn, curve25519);
+    auto txn = lmdb::txn::begin(env_);
+    auto db  = getOlmSessionsDb(txn, curve25519);
 
-        std::string_view session_id, unused;
-        std::vector<std::string> res;
+    std::string_view session_id, unused;
+    std::vector<std::string> res;
 
-        auto cursor = lmdb::cursor::open(txn, db);
-        while (cursor.get(session_id, unused, MDB_NEXT))
-                res.emplace_back(session_id);
-        cursor.close();
+    auto cursor = lmdb::cursor::open(txn, db);
+    while (cursor.get(session_id, unused, MDB_NEXT))
+        res.emplace_back(session_id);
+    cursor.close();
 
-        txn.commit();
+    txn.commit();
 
-        return res;
+    return res;
 }
 
 void
 Cache::saveOlmAccount(const std::string &data)
 {
-        auto txn = lmdb::txn::begin(env_);
-        syncStateDb_.put(txn, OLM_ACCOUNT_KEY, data);
-        txn.commit();
+    auto txn = lmdb::txn::begin(env_);
+    syncStateDb_.put(txn, OLM_ACCOUNT_KEY, data);
+    txn.commit();
 }
 
 std::string
 Cache::restoreOlmAccount()
 {
-        auto txn = ro_txn(env_);
+    auto txn = ro_txn(env_);
 
-        std::string_view pickled;
-        syncStateDb_.get(txn, OLM_ACCOUNT_KEY, pickled);
+    std::string_view pickled;
+    syncStateDb_.get(txn, OLM_ACCOUNT_KEY, pickled);
 
-        return std::string(pickled.data(), pickled.size());
+    return std::string(pickled.data(), pickled.size());
 }
 
 void
 Cache::saveBackupVersion(const OnlineBackupVersion &data)
 {
-        auto txn = lmdb::txn::begin(env_);
-        syncStateDb_.put(txn, CURRENT_ONLINE_BACKUP_VERSION, nlohmann::json(data).dump());
-        txn.commit();
+    auto txn = lmdb::txn::begin(env_);
+    syncStateDb_.put(txn, CURRENT_ONLINE_BACKUP_VERSION, nlohmann::json(data).dump());
+    txn.commit();
 }
 
 void
 Cache::deleteBackupVersion()
 {
-        auto txn = lmdb::txn::begin(env_);
-        syncStateDb_.del(txn, CURRENT_ONLINE_BACKUP_VERSION);
-        txn.commit();
+    auto txn = lmdb::txn::begin(env_);
+    syncStateDb_.del(txn, CURRENT_ONLINE_BACKUP_VERSION);
+    txn.commit();
 }
 
 std::optional<OnlineBackupVersion>
 Cache::backupVersion()
 {
-        try {
-                auto txn = ro_txn(env_);
-                std::string_view v;
-                syncStateDb_.get(txn, CURRENT_ONLINE_BACKUP_VERSION, v);
+    try {
+        auto txn = ro_txn(env_);
+        std::string_view v;
+        syncStateDb_.get(txn, CURRENT_ONLINE_BACKUP_VERSION, v);
 
-                return nlohmann::json::parse(v).get<OnlineBackupVersion>();
-        } catch (...) {
-                return std::nullopt;
-        }
+        return nlohmann::json::parse(v).get<OnlineBackupVersion>();
+    } catch (...) {
+        return std::nullopt;
+    }
 }
 
 static void
 fatalSecretError()
 {
-        QMessageBox::critical(
-          ChatPage::instance(),
-          QCoreApplication::translate("SecretStorage", "Failed to connect to secret storage"),
-          QCoreApplication::translate(
-            "SecretStorage",
-            "Nheko could not connect to the secure storage to save encryption secrets to. "
-            "This can have multiple reasons. Check if your D-Bus service is running and "
-            "you have configured a service like KWallet, Gnome Secrets or the equivalent "
-            "for your platform. If you are having trouble, feel free to open an issue "
-            "here: https://github.com/Nheko-Reborn/nheko/issues"));
+    QMessageBox::critical(
+      ChatPage::instance(),
+      QCoreApplication::translate("SecretStorage", "Failed to connect to secret storage"),
+      QCoreApplication::translate(
+        "SecretStorage",
+        "Nheko could not connect to the secure storage to save encryption secrets to. "
+        "This can have multiple reasons. Check if your D-Bus service is running and "
+        "you have configured a service like KWallet, Gnome Secrets or the equivalent "
+        "for your platform. If you are having trouble, feel free to open an issue "
+        "here: https://github.com/Nheko-Reborn/nheko/issues"));
 
-        QCoreApplication::exit(1);
-        exit(1);
+    QCoreApplication::exit(1);
+    exit(1);
 }
 
 void
 Cache::storeSecret(const std::string name, const std::string secret, bool internal)
 {
-        auto settings = UserSettings::instance();
-        auto job      = new QKeychain::WritePasswordJob(QCoreApplication::applicationName());
-        job->setAutoDelete(true);
-        job->setInsecureFallback(true);
-        job->setSettings(UserSettings::instance()->qsettings());
-
-        job->setKey(
-          (internal ? "nheko." : "matrix.") +
-          QString(QCryptographicHash::hash(settings->profile().toUtf8(), QCryptographicHash::Sha256)
-                    .toBase64()) +
-          "." + QString::fromStdString(name));
-
-        job->setTextData(QString::fromStdString(secret));
-
-        QObject::connect(
-          job,
-          &QKeychain::WritePasswordJob::finished,
-          this,
-          [name, this](QKeychain::Job *job) {
-                  if (job->error()) {
-                          nhlog::db()->warn("Storing secret '{}' failed: {}",
-                                            name,
-                                            job->errorString().toStdString());
-                          fatalSecretError();
-                  } else {
-                          // if we emit the signal directly, qtkeychain breaks and won't execute new
-                          // jobs. You can't start a job from the finish signal of a job.
-                          QTimer::singleShot(100, [this, name] { emit secretChanged(name); });
-                          nhlog::db()->info("Storing secret '{}' successful", name);
-                  }
-          },
-          Qt::ConnectionType::DirectConnection);
-        job->start();
+    auto settings = UserSettings::instance();
+    auto job      = new QKeychain::WritePasswordJob(QCoreApplication::applicationName());
+    job->setAutoDelete(true);
+    job->setInsecureFallback(true);
+    job->setSettings(UserSettings::instance()->qsettings());
+
+    job->setKey(
+      (internal ? "nheko." : "matrix.") +
+      QString(QCryptographicHash::hash(settings->profile().toUtf8(), QCryptographicHash::Sha256)
+                .toBase64()) +
+      "." + QString::fromStdString(name));
+
+    job->setTextData(QString::fromStdString(secret));
+
+    QObject::connect(
+      job,
+      &QKeychain::WritePasswordJob::finished,
+      this,
+      [name, this](QKeychain::Job *job) {
+          if (job->error()) {
+              nhlog::db()->warn(
+                "Storing secret '{}' failed: {}", name, job->errorString().toStdString());
+              fatalSecretError();
+          } else {
+              // if we emit the signal directly, qtkeychain breaks and won't execute new
+              // jobs. You can't start a job from the finish signal of a job.
+              QTimer::singleShot(100, [this, name] { emit secretChanged(name); });
+              nhlog::db()->info("Storing secret '{}' successful", name);
+          }
+      },
+      Qt::ConnectionType::DirectConnection);
+    job->start();
 }
 
 void
 Cache::deleteSecret(const std::string name, bool internal)
 {
-        auto settings = UserSettings::instance();
-        QKeychain::DeletePasswordJob job(QCoreApplication::applicationName());
-        job.setAutoDelete(false);
-        job.setInsecureFallback(true);
-        job.setSettings(UserSettings::instance()->qsettings());
+    auto settings = UserSettings::instance();
+    QKeychain::DeletePasswordJob job(QCoreApplication::applicationName());
+    job.setAutoDelete(false);
+    job.setInsecureFallback(true);
+    job.setSettings(UserSettings::instance()->qsettings());
 
-        job.setKey(
-          (internal ? "nheko." : "matrix.") +
-          QString(QCryptographicHash::hash(settings->profile().toUtf8(), QCryptographicHash::Sha256)
-                    .toBase64()) +
-          "." + QString::fromStdString(name));
+    job.setKey(
+      (internal ? "nheko." : "matrix.") +
+      QString(QCryptographicHash::hash(settings->profile().toUtf8(), QCryptographicHash::Sha256)
+                .toBase64()) +
+      "." + QString::fromStdString(name));
 
-        // FIXME(Nico): Nested event loops are dangerous. Some other slots may resume in the mean
-        // time!
-        QEventLoop loop;
-        job.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit);
-        job.start();
-        loop.exec();
+    // FIXME(Nico): Nested event loops are dangerous. Some other slots may resume in the mean
+    // time!
+    QEventLoop loop;
+    job.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit);
+    job.start();
+    loop.exec();
 
-        emit secretChanged(name);
+    emit secretChanged(name);
 }
 
 std::optional<std::string>
 Cache::secret(const std::string name, bool internal)
 {
-        auto settings = UserSettings::instance();
-        QKeychain::ReadPasswordJob job(QCoreApplication::applicationName());
-        job.setAutoDelete(false);
-        job.setInsecureFallback(true);
-        job.setSettings(UserSettings::instance()->qsettings());
-
-        job.setKey(
-          (internal ? "nheko." : "matrix.") +
-          QString(QCryptographicHash::hash(settings->profile().toUtf8(), QCryptographicHash::Sha256)
-                    .toBase64()) +
-          "." + QString::fromStdString(name));
-
-        // FIXME(Nico): Nested event loops are dangerous. Some other slots may resume in the mean
-        // time!
-        QEventLoop loop;
-        job.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit);
-        job.start();
-        loop.exec();
-
-        const QString secret = job.textData();
-        if (job.error()) {
-                if (job.error() == QKeychain::Error::EntryNotFound)
-                        return std::nullopt;
-                nhlog::db()->error("Restoring secret '{}' failed ({}): {}",
-                                   name,
-                                   job.error(),
-                                   job.errorString().toStdString());
-
-                fatalSecretError();
-                return std::nullopt;
-        }
-        if (secret.isEmpty()) {
-                nhlog::db()->debug("Restored empty secret '{}'.", name);
-                return std::nullopt;
-        }
+    auto settings = UserSettings::instance();
+    QKeychain::ReadPasswordJob job(QCoreApplication::applicationName());
+    job.setAutoDelete(false);
+    job.setInsecureFallback(true);
+    job.setSettings(UserSettings::instance()->qsettings());
+
+    job.setKey(
+      (internal ? "nheko." : "matrix.") +
+      QString(QCryptographicHash::hash(settings->profile().toUtf8(), QCryptographicHash::Sha256)
+                .toBase64()) +
+      "." + QString::fromStdString(name));
+
+    // FIXME(Nico): Nested event loops are dangerous. Some other slots may resume in the mean
+    // time!
+    QEventLoop loop;
+    job.connect(&job, &QKeychain::Job::finished, &loop, &QEventLoop::quit);
+    job.start();
+    loop.exec();
+
+    const QString secret = job.textData();
+    if (job.error()) {
+        if (job.error() == QKeychain::Error::EntryNotFound)
+            return std::nullopt;
+        nhlog::db()->error("Restoring secret '{}' failed ({}): {}",
+                           name,
+                           job.error(),
+                           job.errorString().toStdString());
+
+        fatalSecretError();
+        return std::nullopt;
+    }
+    if (secret.isEmpty()) {
+        nhlog::db()->debug("Restored empty secret '{}'.", name);
+        return std::nullopt;
+    }
 
-        return secret.toStdString();
+    return secret.toStdString();
 }
 
 std::string
 Cache::pickleSecret()
 {
-        if (pickle_secret_.empty()) {
-                auto s = secret("pickle_secret", true);
-                if (!s) {
-                        this->pickle_secret_ = mtx::client::utils::random_token(64, true);
-                        storeSecret("pickle_secret", pickle_secret_, true);
-                } else {
-                        this->pickle_secret_ = *s;
-                }
+    if (pickle_secret_.empty()) {
+        auto s = secret("pickle_secret", true);
+        if (!s) {
+            this->pickle_secret_ = mtx::client::utils::random_token(64, true);
+            storeSecret("pickle_secret", pickle_secret_, true);
+        } else {
+            this->pickle_secret_ = *s;
         }
+    }
 
-        return pickle_secret_;
+    return pickle_secret_;
 }
 
 void
 Cache::removeInvite(lmdb::txn &txn, const std::string &room_id)
 {
-        invitesDb_.del(txn, room_id);
-        getInviteStatesDb(txn, room_id).drop(txn, true);
-        getInviteMembersDb(txn, room_id).drop(txn, true);
+    invitesDb_.del(txn, room_id);
+    getInviteStatesDb(txn, room_id).drop(txn, true);
+    getInviteMembersDb(txn, room_id).drop(txn, true);
 }
 
 void
 Cache::removeInvite(const std::string &room_id)
 {
-        auto txn = lmdb::txn::begin(env_);
-        removeInvite(txn, room_id);
-        txn.commit();
+    auto txn = lmdb::txn::begin(env_);
+    removeInvite(txn, room_id);
+    txn.commit();
 }
 
 void
 Cache::removeRoom(lmdb::txn &txn, const std::string &roomid)
 {
-        roomsDb_.del(txn, roomid);
-        getStatesDb(txn, roomid).drop(txn, true);
-        getAccountDataDb(txn, roomid).drop(txn, true);
-        getMembersDb(txn, roomid).drop(txn, true);
+    roomsDb_.del(txn, roomid);
+    getStatesDb(txn, roomid).drop(txn, true);
+    getAccountDataDb(txn, roomid).drop(txn, true);
+    getMembersDb(txn, roomid).drop(txn, true);
 }
 
 void
 Cache::removeRoom(const std::string &roomid)
 {
-        auto txn = lmdb::txn::begin(env_, nullptr, 0);
-        roomsDb_.del(txn, roomid);
-        txn.commit();
+    auto txn = lmdb::txn::begin(env_, nullptr, 0);
+    roomsDb_.del(txn, roomid);
+    txn.commit();
 }
 
 void
 Cache::setNextBatchToken(lmdb::txn &txn, const std::string &token)
 {
-        syncStateDb_.put(txn, NEXT_BATCH_KEY, token);
+    syncStateDb_.put(txn, NEXT_BATCH_KEY, token);
 }
 
 bool
 Cache::isInitialized()
 {
-        if (!env_.handle())
-                return false;
+    if (!env_.handle())
+        return false;
 
-        auto txn = ro_txn(env_);
-        std::string_view token;
+    auto txn = ro_txn(env_);
+    std::string_view token;
 
-        bool res = syncStateDb_.get(txn, NEXT_BATCH_KEY, token);
+    bool res = syncStateDb_.get(txn, NEXT_BATCH_KEY, token);
 
-        return res;
+    return res;
 }
 
 std::string
 Cache::nextBatchToken()
 {
-        if (!env_.handle())
-                throw lmdb::error("Env already closed", MDB_INVALID);
+    if (!env_.handle())
+        throw lmdb::error("Env already closed", MDB_INVALID);
 
-        auto txn = ro_txn(env_);
-        std::string_view token;
+    auto txn = ro_txn(env_);
+    std::string_view token;
 
-        bool result = syncStateDb_.get(txn, NEXT_BATCH_KEY, token);
+    bool result = syncStateDb_.get(txn, NEXT_BATCH_KEY, token);
 
-        if (result)
-                return std::string(token.data(), token.size());
-        else
-                return "";
+    if (result)
+        return std::string(token.data(), token.size());
+    else
+        return "";
 }
 
 void
 Cache::deleteData()
 {
-        this->databaseReady_ = false;
-        // TODO: We need to remove the env_ while not accepting new requests.
-        lmdb::dbi_close(env_, syncStateDb_);
-        lmdb::dbi_close(env_, roomsDb_);
-        lmdb::dbi_close(env_, invitesDb_);
-        lmdb::dbi_close(env_, readReceiptsDb_);
-        lmdb::dbi_close(env_, notificationsDb_);
+    this->databaseReady_ = false;
+    // TODO: We need to remove the env_ while not accepting new requests.
+    lmdb::dbi_close(env_, syncStateDb_);
+    lmdb::dbi_close(env_, roomsDb_);
+    lmdb::dbi_close(env_, invitesDb_);
+    lmdb::dbi_close(env_, readReceiptsDb_);
+    lmdb::dbi_close(env_, notificationsDb_);
 
-        lmdb::dbi_close(env_, devicesDb_);
-        lmdb::dbi_close(env_, deviceKeysDb_);
+    lmdb::dbi_close(env_, devicesDb_);
+    lmdb::dbi_close(env_, deviceKeysDb_);
 
-        lmdb::dbi_close(env_, inboundMegolmSessionDb_);
-        lmdb::dbi_close(env_, outboundMegolmSessionDb_);
-        lmdb::dbi_close(env_, megolmSessionDataDb_);
+    lmdb::dbi_close(env_, inboundMegolmSessionDb_);
+    lmdb::dbi_close(env_, outboundMegolmSessionDb_);
+    lmdb::dbi_close(env_, megolmSessionDataDb_);
 
-        env_.close();
+    env_.close();
 
-        verification_storage.status.clear();
+    verification_storage.status.clear();
 
-        if (!cacheDirectory_.isEmpty()) {
-                QDir(cacheDirectory_).removeRecursively();
-                nhlog::db()->info("deleted cache files from disk");
-        }
+    if (!cacheDirectory_.isEmpty()) {
+        QDir(cacheDirectory_).removeRecursively();
+        nhlog::db()->info("deleted cache files from disk");
+    }
 
-        deleteSecret(mtx::secret_storage::secrets::megolm_backup_v1);
-        deleteSecret(mtx::secret_storage::secrets::cross_signing_master);
-        deleteSecret(mtx::secret_storage::secrets::cross_signing_user_signing);
-        deleteSecret(mtx::secret_storage::secrets::cross_signing_self_signing);
-        deleteSecret("pickle_secret", true);
+    deleteSecret(mtx::secret_storage::secrets::megolm_backup_v1);
+    deleteSecret(mtx::secret_storage::secrets::cross_signing_master);
+    deleteSecret(mtx::secret_storage::secrets::cross_signing_user_signing);
+    deleteSecret(mtx::secret_storage::secrets::cross_signing_self_signing);
+    deleteSecret("pickle_secret", true);
 }
 
 //! migrates db to the current format
 bool
 Cache::runMigrations()
 {
-        std::string stored_version;
-        {
-                auto txn = ro_txn(env_);
-
-                std::string_view current_version;
-                bool res = syncStateDb_.get(txn, CACHE_FORMAT_VERSION_KEY, current_version);
-
-                if (!res)
-                        return false;
-
-                stored_version = std::string(current_version);
-        }
+    std::string stored_version;
+    {
+        auto txn = ro_txn(env_);
 
-        std::vector<std::pair<std::string, std::function<bool()>>> migrations{
-          {"2020.05.01",
-           [this]() {
-                   try {
-                           auto txn = lmdb::txn::begin(env_, nullptr);
-                           auto pending_receipts =
-                             lmdb::dbi::open(txn, "pending_receipts", MDB_CREATE);
-                           lmdb::dbi_drop(txn, pending_receipts, true);
-                           txn.commit();
-                   } catch (const lmdb::error &) {
-                           nhlog::db()->critical(
-                             "Failed to delete pending_receipts database in migration!");
-                           return false;
-                   }
+        std::string_view current_version;
+        bool res = syncStateDb_.get(txn, CACHE_FORMAT_VERSION_KEY, current_version);
 
-                   nhlog::db()->info("Successfully deleted pending receipts database.");
-                   return true;
-           }},
-          {"2020.07.05",
-           [this]() {
+        if (!res)
+            return false;
+
+        stored_version = std::string(current_version);
+    }
+
+    std::vector<std::pair<std::string, std::function<bool()>>> migrations{
+      {"2020.05.01",
+       [this]() {
+           try {
+               auto txn              = lmdb::txn::begin(env_, nullptr);
+               auto pending_receipts = lmdb::dbi::open(txn, "pending_receipts", MDB_CREATE);
+               lmdb::dbi_drop(txn, pending_receipts, true);
+               txn.commit();
+           } catch (const lmdb::error &) {
+               nhlog::db()->critical("Failed to delete pending_receipts database in migration!");
+               return false;
+           }
+
+           nhlog::db()->info("Successfully deleted pending receipts database.");
+           return true;
+       }},
+      {"2020.07.05",
+       [this]() {
+           try {
+               auto txn      = lmdb::txn::begin(env_, nullptr);
+               auto room_ids = getRoomIds(txn);
+
+               for (const auto &room_id : room_ids) {
                    try {
-                           auto txn      = lmdb::txn::begin(env_, nullptr);
-                           auto room_ids = getRoomIds(txn);
-
-                           for (const auto &room_id : room_ids) {
-                                   try {
-                                           auto messagesDb = lmdb::dbi::open(
-                                             txn, std::string(room_id + "/messages").c_str());
-
-                                           // keep some old messages and batch token
-                                           {
-                                                   auto roomsCursor =
-                                                     lmdb::cursor::open(txn, messagesDb);
-                                                   std::string_view ts, stored_message;
-                                                   bool start = true;
-                                                   mtx::responses::Timeline oldMessages;
-                                                   while (roomsCursor.get(ts,
-                                                                          stored_message,
-                                                                          start ? MDB_FIRST
-                                                                                : MDB_NEXT)) {
-                                                           start = false;
-
-                                                           auto j = json::parse(std::string_view(
-                                                             stored_message.data(),
-                                                             stored_message.size()));
-
-                                                           if (oldMessages.prev_batch.empty())
-                                                                   oldMessages.prev_batch =
-                                                                     j["token"].get<std::string>();
-                                                           else if (j["token"] !=
-                                                                    oldMessages.prev_batch)
-                                                                   break;
-
-                                                           mtx::events::collections::TimelineEvent
-                                                             te;
-                                                           mtx::events::collections::from_json(
-                                                             j["event"], te);
-                                                           oldMessages.events.push_back(te.data);
-                                                   }
-                                                   // messages were stored in reverse order, so we
-                                                   // need to reverse them
-                                                   std::reverse(oldMessages.events.begin(),
-                                                                oldMessages.events.end());
-                                                   // save messages using the new method
-                                                   auto eventsDb = getEventsDb(txn, room_id);
-                                                   saveTimelineMessages(
-                                                     txn, eventsDb, room_id, oldMessages);
-                                           }
-
-                                           // delete old messages db
-                                           lmdb::dbi_drop(txn, messagesDb, true);
-                                   } catch (std::exception &e) {
-                                           nhlog::db()->error(
-                                             "While migrating messages from {}, ignoring error {}",
-                                             room_id,
-                                             e.what());
-                                   }
+                       auto messagesDb =
+                         lmdb::dbi::open(txn, std::string(room_id + "/messages").c_str());
+
+                       // keep some old messages and batch token
+                       {
+                           auto roomsCursor = lmdb::cursor::open(txn, messagesDb);
+                           std::string_view ts, stored_message;
+                           bool start = true;
+                           mtx::responses::Timeline oldMessages;
+                           while (
+                             roomsCursor.get(ts, stored_message, start ? MDB_FIRST : MDB_NEXT)) {
+                               start = false;
+
+                               auto j = json::parse(
+                                 std::string_view(stored_message.data(), stored_message.size()));
+
+                               if (oldMessages.prev_batch.empty())
+                                   oldMessages.prev_batch = j["token"].get<std::string>();
+                               else if (j["token"] != oldMessages.prev_batch)
+                                   break;
+
+                               mtx::events::collections::TimelineEvent te;
+                               mtx::events::collections::from_json(j["event"], te);
+                               oldMessages.events.push_back(te.data);
                            }
-                           txn.commit();
-                   } catch (const lmdb::error &) {
-                           nhlog::db()->critical(
-                             "Failed to delete messages database in migration!");
-                           return false;
+                           // messages were stored in reverse order, so we
+                           // need to reverse them
+                           std::reverse(oldMessages.events.begin(), oldMessages.events.end());
+                           // save messages using the new method
+                           auto eventsDb = getEventsDb(txn, room_id);
+                           saveTimelineMessages(txn, eventsDb, room_id, oldMessages);
+                       }
+
+                       // delete old messages db
+                       lmdb::dbi_drop(txn, messagesDb, true);
+                   } catch (std::exception &e) {
+                       nhlog::db()->error(
+                         "While migrating messages from {}, ignoring error {}", room_id, e.what());
                    }
+               }
+               txn.commit();
+           } catch (const lmdb::error &) {
+               nhlog::db()->critical("Failed to delete messages database in migration!");
+               return false;
+           }
+
+           nhlog::db()->info("Successfully deleted pending receipts database.");
+           return true;
+       }},
+      {"2020.10.20",
+       [this]() {
+           try {
+               using namespace mtx::crypto;
+
+               auto txn = lmdb::txn::begin(env_);
+
+               auto mainDb = lmdb::dbi::open(txn, nullptr);
+
+               std::string_view dbName, ignored;
+               auto olmDbCursor = lmdb::cursor::open(txn, mainDb);
+               while (olmDbCursor.get(dbName, ignored, MDB_NEXT)) {
+                   // skip every db but olm session dbs
+                   nhlog::db()->debug("Db {}", dbName);
+                   if (dbName.find("olm_sessions/") != 0)
+                       continue;
+
+                   nhlog::db()->debug("Migrating {}", dbName);
+
+                   auto olmDb = lmdb::dbi::open(txn, std::string(dbName).c_str());
+
+                   std::string_view session_id, session_value;
+
+                   std::vector<std::pair<std::string, StoredOlmSession>> sessions;
+
+                   auto cursor = lmdb::cursor::open(txn, olmDb);
+                   while (cursor.get(session_id, session_value, MDB_NEXT)) {
+                       nhlog::db()->debug(
+                         "session_id {}, session_value {}", session_id, session_value);
+                       StoredOlmSession session;
+                       bool invalid = false;
+                       for (auto c : session_value)
+                           if (!isprint(c)) {
+                               invalid = true;
+                               break;
+                           }
+                       if (invalid)
+                           continue;
 
-                   nhlog::db()->info("Successfully deleted pending receipts database.");
-                   return true;
-           }},
-          {"2020.10.20",
-           [this]() {
-                   try {
-                           using namespace mtx::crypto;
-
-                           auto txn = lmdb::txn::begin(env_);
-
-                           auto mainDb = lmdb::dbi::open(txn, nullptr);
-
-                           std::string_view dbName, ignored;
-                           auto olmDbCursor = lmdb::cursor::open(txn, mainDb);
-                           while (olmDbCursor.get(dbName, ignored, MDB_NEXT)) {
-                                   // skip every db but olm session dbs
-                                   nhlog::db()->debug("Db {}", dbName);
-                                   if (dbName.find("olm_sessions/") != 0)
-                                           continue;
-
-                                   nhlog::db()->debug("Migrating {}", dbName);
-
-                                   auto olmDb = lmdb::dbi::open(txn, std::string(dbName).c_str());
-
-                                   std::string_view session_id, session_value;
-
-                                   std::vector<std::pair<std::string, StoredOlmSession>> sessions;
-
-                                   auto cursor = lmdb::cursor::open(txn, olmDb);
-                                   while (cursor.get(session_id, session_value, MDB_NEXT)) {
-                                           nhlog::db()->debug("session_id {}, session_value {}",
-                                                              session_id,
-                                                              session_value);
-                                           StoredOlmSession session;
-                                           bool invalid = false;
-                                           for (auto c : session_value)
-                                                   if (!isprint(c)) {
-                                                           invalid = true;
-                                                           break;
-                                                   }
-                                           if (invalid)
-                                                   continue;
-
-                                           nhlog::db()->debug("Not skipped");
-
-                                           session.pickled_session = session_value;
-                                           sessions.emplace_back(session_id, session);
-                                   }
-                                   cursor.close();
+                       nhlog::db()->debug("Not skipped");
 
-                                   olmDb.drop(txn, true);
+                       session.pickled_session = session_value;
+                       sessions.emplace_back(session_id, session);
+                   }
+                   cursor.close();
 
-                                   auto newDbName = std::string(dbName);
-                                   newDbName.erase(0, sizeof("olm_sessions") - 1);
-                                   newDbName = "olm_sessions.v2" + newDbName;
+                   olmDb.drop(txn, true);
 
-                                   auto newDb = lmdb::dbi::open(txn, newDbName.c_str(), MDB_CREATE);
+                   auto newDbName = std::string(dbName);
+                   newDbName.erase(0, sizeof("olm_sessions") - 1);
+                   newDbName = "olm_sessions.v2" + newDbName;
 
-                                   for (const auto &[key, value] : sessions) {
-                                           // nhlog::db()->debug("{}\n{}", key, json(value).dump());
-                                           newDb.put(txn, key, json(value).dump());
-                                   }
-                           }
-                           olmDbCursor.close();
+                   auto newDb = lmdb::dbi::open(txn, newDbName.c_str(), MDB_CREATE);
 
-                           txn.commit();
-                   } catch (const lmdb::error &) {
-                           nhlog::db()->critical("Failed to migrate olm sessions,");
-                           return false;
+                   for (const auto &[key, value] : sessions) {
+                       // nhlog::db()->debug("{}\n{}", key, json(value).dump());
+                       newDb.put(txn, key, json(value).dump());
                    }
-
-                   nhlog::db()->info("Successfully migrated olm sessions.");
-                   return true;
-           }},
-          {"2021.08.22",
-           [this]() {
+               }
+               olmDbCursor.close();
+
+               txn.commit();
+           } catch (const lmdb::error &) {
+               nhlog::db()->critical("Failed to migrate olm sessions,");
+               return false;
+           }
+
+           nhlog::db()->info("Successfully migrated olm sessions.");
+           return true;
+       }},
+      {"2021.08.22",
+       [this]() {
+           try {
+               auto txn      = lmdb::txn::begin(env_, nullptr);
+               auto try_drop = [&txn](const std::string &dbName) {
                    try {
-                           auto txn      = lmdb::txn::begin(env_, nullptr);
-                           auto try_drop = [&txn](const std::string &dbName) {
-                                   try {
-                                           auto db = lmdb::dbi::open(txn, dbName.c_str());
-                                           db.drop(txn, true);
-                                   } catch (std::exception &e) {
-                                           nhlog::db()->warn(
-                                             "Failed to drop '{}': {}", dbName, e.what());
-                                   }
-                           };
-
-                           auto room_ids = getRoomIds(txn);
-
-                           for (const auto &room : room_ids) {
-                                   try_drop(room + "/state");
-                                   try_drop(room + "/state_by_key");
-                                   try_drop(room + "/account_data");
-                                   try_drop(room + "/members");
-                                   try_drop(room + "/mentions");
-                                   try_drop(room + "/events");
-                                   try_drop(room + "/event_order");
-                                   try_drop(room + "/event2order");
-                                   try_drop(room + "/msg2order");
-                                   try_drop(room + "/order2msg");
-                                   try_drop(room + "/pending");
-                                   try_drop(room + "/related");
-                           }
-
-                           // clear db, don't delete
-                           roomsDb_.drop(txn, false);
-                           setNextBatchToken(txn, "");
-
-                           txn.commit();
-                   } catch (const lmdb::error &) {
-                           nhlog::db()->critical("Failed to clear cache!");
-                           return false;
+                       auto db = lmdb::dbi::open(txn, dbName.c_str());
+                       db.drop(txn, true);
+                   } catch (std::exception &e) {
+                       nhlog::db()->warn("Failed to drop '{}': {}", dbName, e.what());
                    }
+               };
+
+               auto room_ids = getRoomIds(txn);
+
+               for (const auto &room : room_ids) {
+                   try_drop(room + "/state");
+                   try_drop(room + "/state_by_key");
+                   try_drop(room + "/account_data");
+                   try_drop(room + "/members");
+                   try_drop(room + "/mentions");
+                   try_drop(room + "/events");
+                   try_drop(room + "/event_order");
+                   try_drop(room + "/event2order");
+                   try_drop(room + "/msg2order");
+                   try_drop(room + "/order2msg");
+                   try_drop(room + "/pending");
+                   try_drop(room + "/related");
+               }
+
+               // clear db, don't delete
+               roomsDb_.drop(txn, false);
+               setNextBatchToken(txn, "");
+
+               txn.commit();
+           } catch (const lmdb::error &) {
+               nhlog::db()->critical("Failed to clear cache!");
+               return false;
+           }
+
+           nhlog::db()->info("Successfully cleared the cache. Will do a clean sync after startup.");
+           return true;
+       }},
+      {"2021.08.31",
+       [this]() {
+           storeSecret("pickle_secret", "secret", true);
+           return true;
+       }},
+    };
+
+    nhlog::db()->info("Running migrations, this may take a while!");
+    for (const auto &[target_version, migration] : migrations) {
+        if (target_version > stored_version)
+            if (!migration()) {
+                nhlog::db()->critical("migration failure!");
+                return false;
+            }
+    }
+    nhlog::db()->info("Migrations finished.");
 
-                   nhlog::db()->info(
-                     "Successfully cleared the cache. Will do a clean sync after startup.");
-                   return true;
-           }},
-          {"2021.08.31",
-           [this]() {
-                   storeSecret("pickle_secret", "secret", true);
-                   return true;
-           }},
-        };
-
-        nhlog::db()->info("Running migrations, this may take a while!");
-        for (const auto &[target_version, migration] : migrations) {
-                if (target_version > stored_version)
-                        if (!migration()) {
-                                nhlog::db()->critical("migration failure!");
-                                return false;
-                        }
-        }
-        nhlog::db()->info("Migrations finished.");
-
-        setCurrentFormat();
-        return true;
+    setCurrentFormat();
+    return true;
 }
 
 cache::CacheVersion
 Cache::formatVersion()
 {
-        auto txn = ro_txn(env_);
+    auto txn = ro_txn(env_);
 
-        std::string_view current_version;
-        bool res = syncStateDb_.get(txn, CACHE_FORMAT_VERSION_KEY, current_version);
+    std::string_view current_version;
+    bool res = syncStateDb_.get(txn, CACHE_FORMAT_VERSION_KEY, current_version);
 
-        if (!res)
-                return cache::CacheVersion::Older;
+    if (!res)
+        return cache::CacheVersion::Older;
 
-        std::string stored_version(current_version.data(), current_version.size());
+    std::string stored_version(current_version.data(), current_version.size());
 
-        if (stored_version < CURRENT_CACHE_FORMAT_VERSION)
-                return cache::CacheVersion::Older;
-        else if (stored_version > CURRENT_CACHE_FORMAT_VERSION)
-                return cache::CacheVersion::Older;
-        else
-                return cache::CacheVersion::Current;
+    if (stored_version < CURRENT_CACHE_FORMAT_VERSION)
+        return cache::CacheVersion::Older;
+    else if (stored_version > CURRENT_CACHE_FORMAT_VERSION)
+        return cache::CacheVersion::Older;
+    else
+        return cache::CacheVersion::Current;
 }
 
 void
 Cache::setCurrentFormat()
 {
-        auto txn = lmdb::txn::begin(env_);
+    auto txn = lmdb::txn::begin(env_);
 
-        syncStateDb_.put(txn, CACHE_FORMAT_VERSION_KEY, CURRENT_CACHE_FORMAT_VERSION);
+    syncStateDb_.put(txn, CACHE_FORMAT_VERSION_KEY, CURRENT_CACHE_FORMAT_VERSION);
 
-        txn.commit();
+    txn.commit();
 }
 
 CachedReceipts
 Cache::readReceipts(const QString &event_id, const QString &room_id)
 {
-        CachedReceipts receipts;
+    CachedReceipts receipts;
 
-        ReadReceiptKey receipt_key{event_id.toStdString(), room_id.toStdString()};
-        nlohmann::json json_key = receipt_key;
-
-        try {
-                auto txn = ro_txn(env_);
-                auto key = json_key.dump();
+    ReadReceiptKey receipt_key{event_id.toStdString(), room_id.toStdString()};
+    nlohmann::json json_key = receipt_key;
 
-                std::string_view value;
+    try {
+        auto txn = ro_txn(env_);
+        auto key = json_key.dump();
 
-                bool res = readReceiptsDb_.get(txn, key, value);
+        std::string_view value;
 
-                if (res) {
-                        auto json_response =
-                          json::parse(std::string_view(value.data(), value.size()));
-                        auto values = json_response.get<std::map<std::string, uint64_t>>();
+        bool res = readReceiptsDb_.get(txn, key, value);
 
-                        for (const auto &v : values)
-                                // timestamp, user_id
-                                receipts.emplace(v.second, v.first);
-                }
+        if (res) {
+            auto json_response = json::parse(std::string_view(value.data(), value.size()));
+            auto values        = json_response.get<std::map<std::string, uint64_t>>();
 
-        } catch (const lmdb::error &e) {
-                nhlog::db()->critical("readReceipts: {}", e.what());
+            for (const auto &v : values)
+                // timestamp, user_id
+                receipts.emplace(v.second, v.first);
         }
 
-        return receipts;
+    } catch (const lmdb::error &e) {
+        nhlog::db()->critical("readReceipts: {}", e.what());
+    }
+
+    return receipts;
 }
 
 void
 Cache::updateReadReceipt(lmdb::txn &txn, const std::string &room_id, const Receipts &receipts)
 {
-        auto user_id = this->localUserId_.toStdString();
-        for (const auto &receipt : receipts) {
-                const auto event_id = receipt.first;
-                auto event_receipts = receipt.second;
+    auto user_id = this->localUserId_.toStdString();
+    for (const auto &receipt : receipts) {
+        const auto event_id = receipt.first;
+        auto event_receipts = receipt.second;
 
-                ReadReceiptKey receipt_key{event_id, room_id};
-                nlohmann::json json_key = receipt_key;
+        ReadReceiptKey receipt_key{event_id, room_id};
+        nlohmann::json json_key = receipt_key;
 
-                try {
-                        const auto key = json_key.dump();
+        try {
+            const auto key = json_key.dump();
 
-                        std::string_view prev_value;
+            std::string_view prev_value;
 
-                        bool exists = readReceiptsDb_.get(txn, key, prev_value);
+            bool exists = readReceiptsDb_.get(txn, key, prev_value);
 
-                        std::map<std::string, uint64_t> saved_receipts;
+            std::map<std::string, uint64_t> saved_receipts;
 
-                        // If an entry for the event id already exists, we would
-                        // merge the existing receipts with the new ones.
-                        if (exists) {
-                                auto json_value = json::parse(
-                                  std::string_view(prev_value.data(), prev_value.size()));
+            // If an entry for the event id already exists, we would
+            // merge the existing receipts with the new ones.
+            if (exists) {
+                auto json_value =
+                  json::parse(std::string_view(prev_value.data(), prev_value.size()));
 
-                                // Retrieve the saved receipts.
-                                saved_receipts = json_value.get<std::map<std::string, uint64_t>>();
-                        }
+                // Retrieve the saved receipts.
+                saved_receipts = json_value.get<std::map<std::string, uint64_t>>();
+            }
 
-                        // Append the new ones.
-                        for (const auto &[read_by, timestamp] : event_receipts) {
-                                if (read_by == user_id) {
-                                        emit removeNotification(QString::fromStdString(room_id),
-                                                                QString::fromStdString(event_id));
-                                }
-                                saved_receipts.emplace(read_by, timestamp);
-                        }
+            // Append the new ones.
+            for (const auto &[read_by, timestamp] : event_receipts) {
+                if (read_by == user_id) {
+                    emit removeNotification(QString::fromStdString(room_id),
+                                            QString::fromStdString(event_id));
+                }
+                saved_receipts.emplace(read_by, timestamp);
+            }
 
-                        // Save back the merged (or only the new) receipts.
-                        nlohmann::json json_updated_value = saved_receipts;
-                        std::string merged_receipts       = json_updated_value.dump();
+            // Save back the merged (or only the new) receipts.
+            nlohmann::json json_updated_value = saved_receipts;
+            std::string merged_receipts       = json_updated_value.dump();
 
-                        readReceiptsDb_.put(txn, key, merged_receipts);
+            readReceiptsDb_.put(txn, key, merged_receipts);
 
-                } catch (const lmdb::error &e) {
-                        nhlog::db()->critical("updateReadReceipts: {}", e.what());
-                }
+        } catch (const lmdb::error &e) {
+            nhlog::db()->critical("updateReadReceipts: {}", e.what());
         }
+    }
 }
 
 void
 Cache::calculateRoomReadStatus()
 {
-        const auto joined_rooms = joinedRooms();
+    const auto joined_rooms = joinedRooms();
 
-        std::map<QString, bool> readStatus;
+    std::map<QString, bool> readStatus;
 
-        for (const auto &room : joined_rooms)
-                readStatus.emplace(QString::fromStdString(room), calculateRoomReadStatus(room));
+    for (const auto &room : joined_rooms)
+        readStatus.emplace(QString::fromStdString(room), calculateRoomReadStatus(room));
 
-        emit roomReadStatus(readStatus);
+    emit roomReadStatus(readStatus);
 }
 
 bool
 Cache::calculateRoomReadStatus(const std::string &room_id)
 {
-        std::string last_event_id_, fullyReadEventId_;
-        {
-                auto txn = ro_txn(env_);
-
-                // Get last event id on the room.
-                const auto last_event_id = getLastEventId(txn, room_id);
-                const auto localUser     = utils::localUser().toStdString();
-
-                std::string fullyReadEventId;
-                if (auto ev = getAccountData(txn, mtx::events::EventType::FullyRead, room_id)) {
-                        if (auto fr = std::get_if<
-                              mtx::events::AccountDataEvent<mtx::events::account_data::FullyRead>>(
-                              &ev.value())) {
-                                fullyReadEventId = fr->content.event_id;
-                        }
-                }
-
-                if (last_event_id.empty() || fullyReadEventId.empty())
-                        return true;
+    std::string last_event_id_, fullyReadEventId_;
+    {
+        auto txn = ro_txn(env_);
 
-                if (last_event_id == fullyReadEventId)
-                        return false;
+        // Get last event id on the room.
+        const auto last_event_id = getLastEventId(txn, room_id);
+        const auto localUser     = utils::localUser().toStdString();
 
-                last_event_id_    = std::string(last_event_id);
-                fullyReadEventId_ = std::string(fullyReadEventId);
+        std::string fullyReadEventId;
+        if (auto ev = getAccountData(txn, mtx::events::EventType::FullyRead, room_id)) {
+            if (auto fr =
+                  std::get_if<mtx::events::AccountDataEvent<mtx::events::account_data::FullyRead>>(
+                    &ev.value())) {
+                fullyReadEventId = fr->content.event_id;
+            }
         }
 
-        // Retrieve all read receipts for that event.
-        return getEventIndex(room_id, last_event_id_) > getEventIndex(room_id, fullyReadEventId_);
+        if (last_event_id.empty() || fullyReadEventId.empty())
+            return true;
+
+        if (last_event_id == fullyReadEventId)
+            return false;
+
+        last_event_id_    = std::string(last_event_id);
+        fullyReadEventId_ = std::string(fullyReadEventId);
+    }
+
+    // Retrieve all read receipts for that event.
+    return getEventIndex(room_id, last_event_id_) > getEventIndex(room_id, fullyReadEventId_);
 }
 
 void
 Cache::saveState(const mtx::responses::Sync &res)
 {
-        using namespace mtx::events;
-        auto local_user_id = this->localUserId_.toStdString();
+    using namespace mtx::events;
+    auto local_user_id = this->localUserId_.toStdString();
 
-        auto currentBatchToken = nextBatchToken();
+    auto currentBatchToken = nextBatchToken();
 
-        auto txn = lmdb::txn::begin(env_);
+    auto txn = lmdb::txn::begin(env_);
 
-        setNextBatchToken(txn, res.next_batch);
-
-        if (!res.account_data.events.empty()) {
-                auto accountDataDb = getAccountDataDb(txn, "");
-                for (const auto &ev : res.account_data.events)
-                        std::visit(
-                          [&txn, &accountDataDb](const auto &event) {
-                                  auto j = json(event);
-                                  accountDataDb.put(txn, j["type"].get<std::string>(), j.dump());
-                          },
-                          ev);
-        }
+    setNextBatchToken(txn, res.next_batch);
 
-        auto userKeyCacheDb = getUserKeysDb(txn);
-
-        std::set<std::string> spaces_with_updates;
-        std::set<std::string> rooms_with_space_updates;
-
-        // Save joined rooms
-        for (const auto &room : res.rooms.join) {
-                auto statesdb    = getStatesDb(txn, room.first);
-                auto stateskeydb = getStatesKeyDb(txn, room.first);
-                auto membersdb   = getMembersDb(txn, room.first);
-                auto eventsDb    = getEventsDb(txn, room.first);
-
-                saveStateEvents(txn,
-                                statesdb,
-                                stateskeydb,
-                                membersdb,
-                                eventsDb,
-                                room.first,
-                                room.second.state.events);
-                saveStateEvents(txn,
-                                statesdb,
-                                stateskeydb,
-                                membersdb,
-                                eventsDb,
-                                room.first,
-                                room.second.timeline.events);
-
-                saveTimelineMessages(txn, eventsDb, room.first, room.second.timeline);
-
-                RoomInfo updatedInfo;
-                updatedInfo.name       = getRoomName(txn, statesdb, membersdb).toStdString();
-                updatedInfo.topic      = getRoomTopic(txn, statesdb).toStdString();
-                updatedInfo.avatar_url = getRoomAvatarUrl(txn, statesdb, membersdb).toStdString();
-                updatedInfo.version    = getRoomVersion(txn, statesdb).toStdString();
-                updatedInfo.is_space   = getRoomIsSpace(txn, statesdb);
-
-                if (updatedInfo.is_space) {
-                        bool space_updates = false;
-                        for (const auto &e : room.second.state.events)
-                                if (std::holds_alternative<StateEvent<state::space::Child>>(e) ||
-                                    std::holds_alternative<StateEvent<state::PowerLevels>>(e))
-                                        space_updates = true;
-                        for (const auto &e : room.second.timeline.events)
-                                if (std::holds_alternative<StateEvent<state::space::Child>>(e) ||
-                                    std::holds_alternative<StateEvent<state::PowerLevels>>(e))
-                                        space_updates = true;
-
-                        if (space_updates)
-                                spaces_with_updates.insert(room.first);
-                }
+    if (!res.account_data.events.empty()) {
+        auto accountDataDb = getAccountDataDb(txn, "");
+        for (const auto &ev : res.account_data.events)
+            std::visit(
+              [&txn, &accountDataDb](const auto &event) {
+                  auto j = json(event);
+                  accountDataDb.put(txn, j["type"].get<std::string>(), j.dump());
+              },
+              ev);
+    }
 
-                {
-                        bool room_has_space_update = false;
-                        for (const auto &e : room.second.state.events) {
-                                if (auto se = std::get_if<StateEvent<state::space::Parent>>(&e)) {
-                                        spaces_with_updates.insert(se->state_key);
-                                        room_has_space_update = true;
-                                }
-                        }
-                        for (const auto &e : room.second.timeline.events) {
-                                if (auto se = std::get_if<StateEvent<state::space::Parent>>(&e)) {
-                                        spaces_with_updates.insert(se->state_key);
-                                        room_has_space_update = true;
-                                }
-                        }
+    auto userKeyCacheDb = getUserKeysDb(txn);
 
-                        if (room_has_space_update)
-                                rooms_with_space_updates.insert(room.first);
-                }
+    std::set<std::string> spaces_with_updates;
+    std::set<std::string> rooms_with_space_updates;
 
-                bool has_new_tags = false;
-                // Process the account_data associated with this room
-                if (!room.second.account_data.events.empty()) {
-                        auto accountDataDb = getAccountDataDb(txn, room.first);
-
-                        for (const auto &evt : room.second.account_data.events) {
-                                std::visit(
-                                  [&txn, &accountDataDb](const auto &event) {
-                                          auto j = json(event);
-                                          accountDataDb.put(
-                                            txn, j["type"].get<std::string>(), j.dump());
-                                  },
-                                  evt);
-
-                                // for tag events
-                                if (std::holds_alternative<AccountDataEvent<account_data::Tags>>(
-                                      evt)) {
-                                        auto tags_evt =
-                                          std::get<AccountDataEvent<account_data::Tags>>(evt);
-                                        has_new_tags = true;
-                                        for (const auto &tag : tags_evt.content.tags) {
-                                                updatedInfo.tags.push_back(tag.first);
-                                        }
-                                }
-                                if (auto fr = std::get_if<mtx::events::AccountDataEvent<
-                                      mtx::events::account_data::FullyRead>>(&evt)) {
-                                        nhlog::db()->debug("Fully read: {}", fr->content.event_id);
-                                }
-                        }
+    // Save joined rooms
+    for (const auto &room : res.rooms.join) {
+        auto statesdb    = getStatesDb(txn, room.first);
+        auto stateskeydb = getStatesKeyDb(txn, room.first);
+        auto membersdb   = getMembersDb(txn, room.first);
+        auto eventsDb    = getEventsDb(txn, room.first);
+
+        saveStateEvents(
+          txn, statesdb, stateskeydb, membersdb, eventsDb, room.first, room.second.state.events);
+        saveStateEvents(
+          txn, statesdb, stateskeydb, membersdb, eventsDb, room.first, room.second.timeline.events);
+
+        saveTimelineMessages(txn, eventsDb, room.first, room.second.timeline);
+
+        RoomInfo updatedInfo;
+        updatedInfo.name       = getRoomName(txn, statesdb, membersdb).toStdString();
+        updatedInfo.topic      = getRoomTopic(txn, statesdb).toStdString();
+        updatedInfo.avatar_url = getRoomAvatarUrl(txn, statesdb, membersdb).toStdString();
+        updatedInfo.version    = getRoomVersion(txn, statesdb).toStdString();
+        updatedInfo.is_space   = getRoomIsSpace(txn, statesdb);
+
+        if (updatedInfo.is_space) {
+            bool space_updates = false;
+            for (const auto &e : room.second.state.events)
+                if (std::holds_alternative<StateEvent<state::space::Child>>(e) ||
+                    std::holds_alternative<StateEvent<state::PowerLevels>>(e))
+                    space_updates = true;
+            for (const auto &e : room.second.timeline.events)
+                if (std::holds_alternative<StateEvent<state::space::Child>>(e) ||
+                    std::holds_alternative<StateEvent<state::PowerLevels>>(e))
+                    space_updates = true;
+
+            if (space_updates)
+                spaces_with_updates.insert(room.first);
+        }
+
+        {
+            bool room_has_space_update = false;
+            for (const auto &e : room.second.state.events) {
+                if (auto se = std::get_if<StateEvent<state::space::Parent>>(&e)) {
+                    spaces_with_updates.insert(se->state_key);
+                    room_has_space_update = true;
                 }
-                if (!has_new_tags) {
-                        // retrieve the old tags, they haven't changed
-                        std::string_view data;
-                        if (roomsDb_.get(txn, room.first, data)) {
-                                try {
-                                        RoomInfo tmp =
-                                          json::parse(std::string_view(data.data(), data.size()));
-                                        updatedInfo.tags = tmp.tags;
-                                } catch (const json::exception &e) {
-                                        nhlog::db()->warn(
-                                          "failed to parse room info: room_id ({}), {}: {}",
-                                          room.first,
-                                          std::string(data.data(), data.size()),
-                                          e.what());
-                                }
-                        }
+            }
+            for (const auto &e : room.second.timeline.events) {
+                if (auto se = std::get_if<StateEvent<state::space::Parent>>(&e)) {
+                    spaces_with_updates.insert(se->state_key);
+                    room_has_space_update = true;
+                }
+            }
+
+            if (room_has_space_update)
+                rooms_with_space_updates.insert(room.first);
+        }
+
+        bool has_new_tags = false;
+        // Process the account_data associated with this room
+        if (!room.second.account_data.events.empty()) {
+            auto accountDataDb = getAccountDataDb(txn, room.first);
+
+            for (const auto &evt : room.second.account_data.events) {
+                std::visit(
+                  [&txn, &accountDataDb](const auto &event) {
+                      auto j = json(event);
+                      accountDataDb.put(txn, j["type"].get<std::string>(), j.dump());
+                  },
+                  evt);
+
+                // for tag events
+                if (std::holds_alternative<AccountDataEvent<account_data::Tags>>(evt)) {
+                    auto tags_evt = std::get<AccountDataEvent<account_data::Tags>>(evt);
+                    has_new_tags  = true;
+                    for (const auto &tag : tags_evt.content.tags) {
+                        updatedInfo.tags.push_back(tag.first);
+                    }
+                }
+                if (auto fr = std::get_if<
+                      mtx::events::AccountDataEvent<mtx::events::account_data::FullyRead>>(&evt)) {
+                    nhlog::db()->debug("Fully read: {}", fr->content.event_id);
+                }
+            }
+        }
+        if (!has_new_tags) {
+            // retrieve the old tags, they haven't changed
+            std::string_view data;
+            if (roomsDb_.get(txn, room.first, data)) {
+                try {
+                    RoomInfo tmp     = json::parse(std::string_view(data.data(), data.size()));
+                    updatedInfo.tags = tmp.tags;
+                } catch (const json::exception &e) {
+                    nhlog::db()->warn("failed to parse room info: room_id ({}), {}: {}",
+                                      room.first,
+                                      std::string(data.data(), data.size()),
+                                      e.what());
                 }
+            }
+        }
 
-                roomsDb_.put(txn, room.first, json(updatedInfo).dump());
+        roomsDb_.put(txn, room.first, json(updatedInfo).dump());
 
-                for (const auto &e : room.second.ephemeral.events) {
-                        if (auto receiptsEv = std::get_if<
-                              mtx::events::EphemeralEvent<mtx::events::ephemeral::Receipt>>(&e)) {
-                                Receipts receipts;
+        for (const auto &e : room.second.ephemeral.events) {
+            if (auto receiptsEv =
+                  std::get_if<mtx::events::EphemeralEvent<mtx::events::ephemeral::Receipt>>(&e)) {
+                Receipts receipts;
 
-                                for (const auto &[event_id, userReceipts] :
-                                     receiptsEv->content.receipts) {
-                                        for (const auto &[user_id, receipt] : userReceipts.users) {
-                                                receipts[event_id][user_id] = receipt.ts;
-                                        }
-                                }
-                                updateReadReceipt(txn, room.first, receipts);
-                        }
+                for (const auto &[event_id, userReceipts] : receiptsEv->content.receipts) {
+                    for (const auto &[user_id, receipt] : userReceipts.users) {
+                        receipts[event_id][user_id] = receipt.ts;
+                    }
                 }
-
-                // Clean up non-valid invites.
-                removeInvite(txn, room.first);
+                updateReadReceipt(txn, room.first, receipts);
+            }
         }
 
-        saveInvites(txn, res.rooms.invite);
+        // Clean up non-valid invites.
+        removeInvite(txn, room.first);
+    }
 
-        savePresence(txn, res.presence);
+    saveInvites(txn, res.rooms.invite);
 
-        markUserKeysOutOfDate(txn, userKeyCacheDb, res.device_lists.changed, currentBatchToken);
+    savePresence(txn, res.presence);
 
-        removeLeftRooms(txn, res.rooms.leave);
+    markUserKeysOutOfDate(txn, userKeyCacheDb, res.device_lists.changed, currentBatchToken);
 
-        updateSpaces(txn, spaces_with_updates, std::move(rooms_with_space_updates));
+    removeLeftRooms(txn, res.rooms.leave);
 
-        txn.commit();
+    updateSpaces(txn, spaces_with_updates, std::move(rooms_with_space_updates));
+
+    txn.commit();
 
-        std::map<QString, bool> readStatus;
-
-        for (const auto &room : res.rooms.join) {
-                for (const auto &e : room.second.ephemeral.events) {
-                        if (auto receiptsEv = std::get_if<
-                              mtx::events::EphemeralEvent<mtx::events::ephemeral::Receipt>>(&e)) {
-                                std::vector<QString> receipts;
-
-                                for (const auto &[event_id, userReceipts] :
-                                     receiptsEv->content.receipts) {
-                                        for (const auto &[user_id, receipt] : userReceipts.users) {
-                                                (void)receipt;
-
-                                                if (user_id != local_user_id) {
-                                                        receipts.push_back(
-                                                          QString::fromStdString(event_id));
-                                                        break;
-                                                }
-                                        }
-                                }
-                                if (!receipts.empty())
-                                        emit newReadReceipts(QString::fromStdString(room.first),
-                                                             receipts);
+    std::map<QString, bool> readStatus;
+
+    for (const auto &room : res.rooms.join) {
+        for (const auto &e : room.second.ephemeral.events) {
+            if (auto receiptsEv =
+                  std::get_if<mtx::events::EphemeralEvent<mtx::events::ephemeral::Receipt>>(&e)) {
+                std::vector<QString> receipts;
+
+                for (const auto &[event_id, userReceipts] : receiptsEv->content.receipts) {
+                    for (const auto &[user_id, receipt] : userReceipts.users) {
+                        (void)receipt;
+
+                        if (user_id != local_user_id) {
+                            receipts.push_back(QString::fromStdString(event_id));
+                            break;
                         }
+                    }
                 }
-                readStatus.emplace(QString::fromStdString(room.first),
-                                   calculateRoomReadStatus(room.first));
+                if (!receipts.empty())
+                    emit newReadReceipts(QString::fromStdString(room.first), receipts);
+            }
         }
+        readStatus.emplace(QString::fromStdString(room.first), calculateRoomReadStatus(room.first));
+    }
 
-        emit roomReadStatus(readStatus);
+    emit roomReadStatus(readStatus);
 }
 
 void
 Cache::saveInvites(lmdb::txn &txn, const std::map<std::string, mtx::responses::InvitedRoom> &rooms)
 {
-        for (const auto &room : rooms) {
-                auto statesdb  = getInviteStatesDb(txn, room.first);
-                auto membersdb = getInviteMembersDb(txn, room.first);
+    for (const auto &room : rooms) {
+        auto statesdb  = getInviteStatesDb(txn, room.first);
+        auto membersdb = getInviteMembersDb(txn, room.first);
 
-                saveInvite(txn, statesdb, membersdb, room.second);
+        saveInvite(txn, statesdb, membersdb, room.second);
 
-                RoomInfo updatedInfo;
-                updatedInfo.name  = getInviteRoomName(txn, statesdb, membersdb).toStdString();
-                updatedInfo.topic = getInviteRoomTopic(txn, statesdb).toStdString();
-                updatedInfo.avatar_url =
-                  getInviteRoomAvatarUrl(txn, statesdb, membersdb).toStdString();
-                updatedInfo.is_space  = getInviteRoomIsSpace(txn, statesdb);
-                updatedInfo.is_invite = true;
+        RoomInfo updatedInfo;
+        updatedInfo.name       = getInviteRoomName(txn, statesdb, membersdb).toStdString();
+        updatedInfo.topic      = getInviteRoomTopic(txn, statesdb).toStdString();
+        updatedInfo.avatar_url = getInviteRoomAvatarUrl(txn, statesdb, membersdb).toStdString();
+        updatedInfo.is_space   = getInviteRoomIsSpace(txn, statesdb);
+        updatedInfo.is_invite  = true;
 
-                invitesDb_.put(txn, room.first, json(updatedInfo).dump());
-        }
+        invitesDb_.put(txn, room.first, json(updatedInfo).dump());
+    }
 }
 
 void
@@ -1638,32 +1586,29 @@ Cache::saveInvite(lmdb::txn &txn,
                   lmdb::dbi &membersdb,
                   const mtx::responses::InvitedRoom &room)
 {
-        using namespace mtx::events;
-        using namespace mtx::events::state;
+    using namespace mtx::events;
+    using namespace mtx::events::state;
 
-        for (const auto &e : room.invite_state) {
-                if (auto msg = std::get_if<StrippedEvent<Member>>(&e)) {
-                        auto display_name = msg->content.display_name.empty()
-                                              ? msg->state_key
-                                              : msg->content.display_name;
+    for (const auto &e : room.invite_state) {
+        if (auto msg = std::get_if<StrippedEvent<Member>>(&e)) {
+            auto display_name =
+              msg->content.display_name.empty() ? msg->state_key : msg->content.display_name;
 
-                        MemberInfo tmp{display_name, msg->content.avatar_url};
+            MemberInfo tmp{display_name, msg->content.avatar_url};
 
-                        membersdb.put(txn, msg->state_key, json(tmp).dump());
-                } else {
-                        std::visit(
-                          [&txn, &statesdb](auto msg) {
-                                  auto j = json(msg);
-                                  bool res =
-                                    statesdb.put(txn, j["type"].get<std::string>(), j.dump());
-
-                                  if (!res)
-                                          nhlog::db()->warn("couldn't save data: {}",
-                                                            json(msg).dump());
-                          },
-                          e);
-                }
+            membersdb.put(txn, msg->state_key, json(tmp).dump());
+        } else {
+            std::visit(
+              [&txn, &statesdb](auto msg) {
+                  auto j   = json(msg);
+                  bool res = statesdb.put(txn, j["type"].get<std::string>(), j.dump());
+
+                  if (!res)
+                      nhlog::db()->warn("couldn't save data: {}", json(msg).dump());
+              },
+              e);
         }
+    }
 }
 
 void
@@ -1671,281 +1616,279 @@ Cache::savePresence(
   lmdb::txn &txn,
   const std::vector<mtx::events::Event<mtx::events::presence::Presence>> &presenceUpdates)
 {
-        for (const auto &update : presenceUpdates) {
-                auto presenceDb = getPresenceDb(txn);
+    for (const auto &update : presenceUpdates) {
+        auto presenceDb = getPresenceDb(txn);
 
-                presenceDb.put(txn, update.sender, json(update.content).dump());
-        }
+        presenceDb.put(txn, update.sender, json(update.content).dump());
+    }
 }
 
 std::vector<std::string>
 Cache::roomsWithStateUpdates(const mtx::responses::Sync &res)
 {
-        std::vector<std::string> rooms;
-        for (const auto &room : res.rooms.join) {
-                bool hasUpdates = false;
-                for (const auto &s : room.second.state.events) {
-                        if (containsStateUpdates(s)) {
-                                hasUpdates = true;
-                                break;
-                        }
-                }
-
-                for (const auto &s : room.second.timeline.events) {
-                        if (containsStateUpdates(s)) {
-                                hasUpdates = true;
-                                break;
-                        }
-                }
+    std::vector<std::string> rooms;
+    for (const auto &room : res.rooms.join) {
+        bool hasUpdates = false;
+        for (const auto &s : room.second.state.events) {
+            if (containsStateUpdates(s)) {
+                hasUpdates = true;
+                break;
+            }
+        }
 
-                if (hasUpdates)
-                        rooms.emplace_back(room.first);
+        for (const auto &s : room.second.timeline.events) {
+            if (containsStateUpdates(s)) {
+                hasUpdates = true;
+                break;
+            }
         }
 
-        for (const auto &room : res.rooms.invite) {
-                for (const auto &s : room.second.invite_state) {
-                        if (containsStateUpdates(s)) {
-                                rooms.emplace_back(room.first);
-                                break;
-                        }
-                }
+        if (hasUpdates)
+            rooms.emplace_back(room.first);
+    }
+
+    for (const auto &room : res.rooms.invite) {
+        for (const auto &s : room.second.invite_state) {
+            if (containsStateUpdates(s)) {
+                rooms.emplace_back(room.first);
+                break;
+            }
         }
+    }
 
-        return rooms;
+    return rooms;
 }
 
 RoomInfo
 Cache::singleRoomInfo(const std::string &room_id)
 {
-        auto txn = ro_txn(env_);
+    auto txn = ro_txn(env_);
 
-        try {
-                auto statesdb = getStatesDb(txn, room_id);
-
-                std::string_view data;
-
-                // Check if the room is joined.
-                if (roomsDb_.get(txn, room_id, data)) {
-                        try {
-                                RoomInfo tmp     = json::parse(data);
-                                tmp.member_count = getMembersDb(txn, room_id).size(txn);
-                                tmp.join_rule    = getRoomJoinRule(txn, statesdb);
-                                tmp.guest_access = getRoomGuestAccess(txn, statesdb);
-
-                                return tmp;
-                        } catch (const json::exception &e) {
-                                nhlog::db()->warn("failed to parse room info: room_id ({}), {}: {}",
-                                                  room_id,
-                                                  std::string(data.data(), data.size()),
-                                                  e.what());
-                        }
-                }
-        } catch (const lmdb::error &e) {
-                nhlog::db()->warn(
-                  "failed to read room info from db: room_id ({}), {}", room_id, e.what());
+    try {
+        auto statesdb = getStatesDb(txn, room_id);
+
+        std::string_view data;
+
+        // Check if the room is joined.
+        if (roomsDb_.get(txn, room_id, data)) {
+            try {
+                RoomInfo tmp     = json::parse(data);
+                tmp.member_count = getMembersDb(txn, room_id).size(txn);
+                tmp.join_rule    = getRoomJoinRule(txn, statesdb);
+                tmp.guest_access = getRoomGuestAccess(txn, statesdb);
+
+                return tmp;
+            } catch (const json::exception &e) {
+                nhlog::db()->warn("failed to parse room info: room_id ({}), {}: {}",
+                                  room_id,
+                                  std::string(data.data(), data.size()),
+                                  e.what());
+            }
         }
+    } catch (const lmdb::error &e) {
+        nhlog::db()->warn("failed to read room info from db: room_id ({}), {}", room_id, e.what());
+    }
 
-        return RoomInfo();
+    return RoomInfo();
 }
 
 std::map<QString, RoomInfo>
 Cache::getRoomInfo(const std::vector<std::string> &rooms)
 {
-        std::map<QString, RoomInfo> room_info;
+    std::map<QString, RoomInfo> room_info;
 
-        // TODO This should be read only.
-        auto txn = lmdb::txn::begin(env_);
+    // TODO This should be read only.
+    auto txn = lmdb::txn::begin(env_);
 
-        for (const auto &room : rooms) {
-                std::string_view data;
-                auto statesdb = getStatesDb(txn, room);
-
-                // Check if the room is joined.
-                if (roomsDb_.get(txn, room, data)) {
-                        try {
-                                RoomInfo tmp     = json::parse(data);
-                                tmp.member_count = getMembersDb(txn, room).size(txn);
-                                tmp.join_rule    = getRoomJoinRule(txn, statesdb);
-                                tmp.guest_access = getRoomGuestAccess(txn, statesdb);
-
-                                room_info.emplace(QString::fromStdString(room), std::move(tmp));
-                        } catch (const json::exception &e) {
-                                nhlog::db()->warn("failed to parse room info: room_id ({}), {}: {}",
-                                                  room,
-                                                  std::string(data.data(), data.size()),
-                                                  e.what());
-                        }
-                } else {
-                        // Check if the room is an invite.
-                        if (invitesDb_.get(txn, room, data)) {
-                                try {
-                                        RoomInfo tmp     = json::parse(std::string_view(data));
-                                        tmp.member_count = getInviteMembersDb(txn, room).size(txn);
-
-                                        room_info.emplace(QString::fromStdString(room),
-                                                          std::move(tmp));
-                                } catch (const json::exception &e) {
-                                        nhlog::db()->warn("failed to parse room info for invite: "
-                                                          "room_id ({}), {}: {}",
-                                                          room,
-                                                          std::string(data.data(), data.size()),
-                                                          e.what());
-                                }
-                        }
+    for (const auto &room : rooms) {
+        std::string_view data;
+        auto statesdb = getStatesDb(txn, room);
+
+        // Check if the room is joined.
+        if (roomsDb_.get(txn, room, data)) {
+            try {
+                RoomInfo tmp     = json::parse(data);
+                tmp.member_count = getMembersDb(txn, room).size(txn);
+                tmp.join_rule    = getRoomJoinRule(txn, statesdb);
+                tmp.guest_access = getRoomGuestAccess(txn, statesdb);
+
+                room_info.emplace(QString::fromStdString(room), std::move(tmp));
+            } catch (const json::exception &e) {
+                nhlog::db()->warn("failed to parse room info: room_id ({}), {}: {}",
+                                  room,
+                                  std::string(data.data(), data.size()),
+                                  e.what());
+            }
+        } else {
+            // Check if the room is an invite.
+            if (invitesDb_.get(txn, room, data)) {
+                try {
+                    RoomInfo tmp     = json::parse(std::string_view(data));
+                    tmp.member_count = getInviteMembersDb(txn, room).size(txn);
+
+                    room_info.emplace(QString::fromStdString(room), std::move(tmp));
+                } catch (const json::exception &e) {
+                    nhlog::db()->warn("failed to parse room info for invite: "
+                                      "room_id ({}), {}: {}",
+                                      room,
+                                      std::string(data.data(), data.size()),
+                                      e.what());
                 }
+            }
         }
+    }
 
-        txn.commit();
+    txn.commit();
 
-        return room_info;
+    return room_info;
 }
 
 std::vector<QString>
 Cache::roomIds()
 {
-        auto txn = ro_txn(env_);
+    auto txn = ro_txn(env_);
 
-        std::vector<QString> rooms;
-        std::string_view room_id, unused;
+    std::vector<QString> rooms;
+    std::string_view room_id, unused;
 
-        auto roomsCursor = lmdb::cursor::open(txn, roomsDb_);
-        while (roomsCursor.get(room_id, unused, MDB_NEXT))
-                rooms.push_back(QString::fromStdString(std::string(room_id)));
+    auto roomsCursor = lmdb::cursor::open(txn, roomsDb_);
+    while (roomsCursor.get(room_id, unused, MDB_NEXT))
+        rooms.push_back(QString::fromStdString(std::string(room_id)));
 
-        roomsCursor.close();
+    roomsCursor.close();
 
-        return rooms;
+    return rooms;
 }
 
 QMap<QString, mtx::responses::Notifications>
 Cache::getTimelineMentions()
 {
-        // TODO: Should be read-only, but getMentionsDb will attempt to create a DB
-        // if it doesn't exist, throwing an error.
-        auto txn = lmdb::txn::begin(env_, nullptr);
+    // TODO: Should be read-only, but getMentionsDb will attempt to create a DB
+    // if it doesn't exist, throwing an error.
+    auto txn = lmdb::txn::begin(env_, nullptr);
 
-        QMap<QString, mtx::responses::Notifications> notifs;
+    QMap<QString, mtx::responses::Notifications> notifs;
 
-        auto room_ids = getRoomIds(txn);
+    auto room_ids = getRoomIds(txn);
 
-        for (const auto &room_id : room_ids) {
-                auto roomNotifs                         = getTimelineMentionsForRoom(txn, room_id);
-                notifs[QString::fromStdString(room_id)] = roomNotifs;
-        }
+    for (const auto &room_id : room_ids) {
+        auto roomNotifs                         = getTimelineMentionsForRoom(txn, room_id);
+        notifs[QString::fromStdString(room_id)] = roomNotifs;
+    }
 
-        txn.commit();
+    txn.commit();
 
-        return notifs;
+    return notifs;
 }
 
 std::string
 Cache::previousBatchToken(const std::string &room_id)
 {
-        auto txn     = lmdb::txn::begin(env_, nullptr);
-        auto orderDb = getEventOrderDb(txn, room_id);
+    auto txn     = lmdb::txn::begin(env_, nullptr);
+    auto orderDb = getEventOrderDb(txn, room_id);
 
-        auto cursor = lmdb::cursor::open(txn, orderDb);
-        std::string_view indexVal, val;
-        if (!cursor.get(indexVal, val, MDB_FIRST)) {
-                return "";
-        }
+    auto cursor = lmdb::cursor::open(txn, orderDb);
+    std::string_view indexVal, val;
+    if (!cursor.get(indexVal, val, MDB_FIRST)) {
+        return "";
+    }
 
-        auto j = json::parse(val);
+    auto j = json::parse(val);
 
-        return j.value("prev_batch", "");
+    return j.value("prev_batch", "");
 }
 
 Cache::Messages
 Cache::getTimelineMessages(lmdb::txn &txn, const std::string &room_id, uint64_t index, bool forward)
 {
-        // TODO(nico): Limit the messages returned by this maybe?
-        auto orderDb  = getOrderToMessageDb(txn, room_id);
-        auto eventsDb = getEventsDb(txn, room_id);
+    // TODO(nico): Limit the messages returned by this maybe?
+    auto orderDb  = getOrderToMessageDb(txn, room_id);
+    auto eventsDb = getEventsDb(txn, room_id);
 
-        Messages messages{};
+    Messages messages{};
 
-        std::string_view indexVal, event_id;
+    std::string_view indexVal, event_id;
 
-        auto cursor = lmdb::cursor::open(txn, orderDb);
-        if (index == std::numeric_limits<uint64_t>::max()) {
-                if (cursor.get(indexVal, event_id, forward ? MDB_FIRST : MDB_LAST)) {
-                        index = lmdb::from_sv<uint64_t>(indexVal);
-                } else {
-                        messages.end_of_cache = true;
-                        return messages;
-                }
+    auto cursor = lmdb::cursor::open(txn, orderDb);
+    if (index == std::numeric_limits<uint64_t>::max()) {
+        if (cursor.get(indexVal, event_id, forward ? MDB_FIRST : MDB_LAST)) {
+            index = lmdb::from_sv<uint64_t>(indexVal);
         } else {
-                if (cursor.get(indexVal, event_id, MDB_SET)) {
-                        index = lmdb::from_sv<uint64_t>(indexVal);
-                } else {
-                        messages.end_of_cache = true;
-                        return messages;
-                }
+            messages.end_of_cache = true;
+            return messages;
         }
+    } else {
+        if (cursor.get(indexVal, event_id, MDB_SET)) {
+            index = lmdb::from_sv<uint64_t>(indexVal);
+        } else {
+            messages.end_of_cache = true;
+            return messages;
+        }
+    }
 
-        int counter = 0;
-
-        bool ret;
-        while ((ret = cursor.get(indexVal,
-                                 event_id,
-                                 counter == 0 ? (forward ? MDB_FIRST : MDB_LAST)
-                                              : (forward ? MDB_NEXT : MDB_PREV))) &&
-               counter++ < BATCH_SIZE) {
-                std::string_view event;
-                bool success = eventsDb.get(txn, event_id, event);
-                if (!success)
-                        continue;
+    int counter = 0;
 
-                mtx::events::collections::TimelineEvent te;
-                try {
-                        mtx::events::collections::from_json(json::parse(event), te);
-                } catch (std::exception &e) {
-                        nhlog::db()->error("Failed to parse message from cache {}", e.what());
-                        continue;
-                }
+    bool ret;
+    while ((ret = cursor.get(indexVal,
+                             event_id,
+                             counter == 0 ? (forward ? MDB_FIRST : MDB_LAST)
+                                          : (forward ? MDB_NEXT : MDB_PREV))) &&
+           counter++ < BATCH_SIZE) {
+        std::string_view event;
+        bool success = eventsDb.get(txn, event_id, event);
+        if (!success)
+            continue;
 
-                messages.timeline.events.push_back(std::move(te.data));
+        mtx::events::collections::TimelineEvent te;
+        try {
+            mtx::events::collections::from_json(json::parse(event), te);
+        } catch (std::exception &e) {
+            nhlog::db()->error("Failed to parse message from cache {}", e.what());
+            continue;
         }
-        cursor.close();
 
-        // std::reverse(timeline.events.begin(), timeline.events.end());
-        messages.next_index   = lmdb::from_sv<uint64_t>(indexVal);
-        messages.end_of_cache = !ret;
+        messages.timeline.events.push_back(std::move(te.data));
+    }
+    cursor.close();
+
+    // std::reverse(timeline.events.begin(), timeline.events.end());
+    messages.next_index   = lmdb::from_sv<uint64_t>(indexVal);
+    messages.end_of_cache = !ret;
 
-        return messages;
+    return messages;
 }
 
 std::optional<mtx::events::collections::TimelineEvent>
 Cache::getEvent(const std::string &room_id, const std::string &event_id)
 {
-        auto txn      = ro_txn(env_);
-        auto eventsDb = getEventsDb(txn, room_id);
+    auto txn      = ro_txn(env_);
+    auto eventsDb = getEventsDb(txn, room_id);
 
-        std::string_view event{};
-        bool success = eventsDb.get(txn, event_id, event);
-        if (!success)
-                return {};
+    std::string_view event{};
+    bool success = eventsDb.get(txn, event_id, event);
+    if (!success)
+        return {};
 
-        mtx::events::collections::TimelineEvent te;
-        try {
-                mtx::events::collections::from_json(json::parse(event), te);
-        } catch (std::exception &e) {
-                nhlog::db()->error("Failed to parse message from cache {}", e.what());
-                return std::nullopt;
-        }
+    mtx::events::collections::TimelineEvent te;
+    try {
+        mtx::events::collections::from_json(json::parse(event), te);
+    } catch (std::exception &e) {
+        nhlog::db()->error("Failed to parse message from cache {}", e.what());
+        return std::nullopt;
+    }
 
-        return te;
+    return te;
 }
 void
 Cache::storeEvent(const std::string &room_id,
                   const std::string &event_id,
                   const mtx::events::collections::TimelineEvent &event)
 {
-        auto txn        = lmdb::txn::begin(env_);
-        auto eventsDb   = getEventsDb(txn, room_id);
-        auto event_json = mtx::accessors::serialize_event(event.data);
-        eventsDb.put(txn, event_id, event_json.dump());
-        txn.commit();
+    auto txn        = lmdb::txn::begin(env_);
+    auto eventsDb   = getEventsDb(txn, room_id);
+    auto event_json = mtx::accessors::serialize_event(event.data);
+    eventsDb.put(txn, event_id, event_json.dump());
+    txn.commit();
 }
 
 void
@@ -1953,962 +1896,944 @@ Cache::replaceEvent(const std::string &room_id,
                     const std::string &event_id,
                     const mtx::events::collections::TimelineEvent &event)
 {
-        auto txn         = lmdb::txn::begin(env_);
-        auto eventsDb    = getEventsDb(txn, room_id);
-        auto relationsDb = getRelationsDb(txn, room_id);
-        auto event_json  = mtx::accessors::serialize_event(event.data).dump();
+    auto txn         = lmdb::txn::begin(env_);
+    auto eventsDb    = getEventsDb(txn, room_id);
+    auto relationsDb = getRelationsDb(txn, room_id);
+    auto event_json  = mtx::accessors::serialize_event(event.data).dump();
 
-        {
-                eventsDb.del(txn, event_id);
-                eventsDb.put(txn, event_id, event_json);
-                for (auto relation : mtx::accessors::relations(event.data).relations) {
-                        relationsDb.put(txn, relation.event_id, event_id);
-                }
+    {
+        eventsDb.del(txn, event_id);
+        eventsDb.put(txn, event_id, event_json);
+        for (auto relation : mtx::accessors::relations(event.data).relations) {
+            relationsDb.put(txn, relation.event_id, event_id);
         }
+    }
 
-        txn.commit();
+    txn.commit();
 }
 
 std::vector<std::string>
 Cache::relatedEvents(const std::string &room_id, const std::string &event_id)
 {
-        auto txn         = ro_txn(env_);
-        auto relationsDb = getRelationsDb(txn, room_id);
+    auto txn         = ro_txn(env_);
+    auto relationsDb = getRelationsDb(txn, room_id);
 
-        std::vector<std::string> related_ids;
+    std::vector<std::string> related_ids;
 
-        auto related_cursor         = lmdb::cursor::open(txn, relationsDb);
-        std::string_view related_to = event_id, related_event;
-        bool first                  = true;
+    auto related_cursor         = lmdb::cursor::open(txn, relationsDb);
+    std::string_view related_to = event_id, related_event;
+    bool first                  = true;
 
-        try {
-                if (!related_cursor.get(related_to, related_event, MDB_SET))
-                        return {};
+    try {
+        if (!related_cursor.get(related_to, related_event, MDB_SET))
+            return {};
 
-                while (related_cursor.get(
-                  related_to, related_event, first ? MDB_FIRST_DUP : MDB_NEXT_DUP)) {
-                        first = false;
-                        if (event_id != std::string_view(related_to.data(), related_to.size()))
-                                break;
+        while (
+          related_cursor.get(related_to, related_event, first ? MDB_FIRST_DUP : MDB_NEXT_DUP)) {
+            first = false;
+            if (event_id != std::string_view(related_to.data(), related_to.size()))
+                break;
 
-                        related_ids.emplace_back(related_event.data(), related_event.size());
-                }
-        } catch (const lmdb::error &e) {
-                nhlog::db()->error("related events error: {}", e.what());
+            related_ids.emplace_back(related_event.data(), related_event.size());
         }
+    } catch (const lmdb::error &e) {
+        nhlog::db()->error("related events error: {}", e.what());
+    }
 
-        return related_ids;
+    return related_ids;
 }
 
 size_t
 Cache::memberCount(const std::string &room_id)
 {
-        auto txn = ro_txn(env_);
-        return getMembersDb(txn, room_id).size(txn);
+    auto txn = ro_txn(env_);
+    return getMembersDb(txn, room_id).size(txn);
 }
 
 QMap<QString, RoomInfo>
 Cache::roomInfo(bool withInvites)
 {
-        QMap<QString, RoomInfo> result;
+    QMap<QString, RoomInfo> result;
 
-        auto txn = ro_txn(env_);
+    auto txn = ro_txn(env_);
 
-        std::string_view room_id;
-        std::string_view room_data;
+    std::string_view room_id;
+    std::string_view room_data;
 
-        // Gather info about the joined rooms.
-        auto roomsCursor = lmdb::cursor::open(txn, roomsDb_);
-        while (roomsCursor.get(room_id, room_data, MDB_NEXT)) {
-                RoomInfo tmp     = json::parse(std::move(room_data));
-                tmp.member_count = getMembersDb(txn, std::string(room_id)).size(txn);
-                result.insert(QString::fromStdString(std::string(room_id)), std::move(tmp));
-        }
-        roomsCursor.close();
-
-        if (withInvites) {
-                // Gather info about the invites.
-                auto invitesCursor = lmdb::cursor::open(txn, invitesDb_);
-                while (invitesCursor.get(room_id, room_data, MDB_NEXT)) {
-                        RoomInfo tmp     = json::parse(room_data);
-                        tmp.member_count = getInviteMembersDb(txn, std::string(room_id)).size(txn);
-                        result.insert(QString::fromStdString(std::string(room_id)), std::move(tmp));
-                }
-                invitesCursor.close();
+    // Gather info about the joined rooms.
+    auto roomsCursor = lmdb::cursor::open(txn, roomsDb_);
+    while (roomsCursor.get(room_id, room_data, MDB_NEXT)) {
+        RoomInfo tmp     = json::parse(std::move(room_data));
+        tmp.member_count = getMembersDb(txn, std::string(room_id)).size(txn);
+        result.insert(QString::fromStdString(std::string(room_id)), std::move(tmp));
+    }
+    roomsCursor.close();
+
+    if (withInvites) {
+        // Gather info about the invites.
+        auto invitesCursor = lmdb::cursor::open(txn, invitesDb_);
+        while (invitesCursor.get(room_id, room_data, MDB_NEXT)) {
+            RoomInfo tmp     = json::parse(room_data);
+            tmp.member_count = getInviteMembersDb(txn, std::string(room_id)).size(txn);
+            result.insert(QString::fromStdString(std::string(room_id)), std::move(tmp));
         }
+        invitesCursor.close();
+    }
 
-        return result;
+    return result;
 }
 
 std::string
 Cache::getLastEventId(lmdb::txn &txn, const std::string &room_id)
 {
-        lmdb::dbi orderDb;
-        try {
-                orderDb = getOrderToMessageDb(txn, room_id);
-        } catch (lmdb::runtime_error &e) {
-                nhlog::db()->error("Can't open db for room '{}', probably doesn't exist yet. ({})",
-                                   room_id,
-                                   e.what());
-                return {};
-        }
+    lmdb::dbi orderDb;
+    try {
+        orderDb = getOrderToMessageDb(txn, room_id);
+    } catch (lmdb::runtime_error &e) {
+        nhlog::db()->error(
+          "Can't open db for room '{}', probably doesn't exist yet. ({})", room_id, e.what());
+        return {};
+    }
 
-        std::string_view indexVal, val;
+    std::string_view indexVal, val;
 
-        auto cursor = lmdb::cursor::open(txn, orderDb);
-        if (!cursor.get(indexVal, val, MDB_LAST)) {
-                return {};
-        }
+    auto cursor = lmdb::cursor::open(txn, orderDb);
+    if (!cursor.get(indexVal, val, MDB_LAST)) {
+        return {};
+    }
 
-        return std::string(val.data(), val.size());
+    return std::string(val.data(), val.size());
 }
 
 std::optional<Cache::TimelineRange>
 Cache::getTimelineRange(const std::string &room_id)
 {
-        auto txn = ro_txn(env_);
-        lmdb::dbi orderDb;
-        try {
-                orderDb = getOrderToMessageDb(txn, room_id);
-        } catch (lmdb::runtime_error &e) {
-                nhlog::db()->error("Can't open db for room '{}', probably doesn't exist yet. ({})",
-                                   room_id,
-                                   e.what());
-                return {};
-        }
+    auto txn = ro_txn(env_);
+    lmdb::dbi orderDb;
+    try {
+        orderDb = getOrderToMessageDb(txn, room_id);
+    } catch (lmdb::runtime_error &e) {
+        nhlog::db()->error(
+          "Can't open db for room '{}', probably doesn't exist yet. ({})", room_id, e.what());
+        return {};
+    }
 
-        std::string_view indexVal, val;
+    std::string_view indexVal, val;
 
-        auto cursor = lmdb::cursor::open(txn, orderDb);
-        if (!cursor.get(indexVal, val, MDB_LAST)) {
-                return {};
-        }
+    auto cursor = lmdb::cursor::open(txn, orderDb);
+    if (!cursor.get(indexVal, val, MDB_LAST)) {
+        return {};
+    }
 
-        TimelineRange range{};
-        range.last = lmdb::from_sv<uint64_t>(indexVal);
+    TimelineRange range{};
+    range.last = lmdb::from_sv<uint64_t>(indexVal);
 
-        if (!cursor.get(indexVal, val, MDB_FIRST)) {
-                return {};
-        }
-        range.first = lmdb::from_sv<uint64_t>(indexVal);
+    if (!cursor.get(indexVal, val, MDB_FIRST)) {
+        return {};
+    }
+    range.first = lmdb::from_sv<uint64_t>(indexVal);
 
-        return range;
+    return range;
 }
 std::optional<uint64_t>
 Cache::getTimelineIndex(const std::string &room_id, std::string_view event_id)
 {
-        if (event_id.empty() || room_id.empty())
-                return {};
+    if (event_id.empty() || room_id.empty())
+        return {};
 
-        auto txn = ro_txn(env_);
+    auto txn = ro_txn(env_);
 
-        lmdb::dbi orderDb;
-        try {
-                orderDb = getMessageToOrderDb(txn, room_id);
-        } catch (lmdb::runtime_error &e) {
-                nhlog::db()->error("Can't open db for room '{}', probably doesn't exist yet. ({})",
-                                   room_id,
-                                   e.what());
-                return {};
-        }
+    lmdb::dbi orderDb;
+    try {
+        orderDb = getMessageToOrderDb(txn, room_id);
+    } catch (lmdb::runtime_error &e) {
+        nhlog::db()->error(
+          "Can't open db for room '{}', probably doesn't exist yet. ({})", room_id, e.what());
+        return {};
+    }
 
-        std::string_view indexVal{event_id.data(), event_id.size()}, val;
+    std::string_view indexVal{event_id.data(), event_id.size()}, val;
 
-        bool success = orderDb.get(txn, indexVal, val);
-        if (!success) {
-                return {};
-        }
+    bool success = orderDb.get(txn, indexVal, val);
+    if (!success) {
+        return {};
+    }
 
-        return lmdb::from_sv<uint64_t>(val);
+    return lmdb::from_sv<uint64_t>(val);
 }
 
 std::optional<uint64_t>
 Cache::getEventIndex(const std::string &room_id, std::string_view event_id)
 {
-        if (room_id.empty() || event_id.empty())
-                return {};
+    if (room_id.empty() || event_id.empty())
+        return {};
 
-        auto txn = ro_txn(env_);
+    auto txn = ro_txn(env_);
 
-        lmdb::dbi orderDb;
-        try {
-                orderDb = getEventToOrderDb(txn, room_id);
-        } catch (lmdb::runtime_error &e) {
-                nhlog::db()->error("Can't open db for room '{}', probably doesn't exist yet. ({})",
-                                   room_id,
-                                   e.what());
-                return {};
-        }
+    lmdb::dbi orderDb;
+    try {
+        orderDb = getEventToOrderDb(txn, room_id);
+    } catch (lmdb::runtime_error &e) {
+        nhlog::db()->error(
+          "Can't open db for room '{}', probably doesn't exist yet. ({})", room_id, e.what());
+        return {};
+    }
 
-        std::string_view val;
+    std::string_view val;
 
-        bool success = orderDb.get(txn, event_id, val);
-        if (!success) {
-                return {};
-        }
+    bool success = orderDb.get(txn, event_id, val);
+    if (!success) {
+        return {};
+    }
 
-        return lmdb::from_sv<uint64_t>(val);
+    return lmdb::from_sv<uint64_t>(val);
 }
 
 std::optional<std::pair<uint64_t, std::string>>
 Cache::lastInvisibleEventAfter(const std::string &room_id, std::string_view event_id)
 {
-        if (room_id.empty() || event_id.empty())
-                return {};
-
-        auto txn = ro_txn(env_);
-
-        lmdb::dbi orderDb;
-        lmdb::dbi eventOrderDb;
-        lmdb::dbi timelineDb;
-        try {
-                orderDb      = getEventToOrderDb(txn, room_id);
-                eventOrderDb = getEventOrderDb(txn, room_id);
-                timelineDb   = getMessageToOrderDb(txn, room_id);
-        } catch (lmdb::runtime_error &e) {
-                nhlog::db()->error("Can't open db for room '{}', probably doesn't exist yet. ({})",
-                                   room_id,
-                                   e.what());
-                return {};
-        }
-
-        std::string_view indexVal;
-
-        bool success = orderDb.get(txn, event_id, indexVal);
-        if (!success) {
-                return {};
-        }
-
-        try {
-                uint64_t prevIdx = lmdb::from_sv<uint64_t>(indexVal);
-                std::string prevId{event_id};
-
-                auto cursor = lmdb::cursor::open(txn, eventOrderDb);
-                cursor.get(indexVal, MDB_SET);
-                while (cursor.get(indexVal, event_id, MDB_NEXT)) {
-                        std::string evId = json::parse(event_id)["event_id"].get<std::string>();
-                        std::string_view temp;
-                        if (timelineDb.get(txn, evId, temp)) {
-                                return std::pair{prevIdx, std::string(prevId)};
-                        } else {
-                                prevIdx = lmdb::from_sv<uint64_t>(indexVal);
-                                prevId  = std::move(evId);
-                        }
-                }
-
+    if (room_id.empty() || event_id.empty())
+        return {};
+
+    auto txn = ro_txn(env_);
+
+    lmdb::dbi orderDb;
+    lmdb::dbi eventOrderDb;
+    lmdb::dbi timelineDb;
+    try {
+        orderDb      = getEventToOrderDb(txn, room_id);
+        eventOrderDb = getEventOrderDb(txn, room_id);
+        timelineDb   = getMessageToOrderDb(txn, room_id);
+    } catch (lmdb::runtime_error &e) {
+        nhlog::db()->error(
+          "Can't open db for room '{}', probably doesn't exist yet. ({})", room_id, e.what());
+        return {};
+    }
+
+    std::string_view indexVal;
+
+    bool success = orderDb.get(txn, event_id, indexVal);
+    if (!success) {
+        return {};
+    }
+
+    try {
+        uint64_t prevIdx = lmdb::from_sv<uint64_t>(indexVal);
+        std::string prevId{event_id};
+
+        auto cursor = lmdb::cursor::open(txn, eventOrderDb);
+        cursor.get(indexVal, MDB_SET);
+        while (cursor.get(indexVal, event_id, MDB_NEXT)) {
+            std::string evId = json::parse(event_id)["event_id"].get<std::string>();
+            std::string_view temp;
+            if (timelineDb.get(txn, evId, temp)) {
                 return std::pair{prevIdx, std::string(prevId)};
-        } catch (lmdb::runtime_error &e) {
-                nhlog::db()->error(
-                  "Failed to get last invisible event after {}", event_id, e.what());
-                return {};
+            } else {
+                prevIdx = lmdb::from_sv<uint64_t>(indexVal);
+                prevId  = std::move(evId);
+            }
         }
+
+        return std::pair{prevIdx, std::string(prevId)};
+    } catch (lmdb::runtime_error &e) {
+        nhlog::db()->error("Failed to get last invisible event after {}", event_id, e.what());
+        return {};
+    }
 }
 
 std::optional<uint64_t>
 Cache::getArrivalIndex(const std::string &room_id, std::string_view event_id)
 {
-        auto txn = ro_txn(env_);
+    auto txn = ro_txn(env_);
 
-        lmdb::dbi orderDb;
-        try {
-                orderDb = getEventToOrderDb(txn, room_id);
-        } catch (lmdb::runtime_error &e) {
-                nhlog::db()->error("Can't open db for room '{}', probably doesn't exist yet. ({})",
-                                   room_id,
-                                   e.what());
-                return {};
-        }
+    lmdb::dbi orderDb;
+    try {
+        orderDb = getEventToOrderDb(txn, room_id);
+    } catch (lmdb::runtime_error &e) {
+        nhlog::db()->error(
+          "Can't open db for room '{}', probably doesn't exist yet. ({})", room_id, e.what());
+        return {};
+    }
 
-        std::string_view val;
+    std::string_view val;
 
-        bool success = orderDb.get(txn, event_id, val);
-        if (!success) {
-                return {};
-        }
+    bool success = orderDb.get(txn, event_id, val);
+    if (!success) {
+        return {};
+    }
 
-        return lmdb::from_sv<uint64_t>(val);
+    return lmdb::from_sv<uint64_t>(val);
 }
 
 std::optional<std::string>
 Cache::getTimelineEventId(const std::string &room_id, uint64_t index)
 {
-        auto txn = ro_txn(env_);
-        lmdb::dbi orderDb;
-        try {
-                orderDb = getOrderToMessageDb(txn, room_id);
-        } catch (lmdb::runtime_error &e) {
-                nhlog::db()->error("Can't open db for room '{}', probably doesn't exist yet. ({})",
-                                   room_id,
-                                   e.what());
-                return {};
-        }
+    auto txn = ro_txn(env_);
+    lmdb::dbi orderDb;
+    try {
+        orderDb = getOrderToMessageDb(txn, room_id);
+    } catch (lmdb::runtime_error &e) {
+        nhlog::db()->error(
+          "Can't open db for room '{}', probably doesn't exist yet. ({})", room_id, e.what());
+        return {};
+    }
 
-        std::string_view val;
+    std::string_view val;
 
-        bool success = orderDb.get(txn, lmdb::to_sv(index), val);
-        if (!success) {
-                return {};
-        }
+    bool success = orderDb.get(txn, lmdb::to_sv(index), val);
+    if (!success) {
+        return {};
+    }
 
-        return std::string(val);
+    return std::string(val);
 }
 
 QHash<QString, RoomInfo>
 Cache::invites()
 {
-        QHash<QString, RoomInfo> result;
+    QHash<QString, RoomInfo> result;
 
-        auto txn    = ro_txn(env_);
-        auto cursor = lmdb::cursor::open(txn, invitesDb_);
+    auto txn    = ro_txn(env_);
+    auto cursor = lmdb::cursor::open(txn, invitesDb_);
 
-        std::string_view room_id, room_data;
+    std::string_view room_id, room_data;
 
-        while (cursor.get(room_id, room_data, MDB_NEXT)) {
-                try {
-                        RoomInfo tmp     = json::parse(room_data);
-                        tmp.member_count = getInviteMembersDb(txn, std::string(room_id)).size(txn);
-                        result.insert(QString::fromStdString(std::string(room_id)), std::move(tmp));
-                } catch (const json::exception &e) {
-                        nhlog::db()->warn("failed to parse room info for invite: "
-                                          "room_id ({}), {}: {}",
-                                          room_id,
-                                          std::string(room_data),
-                                          e.what());
-                }
+    while (cursor.get(room_id, room_data, MDB_NEXT)) {
+        try {
+            RoomInfo tmp     = json::parse(room_data);
+            tmp.member_count = getInviteMembersDb(txn, std::string(room_id)).size(txn);
+            result.insert(QString::fromStdString(std::string(room_id)), std::move(tmp));
+        } catch (const json::exception &e) {
+            nhlog::db()->warn("failed to parse room info for invite: "
+                              "room_id ({}), {}: {}",
+                              room_id,
+                              std::string(room_data),
+                              e.what());
         }
+    }
 
-        cursor.close();
+    cursor.close();
 
-        return result;
+    return result;
 }
 
 std::optional<RoomInfo>
 Cache::invite(std::string_view roomid)
 {
-        std::optional<RoomInfo> result;
+    std::optional<RoomInfo> result;
 
-        auto txn = ro_txn(env_);
+    auto txn = ro_txn(env_);
 
-        std::string_view room_data;
+    std::string_view room_data;
 
-        if (invitesDb_.get(txn, roomid, room_data)) {
-                try {
-                        RoomInfo tmp     = json::parse(room_data);
-                        tmp.member_count = getInviteMembersDb(txn, std::string(roomid)).size(txn);
-                        result           = std::move(tmp);
-                } catch (const json::exception &e) {
-                        nhlog::db()->warn("failed to parse room info for invite: "
-                                          "room_id ({}), {}: {}",
-                                          roomid,
-                                          std::string(room_data),
-                                          e.what());
-                }
+    if (invitesDb_.get(txn, roomid, room_data)) {
+        try {
+            RoomInfo tmp     = json::parse(room_data);
+            tmp.member_count = getInviteMembersDb(txn, std::string(roomid)).size(txn);
+            result           = std::move(tmp);
+        } catch (const json::exception &e) {
+            nhlog::db()->warn("failed to parse room info for invite: "
+                              "room_id ({}), {}: {}",
+                              roomid,
+                              std::string(room_data),
+                              e.what());
         }
+    }
 
-        return result;
+    return result;
 }
 
 QString
 Cache::getRoomAvatarUrl(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb)
 {
-        using namespace mtx::events;
-        using namespace mtx::events::state;
+    using namespace mtx::events;
+    using namespace mtx::events::state;
 
-        std::string_view event;
-        bool res = statesdb.get(txn, to_string(mtx::events::EventType::RoomAvatar), event);
+    std::string_view event;
+    bool res = statesdb.get(txn, to_string(mtx::events::EventType::RoomAvatar), event);
 
-        if (res) {
-                try {
-                        StateEvent<Avatar> msg =
-                          json::parse(std::string_view(event.data(), event.size()));
+    if (res) {
+        try {
+            StateEvent<Avatar> msg = json::parse(std::string_view(event.data(), event.size()));
 
-                        if (!msg.content.url.empty())
-                                return QString::fromStdString(msg.content.url);
-                } catch (const json::exception &e) {
-                        nhlog::db()->warn("failed to parse m.room.avatar event: {}", e.what());
-                }
+            if (!msg.content.url.empty())
+                return QString::fromStdString(msg.content.url);
+        } catch (const json::exception &e) {
+            nhlog::db()->warn("failed to parse m.room.avatar event: {}", e.what());
         }
+    }
 
-        // We don't use an avatar for group chats.
-        if (membersdb.size(txn) > 2)
-                return QString();
+    // We don't use an avatar for group chats.
+    if (membersdb.size(txn) > 2)
+        return QString();
 
-        auto cursor = lmdb::cursor::open(txn, membersdb);
-        std::string_view user_id;
-        std::string_view member_data;
-        std::string fallback_url;
+    auto cursor = lmdb::cursor::open(txn, membersdb);
+    std::string_view user_id;
+    std::string_view member_data;
+    std::string fallback_url;
 
-        // Resolve avatar for 1-1 chats.
-        while (cursor.get(user_id, member_data, MDB_NEXT)) {
-                try {
-                        MemberInfo m = json::parse(member_data);
-                        if (user_id == localUserId_.toStdString()) {
-                                fallback_url = m.avatar_url;
-                                continue;
-                        }
+    // Resolve avatar for 1-1 chats.
+    while (cursor.get(user_id, member_data, MDB_NEXT)) {
+        try {
+            MemberInfo m = json::parse(member_data);
+            if (user_id == localUserId_.toStdString()) {
+                fallback_url = m.avatar_url;
+                continue;
+            }
 
-                        cursor.close();
-                        return QString::fromStdString(m.avatar_url);
-                } catch (const json::exception &e) {
-                        nhlog::db()->warn("failed to parse member info: {}", e.what());
-                }
+            cursor.close();
+            return QString::fromStdString(m.avatar_url);
+        } catch (const json::exception &e) {
+            nhlog::db()->warn("failed to parse member info: {}", e.what());
         }
+    }
 
-        cursor.close();
+    cursor.close();
 
-        // Default case when there is only one member.
-        return QString::fromStdString(fallback_url);
+    // Default case when there is only one member.
+    return QString::fromStdString(fallback_url);
 }
 
 QString
 Cache::getRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb)
 {
-        using namespace mtx::events;
-        using namespace mtx::events::state;
+    using namespace mtx::events;
+    using namespace mtx::events::state;
 
-        std::string_view event;
-        bool res = statesdb.get(txn, to_string(mtx::events::EventType::RoomName), event);
+    std::string_view event;
+    bool res = statesdb.get(txn, to_string(mtx::events::EventType::RoomName), event);
 
-        if (res) {
-                try {
-                        StateEvent<Name> msg =
-                          json::parse(std::string_view(event.data(), event.size()));
+    if (res) {
+        try {
+            StateEvent<Name> msg = json::parse(std::string_view(event.data(), event.size()));
 
-                        if (!msg.content.name.empty())
-                                return QString::fromStdString(msg.content.name);
-                } catch (const json::exception &e) {
-                        nhlog::db()->warn("failed to parse m.room.name event: {}", e.what());
-                }
+            if (!msg.content.name.empty())
+                return QString::fromStdString(msg.content.name);
+        } catch (const json::exception &e) {
+            nhlog::db()->warn("failed to parse m.room.name event: {}", e.what());
         }
+    }
 
-        res = statesdb.get(txn, to_string(mtx::events::EventType::RoomCanonicalAlias), event);
+    res = statesdb.get(txn, to_string(mtx::events::EventType::RoomCanonicalAlias), event);
 
-        if (res) {
-                try {
-                        StateEvent<CanonicalAlias> msg =
-                          json::parse(std::string_view(event.data(), event.size()));
+    if (res) {
+        try {
+            StateEvent<CanonicalAlias> msg =
+              json::parse(std::string_view(event.data(), event.size()));
 
-                        if (!msg.content.alias.empty())
-                                return QString::fromStdString(msg.content.alias);
-                } catch (const json::exception &e) {
-                        nhlog::db()->warn("failed to parse m.room.canonical_alias event: {}",
-                                          e.what());
-                }
+            if (!msg.content.alias.empty())
+                return QString::fromStdString(msg.content.alias);
+        } catch (const json::exception &e) {
+            nhlog::db()->warn("failed to parse m.room.canonical_alias event: {}", e.what());
         }
+    }
 
-        auto cursor      = lmdb::cursor::open(txn, membersdb);
-        const auto total = membersdb.size(txn);
+    auto cursor      = lmdb::cursor::open(txn, membersdb);
+    const auto total = membersdb.size(txn);
 
-        std::size_t ii = 0;
-        std::string_view user_id;
-        std::string_view member_data;
-        std::map<std::string, MemberInfo> members;
+    std::size_t ii = 0;
+    std::string_view user_id;
+    std::string_view member_data;
+    std::map<std::string, MemberInfo> members;
 
-        while (cursor.get(user_id, member_data, MDB_NEXT) && ii < 3) {
-                try {
-                        members.emplace(user_id, json::parse(member_data));
-                } catch (const json::exception &e) {
-                        nhlog::db()->warn("failed to parse member info: {}", e.what());
-                }
-
-                ii++;
+    while (cursor.get(user_id, member_data, MDB_NEXT) && ii < 3) {
+        try {
+            members.emplace(user_id, json::parse(member_data));
+        } catch (const json::exception &e) {
+            nhlog::db()->warn("failed to parse member info: {}", e.what());
         }
 
-        cursor.close();
+        ii++;
+    }
 
-        if (total == 1 && !members.empty())
-                return QString::fromStdString(members.begin()->second.name);
+    cursor.close();
 
-        auto first_member = [&members, this]() {
-                for (const auto &m : members) {
-                        if (m.first != localUserId_.toStdString())
-                                return QString::fromStdString(m.second.name);
-                }
+    if (total == 1 && !members.empty())
+        return QString::fromStdString(members.begin()->second.name);
+
+    auto first_member = [&members, this]() {
+        for (const auto &m : members) {
+            if (m.first != localUserId_.toStdString())
+                return QString::fromStdString(m.second.name);
+        }
 
-                return localUserId_;
-        }();
+        return localUserId_;
+    }();
 
-        if (total == 2)
-                return first_member;
-        else if (total > 2)
-                return QString("%1 and %2 others").arg(first_member).arg(total - 1);
+    if (total == 2)
+        return first_member;
+    else if (total > 2)
+        return QString("%1 and %2 others").arg(first_member).arg(total - 1);
 
-        return "Empty Room";
+    return "Empty Room";
 }
 
 mtx::events::state::JoinRule
 Cache::getRoomJoinRule(lmdb::txn &txn, lmdb::dbi &statesdb)
 {
-        using namespace mtx::events;
-        using namespace mtx::events::state;
+    using namespace mtx::events;
+    using namespace mtx::events::state;
 
-        std::string_view event;
-        bool res = statesdb.get(txn, to_string(mtx::events::EventType::RoomJoinRules), event);
+    std::string_view event;
+    bool res = statesdb.get(txn, to_string(mtx::events::EventType::RoomJoinRules), event);
 
-        if (res) {
-                try {
-                        StateEvent<state::JoinRules> msg = json::parse(event);
-                        return msg.content.join_rule;
-                } catch (const json::exception &e) {
-                        nhlog::db()->warn("failed to parse m.room.join_rule event: {}", e.what());
-                }
+    if (res) {
+        try {
+            StateEvent<state::JoinRules> msg = json::parse(event);
+            return msg.content.join_rule;
+        } catch (const json::exception &e) {
+            nhlog::db()->warn("failed to parse m.room.join_rule event: {}", e.what());
         }
-        return state::JoinRule::Knock;
+    }
+    return state::JoinRule::Knock;
 }
 
 bool
 Cache::getRoomGuestAccess(lmdb::txn &txn, lmdb::dbi &statesdb)
 {
-        using namespace mtx::events;
-        using namespace mtx::events::state;
+    using namespace mtx::events;
+    using namespace mtx::events::state;
 
-        std::string_view event;
-        bool res = statesdb.get(txn, to_string(mtx::events::EventType::RoomGuestAccess), event);
+    std::string_view event;
+    bool res = statesdb.get(txn, to_string(mtx::events::EventType::RoomGuestAccess), event);
 
-        if (res) {
-                try {
-                        StateEvent<GuestAccess> msg = json::parse(event);
-                        return msg.content.guest_access == AccessState::CanJoin;
-                } catch (const json::exception &e) {
-                        nhlog::db()->warn("failed to parse m.room.guest_access event: {}",
-                                          e.what());
-                }
+    if (res) {
+        try {
+            StateEvent<GuestAccess> msg = json::parse(event);
+            return msg.content.guest_access == AccessState::CanJoin;
+        } catch (const json::exception &e) {
+            nhlog::db()->warn("failed to parse m.room.guest_access event: {}", e.what());
         }
-        return false;
+    }
+    return false;
 }
 
 QString
 Cache::getRoomTopic(lmdb::txn &txn, lmdb::dbi &statesdb)
 {
-        using namespace mtx::events;
-        using namespace mtx::events::state;
+    using namespace mtx::events;
+    using namespace mtx::events::state;
 
-        std::string_view event;
-        bool res = statesdb.get(txn, to_string(mtx::events::EventType::RoomTopic), event);
+    std::string_view event;
+    bool res = statesdb.get(txn, to_string(mtx::events::EventType::RoomTopic), event);
 
-        if (res) {
-                try {
-                        StateEvent<Topic> msg = json::parse(event);
+    if (res) {
+        try {
+            StateEvent<Topic> msg = json::parse(event);
 
-                        if (!msg.content.topic.empty())
-                                return QString::fromStdString(msg.content.topic);
-                } catch (const json::exception &e) {
-                        nhlog::db()->warn("failed to parse m.room.topic event: {}", e.what());
-                }
+            if (!msg.content.topic.empty())
+                return QString::fromStdString(msg.content.topic);
+        } catch (const json::exception &e) {
+            nhlog::db()->warn("failed to parse m.room.topic event: {}", e.what());
         }
+    }
 
-        return QString();
+    return QString();
 }
 
 QString
 Cache::getRoomVersion(lmdb::txn &txn, lmdb::dbi &statesdb)
 {
-        using namespace mtx::events;
-        using namespace mtx::events::state;
+    using namespace mtx::events;
+    using namespace mtx::events::state;
 
-        std::string_view event;
-        bool res = statesdb.get(txn, to_string(mtx::events::EventType::RoomCreate), event);
+    std::string_view event;
+    bool res = statesdb.get(txn, to_string(mtx::events::EventType::RoomCreate), event);
 
-        if (res) {
-                try {
-                        StateEvent<Create> msg = json::parse(event);
+    if (res) {
+        try {
+            StateEvent<Create> msg = json::parse(event);
 
-                        if (!msg.content.room_version.empty())
-                                return QString::fromStdString(msg.content.room_version);
-                } catch (const json::exception &e) {
-                        nhlog::db()->warn("failed to parse m.room.create event: {}", e.what());
-                }
+            if (!msg.content.room_version.empty())
+                return QString::fromStdString(msg.content.room_version);
+        } catch (const json::exception &e) {
+            nhlog::db()->warn("failed to parse m.room.create event: {}", e.what());
         }
+    }
 
-        nhlog::db()->warn("m.room.create event is missing room version, assuming version \"1\"");
-        return QString("1");
+    nhlog::db()->warn("m.room.create event is missing room version, assuming version \"1\"");
+    return QString("1");
 }
 
 bool
 Cache::getRoomIsSpace(lmdb::txn &txn, lmdb::dbi &statesdb)
 {
-        using namespace mtx::events;
-        using namespace mtx::events::state;
+    using namespace mtx::events;
+    using namespace mtx::events::state;
 
-        std::string_view event;
-        bool res = statesdb.get(txn, to_string(mtx::events::EventType::RoomCreate), event);
+    std::string_view event;
+    bool res = statesdb.get(txn, to_string(mtx::events::EventType::RoomCreate), event);
 
-        if (res) {
-                try {
-                        StateEvent<Create> msg = json::parse(event);
+    if (res) {
+        try {
+            StateEvent<Create> msg = json::parse(event);
 
-                        return msg.content.type == mtx::events::state::room_type::space;
-                } catch (const json::exception &e) {
-                        nhlog::db()->warn("failed to parse m.room.create event: {}", e.what());
-                }
+            return msg.content.type == mtx::events::state::room_type::space;
+        } catch (const json::exception &e) {
+            nhlog::db()->warn("failed to parse m.room.create event: {}", e.what());
         }
+    }
 
-        nhlog::db()->warn("m.room.create event is missing room version, assuming version \"1\"");
-        return false;
+    nhlog::db()->warn("m.room.create event is missing room version, assuming version \"1\"");
+    return false;
 }
 
 std::optional<mtx::events::state::CanonicalAlias>
 Cache::getRoomAliases(const std::string &roomid)
 {
-        using namespace mtx::events;
-        using namespace mtx::events::state;
+    using namespace mtx::events;
+    using namespace mtx::events::state;
 
-        auto txn      = ro_txn(env_);
-        auto statesdb = getStatesDb(txn, roomid);
+    auto txn      = ro_txn(env_);
+    auto statesdb = getStatesDb(txn, roomid);
 
-        std::string_view event;
-        bool res = statesdb.get(txn, to_string(mtx::events::EventType::RoomCanonicalAlias), event);
+    std::string_view event;
+    bool res = statesdb.get(txn, to_string(mtx::events::EventType::RoomCanonicalAlias), event);
 
-        if (res) {
-                try {
-                        StateEvent<CanonicalAlias> msg = json::parse(event);
+    if (res) {
+        try {
+            StateEvent<CanonicalAlias> msg = json::parse(event);
 
-                        return msg.content;
-                } catch (const json::exception &e) {
-                        nhlog::db()->warn("failed to parse m.room.canonical_alias event: {}",
-                                          e.what());
-                }
+            return msg.content;
+        } catch (const json::exception &e) {
+            nhlog::db()->warn("failed to parse m.room.canonical_alias event: {}", e.what());
         }
+    }
 
-        return std::nullopt;
+    return std::nullopt;
 }
 
 QString
 Cache::getInviteRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb)
 {
-        using namespace mtx::events;
-        using namespace mtx::events::state;
+    using namespace mtx::events;
+    using namespace mtx::events::state;
 
-        std::string_view event;
-        bool res = statesdb.get(txn, to_string(mtx::events::EventType::RoomName), event);
+    std::string_view event;
+    bool res = statesdb.get(txn, to_string(mtx::events::EventType::RoomName), event);
 
-        if (res) {
-                try {
-                        StrippedEvent<state::Name> msg = json::parse(event);
-                        return QString::fromStdString(msg.content.name);
-                } catch (const json::exception &e) {
-                        nhlog::db()->warn("failed to parse m.room.name event: {}", e.what());
-                }
+    if (res) {
+        try {
+            StrippedEvent<state::Name> msg = json::parse(event);
+            return QString::fromStdString(msg.content.name);
+        } catch (const json::exception &e) {
+            nhlog::db()->warn("failed to parse m.room.name event: {}", e.what());
         }
+    }
 
-        auto cursor = lmdb::cursor::open(txn, membersdb);
-        std::string_view user_id, member_data;
+    auto cursor = lmdb::cursor::open(txn, membersdb);
+    std::string_view user_id, member_data;
 
-        while (cursor.get(user_id, member_data, MDB_NEXT)) {
-                if (user_id == localUserId_.toStdString())
-                        continue;
+    while (cursor.get(user_id, member_data, MDB_NEXT)) {
+        if (user_id == localUserId_.toStdString())
+            continue;
 
-                try {
-                        MemberInfo tmp = json::parse(member_data);
-                        cursor.close();
+        try {
+            MemberInfo tmp = json::parse(member_data);
+            cursor.close();
 
-                        return QString::fromStdString(tmp.name);
-                } catch (const json::exception &e) {
-                        nhlog::db()->warn("failed to parse member info: {}", e.what());
-                }
+            return QString::fromStdString(tmp.name);
+        } catch (const json::exception &e) {
+            nhlog::db()->warn("failed to parse member info: {}", e.what());
         }
+    }
 
-        cursor.close();
+    cursor.close();
 
-        return QString("Empty Room");
+    return QString("Empty Room");
 }
 
 QString
 Cache::getInviteRoomAvatarUrl(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb)
 {
-        using namespace mtx::events;
-        using namespace mtx::events::state;
+    using namespace mtx::events;
+    using namespace mtx::events::state;
 
-        std::string_view event;
-        bool res = statesdb.get(txn, to_string(mtx::events::EventType::RoomAvatar), event);
+    std::string_view event;
+    bool res = statesdb.get(txn, to_string(mtx::events::EventType::RoomAvatar), event);
 
-        if (res) {
-                try {
-                        StrippedEvent<state::Avatar> msg = json::parse(event);
-                        return QString::fromStdString(msg.content.url);
-                } catch (const json::exception &e) {
-                        nhlog::db()->warn("failed to parse m.room.avatar event: {}", e.what());
-                }
+    if (res) {
+        try {
+            StrippedEvent<state::Avatar> msg = json::parse(event);
+            return QString::fromStdString(msg.content.url);
+        } catch (const json::exception &e) {
+            nhlog::db()->warn("failed to parse m.room.avatar event: {}", e.what());
         }
+    }
 
-        auto cursor = lmdb::cursor::open(txn, membersdb);
-        std::string_view user_id, member_data;
+    auto cursor = lmdb::cursor::open(txn, membersdb);
+    std::string_view user_id, member_data;
 
-        while (cursor.get(user_id, member_data, MDB_NEXT)) {
-                if (user_id == localUserId_.toStdString())
-                        continue;
+    while (cursor.get(user_id, member_data, MDB_NEXT)) {
+        if (user_id == localUserId_.toStdString())
+            continue;
 
-                try {
-                        MemberInfo tmp = json::parse(member_data);
-                        cursor.close();
+        try {
+            MemberInfo tmp = json::parse(member_data);
+            cursor.close();
 
-                        return QString::fromStdString(tmp.avatar_url);
-                } catch (const json::exception &e) {
-                        nhlog::db()->warn("failed to parse member info: {}", e.what());
-                }
+            return QString::fromStdString(tmp.avatar_url);
+        } catch (const json::exception &e) {
+            nhlog::db()->warn("failed to parse member info: {}", e.what());
         }
+    }
 
-        cursor.close();
+    cursor.close();
 
-        return QString();
+    return QString();
 }
 
 QString
 Cache::getInviteRoomTopic(lmdb::txn &txn, lmdb::dbi &db)
 {
-        using namespace mtx::events;
-        using namespace mtx::events::state;
+    using namespace mtx::events;
+    using namespace mtx::events::state;
 
-        std::string_view event;
-        bool res = db.get(txn, to_string(mtx::events::EventType::RoomTopic), event);
+    std::string_view event;
+    bool res = db.get(txn, to_string(mtx::events::EventType::RoomTopic), event);
 
-        if (res) {
-                try {
-                        StrippedEvent<Topic> msg = json::parse(event);
-                        return QString::fromStdString(msg.content.topic);
-                } catch (const json::exception &e) {
-                        nhlog::db()->warn("failed to parse m.room.topic event: {}", e.what());
-                }
+    if (res) {
+        try {
+            StrippedEvent<Topic> msg = json::parse(event);
+            return QString::fromStdString(msg.content.topic);
+        } catch (const json::exception &e) {
+            nhlog::db()->warn("failed to parse m.room.topic event: {}", e.what());
         }
+    }
 
-        return QString();
+    return QString();
 }
 
 bool
 Cache::getInviteRoomIsSpace(lmdb::txn &txn, lmdb::dbi &db)
 {
-        using namespace mtx::events;
-        using namespace mtx::events::state;
+    using namespace mtx::events;
+    using namespace mtx::events::state;
 
-        std::string_view event;
-        bool res = db.get(txn, to_string(mtx::events::EventType::RoomCreate), event);
+    std::string_view event;
+    bool res = db.get(txn, to_string(mtx::events::EventType::RoomCreate), event);
 
-        if (res) {
-                try {
-                        StrippedEvent<Create> msg = json::parse(event);
-                        return msg.content.type == mtx::events::state::room_type::space;
-                } catch (const json::exception &e) {
-                        nhlog::db()->warn("failed to parse m.room.topic event: {}", e.what());
-                }
+    if (res) {
+        try {
+            StrippedEvent<Create> msg = json::parse(event);
+            return msg.content.type == mtx::events::state::room_type::space;
+        } catch (const json::exception &e) {
+            nhlog::db()->warn("failed to parse m.room.topic event: {}", e.what());
         }
+    }
 
-        return false;
+    return false;
 }
 
 std::vector<std::string>
 Cache::joinedRooms()
 {
-        auto txn         = ro_txn(env_);
-        auto roomsCursor = lmdb::cursor::open(txn, roomsDb_);
+    auto txn         = ro_txn(env_);
+    auto roomsCursor = lmdb::cursor::open(txn, roomsDb_);
 
-        std::string_view id, data;
-        std::vector<std::string> room_ids;
+    std::string_view id, data;
+    std::vector<std::string> room_ids;
 
-        // Gather the room ids for the joined rooms.
-        while (roomsCursor.get(id, data, MDB_NEXT))
-                room_ids.emplace_back(id);
+    // Gather the room ids for the joined rooms.
+    while (roomsCursor.get(id, data, MDB_NEXT))
+        room_ids.emplace_back(id);
 
-        roomsCursor.close();
+    roomsCursor.close();
 
-        return room_ids;
+    return room_ids;
 }
 
 std::optional<MemberInfo>
 Cache::getMember(const std::string &room_id, const std::string &user_id)
 {
-        if (user_id.empty() || !env_.handle())
-                return std::nullopt;
+    if (user_id.empty() || !env_.handle())
+        return std::nullopt;
 
-        try {
-                auto txn = ro_txn(env_);
+    try {
+        auto txn = ro_txn(env_);
 
-                auto membersdb = getMembersDb(txn, room_id);
+        auto membersdb = getMembersDb(txn, room_id);
 
-                std::string_view info;
-                if (membersdb.get(txn, user_id, info)) {
-                        MemberInfo m = json::parse(info);
-                        return m;
-                }
-        } catch (std::exception &e) {
-                nhlog::db()->warn(
-                  "Failed to read member ({}) in room ({}): {}", user_id, room_id, e.what());
+        std::string_view info;
+        if (membersdb.get(txn, user_id, info)) {
+            MemberInfo m = json::parse(info);
+            return m;
         }
-        return std::nullopt;
+    } catch (std::exception &e) {
+        nhlog::db()->warn(
+          "Failed to read member ({}) in room ({}): {}", user_id, room_id, e.what());
+    }
+    return std::nullopt;
 }
 
 std::vector<RoomMember>
 Cache::getMembers(const std::string &room_id, std::size_t startIndex, std::size_t len)
 {
-        auto txn    = ro_txn(env_);
-        auto db     = getMembersDb(txn, room_id);
-        auto cursor = lmdb::cursor::open(txn, db);
-
-        std::size_t currentIndex = 0;
+    auto txn    = ro_txn(env_);
+    auto db     = getMembersDb(txn, room_id);
+    auto cursor = lmdb::cursor::open(txn, db);
 
-        const auto endIndex = std::min(startIndex + len, db.size(txn));
+    std::size_t currentIndex = 0;
 
-        std::vector<RoomMember> members;
+    const auto endIndex = std::min(startIndex + len, db.size(txn));
 
-        std::string_view user_id, user_data;
-        while (cursor.get(user_id, user_data, MDB_NEXT)) {
-                if (currentIndex < startIndex) {
-                        currentIndex += 1;
-                        continue;
-                }
+    std::vector<RoomMember> members;
 
-                if (currentIndex >= endIndex)
-                        break;
+    std::string_view user_id, user_data;
+    while (cursor.get(user_id, user_data, MDB_NEXT)) {
+        if (currentIndex < startIndex) {
+            currentIndex += 1;
+            continue;
+        }
 
-                try {
-                        MemberInfo tmp = json::parse(user_data);
-                        members.emplace_back(
-                          RoomMember{QString::fromStdString(std::string(user_id)),
-                                     QString::fromStdString(tmp.name)});
-                } catch (const json::exception &e) {
-                        nhlog::db()->warn("{}", e.what());
-                }
+        if (currentIndex >= endIndex)
+            break;
 
-                currentIndex += 1;
+        try {
+            MemberInfo tmp = json::parse(user_data);
+            members.emplace_back(RoomMember{QString::fromStdString(std::string(user_id)),
+                                            QString::fromStdString(tmp.name)});
+        } catch (const json::exception &e) {
+            nhlog::db()->warn("{}", e.what());
         }
 
-        cursor.close();
+        currentIndex += 1;
+    }
 
-        return members;
+    cursor.close();
+
+    return members;
 }
 
 std::vector<RoomMember>
 Cache::getMembersFromInvite(const std::string &room_id, std::size_t startIndex, std::size_t len)
 {
-        auto txn    = ro_txn(env_);
-        auto db     = getInviteMembersDb(txn, room_id);
-        auto cursor = lmdb::cursor::open(txn, db);
+    auto txn    = ro_txn(env_);
+    auto db     = getInviteMembersDb(txn, room_id);
+    auto cursor = lmdb::cursor::open(txn, db);
 
-        std::size_t currentIndex = 0;
+    std::size_t currentIndex = 0;
 
-        const auto endIndex = std::min(startIndex + len, db.size(txn));
+    const auto endIndex = std::min(startIndex + len, db.size(txn));
 
-        std::vector<RoomMember> members;
+    std::vector<RoomMember> members;
 
-        std::string_view user_id, user_data;
-        while (cursor.get(user_id, user_data, MDB_NEXT)) {
-                if (currentIndex < startIndex) {
-                        currentIndex += 1;
-                        continue;
-                }
-
-                if (currentIndex >= endIndex)
-                        break;
+    std::string_view user_id, user_data;
+    while (cursor.get(user_id, user_data, MDB_NEXT)) {
+        if (currentIndex < startIndex) {
+            currentIndex += 1;
+            continue;
+        }
 
-                try {
-                        MemberInfo tmp = json::parse(user_data);
-                        members.emplace_back(
-                          RoomMember{QString::fromStdString(std::string(user_id)),
-                                     QString::fromStdString(tmp.name)});
-                } catch (const json::exception &e) {
-                        nhlog::db()->warn("{}", e.what());
-                }
+        if (currentIndex >= endIndex)
+            break;
 
-                currentIndex += 1;
+        try {
+            MemberInfo tmp = json::parse(user_data);
+            members.emplace_back(RoomMember{QString::fromStdString(std::string(user_id)),
+                                            QString::fromStdString(tmp.name)});
+        } catch (const json::exception &e) {
+            nhlog::db()->warn("{}", e.what());
         }
 
-        cursor.close();
+        currentIndex += 1;
+    }
 
-        return members;
+    cursor.close();
+
+    return members;
 }
 
 bool
 Cache::isRoomMember(const std::string &user_id, const std::string &room_id)
 {
-        try {
-                auto txn = ro_txn(env_);
-                auto db  = getMembersDb(txn, room_id);
+    try {
+        auto txn = ro_txn(env_);
+        auto db  = getMembersDb(txn, room_id);
 
-                std::string_view value;
-                bool res = db.get(txn, user_id, value);
+        std::string_view value;
+        bool res = db.get(txn, user_id, value);
 
-                return res;
-        } catch (std::exception &e) {
-                nhlog::db()->warn("Failed to read member membership ({}) in room ({}): {}",
-                                  user_id,
-                                  room_id,
-                                  e.what());
-        }
-        return false;
+        return res;
+    } catch (std::exception &e) {
+        nhlog::db()->warn(
+          "Failed to read member membership ({}) in room ({}): {}", user_id, room_id, e.what());
+    }
+    return false;
 }
 
 void
 Cache::savePendingMessage(const std::string &room_id,
                           const mtx::events::collections::TimelineEvent &message)
 {
-        auto txn      = lmdb::txn::begin(env_);
-        auto eventsDb = getEventsDb(txn, room_id);
+    auto txn      = lmdb::txn::begin(env_);
+    auto eventsDb = getEventsDb(txn, room_id);
 
-        mtx::responses::Timeline timeline;
-        timeline.events.push_back(message.data);
-        saveTimelineMessages(txn, eventsDb, room_id, timeline);
+    mtx::responses::Timeline timeline;
+    timeline.events.push_back(message.data);
+    saveTimelineMessages(txn, eventsDb, room_id, timeline);
 
-        auto pending = getPendingMessagesDb(txn, room_id);
+    auto pending = getPendingMessagesDb(txn, room_id);
 
-        int64_t now = QDateTime::currentMSecsSinceEpoch();
-        pending.put(txn, lmdb::to_sv(now), mtx::accessors::event_id(message.data));
+    int64_t now = QDateTime::currentMSecsSinceEpoch();
+    pending.put(txn, lmdb::to_sv(now), mtx::accessors::event_id(message.data));
 
-        txn.commit();
+    txn.commit();
 }
 
 std::optional<mtx::events::collections::TimelineEvent>
 Cache::firstPendingMessage(const std::string &room_id)
 {
-        auto txn     = lmdb::txn::begin(env_);
-        auto pending = getPendingMessagesDb(txn, room_id);
-
-        {
-                auto pendingCursor = lmdb::cursor::open(txn, pending);
-                std::string_view tsIgnored, pendingTxn;
-                while (pendingCursor.get(tsIgnored, pendingTxn, MDB_NEXT)) {
-                        auto eventsDb = getEventsDb(txn, room_id);
-                        std::string_view event;
-                        if (!eventsDb.get(txn, pendingTxn, event)) {
-                                pending.del(txn, tsIgnored, pendingTxn);
-                                continue;
-                        }
+    auto txn     = lmdb::txn::begin(env_);
+    auto pending = getPendingMessagesDb(txn, room_id);
+
+    {
+        auto pendingCursor = lmdb::cursor::open(txn, pending);
+        std::string_view tsIgnored, pendingTxn;
+        while (pendingCursor.get(tsIgnored, pendingTxn, MDB_NEXT)) {
+            auto eventsDb = getEventsDb(txn, room_id);
+            std::string_view event;
+            if (!eventsDb.get(txn, pendingTxn, event)) {
+                pending.del(txn, tsIgnored, pendingTxn);
+                continue;
+            }
+
+            try {
+                mtx::events::collections::TimelineEvent te;
+                mtx::events::collections::from_json(json::parse(event), te);
 
-                        try {
-                                mtx::events::collections::TimelineEvent te;
-                                mtx::events::collections::from_json(json::parse(event), te);
-
-                                pendingCursor.close();
-                                txn.commit();
-                                return te;
-                        } catch (std::exception &e) {
-                                nhlog::db()->error("Failed to parse message from cache {}",
-                                                   e.what());
-                                pending.del(txn, tsIgnored, pendingTxn);
-                                continue;
-                        }
-                }
+                pendingCursor.close();
+                txn.commit();
+                return te;
+            } catch (std::exception &e) {
+                nhlog::db()->error("Failed to parse message from cache {}", e.what());
+                pending.del(txn, tsIgnored, pendingTxn);
+                continue;
+            }
         }
+    }
 
-        txn.commit();
+    txn.commit();
 
-        return std::nullopt;
+    return std::nullopt;
 }
 
 void
 Cache::removePendingStatus(const std::string &room_id, const std::string &txn_id)
 {
-        auto txn     = lmdb::txn::begin(env_);
-        auto pending = getPendingMessagesDb(txn, room_id);
+    auto txn     = lmdb::txn::begin(env_);
+    auto pending = getPendingMessagesDb(txn, room_id);
 
-        {
-                auto pendingCursor = lmdb::cursor::open(txn, pending);
-                std::string_view tsIgnored, pendingTxn;
-                while (pendingCursor.get(tsIgnored, pendingTxn, MDB_NEXT)) {
-                        if (std::string_view(pendingTxn.data(), pendingTxn.size()) == txn_id)
-                                lmdb::cursor_del(pendingCursor);
-                }
+    {
+        auto pendingCursor = lmdb::cursor::open(txn, pending);
+        std::string_view tsIgnored, pendingTxn;
+        while (pendingCursor.get(tsIgnored, pendingTxn, MDB_NEXT)) {
+            if (std::string_view(pendingTxn.data(), pendingTxn.size()) == txn_id)
+                lmdb::cursor_del(pendingCursor);
         }
+    }
 
-        txn.commit();
+    txn.commit();
 }
 
 void
@@ -2917,403 +2842,398 @@ Cache::saveTimelineMessages(lmdb::txn &txn,
                             const std::string &room_id,
                             const mtx::responses::Timeline &res)
 {
-        if (res.events.empty())
-                return;
-
-        auto relationsDb = getRelationsDb(txn, room_id);
-
-        auto orderDb     = getEventOrderDb(txn, room_id);
-        auto evToOrderDb = getEventToOrderDb(txn, room_id);
-        auto msg2orderDb = getMessageToOrderDb(txn, room_id);
-        auto order2msgDb = getOrderToMessageDb(txn, room_id);
-        auto pending     = getPendingMessagesDb(txn, room_id);
-
-        if (res.limited) {
-                lmdb::dbi_drop(txn, orderDb, false);
-                lmdb::dbi_drop(txn, evToOrderDb, false);
-                lmdb::dbi_drop(txn, msg2orderDb, false);
-                lmdb::dbi_drop(txn, order2msgDb, false);
-                lmdb::dbi_drop(txn, pending, true);
-        }
-
-        using namespace mtx::events;
-        using namespace mtx::events::state;
-
-        std::string_view indexVal, val;
-        uint64_t index = std::numeric_limits<uint64_t>::max() / 2;
-        auto cursor    = lmdb::cursor::open(txn, orderDb);
-        if (cursor.get(indexVal, val, MDB_LAST)) {
-                index = lmdb::from_sv<uint64_t>(indexVal);
-        }
-
-        uint64_t msgIndex = std::numeric_limits<uint64_t>::max() / 2;
-        auto msgCursor    = lmdb::cursor::open(txn, order2msgDb);
-        if (msgCursor.get(indexVal, val, MDB_LAST)) {
-                msgIndex = lmdb::from_sv<uint64_t>(indexVal);
-        }
-
-        bool first = true;
-        for (const auto &e : res.events) {
-                auto event  = mtx::accessors::serialize_event(e);
-                auto txn_id = mtx::accessors::transaction_id(e);
-
-                std::string event_id_val = event.value("event_id", "");
-                if (event_id_val.empty()) {
-                        nhlog::db()->error("Event without id!");
-                        continue;
+    if (res.events.empty())
+        return;
+
+    auto relationsDb = getRelationsDb(txn, room_id);
+
+    auto orderDb     = getEventOrderDb(txn, room_id);
+    auto evToOrderDb = getEventToOrderDb(txn, room_id);
+    auto msg2orderDb = getMessageToOrderDb(txn, room_id);
+    auto order2msgDb = getOrderToMessageDb(txn, room_id);
+    auto pending     = getPendingMessagesDb(txn, room_id);
+
+    if (res.limited) {
+        lmdb::dbi_drop(txn, orderDb, false);
+        lmdb::dbi_drop(txn, evToOrderDb, false);
+        lmdb::dbi_drop(txn, msg2orderDb, false);
+        lmdb::dbi_drop(txn, order2msgDb, false);
+        lmdb::dbi_drop(txn, pending, true);
+    }
+
+    using namespace mtx::events;
+    using namespace mtx::events::state;
+
+    std::string_view indexVal, val;
+    uint64_t index = std::numeric_limits<uint64_t>::max() / 2;
+    auto cursor    = lmdb::cursor::open(txn, orderDb);
+    if (cursor.get(indexVal, val, MDB_LAST)) {
+        index = lmdb::from_sv<uint64_t>(indexVal);
+    }
+
+    uint64_t msgIndex = std::numeric_limits<uint64_t>::max() / 2;
+    auto msgCursor    = lmdb::cursor::open(txn, order2msgDb);
+    if (msgCursor.get(indexVal, val, MDB_LAST)) {
+        msgIndex = lmdb::from_sv<uint64_t>(indexVal);
+    }
+
+    bool first = true;
+    for (const auto &e : res.events) {
+        auto event  = mtx::accessors::serialize_event(e);
+        auto txn_id = mtx::accessors::transaction_id(e);
+
+        std::string event_id_val = event.value("event_id", "");
+        if (event_id_val.empty()) {
+            nhlog::db()->error("Event without id!");
+            continue;
+        }
+
+        std::string_view event_id = event_id_val;
+
+        json orderEntry        = json::object();
+        orderEntry["event_id"] = event_id_val;
+        if (first && !res.prev_batch.empty())
+            orderEntry["prev_batch"] = res.prev_batch;
+
+        std::string_view txn_order;
+        if (!txn_id.empty() && evToOrderDb.get(txn, txn_id, txn_order)) {
+            eventsDb.put(txn, event_id, event.dump());
+            eventsDb.del(txn, txn_id);
+
+            std::string_view msg_txn_order;
+            if (msg2orderDb.get(txn, txn_id, msg_txn_order)) {
+                order2msgDb.put(txn, msg_txn_order, event_id);
+                msg2orderDb.put(txn, event_id, msg_txn_order);
+                msg2orderDb.del(txn, txn_id);
+            }
+
+            orderDb.put(txn, txn_order, orderEntry.dump());
+            evToOrderDb.put(txn, event_id, txn_order);
+            evToOrderDb.del(txn, txn_id);
+
+            auto relations = mtx::accessors::relations(e);
+            if (!relations.relations.empty()) {
+                for (const auto &r : relations.relations) {
+                    if (!r.event_id.empty()) {
+                        relationsDb.del(txn, r.event_id, txn_id);
+                        relationsDb.put(txn, r.event_id, event_id);
+                    }
                 }
+            }
+
+            auto pendingCursor = lmdb::cursor::open(txn, pending);
+            std::string_view tsIgnored, pendingTxn;
+            while (pendingCursor.get(tsIgnored, pendingTxn, MDB_NEXT)) {
+                if (std::string_view(pendingTxn.data(), pendingTxn.size()) == txn_id)
+                    lmdb::cursor_del(pendingCursor);
+            }
+        } else if (auto redaction =
+                     std::get_if<mtx::events::RedactionEvent<mtx::events::msg::Redaction>>(&e)) {
+            if (redaction->redacts.empty())
+                continue;
+
+            std::string_view oldEvent;
+            bool success = eventsDb.get(txn, redaction->redacts, oldEvent);
+            if (!success)
+                continue;
+
+            mtx::events::collections::TimelineEvent te;
+            try {
+                mtx::events::collections::from_json(
+                  json::parse(std::string_view(oldEvent.data(), oldEvent.size())), te);
+                // overwrite the content and add redation data
+                std::visit(
+                  [redaction](auto &ev) {
+                      ev.unsigned_data.redacted_because = *redaction;
+                      ev.unsigned_data.redacted_by      = redaction->event_id;
+                  },
+                  te.data);
+                event = mtx::accessors::serialize_event(te.data);
+                event["content"].clear();
+
+            } catch (std::exception &e) {
+                nhlog::db()->error("Failed to parse message from cache {}", e.what());
+                continue;
+            }
 
-                std::string_view event_id = event_id_val;
-
-                json orderEntry        = json::object();
-                orderEntry["event_id"] = event_id_val;
-                if (first && !res.prev_batch.empty())
-                        orderEntry["prev_batch"] = res.prev_batch;
-
-                std::string_view txn_order;
-                if (!txn_id.empty() && evToOrderDb.get(txn, txn_id, txn_order)) {
-                        eventsDb.put(txn, event_id, event.dump());
-                        eventsDb.del(txn, txn_id);
-
-                        std::string_view msg_txn_order;
-                        if (msg2orderDb.get(txn, txn_id, msg_txn_order)) {
-                                order2msgDb.put(txn, msg_txn_order, event_id);
-                                msg2orderDb.put(txn, event_id, msg_txn_order);
-                                msg2orderDb.del(txn, txn_id);
-                        }
-
-                        orderDb.put(txn, txn_order, orderEntry.dump());
-                        evToOrderDb.put(txn, event_id, txn_order);
-                        evToOrderDb.del(txn, txn_id);
-
-                        auto relations = mtx::accessors::relations(e);
-                        if (!relations.relations.empty()) {
-                                for (const auto &r : relations.relations) {
-                                        if (!r.event_id.empty()) {
-                                                relationsDb.del(txn, r.event_id, txn_id);
-                                                relationsDb.put(txn, r.event_id, event_id);
-                                        }
-                                }
-                        }
-
-                        auto pendingCursor = lmdb::cursor::open(txn, pending);
-                        std::string_view tsIgnored, pendingTxn;
-                        while (pendingCursor.get(tsIgnored, pendingTxn, MDB_NEXT)) {
-                                if (std::string_view(pendingTxn.data(), pendingTxn.size()) ==
-                                    txn_id)
-                                        lmdb::cursor_del(pendingCursor);
-                        }
-                } else if (auto redaction =
-                             std::get_if<mtx::events::RedactionEvent<mtx::events::msg::Redaction>>(
-                               &e)) {
-                        if (redaction->redacts.empty())
-                                continue;
-
-                        std::string_view oldEvent;
-                        bool success = eventsDb.get(txn, redaction->redacts, oldEvent);
-                        if (!success)
-                                continue;
-
-                        mtx::events::collections::TimelineEvent te;
-                        try {
-                                mtx::events::collections::from_json(
-                                  json::parse(std::string_view(oldEvent.data(), oldEvent.size())),
-                                  te);
-                                // overwrite the content and add redation data
-                                std::visit(
-                                  [redaction](auto &ev) {
-                                          ev.unsigned_data.redacted_because = *redaction;
-                                          ev.unsigned_data.redacted_by      = redaction->event_id;
-                                  },
-                                  te.data);
-                                event = mtx::accessors::serialize_event(te.data);
-                                event["content"].clear();
-
-                        } catch (std::exception &e) {
-                                nhlog::db()->error("Failed to parse message from cache {}",
-                                                   e.what());
-                                continue;
-                        }
-
-                        eventsDb.put(txn, redaction->redacts, event.dump());
-                        eventsDb.put(txn, redaction->event_id, json(*redaction).dump());
-                } else {
-                        first = false;
+            eventsDb.put(txn, redaction->redacts, event.dump());
+            eventsDb.put(txn, redaction->event_id, json(*redaction).dump());
+        } else {
+            first = false;
 
-                        // This check protects against duplicates in the timeline. If the event_id
-                        // is already in the DB, we skip putting it (again) in ordered DBs, and only
-                        // update the event itself and its relations.
-                        std::string_view unused_read;
-                        if (!evToOrderDb.get(txn, event_id, unused_read)) {
-                                ++index;
+            // This check protects against duplicates in the timeline. If the event_id
+            // is already in the DB, we skip putting it (again) in ordered DBs, and only
+            // update the event itself and its relations.
+            std::string_view unused_read;
+            if (!evToOrderDb.get(txn, event_id, unused_read)) {
+                ++index;
 
-                                nhlog::db()->debug("saving '{}'", orderEntry.dump());
+                nhlog::db()->debug("saving '{}'", orderEntry.dump());
 
-                                cursor.put(lmdb::to_sv(index), orderEntry.dump(), MDB_APPEND);
-                                evToOrderDb.put(txn, event_id, lmdb::to_sv(index));
+                cursor.put(lmdb::to_sv(index), orderEntry.dump(), MDB_APPEND);
+                evToOrderDb.put(txn, event_id, lmdb::to_sv(index));
 
-                                // TODO(Nico): Allow blacklisting more event types in UI
-                                if (!isHiddenEvent(txn, e, room_id)) {
-                                        ++msgIndex;
-                                        msgCursor.put(lmdb::to_sv(msgIndex), event_id, MDB_APPEND);
+                // TODO(Nico): Allow blacklisting more event types in UI
+                if (!isHiddenEvent(txn, e, room_id)) {
+                    ++msgIndex;
+                    msgCursor.put(lmdb::to_sv(msgIndex), event_id, MDB_APPEND);
 
-                                        msg2orderDb.put(txn, event_id, lmdb::to_sv(msgIndex));
-                                }
-                        } else {
-                                nhlog::db()->warn("duplicate event '{}'", orderEntry.dump());
-                        }
-                        eventsDb.put(txn, event_id, event.dump());
-
-                        auto relations = mtx::accessors::relations(e);
-                        if (!relations.relations.empty()) {
-                                for (const auto &r : relations.relations) {
-                                        if (!r.event_id.empty()) {
-                                                relationsDb.put(txn, r.event_id, event_id);
-                                        }
-                                }
-                        }
+                    msg2orderDb.put(txn, event_id, lmdb::to_sv(msgIndex));
+                }
+            } else {
+                nhlog::db()->warn("duplicate event '{}'", orderEntry.dump());
+            }
+            eventsDb.put(txn, event_id, event.dump());
+
+            auto relations = mtx::accessors::relations(e);
+            if (!relations.relations.empty()) {
+                for (const auto &r : relations.relations) {
+                    if (!r.event_id.empty()) {
+                        relationsDb.put(txn, r.event_id, event_id);
+                    }
                 }
+            }
         }
+    }
 }
 
 uint64_t
 Cache::saveOldMessages(const std::string &room_id, const mtx::responses::Messages &res)
 {
-        auto txn         = lmdb::txn::begin(env_);
-        auto eventsDb    = getEventsDb(txn, room_id);
-        auto relationsDb = getRelationsDb(txn, room_id);
-
-        auto orderDb     = getEventOrderDb(txn, room_id);
-        auto evToOrderDb = getEventToOrderDb(txn, room_id);
-        auto msg2orderDb = getMessageToOrderDb(txn, room_id);
-        auto order2msgDb = getOrderToMessageDb(txn, room_id);
-
-        std::string_view indexVal, val;
-        uint64_t index = std::numeric_limits<uint64_t>::max() / 2;
-        {
-                auto cursor = lmdb::cursor::open(txn, orderDb);
-                if (cursor.get(indexVal, val, MDB_FIRST)) {
-                        index = lmdb::from_sv<uint64_t>(indexVal);
-                }
-        }
+    auto txn         = lmdb::txn::begin(env_);
+    auto eventsDb    = getEventsDb(txn, room_id);
+    auto relationsDb = getRelationsDb(txn, room_id);
 
-        uint64_t msgIndex = std::numeric_limits<uint64_t>::max() / 2;
-        {
-                auto msgCursor = lmdb::cursor::open(txn, order2msgDb);
-                if (msgCursor.get(indexVal, val, MDB_FIRST)) {
-                        msgIndex = lmdb::from_sv<uint64_t>(indexVal);
-                }
-        }
+    auto orderDb     = getEventOrderDb(txn, room_id);
+    auto evToOrderDb = getEventToOrderDb(txn, room_id);
+    auto msg2orderDb = getMessageToOrderDb(txn, room_id);
+    auto order2msgDb = getOrderToMessageDb(txn, room_id);
 
-        if (res.chunk.empty()) {
-                if (orderDb.get(txn, lmdb::to_sv(index), val)) {
-                        auto orderEntry          = json::parse(val);
-                        orderEntry["prev_batch"] = res.end;
-                        orderDb.put(txn, lmdb::to_sv(index), orderEntry.dump());
-                        txn.commit();
-                }
-                return index;
+    std::string_view indexVal, val;
+    uint64_t index = std::numeric_limits<uint64_t>::max() / 2;
+    {
+        auto cursor = lmdb::cursor::open(txn, orderDb);
+        if (cursor.get(indexVal, val, MDB_FIRST)) {
+            index = lmdb::from_sv<uint64_t>(indexVal);
         }
+    }
 
-        std::string event_id_val;
-        for (const auto &e : res.chunk) {
-                if (std::holds_alternative<
-                      mtx::events::RedactionEvent<mtx::events::msg::Redaction>>(e))
-                        continue;
-
-                auto event                = mtx::accessors::serialize_event(e);
-                event_id_val              = event["event_id"].get<std::string>();
-                std::string_view event_id = event_id_val;
-
-                // This check protects against duplicates in the timeline. If the event_id is
-                // already in the DB, we skip putting it (again) in ordered DBs, and only update the
-                // event itself and its relations.
-                std::string_view unused_read;
-                if (!evToOrderDb.get(txn, event_id, unused_read)) {
-                        --index;
-
-                        json orderEntry        = json::object();
-                        orderEntry["event_id"] = event_id_val;
-
-                        orderDb.put(txn, lmdb::to_sv(index), orderEntry.dump());
-                        evToOrderDb.put(txn, event_id, lmdb::to_sv(index));
-
-                        // TODO(Nico): Allow blacklisting more event types in UI
-                        if (!isHiddenEvent(txn, e, room_id)) {
-                                --msgIndex;
-                                order2msgDb.put(txn, lmdb::to_sv(msgIndex), event_id);
-
-                                msg2orderDb.put(txn, event_id, lmdb::to_sv(msgIndex));
-                        }
-                }
-                eventsDb.put(txn, event_id, event.dump());
-
-                auto relations = mtx::accessors::relations(e);
-                if (!relations.relations.empty()) {
-                        for (const auto &r : relations.relations) {
-                                if (!r.event_id.empty()) {
-                                        relationsDb.put(txn, r.event_id, event_id);
-                                }
-                        }
+    uint64_t msgIndex = std::numeric_limits<uint64_t>::max() / 2;
+    {
+        auto msgCursor = lmdb::cursor::open(txn, order2msgDb);
+        if (msgCursor.get(indexVal, val, MDB_FIRST)) {
+            msgIndex = lmdb::from_sv<uint64_t>(indexVal);
+        }
+    }
+
+    if (res.chunk.empty()) {
+        if (orderDb.get(txn, lmdb::to_sv(index), val)) {
+            auto orderEntry          = json::parse(val);
+            orderEntry["prev_batch"] = res.end;
+            orderDb.put(txn, lmdb::to_sv(index), orderEntry.dump());
+            txn.commit();
+        }
+        return index;
+    }
+
+    std::string event_id_val;
+    for (const auto &e : res.chunk) {
+        if (std::holds_alternative<mtx::events::RedactionEvent<mtx::events::msg::Redaction>>(e))
+            continue;
+
+        auto event                = mtx::accessors::serialize_event(e);
+        event_id_val              = event["event_id"].get<std::string>();
+        std::string_view event_id = event_id_val;
+
+        // This check protects against duplicates in the timeline. If the event_id is
+        // already in the DB, we skip putting it (again) in ordered DBs, and only update the
+        // event itself and its relations.
+        std::string_view unused_read;
+        if (!evToOrderDb.get(txn, event_id, unused_read)) {
+            --index;
+
+            json orderEntry        = json::object();
+            orderEntry["event_id"] = event_id_val;
+
+            orderDb.put(txn, lmdb::to_sv(index), orderEntry.dump());
+            evToOrderDb.put(txn, event_id, lmdb::to_sv(index));
+
+            // TODO(Nico): Allow blacklisting more event types in UI
+            if (!isHiddenEvent(txn, e, room_id)) {
+                --msgIndex;
+                order2msgDb.put(txn, lmdb::to_sv(msgIndex), event_id);
+
+                msg2orderDb.put(txn, event_id, lmdb::to_sv(msgIndex));
+            }
+        }
+        eventsDb.put(txn, event_id, event.dump());
+
+        auto relations = mtx::accessors::relations(e);
+        if (!relations.relations.empty()) {
+            for (const auto &r : relations.relations) {
+                if (!r.event_id.empty()) {
+                    relationsDb.put(txn, r.event_id, event_id);
                 }
+            }
         }
+    }
 
-        json orderEntry          = json::object();
-        orderEntry["event_id"]   = event_id_val;
-        orderEntry["prev_batch"] = res.end;
-        orderDb.put(txn, lmdb::to_sv(index), orderEntry.dump());
+    json orderEntry          = json::object();
+    orderEntry["event_id"]   = event_id_val;
+    orderEntry["prev_batch"] = res.end;
+    orderDb.put(txn, lmdb::to_sv(index), orderEntry.dump());
 
-        txn.commit();
+    txn.commit();
 
-        return msgIndex;
+    return msgIndex;
 }
 
 void
 Cache::clearTimeline(const std::string &room_id)
 {
-        auto txn         = lmdb::txn::begin(env_);
-        auto eventsDb    = getEventsDb(txn, room_id);
-        auto relationsDb = getRelationsDb(txn, room_id);
-
-        auto orderDb     = getEventOrderDb(txn, room_id);
-        auto evToOrderDb = getEventToOrderDb(txn, room_id);
-        auto msg2orderDb = getMessageToOrderDb(txn, room_id);
-        auto order2msgDb = getOrderToMessageDb(txn, room_id);
+    auto txn         = lmdb::txn::begin(env_);
+    auto eventsDb    = getEventsDb(txn, room_id);
+    auto relationsDb = getRelationsDb(txn, room_id);
 
-        std::string_view indexVal, val;
-        auto cursor = lmdb::cursor::open(txn, orderDb);
+    auto orderDb     = getEventOrderDb(txn, room_id);
+    auto evToOrderDb = getEventToOrderDb(txn, room_id);
+    auto msg2orderDb = getMessageToOrderDb(txn, room_id);
+    auto order2msgDb = getOrderToMessageDb(txn, room_id);
 
-        bool start                   = true;
-        bool passed_pagination_token = false;
-        while (cursor.get(indexVal, val, start ? MDB_LAST : MDB_PREV)) {
-                start = false;
-                json obj;
+    std::string_view indexVal, val;
+    auto cursor = lmdb::cursor::open(txn, orderDb);
 
-                try {
-                        obj = json::parse(std::string_view(val.data(), val.size()));
-                } catch (std::exception &) {
-                        // workaround bug in the initial db format, where we sometimes didn't store
-                        // json...
-                        obj = {{"event_id", std::string(val.data(), val.size())}};
-                }
+    bool start                   = true;
+    bool passed_pagination_token = false;
+    while (cursor.get(indexVal, val, start ? MDB_LAST : MDB_PREV)) {
+        start = false;
+        json obj;
 
-                if (passed_pagination_token) {
-                        if (obj.count("event_id") != 0) {
-                                std::string event_id = obj["event_id"].get<std::string>();
-
-                                if (!event_id.empty()) {
-                                        evToOrderDb.del(txn, event_id);
-                                        eventsDb.del(txn, event_id);
-                                        relationsDb.del(txn, event_id);
-
-                                        std::string_view order{};
-                                        bool exists = msg2orderDb.get(txn, event_id, order);
-                                        if (exists) {
-                                                order2msgDb.del(txn, order);
-                                                msg2orderDb.del(txn, event_id);
-                                        }
-                                }
-                        }
-                        lmdb::cursor_del(cursor);
-                } else {
-                        if (obj.count("prev_batch") != 0)
-                                passed_pagination_token = true;
+        try {
+            obj = json::parse(std::string_view(val.data(), val.size()));
+        } catch (std::exception &) {
+            // workaround bug in the initial db format, where we sometimes didn't store
+            // json...
+            obj = {{"event_id", std::string(val.data(), val.size())}};
+        }
+
+        if (passed_pagination_token) {
+            if (obj.count("event_id") != 0) {
+                std::string event_id = obj["event_id"].get<std::string>();
+
+                if (!event_id.empty()) {
+                    evToOrderDb.del(txn, event_id);
+                    eventsDb.del(txn, event_id);
+                    relationsDb.del(txn, event_id);
+
+                    std::string_view order{};
+                    bool exists = msg2orderDb.get(txn, event_id, order);
+                    if (exists) {
+                        order2msgDb.del(txn, order);
+                        msg2orderDb.del(txn, event_id);
+                    }
                 }
+            }
+            lmdb::cursor_del(cursor);
+        } else {
+            if (obj.count("prev_batch") != 0)
+                passed_pagination_token = true;
         }
+    }
 
-        auto msgCursor = lmdb::cursor::open(txn, order2msgDb);
-        start          = true;
-        while (msgCursor.get(indexVal, val, start ? MDB_LAST : MDB_PREV)) {
-                start = false;
-
-                std::string_view eventId;
-                bool innerStart = true;
-                bool found      = false;
-                while (cursor.get(indexVal, eventId, innerStart ? MDB_LAST : MDB_PREV)) {
-                        innerStart = false;
-
-                        json obj;
-                        try {
-                                obj = json::parse(std::string_view(eventId.data(), eventId.size()));
-                        } catch (std::exception &) {
-                                obj = {{"event_id", std::string(eventId.data(), eventId.size())}};
-                        }
+    auto msgCursor = lmdb::cursor::open(txn, order2msgDb);
+    start          = true;
+    while (msgCursor.get(indexVal, val, start ? MDB_LAST : MDB_PREV)) {
+        start = false;
 
-                        if (obj["event_id"] == std::string(val.data(), val.size())) {
-                                found = true;
-                                break;
-                        }
-                }
+        std::string_view eventId;
+        bool innerStart = true;
+        bool found      = false;
+        while (cursor.get(indexVal, eventId, innerStart ? MDB_LAST : MDB_PREV)) {
+            innerStart = false;
 
-                if (!found)
-                        break;
+            json obj;
+            try {
+                obj = json::parse(std::string_view(eventId.data(), eventId.size()));
+            } catch (std::exception &) {
+                obj = {{"event_id", std::string(eventId.data(), eventId.size())}};
+            }
+
+            if (obj["event_id"] == std::string(val.data(), val.size())) {
+                found = true;
+                break;
+            }
         }
 
-        do {
-                lmdb::cursor_del(msgCursor);
-        } while (msgCursor.get(indexVal, val, MDB_PREV));
+        if (!found)
+            break;
+    }
 
-        cursor.close();
-        msgCursor.close();
-        txn.commit();
+    do {
+        lmdb::cursor_del(msgCursor);
+    } while (msgCursor.get(indexVal, val, MDB_PREV));
+
+    cursor.close();
+    msgCursor.close();
+    txn.commit();
 }
 
 mtx::responses::Notifications
 Cache::getTimelineMentionsForRoom(lmdb::txn &txn, const std::string &room_id)
 {
-        auto db = getMentionsDb(txn, room_id);
+    auto db = getMentionsDb(txn, room_id);
 
-        if (db.size(txn) == 0) {
-                return mtx::responses::Notifications{};
-        }
+    if (db.size(txn) == 0) {
+        return mtx::responses::Notifications{};
+    }
 
-        mtx::responses::Notifications notif;
-        std::string_view event_id, msg;
+    mtx::responses::Notifications notif;
+    std::string_view event_id, msg;
 
-        auto cursor = lmdb::cursor::open(txn, db);
+    auto cursor = lmdb::cursor::open(txn, db);
 
-        while (cursor.get(event_id, msg, MDB_NEXT)) {
-                auto obj = json::parse(msg);
+    while (cursor.get(event_id, msg, MDB_NEXT)) {
+        auto obj = json::parse(msg);
 
-                if (obj.count("event") == 0)
-                        continue;
+        if (obj.count("event") == 0)
+            continue;
 
-                mtx::responses::Notification notification;
-                mtx::responses::from_json(obj, notification);
+        mtx::responses::Notification notification;
+        mtx::responses::from_json(obj, notification);
 
-                notif.notifications.push_back(notification);
-        }
-        cursor.close();
+        notif.notifications.push_back(notification);
+    }
+    cursor.close();
 
-        std::reverse(notif.notifications.begin(), notif.notifications.end());
+    std::reverse(notif.notifications.begin(), notif.notifications.end());
 
-        return notif;
+    return notif;
 }
 
 //! Add all notifications containing a user mention to the db.
 void
 Cache::saveTimelineMentions(const mtx::responses::Notifications &res)
 {
-        QMap<std::string, QList<mtx::responses::Notification>> notifsByRoom;
+    QMap<std::string, QList<mtx::responses::Notification>> notifsByRoom;
 
-        // Sort into room-specific 'buckets'
-        for (const auto &notif : res.notifications) {
-                json val = notif;
-                notifsByRoom[notif.room_id].push_back(notif);
-        }
+    // Sort into room-specific 'buckets'
+    for (const auto &notif : res.notifications) {
+        json val = notif;
+        notifsByRoom[notif.room_id].push_back(notif);
+    }
 
-        auto txn = lmdb::txn::begin(env_);
-        // Insert the entire set of mentions for each room at a time.
-        QMap<std::string, QList<mtx::responses::Notification>>::const_iterator it =
-          notifsByRoom.constBegin();
-        auto end = notifsByRoom.constEnd();
-        while (it != end) {
-                nhlog::db()->debug("Storing notifications for " + it.key());
-                saveTimelineMentions(txn, it.key(), std::move(it.value()));
-                ++it;
-        }
+    auto txn = lmdb::txn::begin(env_);
+    // Insert the entire set of mentions for each room at a time.
+    QMap<std::string, QList<mtx::responses::Notification>>::const_iterator it =
+      notifsByRoom.constBegin();
+    auto end = notifsByRoom.constEnd();
+    while (it != end) {
+        nhlog::db()->debug("Storing notifications for " + it.key());
+        saveTimelineMentions(txn, it.key(), std::move(it.value()));
+        ++it;
+    }
 
-        txn.commit();
+    txn.commit();
 }
 
 void
@@ -3321,138 +3241,138 @@ Cache::saveTimelineMentions(lmdb::txn &txn,
                             const std::string &room_id,
                             const QList<mtx::responses::Notification> &res)
 {
-        auto db = getMentionsDb(txn, room_id);
+    auto db = getMentionsDb(txn, room_id);
 
-        using namespace mtx::events;
-        using namespace mtx::events::state;
+    using namespace mtx::events;
+    using namespace mtx::events::state;
 
-        for (const auto &notif : res) {
-                const auto event_id = mtx::accessors::event_id(notif.event);
+    for (const auto &notif : res) {
+        const auto event_id = mtx::accessors::event_id(notif.event);
 
-                // double check that we have the correct room_id...
-                if (room_id.compare(notif.room_id) != 0) {
-                        return;
-                }
+        // double check that we have the correct room_id...
+        if (room_id.compare(notif.room_id) != 0) {
+            return;
+        }
 
-                json obj = notif;
+        json obj = notif;
 
-                db.put(txn, event_id, obj.dump());
-        }
+        db.put(txn, event_id, obj.dump());
+    }
 }
 
 void
 Cache::markSentNotification(const std::string &event_id)
 {
-        auto txn = lmdb::txn::begin(env_);
-        notificationsDb_.put(txn, event_id, "");
-        txn.commit();
+    auto txn = lmdb::txn::begin(env_);
+    notificationsDb_.put(txn, event_id, "");
+    txn.commit();
 }
 
 void
 Cache::removeReadNotification(const std::string &event_id)
 {
-        auto txn = lmdb::txn::begin(env_);
+    auto txn = lmdb::txn::begin(env_);
 
-        notificationsDb_.del(txn, event_id);
+    notificationsDb_.del(txn, event_id);
 
-        txn.commit();
+    txn.commit();
 }
 
 bool
 Cache::isNotificationSent(const std::string &event_id)
 {
-        auto txn = ro_txn(env_);
+    auto txn = ro_txn(env_);
 
-        std::string_view value;
-        bool res = notificationsDb_.get(txn, event_id, value);
+    std::string_view value;
+    bool res = notificationsDb_.get(txn, event_id, value);
 
-        return res;
+    return res;
 }
 
 std::vector<std::string>
 Cache::getRoomIds(lmdb::txn &txn)
 {
-        auto cursor = lmdb::cursor::open(txn, roomsDb_);
+    auto cursor = lmdb::cursor::open(txn, roomsDb_);
 
-        std::vector<std::string> rooms;
+    std::vector<std::string> rooms;
 
-        std::string_view room_id, _unused;
-        while (cursor.get(room_id, _unused, MDB_NEXT))
-                rooms.emplace_back(room_id);
+    std::string_view room_id, _unused;
+    while (cursor.get(room_id, _unused, MDB_NEXT))
+        rooms.emplace_back(room_id);
 
-        cursor.close();
+    cursor.close();
 
-        return rooms;
+    return rooms;
 }
 
 void
 Cache::deleteOldMessages()
 {
-        std::string_view indexVal, val;
+    std::string_view indexVal, val;
 
-        auto txn      = lmdb::txn::begin(env_);
-        auto room_ids = getRoomIds(txn);
+    auto txn      = lmdb::txn::begin(env_);
+    auto room_ids = getRoomIds(txn);
 
-        for (const auto &room_id : room_ids) {
-                auto orderDb     = getEventOrderDb(txn, room_id);
-                auto evToOrderDb = getEventToOrderDb(txn, room_id);
-                auto o2m         = getOrderToMessageDb(txn, room_id);
-                auto m2o         = getMessageToOrderDb(txn, room_id);
-                auto eventsDb    = getEventsDb(txn, room_id);
-                auto relationsDb = getRelationsDb(txn, room_id);
-                auto cursor      = lmdb::cursor::open(txn, orderDb);
+    for (const auto &room_id : room_ids) {
+        auto orderDb     = getEventOrderDb(txn, room_id);
+        auto evToOrderDb = getEventToOrderDb(txn, room_id);
+        auto o2m         = getOrderToMessageDb(txn, room_id);
+        auto m2o         = getMessageToOrderDb(txn, room_id);
+        auto eventsDb    = getEventsDb(txn, room_id);
+        auto relationsDb = getRelationsDb(txn, room_id);
+        auto cursor      = lmdb::cursor::open(txn, orderDb);
 
-                uint64_t first, last;
-                if (cursor.get(indexVal, val, MDB_LAST)) {
-                        last = lmdb::from_sv<uint64_t>(indexVal);
-                } else {
-                        continue;
-                }
-                if (cursor.get(indexVal, val, MDB_FIRST)) {
-                        first = lmdb::from_sv<uint64_t>(indexVal);
-                } else {
-                        continue;
-                }
+        uint64_t first, last;
+        if (cursor.get(indexVal, val, MDB_LAST)) {
+            last = lmdb::from_sv<uint64_t>(indexVal);
+        } else {
+            continue;
+        }
+        if (cursor.get(indexVal, val, MDB_FIRST)) {
+            first = lmdb::from_sv<uint64_t>(indexVal);
+        } else {
+            continue;
+        }
 
-                size_t message_count = static_cast<size_t>(last - first);
-                if (message_count < MAX_RESTORED_MESSAGES)
-                        continue;
-
-                bool start = true;
-                while (cursor.get(indexVal, val, start ? MDB_FIRST : MDB_NEXT) &&
-                       message_count-- > MAX_RESTORED_MESSAGES) {
-                        start    = false;
-                        auto obj = json::parse(std::string_view(val.data(), val.size()));
-
-                        if (obj.count("event_id") != 0) {
-                                std::string event_id = obj["event_id"].get<std::string>();
-                                evToOrderDb.del(txn, event_id);
-                                eventsDb.del(txn, event_id);
-
-                                relationsDb.del(txn, event_id);
-
-                                std::string_view order{};
-                                bool exists = m2o.get(txn, event_id, order);
-                                if (exists) {
-                                        o2m.del(txn, order);
-                                        m2o.del(txn, event_id);
-                                }
-                        }
-                        cursor.del();
+        size_t message_count = static_cast<size_t>(last - first);
+        if (message_count < MAX_RESTORED_MESSAGES)
+            continue;
+
+        bool start = true;
+        while (cursor.get(indexVal, val, start ? MDB_FIRST : MDB_NEXT) &&
+               message_count-- > MAX_RESTORED_MESSAGES) {
+            start    = false;
+            auto obj = json::parse(std::string_view(val.data(), val.size()));
+
+            if (obj.count("event_id") != 0) {
+                std::string event_id = obj["event_id"].get<std::string>();
+                evToOrderDb.del(txn, event_id);
+                eventsDb.del(txn, event_id);
+
+                relationsDb.del(txn, event_id);
+
+                std::string_view order{};
+                bool exists = m2o.get(txn, event_id, order);
+                if (exists) {
+                    o2m.del(txn, order);
+                    m2o.del(txn, event_id);
                 }
-                cursor.close();
+            }
+            cursor.del();
         }
-        txn.commit();
+        cursor.close();
+    }
+    txn.commit();
 }
 
 void
 Cache::deleteOldData() noexcept
 {
-        try {
-                deleteOldMessages();
-        } catch (const lmdb::error &e) {
-                nhlog::db()->error("failed to delete old messages: {}", e.what());
-        }
+    try {
+        deleteOldMessages();
+    } catch (const lmdb::error &e) {
+        nhlog::db()->error("failed to delete old messages: {}", e.what());
+    }
 }
 
 void
@@ -3460,241 +3380,232 @@ Cache::updateSpaces(lmdb::txn &txn,
                     const std::set<std::string> &spaces_with_updates,
                     std::set<std::string> rooms_with_updates)
 {
-        if (spaces_with_updates.empty() && rooms_with_updates.empty())
-                return;
+    if (spaces_with_updates.empty() && rooms_with_updates.empty())
+        return;
 
-        for (const auto &space : spaces_with_updates) {
-                // delete old entries
-                {
-                        auto cursor         = lmdb::cursor::open(txn, spacesChildrenDb_);
-                        bool first          = true;
-                        std::string_view sp = space, space_child = "";
-
-                        if (cursor.get(sp, space_child, MDB_SET)) {
-                                while (cursor.get(
-                                  sp, space_child, first ? MDB_FIRST_DUP : MDB_NEXT_DUP)) {
-                                        first = false;
-                                        spacesParentsDb_.del(txn, space_child, space);
-                                }
-                        }
-                        cursor.close();
-                        spacesChildrenDb_.del(txn, space);
+    for (const auto &space : spaces_with_updates) {
+        // delete old entries
+        {
+            auto cursor         = lmdb::cursor::open(txn, spacesChildrenDb_);
+            bool first          = true;
+            std::string_view sp = space, space_child = "";
+
+            if (cursor.get(sp, space_child, MDB_SET)) {
+                while (cursor.get(sp, space_child, first ? MDB_FIRST_DUP : MDB_NEXT_DUP)) {
+                    first = false;
+                    spacesParentsDb_.del(txn, space_child, space);
                 }
+            }
+            cursor.close();
+            spacesChildrenDb_.del(txn, space);
+        }
 
-                for (const auto &event :
-                     getStateEventsWithType<mtx::events::state::space::Child>(txn, space)) {
-                        if (event.content.via.has_value() && event.state_key.size() > 3 &&
-                            event.state_key.at(0) == '!') {
-                                spacesChildrenDb_.put(txn, space, event.state_key);
-                                spacesParentsDb_.put(txn, event.state_key, space);
-                        }
-                }
+        for (const auto &event :
+             getStateEventsWithType<mtx::events::state::space::Child>(txn, space)) {
+            if (event.content.via.has_value() && event.state_key.size() > 3 &&
+                event.state_key.at(0) == '!') {
+                spacesChildrenDb_.put(txn, space, event.state_key);
+                spacesParentsDb_.put(txn, event.state_key, space);
+            }
         }
+    }
 
-        const auto space_event_type = to_string(mtx::events::EventType::RoomPowerLevels);
+    const auto space_event_type = to_string(mtx::events::EventType::RoomPowerLevels);
 
-        for (const auto &room : rooms_with_updates) {
-                for (const auto &event :
-                     getStateEventsWithType<mtx::events::state::space::Parent>(txn, room)) {
-                        if (event.content.via.has_value() && event.state_key.size() > 3 &&
-                            event.state_key.at(0) == '!') {
-                                const std::string &space = event.state_key;
+    for (const auto &room : rooms_with_updates) {
+        for (const auto &event :
+             getStateEventsWithType<mtx::events::state::space::Parent>(txn, room)) {
+            if (event.content.via.has_value() && event.state_key.size() > 3 &&
+                event.state_key.at(0) == '!') {
+                const std::string &space = event.state_key;
 
-                                auto pls =
-                                  getStateEvent<mtx::events::state::PowerLevels>(txn, space);
+                auto pls = getStateEvent<mtx::events::state::PowerLevels>(txn, space);
 
-                                if (!pls)
-                                        continue;
+                if (!pls)
+                    continue;
 
-                                if (pls->content.user_level(event.sender) >=
-                                    pls->content.state_level(space_event_type)) {
-                                        spacesChildrenDb_.put(txn, space, room);
-                                        spacesParentsDb_.put(txn, room, space);
-                                }
-                        }
+                if (pls->content.user_level(event.sender) >=
+                    pls->content.state_level(space_event_type)) {
+                    spacesChildrenDb_.put(txn, space, room);
+                    spacesParentsDb_.put(txn, room, space);
                 }
+            }
         }
+    }
 }
 
 QMap<QString, std::optional<RoomInfo>>
 Cache::spaces()
 {
-        auto txn = ro_txn(env_);
-
-        QMap<QString, std::optional<RoomInfo>> ret;
-        {
-                auto cursor = lmdb::cursor::open(txn, spacesChildrenDb_);
-                bool first  = true;
-                std::string_view space_id, space_child;
-                while (cursor.get(space_id, space_child, first ? MDB_FIRST : MDB_NEXT)) {
-                        first = false;
-
-                        if (!space_child.empty()) {
-                                std::string_view room_data;
-                                if (roomsDb_.get(txn, space_id, room_data)) {
-                                        RoomInfo tmp = json::parse(std::move(room_data));
-                                        ret.insert(
-                                          QString::fromUtf8(space_id.data(), space_id.size()), tmp);
-                                } else {
-                                        ret.insert(
-                                          QString::fromUtf8(space_id.data(), space_id.size()),
-                                          std::nullopt);
-                                }
-                        }
+    auto txn = ro_txn(env_);
+
+    QMap<QString, std::optional<RoomInfo>> ret;
+    {
+        auto cursor = lmdb::cursor::open(txn, spacesChildrenDb_);
+        bool first  = true;
+        std::string_view space_id, space_child;
+        while (cursor.get(space_id, space_child, first ? MDB_FIRST : MDB_NEXT)) {
+            first = false;
+
+            if (!space_child.empty()) {
+                std::string_view room_data;
+                if (roomsDb_.get(txn, space_id, room_data)) {
+                    RoomInfo tmp = json::parse(std::move(room_data));
+                    ret.insert(QString::fromUtf8(space_id.data(), space_id.size()), tmp);
+                } else {
+                    ret.insert(QString::fromUtf8(space_id.data(), space_id.size()), std::nullopt);
                 }
-                cursor.close();
+            }
         }
+        cursor.close();
+    }
 
-        return ret;
+    return ret;
 }
 
 std::vector<std::string>
 Cache::getParentRoomIds(const std::string &room_id)
 {
-        auto txn = ro_txn(env_);
+    auto txn = ro_txn(env_);
 
-        std::vector<std::string> roomids;
-        {
-                auto cursor         = lmdb::cursor::open(txn, spacesParentsDb_);
-                bool first          = true;
-                std::string_view sp = room_id, space_parent;
-                if (cursor.get(sp, space_parent, MDB_SET)) {
-                        while (cursor.get(sp, space_parent, first ? MDB_FIRST_DUP : MDB_NEXT_DUP)) {
-                                first = false;
-
-                                if (!space_parent.empty())
-                                        roomids.emplace_back(space_parent);
-                        }
-                }
-                cursor.close();
+    std::vector<std::string> roomids;
+    {
+        auto cursor         = lmdb::cursor::open(txn, spacesParentsDb_);
+        bool first          = true;
+        std::string_view sp = room_id, space_parent;
+        if (cursor.get(sp, space_parent, MDB_SET)) {
+            while (cursor.get(sp, space_parent, first ? MDB_FIRST_DUP : MDB_NEXT_DUP)) {
+                first = false;
+
+                if (!space_parent.empty())
+                    roomids.emplace_back(space_parent);
+            }
         }
+        cursor.close();
+    }
 
-        return roomids;
+    return roomids;
 }
 
 std::vector<std::string>
 Cache::getChildRoomIds(const std::string &room_id)
 {
-        auto txn = ro_txn(env_);
+    auto txn = ro_txn(env_);
 
-        std::vector<std::string> roomids;
-        {
-                auto cursor         = lmdb::cursor::open(txn, spacesChildrenDb_);
-                bool first          = true;
-                std::string_view sp = room_id, space_child;
-                if (cursor.get(sp, space_child, MDB_SET)) {
-                        while (cursor.get(sp, space_child, first ? MDB_FIRST_DUP : MDB_NEXT_DUP)) {
-                                first = false;
-
-                                if (!space_child.empty())
-                                        roomids.emplace_back(space_child);
-                        }
-                }
-                cursor.close();
+    std::vector<std::string> roomids;
+    {
+        auto cursor         = lmdb::cursor::open(txn, spacesChildrenDb_);
+        bool first          = true;
+        std::string_view sp = room_id, space_child;
+        if (cursor.get(sp, space_child, MDB_SET)) {
+            while (cursor.get(sp, space_child, first ? MDB_FIRST_DUP : MDB_NEXT_DUP)) {
+                first = false;
+
+                if (!space_child.empty())
+                    roomids.emplace_back(space_child);
+            }
         }
+        cursor.close();
+    }
 
-        return roomids;
+    return roomids;
 }
 
 std::vector<ImagePackInfo>
 Cache::getImagePacks(const std::string &room_id, std::optional<bool> stickers)
 {
-        auto txn = ro_txn(env_);
-        std::vector<ImagePackInfo> infos;
-
-        auto addPack = [&infos, stickers](const mtx::events::msc2545::ImagePack &pack,
-                                          const std::string &source_room,
-                                          const std::string &state_key) {
-                if (!pack.pack || !stickers.has_value() ||
-                    (stickers.value() ? pack.pack->is_sticker() : pack.pack->is_emoji())) {
-                        ImagePackInfo info;
-                        info.source_room = source_room;
-                        info.state_key   = state_key;
-                        info.pack.pack   = pack.pack;
-
-                        for (const auto &img : pack.images) {
-                                if (stickers.has_value() && img.second.overrides_usage() &&
-                                    (stickers ? !img.second.is_sticker() : !img.second.is_emoji()))
-                                        continue;
-
-                                info.pack.images.insert(img);
-                        }
-
-                        if (!info.pack.images.empty())
-                                infos.push_back(std::move(info));
-                }
-        };
-
-        // packs from account data
-        if (auto accountpack =
-              getAccountData(txn, mtx::events::EventType::ImagePackInAccountData, "")) {
-                auto tmp =
-                  std::get_if<mtx::events::EphemeralEvent<mtx::events::msc2545::ImagePack>>(
-                    &*accountpack);
-                if (tmp)
-                        addPack(tmp->content, "", "");
-        }
-
-        // packs from rooms, that were enabled globally
-        if (auto roomPacks = getAccountData(txn, mtx::events::EventType::ImagePackRooms, "")) {
-                auto tmp =
-                  std::get_if<mtx::events::EphemeralEvent<mtx::events::msc2545::ImagePackRooms>>(
-                    &*roomPacks);
-                if (tmp) {
-                        for (const auto &[room_id2, state_to_d] : tmp->content.rooms) {
-                                // don't add stickers from this room twice
-                                if (room_id2 == room_id)
-                                        continue;
-
-                                for (const auto &[state_id, d] : state_to_d) {
-                                        (void)d;
-                                        if (auto pack =
-                                              getStateEvent<mtx::events::msc2545::ImagePack>(
-                                                txn, room_id2, state_id))
-                                                addPack(pack->content, room_id2, state_id);
-                                }
-                        }
+    auto txn = ro_txn(env_);
+    std::vector<ImagePackInfo> infos;
+
+    auto addPack = [&infos, stickers](const mtx::events::msc2545::ImagePack &pack,
+                                      const std::string &source_room,
+                                      const std::string &state_key) {
+        if (!pack.pack || !stickers.has_value() ||
+            (stickers.value() ? pack.pack->is_sticker() : pack.pack->is_emoji())) {
+            ImagePackInfo info;
+            info.source_room = source_room;
+            info.state_key   = state_key;
+            info.pack.pack   = pack.pack;
+
+            for (const auto &img : pack.images) {
+                if (stickers.has_value() && img.second.overrides_usage() &&
+                    (stickers ? !img.second.is_sticker() : !img.second.is_emoji()))
+                    continue;
+
+                info.pack.images.insert(img);
+            }
+
+            if (!info.pack.images.empty())
+                infos.push_back(std::move(info));
+        }
+    };
+
+    // packs from account data
+    if (auto accountpack =
+          getAccountData(txn, mtx::events::EventType::ImagePackInAccountData, "")) {
+        auto tmp =
+          std::get_if<mtx::events::EphemeralEvent<mtx::events::msc2545::ImagePack>>(&*accountpack);
+        if (tmp)
+            addPack(tmp->content, "", "");
+    }
+
+    // packs from rooms, that were enabled globally
+    if (auto roomPacks = getAccountData(txn, mtx::events::EventType::ImagePackRooms, "")) {
+        auto tmp = std::get_if<mtx::events::EphemeralEvent<mtx::events::msc2545::ImagePackRooms>>(
+          &*roomPacks);
+        if (tmp) {
+            for (const auto &[room_id2, state_to_d] : tmp->content.rooms) {
+                // don't add stickers from this room twice
+                if (room_id2 == room_id)
+                    continue;
+
+                for (const auto &[state_id, d] : state_to_d) {
+                    (void)d;
+                    if (auto pack =
+                          getStateEvent<mtx::events::msc2545::ImagePack>(txn, room_id2, state_id))
+                        addPack(pack->content, room_id2, state_id);
                 }
+            }
         }
+    }
 
-        // packs from current room
-        if (auto pack = getStateEvent<mtx::events::msc2545::ImagePack>(txn, room_id)) {
-                addPack(pack->content, room_id, "");
-        }
-        for (const auto &pack :
-             getStateEventsWithType<mtx::events::msc2545::ImagePack>(txn, room_id)) {
-                addPack(pack.content, room_id, pack.state_key);
-        }
+    // packs from current room
+    if (auto pack = getStateEvent<mtx::events::msc2545::ImagePack>(txn, room_id)) {
+        addPack(pack->content, room_id, "");
+    }
+    for (const auto &pack : getStateEventsWithType<mtx::events::msc2545::ImagePack>(txn, room_id)) {
+        addPack(pack.content, room_id, pack.state_key);
+    }
 
-        return infos;
+    return infos;
 }
 
 std::optional<mtx::events::collections::RoomAccountDataEvents>
 Cache::getAccountData(mtx::events::EventType type, const std::string &room_id)
 {
-        auto txn = ro_txn(env_);
-        return getAccountData(txn, type, room_id);
+    auto txn = ro_txn(env_);
+    return getAccountData(txn, type, room_id);
 }
 
 std::optional<mtx::events::collections::RoomAccountDataEvents>
 Cache::getAccountData(lmdb::txn &txn, mtx::events::EventType type, const std::string &room_id)
 {
-        try {
-                auto db = getAccountDataDb(txn, room_id);
-
-                std::string_view data;
-                if (db.get(txn, to_string(type), data)) {
-                        mtx::responses::utils::RoomAccountDataEvents events;
-                        json j = json::array({
-                          json::parse(data),
-                        });
-                        mtx::responses::utils::parse_room_account_data_events(j, events);
-                        if (events.size() == 1)
-                                return events.front();
-                }
-        } catch (...) {
+    try {
+        auto db = getAccountDataDb(txn, room_id);
+
+        std::string_view data;
+        if (db.get(txn, to_string(type), data)) {
+            mtx::responses::utils::RoomAccountDataEvents events;
+            json j = json::array({
+              json::parse(data),
+            });
+            mtx::responses::utils::parse_room_account_data_events(j, events);
+            if (events.size() == 1)
+                return events.front();
         }
-        return std::nullopt;
+    } catch (...) {
+    }
+    return std::nullopt;
 }
 
 bool
@@ -3702,465 +3613,436 @@ Cache::hasEnoughPowerLevel(const std::vector<mtx::events::EventType> &eventTypes
                            const std::string &room_id,
                            const std::string &user_id)
 {
-        using namespace mtx::events;
-        using namespace mtx::events::state;
+    using namespace mtx::events;
+    using namespace mtx::events::state;
 
-        auto txn = lmdb::txn::begin(env_);
-        auto db  = getStatesDb(txn, room_id);
+    auto txn = lmdb::txn::begin(env_);
+    auto db  = getStatesDb(txn, room_id);
 
-        int64_t min_event_level = std::numeric_limits<int64_t>::max();
-        int64_t user_level      = std::numeric_limits<int64_t>::min();
+    int64_t min_event_level = std::numeric_limits<int64_t>::max();
+    int64_t user_level      = std::numeric_limits<int64_t>::min();
 
-        std::string_view event;
-        bool res = db.get(txn, to_string(EventType::RoomPowerLevels), event);
+    std::string_view event;
+    bool res = db.get(txn, to_string(EventType::RoomPowerLevels), event);
 
-        if (res) {
-                try {
-                        StateEvent<PowerLevels> msg =
-                          json::parse(std::string_view(event.data(), event.size()));
+    if (res) {
+        try {
+            StateEvent<PowerLevels> msg = json::parse(std::string_view(event.data(), event.size()));
 
-                        user_level = msg.content.user_level(user_id);
+            user_level = msg.content.user_level(user_id);
 
-                        for (const auto &ty : eventTypes)
-                                min_event_level =
-                                  std::min(min_event_level, msg.content.state_level(to_string(ty)));
-                } catch (const json::exception &e) {
-                        nhlog::db()->warn("failed to parse m.room.power_levels event: {}",
-                                          e.what());
-                }
+            for (const auto &ty : eventTypes)
+                min_event_level = std::min(min_event_level, msg.content.state_level(to_string(ty)));
+        } catch (const json::exception &e) {
+            nhlog::db()->warn("failed to parse m.room.power_levels event: {}", e.what());
         }
+    }
 
-        txn.commit();
+    txn.commit();
 
-        return user_level >= min_event_level;
+    return user_level >= min_event_level;
 }
 
 std::vector<std::string>
 Cache::roomMembers(const std::string &room_id)
 {
-        auto txn = ro_txn(env_);
+    auto txn = ro_txn(env_);
 
-        std::vector<std::string> members;
-        std::string_view user_id, unused;
+    std::vector<std::string> members;
+    std::string_view user_id, unused;
 
-        auto db = getMembersDb(txn, room_id);
+    auto db = getMembersDb(txn, room_id);
 
-        auto cursor = lmdb::cursor::open(txn, db);
-        while (cursor.get(user_id, unused, MDB_NEXT))
-                members.emplace_back(user_id);
-        cursor.close();
+    auto cursor = lmdb::cursor::open(txn, db);
+    while (cursor.get(user_id, unused, MDB_NEXT))
+        members.emplace_back(user_id);
+    cursor.close();
 
-        return members;
+    return members;
 }
 
 crypto::Trust
 Cache::roomVerificationStatus(const std::string &room_id)
 {
-        crypto::Trust trust = crypto::Verified;
+    crypto::Trust trust = crypto::Verified;
 
-        try {
-                auto txn = lmdb::txn::begin(env_);
-
-                auto db     = getMembersDb(txn, room_id);
-                auto keysDb = getUserKeysDb(txn);
-                std::vector<std::string> keysToRequest;
-
-                std::string_view user_id, unused;
-                auto cursor = lmdb::cursor::open(txn, db);
-                while (cursor.get(user_id, unused, MDB_NEXT)) {
-                        auto verif = verificationStatus_(std::string(user_id), txn);
-                        if (verif.unverified_device_count) {
-                                trust = crypto::Unverified;
-                                if (verif.verified_devices.empty() && verif.no_keys) {
-                                        // we probably don't have the keys yet, so query them
-                                        keysToRequest.push_back(std::string(user_id));
-                                }
-                        } else if (verif.user_verified == crypto::TOFU && trust == crypto::Verified)
-                                trust = crypto::TOFU;
-                }
+    try {
+        auto txn = lmdb::txn::begin(env_);
 
-                if (!keysToRequest.empty())
-                        markUserKeysOutOfDate(txn, keysDb, keysToRequest, "");
+        auto db     = getMembersDb(txn, room_id);
+        auto keysDb = getUserKeysDb(txn);
+        std::vector<std::string> keysToRequest;
 
-        } catch (std::exception &e) {
-                nhlog::db()->error(
-                  "Failed to calculate verification status for {}: {}", room_id, e.what());
+        std::string_view user_id, unused;
+        auto cursor = lmdb::cursor::open(txn, db);
+        while (cursor.get(user_id, unused, MDB_NEXT)) {
+            auto verif = verificationStatus_(std::string(user_id), txn);
+            if (verif.unverified_device_count) {
                 trust = crypto::Unverified;
+                if (verif.verified_devices.empty() && verif.no_keys) {
+                    // we probably don't have the keys yet, so query them
+                    keysToRequest.push_back(std::string(user_id));
+                }
+            } else if (verif.user_verified == crypto::TOFU && trust == crypto::Verified)
+                trust = crypto::TOFU;
         }
 
-        return trust;
+        if (!keysToRequest.empty())
+            markUserKeysOutOfDate(txn, keysDb, keysToRequest, "");
+
+    } catch (std::exception &e) {
+        nhlog::db()->error("Failed to calculate verification status for {}: {}", room_id, e.what());
+        trust = crypto::Unverified;
+    }
+
+    return trust;
 }
 
 std::map<std::string, std::optional<UserKeyCache>>
 Cache::getMembersWithKeys(const std::string &room_id, bool verified_only)
 {
-        std::string_view keys;
+    std::string_view keys;
 
-        try {
-                auto txn = ro_txn(env_);
-                std::map<std::string, std::optional<UserKeyCache>> members;
-
-                auto db     = getMembersDb(txn, room_id);
-                auto keysDb = getUserKeysDb(txn);
-
-                std::string_view user_id, unused;
-                auto cursor = lmdb::cursor::open(txn, db);
-                while (cursor.get(user_id, unused, MDB_NEXT)) {
-                        auto res = keysDb.get(txn, user_id, keys);
-
-                        if (res) {
-                                auto k = json::parse(keys).get<UserKeyCache>();
-                                if (verified_only) {
-                                        auto verif = verificationStatus_(std::string(user_id), txn);
-
-                                        if (verif.user_verified == crypto::Trust::Verified ||
-                                            !verif.verified_devices.empty()) {
-                                                auto keyCopy = k;
-                                                keyCopy.device_keys.clear();
-
-                                                std::copy_if(
-                                                  k.device_keys.begin(),
-                                                  k.device_keys.end(),
-                                                  std::inserter(keyCopy.device_keys,
-                                                                keyCopy.device_keys.end()),
-                                                  [&verif](const auto &key) {
-                                                          auto curve25519 = key.second.keys.find(
-                                                            "curve25519:" + key.first);
-                                                          if (curve25519 == key.second.keys.end())
-                                                                  return false;
-                                                          if (auto t =
-                                                                verif.verified_device_keys.find(
-                                                                  curve25519->second);
-                                                              t ==
-                                                                verif.verified_device_keys.end() ||
-                                                              t->second != crypto::Trust::Verified)
-                                                                  return false;
-
-                                                          return key.first ==
-                                                                   key.second.device_id &&
-                                                                 std::find(
-                                                                   verif.verified_devices.begin(),
-                                                                   verif.verified_devices.end(),
-                                                                   key.first) !=
-                                                                   verif.verified_devices.end();
-                                                  });
-
-                                                if (!keyCopy.device_keys.empty())
-                                                        members[std::string(user_id)] =
-                                                          std::move(keyCopy);
-                                        }
-                                } else {
-                                        members[std::string(user_id)] = std::move(k);
-                                }
-                        } else {
-                                if (!verified_only)
-                                        members[std::string(user_id)] = {};
-                        }
-                }
-                cursor.close();
+    try {
+        auto txn = ro_txn(env_);
+        std::map<std::string, std::optional<UserKeyCache>> members;
 
-                return members;
-        } catch (std::exception &e) {
-                nhlog::db()->debug("Error retrieving members: {}", e.what());
-                return {};
+        auto db     = getMembersDb(txn, room_id);
+        auto keysDb = getUserKeysDb(txn);
+
+        std::string_view user_id, unused;
+        auto cursor = lmdb::cursor::open(txn, db);
+        while (cursor.get(user_id, unused, MDB_NEXT)) {
+            auto res = keysDb.get(txn, user_id, keys);
+
+            if (res) {
+                auto k = json::parse(keys).get<UserKeyCache>();
+                if (verified_only) {
+                    auto verif = verificationStatus_(std::string(user_id), txn);
+
+                    if (verif.user_verified == crypto::Trust::Verified ||
+                        !verif.verified_devices.empty()) {
+                        auto keyCopy = k;
+                        keyCopy.device_keys.clear();
+
+                        std::copy_if(
+                          k.device_keys.begin(),
+                          k.device_keys.end(),
+                          std::inserter(keyCopy.device_keys, keyCopy.device_keys.end()),
+                          [&verif](const auto &key) {
+                              auto curve25519 = key.second.keys.find("curve25519:" + key.first);
+                              if (curve25519 == key.second.keys.end())
+                                  return false;
+                              if (auto t = verif.verified_device_keys.find(curve25519->second);
+                                  t == verif.verified_device_keys.end() ||
+                                  t->second != crypto::Trust::Verified)
+                                  return false;
+
+                              return key.first == key.second.device_id &&
+                                     std::find(verif.verified_devices.begin(),
+                                               verif.verified_devices.end(),
+                                               key.first) != verif.verified_devices.end();
+                          });
+
+                        if (!keyCopy.device_keys.empty())
+                            members[std::string(user_id)] = std::move(keyCopy);
+                    }
+                } else {
+                    members[std::string(user_id)] = std::move(k);
+                }
+            } else {
+                if (!verified_only)
+                    members[std::string(user_id)] = {};
+            }
         }
+        cursor.close();
+
+        return members;
+    } catch (std::exception &e) {
+        nhlog::db()->debug("Error retrieving members: {}", e.what());
+        return {};
+    }
 }
 
 QString
 Cache::displayName(const QString &room_id, const QString &user_id)
 {
-        if (auto info = getMember(room_id.toStdString(), user_id.toStdString());
-            info && !info->name.empty())
-                return QString::fromStdString(info->name);
+    if (auto info = getMember(room_id.toStdString(), user_id.toStdString());
+        info && !info->name.empty())
+        return QString::fromStdString(info->name);
 
-        return user_id;
+    return user_id;
 }
 
 std::string
 Cache::displayName(const std::string &room_id, const std::string &user_id)
 {
-        if (auto info = getMember(room_id, user_id); info && !info->name.empty())
-                return info->name;
+    if (auto info = getMember(room_id, user_id); info && !info->name.empty())
+        return info->name;
 
-        return user_id;
+    return user_id;
 }
 
 QString
 Cache::avatarUrl(const QString &room_id, const QString &user_id)
 {
-        if (auto info = getMember(room_id.toStdString(), user_id.toStdString());
-            info && !info->avatar_url.empty())
-                return QString::fromStdString(info->avatar_url);
+    if (auto info = getMember(room_id.toStdString(), user_id.toStdString());
+        info && !info->avatar_url.empty())
+        return QString::fromStdString(info->avatar_url);
 
-        return "";
+    return "";
 }
 
 mtx::presence::PresenceState
 Cache::presenceState(const std::string &user_id)
 {
-        if (user_id.empty())
-                return {};
+    if (user_id.empty())
+        return {};
 
-        std::string_view presenceVal;
+    std::string_view presenceVal;
 
-        auto txn = lmdb::txn::begin(env_);
-        auto db  = getPresenceDb(txn);
-        auto res = db.get(txn, user_id, presenceVal);
+    auto txn = lmdb::txn::begin(env_);
+    auto db  = getPresenceDb(txn);
+    auto res = db.get(txn, user_id, presenceVal);
 
-        mtx::presence::PresenceState state = mtx::presence::offline;
+    mtx::presence::PresenceState state = mtx::presence::offline;
 
-        if (res) {
-                mtx::events::presence::Presence presence =
-                  json::parse(std::string_view(presenceVal.data(), presenceVal.size()));
-                state = presence.presence;
-        }
+    if (res) {
+        mtx::events::presence::Presence presence =
+          json::parse(std::string_view(presenceVal.data(), presenceVal.size()));
+        state = presence.presence;
+    }
 
-        txn.commit();
+    txn.commit();
 
-        return state;
+    return state;
 }
 
 std::string
 Cache::statusMessage(const std::string &user_id)
 {
-        if (user_id.empty())
-                return {};
+    if (user_id.empty())
+        return {};
 
-        std::string_view presenceVal;
+    std::string_view presenceVal;
 
-        auto txn = lmdb::txn::begin(env_);
-        auto db  = getPresenceDb(txn);
-        auto res = db.get(txn, user_id, presenceVal);
+    auto txn = lmdb::txn::begin(env_);
+    auto db  = getPresenceDb(txn);
+    auto res = db.get(txn, user_id, presenceVal);
 
-        std::string status_msg;
+    std::string status_msg;
 
-        if (res) {
-                mtx::events::presence::Presence presence = json::parse(presenceVal);
-                status_msg                               = presence.status_msg;
-        }
+    if (res) {
+        mtx::events::presence::Presence presence = json::parse(presenceVal);
+        status_msg                               = presence.status_msg;
+    }
 
-        txn.commit();
+    txn.commit();
 
-        return status_msg;
+    return status_msg;
 }
 
 void
 to_json(json &j, const UserKeyCache &info)
 {
-        j["device_keys"]        = info.device_keys;
-        j["seen_device_keys"]   = info.seen_device_keys;
-        j["seen_device_ids"]    = info.seen_device_ids;
-        j["master_keys"]        = info.master_keys;
-        j["master_key_changed"] = info.master_key_changed;
-        j["user_signing_keys"]  = info.user_signing_keys;
-        j["self_signing_keys"]  = info.self_signing_keys;
-        j["updated_at"]         = info.updated_at;
-        j["last_changed"]       = info.last_changed;
+    j["device_keys"]        = info.device_keys;
+    j["seen_device_keys"]   = info.seen_device_keys;
+    j["seen_device_ids"]    = info.seen_device_ids;
+    j["master_keys"]        = info.master_keys;
+    j["master_key_changed"] = info.master_key_changed;
+    j["user_signing_keys"]  = info.user_signing_keys;
+    j["self_signing_keys"]  = info.self_signing_keys;
+    j["updated_at"]         = info.updated_at;
+    j["last_changed"]       = info.last_changed;
 }
 
 void
 from_json(const json &j, UserKeyCache &info)
 {
-        info.device_keys = j.value("device_keys", std::map<std::string, mtx::crypto::DeviceKeys>{});
-        info.seen_device_keys   = j.value("seen_device_keys", std::set<std::string>{});
-        info.seen_device_ids    = j.value("seen_device_ids", std::set<std::string>{});
-        info.master_keys        = j.value("master_keys", mtx::crypto::CrossSigningKeys{});
-        info.master_key_changed = j.value("master_key_changed", false);
-        info.user_signing_keys  = j.value("user_signing_keys", mtx::crypto::CrossSigningKeys{});
-        info.self_signing_keys  = j.value("self_signing_keys", mtx::crypto::CrossSigningKeys{});
-        info.updated_at         = j.value("updated_at", "");
-        info.last_changed       = j.value("last_changed", "");
+    info.device_keys = j.value("device_keys", std::map<std::string, mtx::crypto::DeviceKeys>{});
+    info.seen_device_keys   = j.value("seen_device_keys", std::set<std::string>{});
+    info.seen_device_ids    = j.value("seen_device_ids", std::set<std::string>{});
+    info.master_keys        = j.value("master_keys", mtx::crypto::CrossSigningKeys{});
+    info.master_key_changed = j.value("master_key_changed", false);
+    info.user_signing_keys  = j.value("user_signing_keys", mtx::crypto::CrossSigningKeys{});
+    info.self_signing_keys  = j.value("self_signing_keys", mtx::crypto::CrossSigningKeys{});
+    info.updated_at         = j.value("updated_at", "");
+    info.last_changed       = j.value("last_changed", "");
 }
 
 std::optional<UserKeyCache>
 Cache::userKeys(const std::string &user_id)
 {
-        auto txn = ro_txn(env_);
-        return userKeys_(user_id, txn);
+    auto txn = ro_txn(env_);
+    return userKeys_(user_id, txn);
 }
 
 std::optional<UserKeyCache>
 Cache::userKeys_(const std::string &user_id, lmdb::txn &txn)
 {
-        std::string_view keys;
+    std::string_view keys;
 
-        try {
-                auto db  = getUserKeysDb(txn);
-                auto res = db.get(txn, user_id, keys);
+    try {
+        auto db  = getUserKeysDb(txn);
+        auto res = db.get(txn, user_id, keys);
 
-                if (res) {
-                        return json::parse(keys).get<UserKeyCache>();
-                } else {
-                        return {};
-                }
-        } catch (std::exception &e) {
-                nhlog::db()->error("Failed to retrieve user keys for {}: {}", user_id, e.what());
-                return {};
+        if (res) {
+            return json::parse(keys).get<UserKeyCache>();
+        } else {
+            return {};
         }
+    } catch (std::exception &e) {
+        nhlog::db()->error("Failed to retrieve user keys for {}: {}", user_id, e.what());
+        return {};
+    }
 }
 
 void
 Cache::updateUserKeys(const std::string &sync_token, const mtx::responses::QueryKeys &keyQuery)
 {
-        auto txn = lmdb::txn::begin(env_);
-        auto db  = getUserKeysDb(txn);
+    auto txn = lmdb::txn::begin(env_);
+    auto db  = getUserKeysDb(txn);
 
-        std::map<std::string, UserKeyCache> updates;
-
-        for (const auto &[user, keys] : keyQuery.device_keys)
-                updates[user].device_keys = keys;
-        for (const auto &[user, keys] : keyQuery.master_keys)
-                updates[user].master_keys = keys;
-        for (const auto &[user, keys] : keyQuery.user_signing_keys)
-                updates[user].user_signing_keys = keys;
-        for (const auto &[user, keys] : keyQuery.self_signing_keys)
-                updates[user].self_signing_keys = keys;
-
-        for (auto &[user, update] : updates) {
-                nhlog::db()->debug("Updated user keys: {}", user);
-
-                auto updateToWrite = update;
-
-                std::string_view oldKeys;
-                auto res = db.get(txn, user, oldKeys);
-
-                if (res) {
-                        updateToWrite     = json::parse(oldKeys).get<UserKeyCache>();
-                        auto last_changed = updateToWrite.last_changed;
-                        // skip if we are tracking this and expect it to be up to date with the last
-                        // sync token
-                        if (!last_changed.empty() && last_changed != sync_token) {
-                                nhlog::db()->debug("Not storing update for user {}, because "
-                                                   "last_changed {}, but we fetched update for {}",
-                                                   user,
-                                                   last_changed,
-                                                   sync_token);
-                                continue;
-                        }
+    std::map<std::string, UserKeyCache> updates;
+
+    for (const auto &[user, keys] : keyQuery.device_keys)
+        updates[user].device_keys = keys;
+    for (const auto &[user, keys] : keyQuery.master_keys)
+        updates[user].master_keys = keys;
+    for (const auto &[user, keys] : keyQuery.user_signing_keys)
+        updates[user].user_signing_keys = keys;
+    for (const auto &[user, keys] : keyQuery.self_signing_keys)
+        updates[user].self_signing_keys = keys;
+
+    for (auto &[user, update] : updates) {
+        nhlog::db()->debug("Updated user keys: {}", user);
+
+        auto updateToWrite = update;
 
-                        if (!updateToWrite.master_keys.keys.empty() &&
-                            update.master_keys.keys != updateToWrite.master_keys.keys) {
-                                nhlog::db()->debug("Master key of {} changed:\nold: {}\nnew: {}",
-                                                   user,
-                                                   updateToWrite.master_keys.keys.size(),
-                                                   update.master_keys.keys.size());
-                                updateToWrite.master_key_changed = true;
+        std::string_view oldKeys;
+        auto res = db.get(txn, user, oldKeys);
+
+        if (res) {
+            updateToWrite     = json::parse(oldKeys).get<UserKeyCache>();
+            auto last_changed = updateToWrite.last_changed;
+            // skip if we are tracking this and expect it to be up to date with the last
+            // sync token
+            if (!last_changed.empty() && last_changed != sync_token) {
+                nhlog::db()->debug("Not storing update for user {}, because "
+                                   "last_changed {}, but we fetched update for {}",
+                                   user,
+                                   last_changed,
+                                   sync_token);
+                continue;
+            }
+
+            if (!updateToWrite.master_keys.keys.empty() &&
+                update.master_keys.keys != updateToWrite.master_keys.keys) {
+                nhlog::db()->debug("Master key of {} changed:\nold: {}\nnew: {}",
+                                   user,
+                                   updateToWrite.master_keys.keys.size(),
+                                   update.master_keys.keys.size());
+                updateToWrite.master_key_changed = true;
+            }
+
+            updateToWrite.master_keys       = update.master_keys;
+            updateToWrite.self_signing_keys = update.self_signing_keys;
+            updateToWrite.user_signing_keys = update.user_signing_keys;
+
+            auto oldDeviceKeys = std::move(updateToWrite.device_keys);
+            updateToWrite.device_keys.clear();
+
+            // Don't insert keys, which we have seen once already
+            for (const auto &[device_id, device_keys] : update.device_keys) {
+                if (oldDeviceKeys.count(device_id) &&
+                    oldDeviceKeys.at(device_id).keys == device_keys.keys) {
+                    // this is safe, since the keys are the same
+                    updateToWrite.device_keys[device_id] = device_keys;
+                } else {
+                    bool keyReused = false;
+                    for (const auto &[key_id, key] : device_keys.keys) {
+                        (void)key_id;
+                        if (updateToWrite.seen_device_keys.count(key)) {
+                            nhlog::crypto()->warn(
+                              "Key '{}' reused by ({}: {})", key, user, device_id);
+                            keyReused = true;
+                            break;
+                        }
+                        if (updateToWrite.seen_device_ids.count(device_id)) {
+                            nhlog::crypto()->warn("device_id '{}' reused by ({})", device_id, user);
+                            keyReused = true;
+                            break;
+                        }
+                    }
+
+                    if (!keyReused && !oldDeviceKeys.count(device_id)) {
+                        // ensure the key has a valid signature from itself
+                        std::string device_signing_key = "ed25519:" + device_keys.device_id;
+                        if (device_id != device_keys.device_id) {
+                            nhlog::crypto()->warn("device {}:{} has a different device id "
+                                                  "in the body: {}",
+                                                  user,
+                                                  device_id,
+                                                  device_keys.device_id);
+                            continue;
+                        }
+                        if (!device_keys.signatures.count(user) ||
+                            !device_keys.signatures.at(user).count(device_signing_key)) {
+                            nhlog::crypto()->warn("device {}:{} has no signature", user, device_id);
+                            continue;
                         }
 
-                        updateToWrite.master_keys       = update.master_keys;
-                        updateToWrite.self_signing_keys = update.self_signing_keys;
-                        updateToWrite.user_signing_keys = update.user_signing_keys;
-
-                        auto oldDeviceKeys = std::move(updateToWrite.device_keys);
-                        updateToWrite.device_keys.clear();
-
-                        // Don't insert keys, which we have seen once already
-                        for (const auto &[device_id, device_keys] : update.device_keys) {
-                                if (oldDeviceKeys.count(device_id) &&
-                                    oldDeviceKeys.at(device_id).keys == device_keys.keys) {
-                                        // this is safe, since the keys are the same
-                                        updateToWrite.device_keys[device_id] = device_keys;
-                                } else {
-                                        bool keyReused = false;
-                                        for (const auto &[key_id, key] : device_keys.keys) {
-                                                (void)key_id;
-                                                if (updateToWrite.seen_device_keys.count(key)) {
-                                                        nhlog::crypto()->warn(
-                                                          "Key '{}' reused by ({}: {})",
-                                                          key,
-                                                          user,
-                                                          device_id);
-                                                        keyReused = true;
-                                                        break;
-                                                }
-                                                if (updateToWrite.seen_device_ids.count(
-                                                      device_id)) {
-                                                        nhlog::crypto()->warn(
-                                                          "device_id '{}' reused by ({})",
-                                                          device_id,
-                                                          user);
-                                                        keyReused = true;
-                                                        break;
-                                                }
-                                        }
-
-                                        if (!keyReused && !oldDeviceKeys.count(device_id)) {
-                                                // ensure the key has a valid signature from itself
-                                                std::string device_signing_key =
-                                                  "ed25519:" + device_keys.device_id;
-                                                if (device_id != device_keys.device_id) {
-                                                        nhlog::crypto()->warn(
-                                                          "device {}:{} has a different device id "
-                                                          "in the body: {}",
-                                                          user,
-                                                          device_id,
-                                                          device_keys.device_id);
-                                                        continue;
-                                                }
-                                                if (!device_keys.signatures.count(user) ||
-                                                    !device_keys.signatures.at(user).count(
-                                                      device_signing_key)) {
-                                                        nhlog::crypto()->warn(
-                                                          "device {}:{} has no signature",
-                                                          user,
-                                                          device_id);
-                                                        continue;
-                                                }
-
-                                                if (!mtx::crypto::ed25519_verify_signature(
-                                                      device_keys.keys.at(device_signing_key),
-                                                      json(device_keys),
-                                                      device_keys.signatures.at(user).at(
-                                                        device_signing_key))) {
-                                                        nhlog::crypto()->warn(
-                                                          "device {}:{} has an invalid signature",
-                                                          user,
-                                                          device_id);
-                                                        continue;
-                                                }
-
-                                                updateToWrite.device_keys[device_id] = device_keys;
-                                        }
-                                }
-
-                                for (const auto &[key_id, key] : device_keys.keys) {
-                                        (void)key_id;
-                                        updateToWrite.seen_device_keys.insert(key);
-                                }
-                                updateToWrite.seen_device_ids.insert(device_id);
+                        if (!mtx::crypto::ed25519_verify_signature(
+                              device_keys.keys.at(device_signing_key),
+                              json(device_keys),
+                              device_keys.signatures.at(user).at(device_signing_key))) {
+                            nhlog::crypto()->warn(
+                              "device {}:{} has an invalid signature", user, device_id);
+                            continue;
                         }
+
+                        updateToWrite.device_keys[device_id] = device_keys;
+                    }
                 }
-                updateToWrite.updated_at = sync_token;
-                db.put(txn, user, json(updateToWrite).dump());
+
+                for (const auto &[key_id, key] : device_keys.keys) {
+                    (void)key_id;
+                    updateToWrite.seen_device_keys.insert(key);
+                }
+                updateToWrite.seen_device_ids.insert(device_id);
+            }
         }
+        updateToWrite.updated_at = sync_token;
+        db.put(txn, user, json(updateToWrite).dump());
+    }
 
-        txn.commit();
+    txn.commit();
 
-        std::map<std::string, VerificationStatus> tmp;
-        const auto local_user = utils::localUser().toStdString();
+    std::map<std::string, VerificationStatus> tmp;
+    const auto local_user = utils::localUser().toStdString();
 
-        {
-                std::unique_lock<std::mutex> lock(verification_storage.verification_storage_mtx);
-                for (auto &[user_id, update] : updates) {
-                        (void)update;
-                        if (user_id == local_user) {
-                                std::swap(tmp, verification_storage.status);
-                        } else {
-                                verification_storage.status.erase(user_id);
-                        }
-                }
+    {
+        std::unique_lock<std::mutex> lock(verification_storage.verification_storage_mtx);
+        for (auto &[user_id, update] : updates) {
+            (void)update;
+            if (user_id == local_user) {
+                std::swap(tmp, verification_storage.status);
+            } else {
+                verification_storage.status.erase(user_id);
+            }
         }
+    }
 
-        for (auto &[user_id, update] : updates) {
-                (void)update;
-                if (user_id == local_user) {
-                        for (const auto &[user, status] : tmp) {
-                                (void)status;
-                                emit verificationStatusChanged(user);
-                        }
-                }
-                emit verificationStatusChanged(user_id);
+    for (auto &[user_id, update] : updates) {
+        (void)update;
+        if (user_id == local_user) {
+            for (const auto &[user, status] : tmp) {
+                (void)status;
+                emit verificationStatusChanged(user);
+            }
         }
+        emit verificationStatusChanged(user_id);
+    }
 }
 
 void
@@ -4169,780 +4051,772 @@ Cache::markUserKeysOutOfDate(lmdb::txn &txn,
                              const std::vector<std::string> &user_ids,
                              const std::string &sync_token)
 {
-        mtx::requests::QueryKeys query;
-        query.token = sync_token;
-
-        for (const auto &user : user_ids) {
-                nhlog::db()->debug("Marking user keys out of date: {}", user);
-
-                std::string_view oldKeys;
+    mtx::requests::QueryKeys query;
+    query.token = sync_token;
 
-                UserKeyCache cacheEntry;
-                auto res = db.get(txn, user, oldKeys);
-                if (res) {
-                        cacheEntry = json::parse(std::string_view(oldKeys.data(), oldKeys.size()))
-                                       .get<UserKeyCache>();
-                }
-                cacheEntry.last_changed = sync_token;
+    for (const auto &user : user_ids) {
+        nhlog::db()->debug("Marking user keys out of date: {}", user);
 
-                db.put(txn, user, json(cacheEntry).dump());
+        std::string_view oldKeys;
 
-                query.device_keys[user] = {};
+        UserKeyCache cacheEntry;
+        auto res = db.get(txn, user, oldKeys);
+        if (res) {
+            cacheEntry =
+              json::parse(std::string_view(oldKeys.data(), oldKeys.size())).get<UserKeyCache>();
         }
+        cacheEntry.last_changed = sync_token;
 
-        if (!query.device_keys.empty())
-                http::client()->query_keys(query,
-                                           [this, sync_token](const mtx::responses::QueryKeys &keys,
-                                                              mtx::http::RequestErr err) {
-                                                   if (err) {
-                                                           nhlog::net()->warn(
-                                                             "failed to query device keys: {} {}",
-                                                             err->matrix_error.error,
-                                                             static_cast<int>(err->status_code));
-                                                           return;
-                                                   }
+        db.put(txn, user, json(cacheEntry).dump());
 
-                                                   emit userKeysUpdate(sync_token, keys);
-                                           });
+        query.device_keys[user] = {};
+    }
+
+    if (!query.device_keys.empty())
+        http::client()->query_keys(
+          query,
+          [this, sync_token](const mtx::responses::QueryKeys &keys, mtx::http::RequestErr err) {
+              if (err) {
+                  nhlog::net()->warn("failed to query device keys: {} {}",
+                                     err->matrix_error.error,
+                                     static_cast<int>(err->status_code));
+                  return;
+              }
+
+              emit userKeysUpdate(sync_token, keys);
+          });
 }
 
 void
 Cache::query_keys(const std::string &user_id,
                   std::function<void(const UserKeyCache &, mtx::http::RequestErr)> cb)
 {
-        mtx::requests::QueryKeys req;
-        std::string last_changed;
-        {
-                auto txn    = ro_txn(env_);
-                auto cache_ = userKeys_(user_id, txn);
-
-                if (cache_.has_value()) {
-                        if (cache_->updated_at == cache_->last_changed) {
-                                cb(cache_.value(), {});
-                                return;
-                        } else
-                                nhlog::db()->info("Keys outdated for {}: {} vs {}",
-                                                  user_id,
-                                                  cache_->updated_at,
-                                                  cache_->last_changed);
-                } else
-                        nhlog::db()->info("No keys found for {}", user_id);
-
-                req.device_keys[user_id] = {};
-
-                if (cache_)
-                        last_changed = cache_->last_changed;
-                req.token = last_changed;
-        }
-
-        // use context object so that we can disconnect again
-        QObject *context{new QObject(this)};
-        QObject::connect(
-          this,
-          &Cache::verificationStatusChanged,
-          context,
-          [cb, user_id, context_ = context, this](std::string updated_user) mutable {
-                  if (user_id == updated_user) {
-                          context_->deleteLater();
-                          auto txn  = ro_txn(env_);
-                          auto keys = this->userKeys_(user_id, txn);
-                          cb(keys.value_or(UserKeyCache{}), {});
-                  }
-          },
-          Qt::QueuedConnection);
+    mtx::requests::QueryKeys req;
+    std::string last_changed;
+    {
+        auto txn    = ro_txn(env_);
+        auto cache_ = userKeys_(user_id, txn);
 
-        http::client()->query_keys(
-          req,
-          [cb, user_id, last_changed, this](const mtx::responses::QueryKeys &res,
-                                            mtx::http::RequestErr err) {
-                  if (err) {
-                          nhlog::net()->warn("failed to query device keys: {},{}",
-                                             mtx::errors::to_string(err->matrix_error.errcode),
-                                             static_cast<int>(err->status_code));
-                          cb({}, err);
-                          return;
-                  }
-
-                  emit userKeysUpdate(last_changed, res);
-          });
+        if (cache_.has_value()) {
+            if (cache_->updated_at == cache_->last_changed) {
+                cb(cache_.value(), {});
+                return;
+            } else
+                nhlog::db()->info("Keys outdated for {}: {} vs {}",
+                                  user_id,
+                                  cache_->updated_at,
+                                  cache_->last_changed);
+        } else
+            nhlog::db()->info("No keys found for {}", user_id);
+
+        req.device_keys[user_id] = {};
+
+        if (cache_)
+            last_changed = cache_->last_changed;
+        req.token = last_changed;
+    }
+
+    // use context object so that we can disconnect again
+    QObject *context{new QObject(this)};
+    QObject::connect(
+      this,
+      &Cache::verificationStatusChanged,
+      context,
+      [cb, user_id, context_ = context, this](std::string updated_user) mutable {
+          if (user_id == updated_user) {
+              context_->deleteLater();
+              auto txn  = ro_txn(env_);
+              auto keys = this->userKeys_(user_id, txn);
+              cb(keys.value_or(UserKeyCache{}), {});
+          }
+      },
+      Qt::QueuedConnection);
+
+    http::client()->query_keys(
+      req,
+      [cb, user_id, last_changed, this](const mtx::responses::QueryKeys &res,
+                                        mtx::http::RequestErr err) {
+          if (err) {
+              nhlog::net()->warn("failed to query device keys: {},{}",
+                                 mtx::errors::to_string(err->matrix_error.errcode),
+                                 static_cast<int>(err->status_code));
+              cb({}, err);
+              return;
+          }
+
+          emit userKeysUpdate(last_changed, res);
+      });
 }
 
 void
 to_json(json &j, const VerificationCache &info)
 {
-        j["device_verified"] = info.device_verified;
-        j["device_blocked"]  = info.device_blocked;
+    j["device_verified"] = info.device_verified;
+    j["device_blocked"]  = info.device_blocked;
 }
 
 void
 from_json(const json &j, VerificationCache &info)
 {
-        info.device_verified = j.at("device_verified").get<std::set<std::string>>();
-        info.device_blocked  = j.at("device_blocked").get<std::set<std::string>>();
+    info.device_verified = j.at("device_verified").get<std::set<std::string>>();
+    info.device_blocked  = j.at("device_blocked").get<std::set<std::string>>();
 }
 
 void
 to_json(json &j, const OnlineBackupVersion &info)
 {
-        j["v"] = info.version;
-        j["a"] = info.algorithm;
+    j["v"] = info.version;
+    j["a"] = info.algorithm;
 }
 
 void
 from_json(const json &j, OnlineBackupVersion &info)
 {
-        info.version   = j.at("v").get<std::string>();
-        info.algorithm = j.at("a").get<std::string>();
+    info.version   = j.at("v").get<std::string>();
+    info.algorithm = j.at("a").get<std::string>();
 }
 
 std::optional<VerificationCache>
 Cache::verificationCache(const std::string &user_id, lmdb::txn &txn)
 {
-        std::string_view verifiedVal;
+    std::string_view verifiedVal;
 
-        auto db = getVerificationDb(txn);
+    auto db = getVerificationDb(txn);
 
-        try {
-                VerificationCache verified_state;
-                auto res = db.get(txn, user_id, verifiedVal);
-                if (res) {
-                        verified_state = json::parse(verifiedVal);
-                        return verified_state;
-                } else {
-                        return {};
-                }
-        } catch (std::exception &) {
-                return {};
+    try {
+        VerificationCache verified_state;
+        auto res = db.get(txn, user_id, verifiedVal);
+        if (res) {
+            verified_state = json::parse(verifiedVal);
+            return verified_state;
+        } else {
+            return {};
         }
+    } catch (std::exception &) {
+        return {};
+    }
 }
 
 void
 Cache::markDeviceVerified(const std::string &user_id, const std::string &key)
 {
-        {
-                std::string_view val;
-
-                auto txn = lmdb::txn::begin(env_);
-                auto db  = getVerificationDb(txn);
-
-                try {
-                        VerificationCache verified_state;
-                        auto res = db.get(txn, user_id, val);
-                        if (res) {
-                                verified_state = json::parse(val);
-                        }
+    {
+        std::string_view val;
 
-                        for (const auto &device : verified_state.device_verified)
-                                if (device == key)
-                                        return;
+        auto txn = lmdb::txn::begin(env_);
+        auto db  = getVerificationDb(txn);
 
-                        verified_state.device_verified.insert(key);
-                        db.put(txn, user_id, json(verified_state).dump());
-                        txn.commit();
-                } catch (std::exception &) {
-                }
+        try {
+            VerificationCache verified_state;
+            auto res = db.get(txn, user_id, val);
+            if (res) {
+                verified_state = json::parse(val);
+            }
+
+            for (const auto &device : verified_state.device_verified)
+                if (device == key)
+                    return;
+
+            verified_state.device_verified.insert(key);
+            db.put(txn, user_id, json(verified_state).dump());
+            txn.commit();
+        } catch (std::exception &) {
         }
+    }
 
-        const auto local_user = utils::localUser().toStdString();
-        std::map<std::string, VerificationStatus> tmp;
-        {
-                std::unique_lock<std::mutex> lock(verification_storage.verification_storage_mtx);
-                if (user_id == local_user) {
-                        std::swap(tmp, verification_storage.status);
-                } else {
-                        verification_storage.status.erase(user_id);
-                }
-        }
+    const auto local_user = utils::localUser().toStdString();
+    std::map<std::string, VerificationStatus> tmp;
+    {
+        std::unique_lock<std::mutex> lock(verification_storage.verification_storage_mtx);
         if (user_id == local_user) {
-                for (const auto &[user, status] : tmp) {
-                        (void)status;
-                        emit verificationStatusChanged(user);
-                }
+            std::swap(tmp, verification_storage.status);
         } else {
-                emit verificationStatusChanged(user_id);
+            verification_storage.status.erase(user_id);
+        }
+    }
+    if (user_id == local_user) {
+        for (const auto &[user, status] : tmp) {
+            (void)status;
+            emit verificationStatusChanged(user);
         }
+    } else {
+        emit verificationStatusChanged(user_id);
+    }
 }
 
 void
 Cache::markDeviceUnverified(const std::string &user_id, const std::string &key)
 {
-        std::string_view val;
+    std::string_view val;
 
-        auto txn = lmdb::txn::begin(env_);
-        auto db  = getVerificationDb(txn);
+    auto txn = lmdb::txn::begin(env_);
+    auto db  = getVerificationDb(txn);
 
-        try {
-                VerificationCache verified_state;
-                auto res = db.get(txn, user_id, val);
-                if (res) {
-                        verified_state = json::parse(val);
-                }
+    try {
+        VerificationCache verified_state;
+        auto res = db.get(txn, user_id, val);
+        if (res) {
+            verified_state = json::parse(val);
+        }
 
-                verified_state.device_verified.erase(key);
+        verified_state.device_verified.erase(key);
 
-                db.put(txn, user_id, json(verified_state).dump());
-                txn.commit();
-        } catch (std::exception &) {
-        }
+        db.put(txn, user_id, json(verified_state).dump());
+        txn.commit();
+    } catch (std::exception &) {
+    }
 
-        const auto local_user = utils::localUser().toStdString();
-        std::map<std::string, VerificationStatus> tmp;
-        {
-                std::unique_lock<std::mutex> lock(verification_storage.verification_storage_mtx);
-                if (user_id == local_user) {
-                        std::swap(tmp, verification_storage.status);
-                } else {
-                        verification_storage.status.erase(user_id);
-                }
-        }
+    const auto local_user = utils::localUser().toStdString();
+    std::map<std::string, VerificationStatus> tmp;
+    {
+        std::unique_lock<std::mutex> lock(verification_storage.verification_storage_mtx);
         if (user_id == local_user) {
-                for (const auto &[user, status] : tmp) {
-                        (void)status;
-                        emit verificationStatusChanged(user);
-                }
+            std::swap(tmp, verification_storage.status);
         } else {
-                emit verificationStatusChanged(user_id);
+            verification_storage.status.erase(user_id);
+        }
+    }
+    if (user_id == local_user) {
+        for (const auto &[user, status] : tmp) {
+            (void)status;
+            emit verificationStatusChanged(user);
         }
+    } else {
+        emit verificationStatusChanged(user_id);
+    }
 }
 
 VerificationStatus
 Cache::verificationStatus(const std::string &user_id)
 {
-        auto txn = ro_txn(env_);
-        return verificationStatus_(user_id, txn);
+    auto txn = ro_txn(env_);
+    return verificationStatus_(user_id, txn);
 }
 
 VerificationStatus
 Cache::verificationStatus_(const std::string &user_id, lmdb::txn &txn)
 {
-        std::unique_lock<std::mutex> lock(verification_storage.verification_storage_mtx);
-        if (verification_storage.status.count(user_id))
-                return verification_storage.status.at(user_id);
+    std::unique_lock<std::mutex> lock(verification_storage.verification_storage_mtx);
+    if (verification_storage.status.count(user_id))
+        return verification_storage.status.at(user_id);
 
-        VerificationStatus status;
+    VerificationStatus status;
 
-        // assume there is at least one unverified device until we have checked we have the device
-        // list for that user.
-        status.unverified_device_count = 1;
-        status.no_keys                 = true;
+    // assume there is at least one unverified device until we have checked we have the device
+    // list for that user.
+    status.unverified_device_count = 1;
+    status.no_keys                 = true;
 
-        if (auto verifCache = verificationCache(user_id, txn)) {
-                status.verified_devices = verifCache->device_verified;
-        }
+    if (auto verifCache = verificationCache(user_id, txn)) {
+        status.verified_devices = verifCache->device_verified;
+    }
 
-        const auto local_user = utils::localUser().toStdString();
+    const auto local_user = utils::localUser().toStdString();
 
-        crypto::Trust trustlevel = crypto::Trust::Unverified;
-        if (user_id == local_user) {
-                status.verified_devices.insert(http::client()->device_id());
-                trustlevel = crypto::Trust::Verified;
-        }
+    crypto::Trust trustlevel = crypto::Trust::Unverified;
+    if (user_id == local_user) {
+        status.verified_devices.insert(http::client()->device_id());
+        trustlevel = crypto::Trust::Verified;
+    }
 
-        auto verifyAtLeastOneSig = [](const auto &toVerif,
-                                      const std::map<std::string, std::string> &keys,
-                                      const std::string &keyOwner) {
-                if (!toVerif.signatures.count(keyOwner))
-                        return false;
+    auto verifyAtLeastOneSig = [](const auto &toVerif,
+                                  const std::map<std::string, std::string> &keys,
+                                  const std::string &keyOwner) {
+        if (!toVerif.signatures.count(keyOwner))
+            return false;
 
-                for (const auto &[key_id, signature] : toVerif.signatures.at(keyOwner)) {
-                        if (!keys.count(key_id))
-                                continue;
+        for (const auto &[key_id, signature] : toVerif.signatures.at(keyOwner)) {
+            if (!keys.count(key_id))
+                continue;
 
-                        if (mtx::crypto::ed25519_verify_signature(
-                              keys.at(key_id), json(toVerif), signature))
-                                return true;
-                }
-                return false;
-        };
+            if (mtx::crypto::ed25519_verify_signature(keys.at(key_id), json(toVerif), signature))
+                return true;
+        }
+        return false;
+    };
+
+    auto updateUnverifiedDevices = [&status](auto &theirDeviceKeys) {
+        int currentVerifiedDevices = 0;
+        for (auto device_id : status.verified_devices) {
+            if (theirDeviceKeys.count(device_id))
+                currentVerifiedDevices++;
+        }
+        status.unverified_device_count =
+          static_cast<int>(theirDeviceKeys.size()) - currentVerifiedDevices;
+    };
+
+    try {
+        // for local user verify this device_key -> our master_key -> our self_signing_key
+        // -> our device_keys
+        //
+        // for other user verify this device_key -> our master_key -> our user_signing_key
+        // -> their master_key -> their self_signing_key -> their device_keys
+        //
+        // This means verifying the other user adds 2 extra steps,verifying our user_signing
+        // key and their master key
+        auto ourKeys   = userKeys_(local_user, txn);
+        auto theirKeys = userKeys_(user_id, txn);
+        if (theirKeys)
+            status.no_keys = false;
+
+        if (!ourKeys || !theirKeys) {
+            verification_storage.status[user_id] = status;
+            return status;
+        }
+
+        // Update verified devices count to count without cross-signing
+        updateUnverifiedDevices(theirKeys->device_keys);
 
-        auto updateUnverifiedDevices = [&status](auto &theirDeviceKeys) {
-                int currentVerifiedDevices = 0;
-                for (auto device_id : status.verified_devices) {
-                        if (theirDeviceKeys.count(device_id))
-                                currentVerifiedDevices++;
-                }
-                status.unverified_device_count =
-                  static_cast<int>(theirDeviceKeys.size()) - currentVerifiedDevices;
-        };
+        {
+            auto &mk           = ourKeys->master_keys;
+            std::string dev_id = "ed25519:" + http::client()->device_id();
+            if (!mk.signatures.count(local_user) || !mk.signatures.at(local_user).count(dev_id) ||
+                !mtx::crypto::ed25519_verify_signature(olm::client()->identity_keys().ed25519,
+                                                       json(mk),
+                                                       mk.signatures.at(local_user).at(dev_id))) {
+                nhlog::crypto()->debug("We have not verified our own master key");
+                verification_storage.status[user_id] = status;
+                return status;
+            }
+        }
 
-        try {
-                // for local user verify this device_key -> our master_key -> our self_signing_key
-                // -> our device_keys
-                //
-                // for other user verify this device_key -> our master_key -> our user_signing_key
-                // -> their master_key -> their self_signing_key -> their device_keys
-                //
-                // This means verifying the other user adds 2 extra steps,verifying our user_signing
-                // key and their master key
-                auto ourKeys   = userKeys_(local_user, txn);
-                auto theirKeys = userKeys_(user_id, txn);
-                if (theirKeys)
-                        status.no_keys = false;
-
-                if (!ourKeys || !theirKeys) {
-                        verification_storage.status[user_id] = status;
-                        return status;
-                }
+        auto master_keys = ourKeys->master_keys.keys;
 
-                // Update verified devices count to count without cross-signing
-                updateUnverifiedDevices(theirKeys->device_keys);
-
-                {
-                        auto &mk           = ourKeys->master_keys;
-                        std::string dev_id = "ed25519:" + http::client()->device_id();
-                        if (!mk.signatures.count(local_user) ||
-                            !mk.signatures.at(local_user).count(dev_id) ||
-                            !mtx::crypto::ed25519_verify_signature(
-                              olm::client()->identity_keys().ed25519,
-                              json(mk),
-                              mk.signatures.at(local_user).at(dev_id))) {
-                                nhlog::crypto()->debug("We have not verified our own master key");
-                                verification_storage.status[user_id] = status;
-                                return status;
-                        }
-                }
+        if (user_id != local_user) {
+            bool theirMasterKeyVerified =
+              verifyAtLeastOneSig(ourKeys->user_signing_keys, master_keys, local_user) &&
+              verifyAtLeastOneSig(
+                theirKeys->master_keys, ourKeys->user_signing_keys.keys, local_user);
 
-                auto master_keys = ourKeys->master_keys.keys;
-
-                if (user_id != local_user) {
-                        bool theirMasterKeyVerified =
-                          verifyAtLeastOneSig(
-                            ourKeys->user_signing_keys, master_keys, local_user) &&
-                          verifyAtLeastOneSig(
-                            theirKeys->master_keys, ourKeys->user_signing_keys.keys, local_user);
-
-                        if (theirMasterKeyVerified)
-                                trustlevel = crypto::Trust::Verified;
-                        else if (!theirKeys->master_key_changed)
-                                trustlevel = crypto::Trust::TOFU;
-                        else {
-                                verification_storage.status[user_id] = status;
-                                return status;
-                        }
+            if (theirMasterKeyVerified)
+                trustlevel = crypto::Trust::Verified;
+            else if (!theirKeys->master_key_changed)
+                trustlevel = crypto::Trust::TOFU;
+            else {
+                verification_storage.status[user_id] = status;
+                return status;
+            }
 
-                        master_keys = theirKeys->master_keys.keys;
-                }
+            master_keys = theirKeys->master_keys.keys;
+        }
 
-                status.user_verified = trustlevel;
+        status.user_verified = trustlevel;
 
-                verification_storage.status[user_id] = status;
-                if (!verifyAtLeastOneSig(theirKeys->self_signing_keys, master_keys, user_id))
-                        return status;
-
-                for (const auto &[device, device_key] : theirKeys->device_keys) {
-                        (void)device;
-                        try {
-                                auto identkey =
-                                  device_key.keys.at("curve25519:" + device_key.device_id);
-                                if (verifyAtLeastOneSig(
-                                      device_key, theirKeys->self_signing_keys.keys, user_id)) {
-                                        status.verified_devices.insert(device_key.device_id);
-                                        status.verified_device_keys[identkey] = trustlevel;
-                                }
-                        } catch (...) {
-                        }
-                }
+        verification_storage.status[user_id] = status;
+        if (!verifyAtLeastOneSig(theirKeys->self_signing_keys, master_keys, user_id))
+            return status;
 
-                updateUnverifiedDevices(theirKeys->device_keys);
-                verification_storage.status[user_id] = status;
-                return status;
-        } catch (std::exception &e) {
-                nhlog::db()->error(
-                  "Failed to calculate verification status of {}: {}", user_id, e.what());
-                return status;
+        for (const auto &[device, device_key] : theirKeys->device_keys) {
+            (void)device;
+            try {
+                auto identkey = device_key.keys.at("curve25519:" + device_key.device_id);
+                if (verifyAtLeastOneSig(device_key, theirKeys->self_signing_keys.keys, user_id)) {
+                    status.verified_devices.insert(device_key.device_id);
+                    status.verified_device_keys[identkey] = trustlevel;
+                }
+            } catch (...) {
+            }
         }
+
+        updateUnverifiedDevices(theirKeys->device_keys);
+        verification_storage.status[user_id] = status;
+        return status;
+    } catch (std::exception &e) {
+        nhlog::db()->error("Failed to calculate verification status of {}: {}", user_id, e.what());
+        return status;
+    }
 }
 
 void
 to_json(json &j, const RoomInfo &info)
 {
-        j["name"]         = info.name;
-        j["topic"]        = info.topic;
-        j["avatar_url"]   = info.avatar_url;
-        j["version"]      = info.version;
-        j["is_invite"]    = info.is_invite;
-        j["is_space"]     = info.is_space;
-        j["join_rule"]    = info.join_rule;
-        j["guest_access"] = info.guest_access;
+    j["name"]         = info.name;
+    j["topic"]        = info.topic;
+    j["avatar_url"]   = info.avatar_url;
+    j["version"]      = info.version;
+    j["is_invite"]    = info.is_invite;
+    j["is_space"]     = info.is_space;
+    j["join_rule"]    = info.join_rule;
+    j["guest_access"] = info.guest_access;
 
-        if (info.member_count != 0)
-                j["member_count"] = info.member_count;
+    if (info.member_count != 0)
+        j["member_count"] = info.member_count;
 
-        if (info.tags.size() != 0)
-                j["tags"] = info.tags;
+    if (info.tags.size() != 0)
+        j["tags"] = info.tags;
 }
 
 void
 from_json(const json &j, RoomInfo &info)
 {
-        info.name       = j.at("name");
-        info.topic      = j.at("topic");
-        info.avatar_url = j.at("avatar_url");
-        info.version    = j.value(
-          "version", QCoreApplication::translate("RoomInfo", "no version stored").toStdString());
-        info.is_invite    = j.at("is_invite");
-        info.is_space     = j.value("is_space", false);
-        info.join_rule    = j.at("join_rule");
-        info.guest_access = j.at("guest_access");
+    info.name       = j.at("name");
+    info.topic      = j.at("topic");
+    info.avatar_url = j.at("avatar_url");
+    info.version    = j.value(
+      "version", QCoreApplication::translate("RoomInfo", "no version stored").toStdString());
+    info.is_invite    = j.at("is_invite");
+    info.is_space     = j.value("is_space", false);
+    info.join_rule    = j.at("join_rule");
+    info.guest_access = j.at("guest_access");
 
-        if (j.count("member_count"))
-                info.member_count = j.at("member_count");
+    if (j.count("member_count"))
+        info.member_count = j.at("member_count");
 
-        if (j.count("tags"))
-                info.tags = j.at("tags").get<std::vector<std::string>>();
+    if (j.count("tags"))
+        info.tags = j.at("tags").get<std::vector<std::string>>();
 }
 
 void
 to_json(json &j, const ReadReceiptKey &key)
 {
-        j = json{{"event_id", key.event_id}, {"room_id", key.room_id}};
+    j = json{{"event_id", key.event_id}, {"room_id", key.room_id}};
 }
 
 void
 from_json(const json &j, ReadReceiptKey &key)
 {
-        key.event_id = j.at("event_id").get<std::string>();
-        key.room_id  = j.at("room_id").get<std::string>();
+    key.event_id = j.at("event_id").get<std::string>();
+    key.room_id  = j.at("room_id").get<std::string>();
 }
 
 void
 to_json(json &j, const MemberInfo &info)
 {
-        j["name"]       = info.name;
-        j["avatar_url"] = info.avatar_url;
+    j["name"]       = info.name;
+    j["avatar_url"] = info.avatar_url;
 }
 
 void
 from_json(const json &j, MemberInfo &info)
 {
-        info.name       = j.at("name");
-        info.avatar_url = j.at("avatar_url");
+    info.name       = j.at("name");
+    info.avatar_url = j.at("avatar_url");
 }
 
 void
 to_json(nlohmann::json &obj, const DeviceKeysToMsgIndex &msg)
 {
-        obj["deviceids"] = msg.deviceids;
+    obj["deviceids"] = msg.deviceids;
 }
 
 void
 from_json(const nlohmann::json &obj, DeviceKeysToMsgIndex &msg)
 {
-        msg.deviceids = obj.at("deviceids").get<decltype(msg.deviceids)>();
+    msg.deviceids = obj.at("deviceids").get<decltype(msg.deviceids)>();
 }
 
 void
 to_json(nlohmann::json &obj, const SharedWithUsers &msg)
 {
-        obj["keys"] = msg.keys;
+    obj["keys"] = msg.keys;
 }
 
 void
 from_json(const nlohmann::json &obj, SharedWithUsers &msg)
 {
-        msg.keys = obj.at("keys").get<std::map<std::string, DeviceKeysToMsgIndex>>();
+    msg.keys = obj.at("keys").get<std::map<std::string, DeviceKeysToMsgIndex>>();
 }
 
 void
 to_json(nlohmann::json &obj, const GroupSessionData &msg)
 {
-        obj["message_index"] = msg.message_index;
-        obj["ts"]            = msg.timestamp;
-        obj["trust"]         = msg.trusted;
+    obj["message_index"] = msg.message_index;
+    obj["ts"]            = msg.timestamp;
+    obj["trust"]         = msg.trusted;
 
-        obj["sender_claimed_ed25519_key"]      = msg.sender_claimed_ed25519_key;
-        obj["forwarding_curve25519_key_chain"] = msg.forwarding_curve25519_key_chain;
+    obj["sender_claimed_ed25519_key"]      = msg.sender_claimed_ed25519_key;
+    obj["forwarding_curve25519_key_chain"] = msg.forwarding_curve25519_key_chain;
 
-        obj["currently"] = msg.currently;
+    obj["currently"] = msg.currently;
 
-        obj["indices"] = msg.indices;
+    obj["indices"] = msg.indices;
 }
 
 void
 from_json(const nlohmann::json &obj, GroupSessionData &msg)
 {
-        msg.message_index = obj.at("message_index");
-        msg.timestamp     = obj.value("ts", 0ULL);
-        msg.trusted       = obj.value("trust", true);
+    msg.message_index = obj.at("message_index");
+    msg.timestamp     = obj.value("ts", 0ULL);
+    msg.trusted       = obj.value("trust", true);
 
-        msg.sender_claimed_ed25519_key = obj.value("sender_claimed_ed25519_key", "");
-        msg.forwarding_curve25519_key_chain =
-          obj.value("forwarding_curve25519_key_chain", std::vector<std::string>{});
+    msg.sender_claimed_ed25519_key = obj.value("sender_claimed_ed25519_key", "");
+    msg.forwarding_curve25519_key_chain =
+      obj.value("forwarding_curve25519_key_chain", std::vector<std::string>{});
 
-        msg.currently = obj.value("currently", SharedWithUsers{});
+    msg.currently = obj.value("currently", SharedWithUsers{});
 
-        msg.indices = obj.value("indices", std::map<uint32_t, std::string>());
+    msg.indices = obj.value("indices", std::map<uint32_t, std::string>());
 }
 
 void
 to_json(nlohmann::json &obj, const DevicePublicKeys &msg)
 {
-        obj["ed25519"]    = msg.ed25519;
-        obj["curve25519"] = msg.curve25519;
+    obj["ed25519"]    = msg.ed25519;
+    obj["curve25519"] = msg.curve25519;
 }
 
 void
 from_json(const nlohmann::json &obj, DevicePublicKeys &msg)
 {
-        msg.ed25519    = obj.at("ed25519");
-        msg.curve25519 = obj.at("curve25519");
+    msg.ed25519    = obj.at("ed25519");
+    msg.curve25519 = obj.at("curve25519");
 }
 
 void
 to_json(nlohmann::json &obj, const MegolmSessionIndex &msg)
 {
-        obj["room_id"]    = msg.room_id;
-        obj["session_id"] = msg.session_id;
-        obj["sender_key"] = msg.sender_key;
+    obj["room_id"]    = msg.room_id;
+    obj["session_id"] = msg.session_id;
+    obj["sender_key"] = msg.sender_key;
 }
 
 void
 from_json(const nlohmann::json &obj, MegolmSessionIndex &msg)
 {
-        msg.room_id    = obj.at("room_id");
-        msg.session_id = obj.at("session_id");
-        msg.sender_key = obj.at("sender_key");
+    msg.room_id    = obj.at("room_id");
+    msg.session_id = obj.at("session_id");
+    msg.sender_key = obj.at("sender_key");
 }
 
 void
 to_json(nlohmann::json &obj, const StoredOlmSession &msg)
 {
-        obj["ts"] = msg.last_message_ts;
-        obj["s"]  = msg.pickled_session;
+    obj["ts"] = msg.last_message_ts;
+    obj["s"]  = msg.pickled_session;
 }
 void
 from_json(const nlohmann::json &obj, StoredOlmSession &msg)
 {
-        msg.last_message_ts = obj.at("ts").get<uint64_t>();
-        msg.pickled_session = obj.at("s").get<std::string>();
+    msg.last_message_ts = obj.at("ts").get<uint64_t>();
+    msg.pickled_session = obj.at("s").get<std::string>();
 }
 
 namespace cache {
 void
 init(const QString &user_id)
 {
-        qRegisterMetaType<RoomMember>();
-        qRegisterMetaType<RoomSearchResult>();
-        qRegisterMetaType<RoomInfo>();
-        qRegisterMetaType<QMap<QString, RoomInfo>>();
-        qRegisterMetaType<std::map<QString, RoomInfo>>();
-        qRegisterMetaType<std::map<QString, mtx::responses::Timeline>>();
-        qRegisterMetaType<mtx::responses::QueryKeys>();
+    qRegisterMetaType<RoomMember>();
+    qRegisterMetaType<RoomSearchResult>();
+    qRegisterMetaType<RoomInfo>();
+    qRegisterMetaType<QMap<QString, RoomInfo>>();
+    qRegisterMetaType<std::map<QString, RoomInfo>>();
+    qRegisterMetaType<std::map<QString, mtx::responses::Timeline>>();
+    qRegisterMetaType<mtx::responses::QueryKeys>();
 
-        instance_ = std::make_unique<Cache>(user_id);
+    instance_ = std::make_unique<Cache>(user_id);
 }
 
 Cache *
 client()
 {
-        return instance_.get();
+    return instance_.get();
 }
 
 std::string
 displayName(const std::string &room_id, const std::string &user_id)
 {
-        return instance_->displayName(room_id, user_id);
+    return instance_->displayName(room_id, user_id);
 }
 
 QString
 displayName(const QString &room_id, const QString &user_id)
 {
-        return instance_->displayName(room_id, user_id);
+    return instance_->displayName(room_id, user_id);
 }
 QString
 avatarUrl(const QString &room_id, const QString &user_id)
 {
-        return instance_->avatarUrl(room_id, user_id);
+    return instance_->avatarUrl(room_id, user_id);
 }
 
 mtx::presence::PresenceState
 presenceState(const std::string &user_id)
 {
-        if (!instance_)
-                return {};
-        return instance_->presenceState(user_id);
+    if (!instance_)
+        return {};
+    return instance_->presenceState(user_id);
 }
 std::string
 statusMessage(const std::string &user_id)
 {
-        return instance_->statusMessage(user_id);
+    return instance_->statusMessage(user_id);
 }
 
 // user cache stores user keys
 std::optional<UserKeyCache>
 userKeys(const std::string &user_id)
 {
-        return instance_->userKeys(user_id);
+    return instance_->userKeys(user_id);
 }
 void
 updateUserKeys(const std::string &sync_token, const mtx::responses::QueryKeys &keyQuery)
 {
-        instance_->updateUserKeys(sync_token, keyQuery);
+    instance_->updateUserKeys(sync_token, keyQuery);
 }
 
 // device & user verification cache
 std::optional<VerificationStatus>
 verificationStatus(const std::string &user_id)
 {
-        return instance_->verificationStatus(user_id);
+    return instance_->verificationStatus(user_id);
 }
 
 void
 markDeviceVerified(const std::string &user_id, const std::string &device)
 {
-        instance_->markDeviceVerified(user_id, device);
+    instance_->markDeviceVerified(user_id, device);
 }
 
 void
 markDeviceUnverified(const std::string &user_id, const std::string &device)
 {
-        instance_->markDeviceUnverified(user_id, device);
+    instance_->markDeviceUnverified(user_id, device);
 }
 
 std::vector<std::string>
 joinedRooms()
 {
-        return instance_->joinedRooms();
+    return instance_->joinedRooms();
 }
 
 QMap<QString, RoomInfo>
 roomInfo(bool withInvites)
 {
-        return instance_->roomInfo(withInvites);
+    return instance_->roomInfo(withInvites);
 }
 QHash<QString, RoomInfo>
 invites()
 {
-        return instance_->invites();
+    return instance_->invites();
 }
 
 QString
 getRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb)
 {
-        return instance_->getRoomName(txn, statesdb, membersdb);
+    return instance_->getRoomName(txn, statesdb, membersdb);
 }
 mtx::events::state::JoinRule
 getRoomJoinRule(lmdb::txn &txn, lmdb::dbi &statesdb)
 {
-        return instance_->getRoomJoinRule(txn, statesdb);
+    return instance_->getRoomJoinRule(txn, statesdb);
 }
 bool
 getRoomGuestAccess(lmdb::txn &txn, lmdb::dbi &statesdb)
 {
-        return instance_->getRoomGuestAccess(txn, statesdb);
+    return instance_->getRoomGuestAccess(txn, statesdb);
 }
 QString
 getRoomTopic(lmdb::txn &txn, lmdb::dbi &statesdb)
 {
-        return instance_->getRoomTopic(txn, statesdb);
+    return instance_->getRoomTopic(txn, statesdb);
 }
 QString
 getRoomAvatarUrl(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb)
 {
-        return instance_->getRoomAvatarUrl(txn, statesdb, membersdb);
+    return instance_->getRoomAvatarUrl(txn, statesdb, membersdb);
 }
 
 std::vector<RoomMember>
 getMembers(const std::string &room_id, std::size_t startIndex, std::size_t len)
 {
-        return instance_->getMembers(room_id, startIndex, len);
+    return instance_->getMembers(room_id, startIndex, len);
 }
 
 std::vector<RoomMember>
 getMembersFromInvite(const std::string &room_id, std::size_t startIndex, std::size_t len)
 {
-        return instance_->getMembersFromInvite(room_id, startIndex, len);
+    return instance_->getMembersFromInvite(room_id, startIndex, len);
 }
 
 void
 saveState(const mtx::responses::Sync &res)
 {
-        instance_->saveState(res);
+    instance_->saveState(res);
 }
 bool
 isInitialized()
 {
-        return instance_->isInitialized();
+    return instance_->isInitialized();
 }
 
 std::string
 nextBatchToken()
 {
-        return instance_->nextBatchToken();
+    return instance_->nextBatchToken();
 }
 
 void
 deleteData()
 {
-        instance_->deleteData();
+    instance_->deleteData();
 }
 
 void
 removeInvite(lmdb::txn &txn, const std::string &room_id)
 {
-        instance_->removeInvite(txn, room_id);
+    instance_->removeInvite(txn, room_id);
 }
 void
 removeInvite(const std::string &room_id)
 {
-        instance_->removeInvite(room_id);
+    instance_->removeInvite(room_id);
 }
 void
 removeRoom(lmdb::txn &txn, const std::string &roomid)
 {
-        instance_->removeRoom(txn, roomid);
+    instance_->removeRoom(txn, roomid);
 }
 void
 removeRoom(const std::string &roomid)
 {
-        instance_->removeRoom(roomid);
+    instance_->removeRoom(roomid);
 }
 void
 removeRoom(const QString &roomid)
 {
-        instance_->removeRoom(roomid.toStdString());
+    instance_->removeRoom(roomid.toStdString());
 }
 void
 setup()
 {
-        instance_->setup();
+    instance_->setup();
 }
 
 bool
 runMigrations()
 {
-        return instance_->runMigrations();
+    return instance_->runMigrations();
 }
 
 cache::CacheVersion
 formatVersion()
 {
-        return instance_->formatVersion();
+    return instance_->formatVersion();
 }
 
 void
 setCurrentFormat()
 {
-        instance_->setCurrentFormat();
+    instance_->setCurrentFormat();
 }
 
 std::vector<QString>
 roomIds()
 {
-        return instance_->roomIds();
+    return instance_->roomIds();
 }
 
 QMap<QString, mtx::responses::Notifications>
 getTimelineMentions()
 {
-        return instance_->getTimelineMentions();
+    return instance_->getTimelineMentions();
 }
 
 //! Retrieve all the user ids from a room.
 std::vector<std::string>
 roomMembers(const std::string &room_id)
 {
-        return instance_->roomMembers(room_id);
+    return instance_->roomMembers(room_id);
 }
 
 //! Check if the given user has power leve greater than than
@@ -4952,48 +4826,48 @@ hasEnoughPowerLevel(const std::vector<mtx::events::EventType> &eventTypes,
                     const std::string &room_id,
                     const std::string &user_id)
 {
-        return instance_->hasEnoughPowerLevel(eventTypes, room_id, user_id);
+    return instance_->hasEnoughPowerLevel(eventTypes, room_id, user_id);
 }
 
 void
 updateReadReceipt(lmdb::txn &txn, const std::string &room_id, const Receipts &receipts)
 {
-        instance_->updateReadReceipt(txn, room_id, receipts);
+    instance_->updateReadReceipt(txn, room_id, receipts);
 }
 
 UserReceipts
 readReceipts(const QString &event_id, const QString &room_id)
 {
-        return instance_->readReceipts(event_id, room_id);
+    return instance_->readReceipts(event_id, room_id);
 }
 
 std::optional<uint64_t>
 getEventIndex(const std::string &room_id, std::string_view event_id)
 {
-        return instance_->getEventIndex(room_id, event_id);
+    return instance_->getEventIndex(room_id, event_id);
 }
 
 std::optional<std::pair<uint64_t, std::string>>
 lastInvisibleEventAfter(const std::string &room_id, std::string_view event_id)
 {
-        return instance_->lastInvisibleEventAfter(room_id, event_id);
+    return instance_->lastInvisibleEventAfter(room_id, event_id);
 }
 
 RoomInfo
 singleRoomInfo(const std::string &room_id)
 {
-        return instance_->singleRoomInfo(room_id);
+    return instance_->singleRoomInfo(room_id);
 }
 std::vector<std::string>
 roomsWithStateUpdates(const mtx::responses::Sync &res)
 {
-        return instance_->roomsWithStateUpdates(res);
+    return instance_->roomsWithStateUpdates(res);
 }
 
 std::map<QString, RoomInfo>
 getRoomInfo(const std::vector<std::string> &rooms)
 {
-        return instance_->getRoomInfo(rooms);
+    return instance_->getRoomInfo(rooms);
 }
 
 //! Calculates which the read status of a room.
@@ -5001,74 +4875,74 @@ getRoomInfo(const std::vector<std::string> &rooms)
 bool
 calculateRoomReadStatus(const std::string &room_id)
 {
-        return instance_->calculateRoomReadStatus(room_id);
+    return instance_->calculateRoomReadStatus(room_id);
 }
 void
 calculateRoomReadStatus()
 {
-        instance_->calculateRoomReadStatus();
+    instance_->calculateRoomReadStatus();
 }
 
 void
 markSentNotification(const std::string &event_id)
 {
-        instance_->markSentNotification(event_id);
+    instance_->markSentNotification(event_id);
 }
 //! Removes an event from the sent notifications.
 void
 removeReadNotification(const std::string &event_id)
 {
-        instance_->removeReadNotification(event_id);
+    instance_->removeReadNotification(event_id);
 }
 //! Check if we have sent a desktop notification for the given event id.
 bool
 isNotificationSent(const std::string &event_id)
 {
-        return instance_->isNotificationSent(event_id);
+    return instance_->isNotificationSent(event_id);
 }
 
 //! Add all notifications containing a user mention to the db.
 void
 saveTimelineMentions(const mtx::responses::Notifications &res)
 {
-        instance_->saveTimelineMentions(res);
+    instance_->saveTimelineMentions(res);
 }
 
 //! Remove old unused data.
 void
 deleteOldMessages()
 {
-        instance_->deleteOldMessages();
+    instance_->deleteOldMessages();
 }
 void
 deleteOldData() noexcept
 {
-        instance_->deleteOldData();
+    instance_->deleteOldData();
 }
 //! Retrieve all saved room ids.
 std::vector<std::string>
 getRoomIds(lmdb::txn &txn)
 {
-        return instance_->getRoomIds(txn);
+    return instance_->getRoomIds(txn);
 }
 
 //! Mark a room that uses e2e encryption.
 void
 setEncryptedRoom(lmdb::txn &txn, const std::string &room_id)
 {
-        instance_->setEncryptedRoom(txn, room_id);
+    instance_->setEncryptedRoom(txn, room_id);
 }
 bool
 isRoomEncrypted(const std::string &room_id)
 {
-        return instance_->isRoomEncrypted(room_id);
+    return instance_->isRoomEncrypted(room_id);
 }
 
 //! Check if a user is a member of the room.
 bool
 isRoomMember(const std::string &user_id, const std::string &room_id)
 {
-        return instance_->isRoomMember(user_id, room_id);
+    return instance_->isRoomMember(user_id, room_id);
 }
 
 //
@@ -5079,40 +4953,40 @@ saveOutboundMegolmSession(const std::string &room_id,
                           const GroupSessionData &data,
                           mtx::crypto::OutboundGroupSessionPtr &session)
 {
-        instance_->saveOutboundMegolmSession(room_id, data, session);
+    instance_->saveOutboundMegolmSession(room_id, data, session);
 }
 OutboundGroupSessionDataRef
 getOutboundMegolmSession(const std::string &room_id)
 {
-        return instance_->getOutboundMegolmSession(room_id);
+    return instance_->getOutboundMegolmSession(room_id);
 }
 bool
 outboundMegolmSessionExists(const std::string &room_id) noexcept
 {
-        return instance_->outboundMegolmSessionExists(room_id);
+    return instance_->outboundMegolmSessionExists(room_id);
 }
 void
 updateOutboundMegolmSession(const std::string &room_id,
                             const GroupSessionData &data,
                             mtx::crypto::OutboundGroupSessionPtr &session)
 {
-        instance_->updateOutboundMegolmSession(room_id, data, session);
+    instance_->updateOutboundMegolmSession(room_id, data, session);
 }
 void
 dropOutboundMegolmSession(const std::string &room_id)
 {
-        instance_->dropOutboundMegolmSession(room_id);
+    instance_->dropOutboundMegolmSession(room_id);
 }
 
 void
 importSessionKeys(const mtx::crypto::ExportedSessionKeys &keys)
 {
-        instance_->importSessionKeys(keys);
+    instance_->importSessionKeys(keys);
 }
 mtx::crypto::ExportedSessionKeys
 exportSessionKeys()
 {
-        return instance_->exportSessionKeys();
+    return instance_->exportSessionKeys();
 }
 
 //
@@ -5123,22 +4997,22 @@ saveInboundMegolmSession(const MegolmSessionIndex &index,
                          mtx::crypto::InboundGroupSessionPtr session,
                          const GroupSessionData &data)
 {
-        instance_->saveInboundMegolmSession(index, std::move(session), data);
+    instance_->saveInboundMegolmSession(index, std::move(session), data);
 }
 mtx::crypto::InboundGroupSessionPtr
 getInboundMegolmSession(const MegolmSessionIndex &index)
 {
-        return instance_->getInboundMegolmSession(index);
+    return instance_->getInboundMegolmSession(index);
 }
 bool
 inboundMegolmSessionExists(const MegolmSessionIndex &index)
 {
-        return instance_->inboundMegolmSessionExists(index);
+    return instance_->inboundMegolmSessionExists(index);
 }
 std::optional<GroupSessionData>
 getMegolmSessionData(const MegolmSessionIndex &index)
 {
-        return instance_->getMegolmSessionData(index);
+    return instance_->getMegolmSessionData(index);
 }
 
 //
@@ -5149,43 +5023,43 @@ saveOlmSession(const std::string &curve25519,
                mtx::crypto::OlmSessionPtr session,
                uint64_t timestamp)
 {
-        instance_->saveOlmSession(curve25519, std::move(session), timestamp);
+    instance_->saveOlmSession(curve25519, std::move(session), timestamp);
 }
 std::vector<std::string>
 getOlmSessions(const std::string &curve25519)
 {
-        return instance_->getOlmSessions(curve25519);
+    return instance_->getOlmSessions(curve25519);
 }
 std::optional<mtx::crypto::OlmSessionPtr>
 getOlmSession(const std::string &curve25519, const std::string &session_id)
 {
-        return instance_->getOlmSession(curve25519, session_id);
+    return instance_->getOlmSession(curve25519, session_id);
 }
 std::optional<mtx::crypto::OlmSessionPtr>
 getLatestOlmSession(const std::string &curve25519)
 {
-        return instance_->getLatestOlmSession(curve25519);
+    return instance_->getLatestOlmSession(curve25519);
 }
 
 void
 saveOlmAccount(const std::string &pickled)
 {
-        instance_->saveOlmAccount(pickled);
+    instance_->saveOlmAccount(pickled);
 }
 std::string
 restoreOlmAccount()
 {
-        return instance_->restoreOlmAccount();
+    return instance_->restoreOlmAccount();
 }
 
 void
 storeSecret(const std::string &name, const std::string &secret)
 {
-        instance_->storeSecret(name, secret);
+    instance_->storeSecret(name, secret);
 }
 std::optional<std::string>
 secret(const std::string &name)
 {
-        return instance_->secret(name);
+    return instance_->secret(name);
 }
 } // namespace cache
diff --git a/src/CacheCryptoStructs.h b/src/CacheCryptoStructs.h
index 80dd1046..b7461848 100644
--- a/src/CacheCryptoStructs.h
+++ b/src/CacheCryptoStructs.h
@@ -19,48 +19,48 @@ Q_NAMESPACE
 //! How much a participant is trusted.
 enum Trust
 {
-        Unverified, //! Device unverified or master key changed.
-        TOFU,       //! Device is signed by the sender, but the user is not verified, but they never
-                    //! changed the master key.
-        Verified,   //! User was verified and has crosssigned this device or device is verified.
+    Unverified, //! Device unverified or master key changed.
+    TOFU,       //! Device is signed by the sender, but the user is not verified, but they never
+                //! changed the master key.
+    Verified,   //! User was verified and has crosssigned this device or device is verified.
 };
 Q_ENUM_NS(Trust)
 }
 
 struct DeviceKeysToMsgIndex
 {
-        // map from device key to message_index
-        // Using the device id is safe because we check for reuse on device list updates
-        // Using the device id makes our logic much easier to read.
-        std::map<std::string, uint64_t> deviceids;
+    // map from device key to message_index
+    // Using the device id is safe because we check for reuse on device list updates
+    // Using the device id makes our logic much easier to read.
+    std::map<std::string, uint64_t> deviceids;
 };
 
 struct SharedWithUsers
 {
-        // userid to keys
-        std::map<std::string, DeviceKeysToMsgIndex> keys;
+    // userid to keys
+    std::map<std::string, DeviceKeysToMsgIndex> keys;
 };
 
 // Extra information associated with an outbound megolm session.
 struct GroupSessionData
 {
-        uint64_t message_index = 0;
-        uint64_t timestamp     = 0;
+    uint64_t message_index = 0;
+    uint64_t timestamp     = 0;
 
-        // If we got the session via key sharing or forwarding, we can usually trust it.
-        // If it came from asymmetric key backup, it is not trusted.
-        // TODO(Nico): What about forwards? They might come from key backup?
-        bool trusted = true;
+    // If we got the session via key sharing or forwarding, we can usually trust it.
+    // If it came from asymmetric key backup, it is not trusted.
+    // TODO(Nico): What about forwards? They might come from key backup?
+    bool trusted = true;
 
-        std::string sender_claimed_ed25519_key;
-        std::vector<std::string> forwarding_curve25519_key_chain;
+    std::string sender_claimed_ed25519_key;
+    std::vector<std::string> forwarding_curve25519_key_chain;
 
-        //! map from index to event_id to check for replay attacks
-        std::map<uint32_t, std::string> indices;
+    //! map from index to event_id to check for replay attacks
+    std::map<uint32_t, std::string> indices;
 
-        // who has access to this session.
-        // Rotate, when a user leaves the room and share, when a user gets added.
-        SharedWithUsers currently;
+    // who has access to this session.
+    // Rotate, when a user leaves the room and share, when a user gets added.
+    SharedWithUsers currently;
 };
 
 void
@@ -70,14 +70,14 @@ from_json(const nlohmann::json &obj, GroupSessionData &msg);
 
 struct OutboundGroupSessionDataRef
 {
-        mtx::crypto::OutboundGroupSessionPtr session;
-        GroupSessionData data;
+    mtx::crypto::OutboundGroupSessionPtr session;
+    GroupSessionData data;
 };
 
 struct DevicePublicKeys
 {
-        std::string ed25519;
-        std::string curve25519;
+    std::string ed25519;
+    std::string curve25519;
 };
 
 void
@@ -88,19 +88,19 @@ from_json(const nlohmann::json &obj, DevicePublicKeys &msg);
 //! Represents a unique megolm session identifier.
 struct MegolmSessionIndex
 {
-        MegolmSessionIndex() = default;
-        MegolmSessionIndex(std::string room_id_, const mtx::events::msg::Encrypted &e)
-          : room_id(std::move(room_id_))
-          , session_id(e.session_id)
-          , sender_key(e.sender_key)
-        {}
-
-        //! The room in which this session exists.
-        std::string room_id;
-        //! The session_id of the megolm session.
-        std::string session_id;
-        //! The curve25519 public key of the sender.
-        std::string sender_key;
+    MegolmSessionIndex() = default;
+    MegolmSessionIndex(std::string room_id_, const mtx::events::msg::Encrypted &e)
+      : room_id(std::move(room_id_))
+      , session_id(e.session_id)
+      , sender_key(e.sender_key)
+    {}
+
+    //! The room in which this session exists.
+    std::string room_id;
+    //! The session_id of the megolm session.
+    std::string session_id;
+    //! The curve25519 public key of the sender.
+    std::string sender_key;
 };
 
 void
@@ -110,8 +110,8 @@ from_json(const nlohmann::json &obj, MegolmSessionIndex &msg);
 
 struct StoredOlmSession
 {
-        std::uint64_t last_message_ts = 0;
-        std::string pickled_session;
+    std::uint64_t last_message_ts = 0;
+    std::string pickled_session;
 };
 void
 to_json(nlohmann::json &obj, const StoredOlmSession &msg);
@@ -121,43 +121,43 @@ from_json(const nlohmann::json &obj, StoredOlmSession &msg);
 //! Verification status of a single user
 struct VerificationStatus
 {
-        //! True, if the users master key is verified
-        crypto::Trust user_verified = crypto::Trust::Unverified;
-        //! List of all devices marked as verified
-        std::set<std::string> verified_devices;
-        //! Map from sender key/curve25519 to trust status
-        std::map<std::string, crypto::Trust> verified_device_keys;
-        //! Count of unverified devices
-        int unverified_device_count = 0;
-        // if the keys are not in cache
-        bool no_keys = false;
+    //! True, if the users master key is verified
+    crypto::Trust user_verified = crypto::Trust::Unverified;
+    //! List of all devices marked as verified
+    std::set<std::string> verified_devices;
+    //! Map from sender key/curve25519 to trust status
+    std::map<std::string, crypto::Trust> verified_device_keys;
+    //! Count of unverified devices
+    int unverified_device_count = 0;
+    // if the keys are not in cache
+    bool no_keys = false;
 };
 
 //! In memory cache of verification status
 struct VerificationStorage
 {
-        //! mapping of user to verification status
-        std::map<std::string, VerificationStatus> status;
-        std::mutex verification_storage_mtx;
+    //! mapping of user to verification status
+    std::map<std::string, VerificationStatus> status;
+    std::mutex verification_storage_mtx;
 };
 
 // this will store the keys of the user with whom a encrypted room is shared with
 struct UserKeyCache
 {
-        //! Device id to device keys
-        std::map<std::string, mtx::crypto::DeviceKeys> device_keys;
-        //! cross signing keys
-        mtx::crypto::CrossSigningKeys master_keys, user_signing_keys, self_signing_keys;
-        //! Sync token when nheko last fetched the keys
-        std::string updated_at;
-        //! Sync token when the keys last changed. updated != last_changed means they are outdated.
-        std::string last_changed;
-        //! if the master key has ever changed
-        bool master_key_changed = false;
-        //! Device keys that were already used at least once
-        std::set<std::string> seen_device_keys;
-        //! Device ids that were already used at least once
-        std::set<std::string> seen_device_ids;
+    //! Device id to device keys
+    std::map<std::string, mtx::crypto::DeviceKeys> device_keys;
+    //! cross signing keys
+    mtx::crypto::CrossSigningKeys master_keys, user_signing_keys, self_signing_keys;
+    //! Sync token when nheko last fetched the keys
+    std::string updated_at;
+    //! Sync token when the keys last changed. updated != last_changed means they are outdated.
+    std::string last_changed;
+    //! if the master key has ever changed
+    bool master_key_changed = false;
+    //! Device keys that were already used at least once
+    std::set<std::string> seen_device_keys;
+    //! Device ids that were already used at least once
+    std::set<std::string> seen_device_ids;
 };
 
 void
@@ -169,10 +169,10 @@ from_json(const nlohmann::json &j, UserKeyCache &info);
 // UserKeyCache stores only keys of users with which encrypted room is shared
 struct VerificationCache
 {
-        //! list of verified device_ids with device-verification
-        std::set<std::string> device_verified;
-        //! list of devices the user blocks
-        std::set<std::string> device_blocked;
+    //! list of verified device_ids with device-verification
+    std::set<std::string> device_verified;
+    //! list of devices the user blocks
+    std::set<std::string> device_blocked;
 };
 
 void
@@ -182,10 +182,10 @@ from_json(const nlohmann::json &j, VerificationCache &info);
 
 struct OnlineBackupVersion
 {
-        //! the version of the online backup currently enabled
-        std::string version;
-        //! the algorithm used by the backup
-        std::string algorithm;
+    //! the version of the online backup currently enabled
+    std::string version;
+    //! the algorithm used by the backup
+    std::string algorithm;
 };
 
 void
diff --git a/src/CacheStructs.h b/src/CacheStructs.h
index 5f4d392a..e28f5b2d 100644
--- a/src/CacheStructs.h
+++ b/src/CacheStructs.h
@@ -16,23 +16,23 @@
 namespace cache {
 enum class CacheVersion : int
 {
-        Older   = -1,
-        Current = 0,
-        Newer   = 1,
+    Older   = -1,
+    Current = 0,
+    Newer   = 1,
 };
 }
 
 struct RoomMember
 {
-        QString user_id;
-        QString display_name;
+    QString user_id;
+    QString display_name;
 };
 
 //! Used to uniquely identify a list of read receipts.
 struct ReadReceiptKey
 {
-        std::string event_id;
-        std::string room_id;
+    std::string event_id;
+    std::string room_id;
 };
 
 void
@@ -43,49 +43,49 @@ from_json(const nlohmann::json &j, ReadReceiptKey &key);
 
 struct DescInfo
 {
-        QString event_id;
-        QString userid;
-        QString body;
-        QString descriptiveTime;
-        uint64_t timestamp;
-        QDateTime datetime;
+    QString event_id;
+    QString userid;
+    QString body;
+    QString descriptiveTime;
+    uint64_t timestamp;
+    QDateTime datetime;
 };
 
 inline bool
 operator==(const DescInfo &a, const DescInfo &b)
 {
-        return std::tie(a.timestamp, a.event_id, a.userid, a.body, a.descriptiveTime) ==
-               std::tie(b.timestamp, b.event_id, b.userid, b.body, b.descriptiveTime);
+    return std::tie(a.timestamp, a.event_id, a.userid, a.body, a.descriptiveTime) ==
+           std::tie(b.timestamp, b.event_id, b.userid, b.body, b.descriptiveTime);
 }
 inline bool
 operator!=(const DescInfo &a, const DescInfo &b)
 {
-        return std::tie(a.timestamp, a.event_id, a.userid, a.body, a.descriptiveTime) !=
-               std::tie(b.timestamp, b.event_id, b.userid, b.body, b.descriptiveTime);
+    return std::tie(a.timestamp, a.event_id, a.userid, a.body, a.descriptiveTime) !=
+           std::tie(b.timestamp, b.event_id, b.userid, b.body, b.descriptiveTime);
 }
 
 //! UI info associated with a room.
 struct RoomInfo
 {
-        //! The calculated name of the room.
-        std::string name;
-        //! The topic of the room.
-        std::string topic;
-        //! The calculated avatar url of the room.
-        std::string avatar_url;
-        //! The calculated version of this room set at creation time.
-        std::string version;
-        //! Whether or not the room is an invite.
-        bool is_invite = false;
-        //! Wheter or not the room is a space
-        bool is_space = false;
-        //! Total number of members in the room.
-        size_t member_count = 0;
-        //! Who can access to the room.
-        mtx::events::state::JoinRule join_rule = mtx::events::state::JoinRule::Public;
-        bool guest_access                      = false;
-        //! The list of tags associated with this room
-        std::vector<std::string> tags;
+    //! The calculated name of the room.
+    std::string name;
+    //! The topic of the room.
+    std::string topic;
+    //! The calculated avatar url of the room.
+    std::string avatar_url;
+    //! The calculated version of this room set at creation time.
+    std::string version;
+    //! Whether or not the room is an invite.
+    bool is_invite = false;
+    //! Wheter or not the room is a space
+    bool is_space = false;
+    //! Total number of members in the room.
+    size_t member_count = 0;
+    //! Who can access to the room.
+    mtx::events::state::JoinRule join_rule = mtx::events::state::JoinRule::Public;
+    bool guest_access                      = false;
+    //! The list of tags associated with this room
+    std::vector<std::string> tags;
 };
 
 void
@@ -96,8 +96,8 @@ from_json(const nlohmann::json &j, RoomInfo &info);
 //! Basic information per member.
 struct MemberInfo
 {
-        std::string name;
-        std::string avatar_url;
+    std::string name;
+    std::string avatar_url;
 };
 
 void
@@ -107,13 +107,13 @@ from_json(const nlohmann::json &j, MemberInfo &info);
 
 struct RoomSearchResult
 {
-        std::string room_id;
-        RoomInfo info;
+    std::string room_id;
+    RoomInfo info;
 };
 
 struct ImagePackInfo
 {
-        mtx::events::msc2545::ImagePack pack;
-        std::string source_room;
-        std::string state_key;
+    mtx::events::msc2545::ImagePack pack;
+    std::string source_room;
+    std::string state_key;
 };
diff --git a/src/Cache_p.h b/src/Cache_p.h
index ff2f31e5..a15010e6 100644
--- a/src/Cache_p.h
+++ b/src/Cache_p.h
@@ -32,694 +32,658 @@
 
 class Cache : public QObject
 {
-        Q_OBJECT
+    Q_OBJECT
 
 public:
-        Cache(const QString &userId, QObject *parent = nullptr);
-
-        std::string displayName(const std::string &room_id, const std::string &user_id);
-        QString displayName(const QString &room_id, const QString &user_id);
-        QString avatarUrl(const QString &room_id, const QString &user_id);
-
-        // presence
-        mtx::presence::PresenceState presenceState(const std::string &user_id);
-        std::string statusMessage(const std::string &user_id);
-
-        // user cache stores user keys
-        std::map<std::string, std::optional<UserKeyCache>> getMembersWithKeys(
-          const std::string &room_id,
-          bool verified_only);
-        void updateUserKeys(const std::string &sync_token,
-                            const mtx::responses::QueryKeys &keyQuery);
-        void markUserKeysOutOfDate(lmdb::txn &txn,
-                                   lmdb::dbi &db,
-                                   const std::vector<std::string> &user_ids,
-                                   const std::string &sync_token);
-        void query_keys(const std::string &user_id,
-                        std::function<void(const UserKeyCache &, mtx::http::RequestErr)> cb);
-
-        // device & user verification cache
-        std::optional<UserKeyCache> userKeys(const std::string &user_id);
-        VerificationStatus verificationStatus(const std::string &user_id);
-        void markDeviceVerified(const std::string &user_id, const std::string &device);
-        void markDeviceUnverified(const std::string &user_id, const std::string &device);
-        crypto::Trust roomVerificationStatus(const std::string &room_id);
-
-        std::vector<std::string> joinedRooms();
-
-        QMap<QString, RoomInfo> roomInfo(bool withInvites = true);
-        std::optional<mtx::events::state::CanonicalAlias> getRoomAliases(const std::string &roomid);
-        QHash<QString, RoomInfo> invites();
-        std::optional<RoomInfo> invite(std::string_view roomid);
-        QMap<QString, std::optional<RoomInfo>> spaces();
-
-        //! Calculate & return the name of the room.
-        QString getRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb);
-        //! Get room join rules
-        mtx::events::state::JoinRule getRoomJoinRule(lmdb::txn &txn, lmdb::dbi &statesdb);
-        bool getRoomGuestAccess(lmdb::txn &txn, lmdb::dbi &statesdb);
-        //! Retrieve the topic of the room if any.
-        QString getRoomTopic(lmdb::txn &txn, lmdb::dbi &statesdb);
-        //! Retrieve the room avatar's url if any.
-        QString getRoomAvatarUrl(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb);
-        //! Retrieve the version of the room if any.
-        QString getRoomVersion(lmdb::txn &txn, lmdb::dbi &statesdb);
-        //! Retrieve if the room is a space
-        bool getRoomIsSpace(lmdb::txn &txn, lmdb::dbi &statesdb);
-
-        //! Get a specific state event
-        template<typename T>
-        std::optional<mtx::events::StateEvent<T>> getStateEvent(const std::string &room_id,
-                                                                std::string_view state_key = "")
-        {
-                auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY);
-                return getStateEvent<T>(txn, room_id, state_key);
-        }
-
-        //! retrieve a specific event from account data
-        //! pass empty room_id for global account data
-        std::optional<mtx::events::collections::RoomAccountDataEvents> getAccountData(
-          mtx::events::EventType type,
-          const std::string &room_id = "");
-
-        //! Retrieve member info from a room.
-        std::vector<RoomMember> getMembers(const std::string &room_id,
-                                           std::size_t startIndex = 0,
-                                           std::size_t len        = 30);
-
-        std::vector<RoomMember> getMembersFromInvite(const std::string &room_id,
-                                                     std::size_t startIndex = 0,
-                                                     std::size_t len        = 30);
-        size_t memberCount(const std::string &room_id);
-
-        void saveState(const mtx::responses::Sync &res);
-        bool isInitialized();
-        bool isDatabaseReady() { return databaseReady_ && isInitialized(); }
-
-        std::string nextBatchToken();
-
-        void deleteData();
-
-        void removeInvite(lmdb::txn &txn, const std::string &room_id);
-        void removeInvite(const std::string &room_id);
-        void removeRoom(lmdb::txn &txn, const std::string &roomid);
-        void removeRoom(const std::string &roomid);
-        void setup();
-
-        cache::CacheVersion formatVersion();
-        void setCurrentFormat();
-        bool runMigrations();
-
-        std::vector<QString> roomIds();
-        QMap<QString, mtx::responses::Notifications> getTimelineMentions();
-
-        //! Retrieve all the user ids from a room.
-        std::vector<std::string> roomMembers(const std::string &room_id);
-
-        //! Check if the given user has power leve greater than than
-        //! lowest power level of the given events.
-        bool hasEnoughPowerLevel(const std::vector<mtx::events::EventType> &eventTypes,
+    Cache(const QString &userId, QObject *parent = nullptr);
+
+    std::string displayName(const std::string &room_id, const std::string &user_id);
+    QString displayName(const QString &room_id, const QString &user_id);
+    QString avatarUrl(const QString &room_id, const QString &user_id);
+
+    // presence
+    mtx::presence::PresenceState presenceState(const std::string &user_id);
+    std::string statusMessage(const std::string &user_id);
+
+    // user cache stores user keys
+    std::map<std::string, std::optional<UserKeyCache>> getMembersWithKeys(
+      const std::string &room_id,
+      bool verified_only);
+    void updateUserKeys(const std::string &sync_token, const mtx::responses::QueryKeys &keyQuery);
+    void markUserKeysOutOfDate(lmdb::txn &txn,
+                               lmdb::dbi &db,
+                               const std::vector<std::string> &user_ids,
+                               const std::string &sync_token);
+    void query_keys(const std::string &user_id,
+                    std::function<void(const UserKeyCache &, mtx::http::RequestErr)> cb);
+
+    // device & user verification cache
+    std::optional<UserKeyCache> userKeys(const std::string &user_id);
+    VerificationStatus verificationStatus(const std::string &user_id);
+    void markDeviceVerified(const std::string &user_id, const std::string &device);
+    void markDeviceUnverified(const std::string &user_id, const std::string &device);
+    crypto::Trust roomVerificationStatus(const std::string &room_id);
+
+    std::vector<std::string> joinedRooms();
+
+    QMap<QString, RoomInfo> roomInfo(bool withInvites = true);
+    std::optional<mtx::events::state::CanonicalAlias> getRoomAliases(const std::string &roomid);
+    QHash<QString, RoomInfo> invites();
+    std::optional<RoomInfo> invite(std::string_view roomid);
+    QMap<QString, std::optional<RoomInfo>> spaces();
+
+    //! Calculate & return the name of the room.
+    QString getRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb);
+    //! Get room join rules
+    mtx::events::state::JoinRule getRoomJoinRule(lmdb::txn &txn, lmdb::dbi &statesdb);
+    bool getRoomGuestAccess(lmdb::txn &txn, lmdb::dbi &statesdb);
+    //! Retrieve the topic of the room if any.
+    QString getRoomTopic(lmdb::txn &txn, lmdb::dbi &statesdb);
+    //! Retrieve the room avatar's url if any.
+    QString getRoomAvatarUrl(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb);
+    //! Retrieve the version of the room if any.
+    QString getRoomVersion(lmdb::txn &txn, lmdb::dbi &statesdb);
+    //! Retrieve if the room is a space
+    bool getRoomIsSpace(lmdb::txn &txn, lmdb::dbi &statesdb);
+
+    //! Get a specific state event
+    template<typename T>
+    std::optional<mtx::events::StateEvent<T>> getStateEvent(const std::string &room_id,
+                                                            std::string_view state_key = "")
+    {
+        auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY);
+        return getStateEvent<T>(txn, room_id, state_key);
+    }
+
+    //! retrieve a specific event from account data
+    //! pass empty room_id for global account data
+    std::optional<mtx::events::collections::RoomAccountDataEvents> getAccountData(
+      mtx::events::EventType type,
+      const std::string &room_id = "");
+
+    //! Retrieve member info from a room.
+    std::vector<RoomMember> getMembers(const std::string &room_id,
+                                       std::size_t startIndex = 0,
+                                       std::size_t len        = 30);
+
+    std::vector<RoomMember> getMembersFromInvite(const std::string &room_id,
+                                                 std::size_t startIndex = 0,
+                                                 std::size_t len        = 30);
+    size_t memberCount(const std::string &room_id);
+
+    void saveState(const mtx::responses::Sync &res);
+    bool isInitialized();
+    bool isDatabaseReady() { return databaseReady_ && isInitialized(); }
+
+    std::string nextBatchToken();
+
+    void deleteData();
+
+    void removeInvite(lmdb::txn &txn, const std::string &room_id);
+    void removeInvite(const std::string &room_id);
+    void removeRoom(lmdb::txn &txn, const std::string &roomid);
+    void removeRoom(const std::string &roomid);
+    void setup();
+
+    cache::CacheVersion formatVersion();
+    void setCurrentFormat();
+    bool runMigrations();
+
+    std::vector<QString> roomIds();
+    QMap<QString, mtx::responses::Notifications> getTimelineMentions();
+
+    //! Retrieve all the user ids from a room.
+    std::vector<std::string> roomMembers(const std::string &room_id);
+
+    //! Check if the given user has power leve greater than than
+    //! lowest power level of the given events.
+    bool hasEnoughPowerLevel(const std::vector<mtx::events::EventType> &eventTypes,
+                             const std::string &room_id,
+                             const std::string &user_id);
+
+    //! Adds a user to the read list for the given event.
+    //!
+    //! There should be only one user id present in a receipt list per room.
+    //! The user id should be removed from any other lists.
+    using Receipts = std::map<std::string, std::map<std::string, uint64_t>>;
+    void updateReadReceipt(lmdb::txn &txn, const std::string &room_id, const Receipts &receipts);
+
+    //! Retrieve all the read receipts for the given event id and room.
+    //!
+    //! Returns a map of user ids and the time of the read receipt in milliseconds.
+    using UserReceipts = std::multimap<uint64_t, std::string, std::greater<uint64_t>>;
+    UserReceipts readReceipts(const QString &event_id, const QString &room_id);
+
+    RoomInfo singleRoomInfo(const std::string &room_id);
+    std::vector<std::string> roomsWithStateUpdates(const mtx::responses::Sync &res);
+    std::map<QString, RoomInfo> getRoomInfo(const std::vector<std::string> &rooms);
+
+    //! Calculates which the read status of a room.
+    //! Whether all the events in the timeline have been read.
+    bool calculateRoomReadStatus(const std::string &room_id);
+    void calculateRoomReadStatus();
+
+    void markSentNotification(const std::string &event_id);
+    //! Removes an event from the sent notifications.
+    void removeReadNotification(const std::string &event_id);
+    //! Check if we have sent a desktop notification for the given event id.
+    bool isNotificationSent(const std::string &event_id);
+
+    //! Add all notifications containing a user mention to the db.
+    void saveTimelineMentions(const mtx::responses::Notifications &res);
+
+    //! retrieve events in timeline and related functions
+    struct Messages
+    {
+        mtx::responses::Timeline timeline;
+        uint64_t next_index;
+        bool end_of_cache = false;
+    };
+    Messages getTimelineMessages(lmdb::txn &txn,
                                  const std::string &room_id,
-                                 const std::string &user_id);
-
-        //! Adds a user to the read list for the given event.
-        //!
-        //! There should be only one user id present in a receipt list per room.
-        //! The user id should be removed from any other lists.
-        using Receipts = std::map<std::string, std::map<std::string, uint64_t>>;
-        void updateReadReceipt(lmdb::txn &txn,
-                               const std::string &room_id,
-                               const Receipts &receipts);
-
-        //! Retrieve all the read receipts for the given event id and room.
-        //!
-        //! Returns a map of user ids and the time of the read receipt in milliseconds.
-        using UserReceipts = std::multimap<uint64_t, std::string, std::greater<uint64_t>>;
-        UserReceipts readReceipts(const QString &event_id, const QString &room_id);
-
-        RoomInfo singleRoomInfo(const std::string &room_id);
-        std::vector<std::string> roomsWithStateUpdates(const mtx::responses::Sync &res);
-        std::map<QString, RoomInfo> getRoomInfo(const std::vector<std::string> &rooms);
-
-        //! Calculates which the read status of a room.
-        //! Whether all the events in the timeline have been read.
-        bool calculateRoomReadStatus(const std::string &room_id);
-        void calculateRoomReadStatus();
-
-        void markSentNotification(const std::string &event_id);
-        //! Removes an event from the sent notifications.
-        void removeReadNotification(const std::string &event_id);
-        //! Check if we have sent a desktop notification for the given event id.
-        bool isNotificationSent(const std::string &event_id);
-
-        //! Add all notifications containing a user mention to the db.
-        void saveTimelineMentions(const mtx::responses::Notifications &res);
-
-        //! retrieve events in timeline and related functions
-        struct Messages
-        {
-                mtx::responses::Timeline timeline;
-                uint64_t next_index;
-                bool end_of_cache = false;
-        };
-        Messages getTimelineMessages(lmdb::txn &txn,
-                                     const std::string &room_id,
-                                     uint64_t index = std::numeric_limits<uint64_t>::max(),
-                                     bool forward   = false);
-
-        std::optional<mtx::events::collections::TimelineEvent> getEvent(
-          const std::string &room_id,
-          const std::string &event_id);
-        void storeEvent(const std::string &room_id,
-                        const std::string &event_id,
-                        const mtx::events::collections::TimelineEvent &event);
-        void replaceEvent(const std::string &room_id,
-                          const std::string &event_id,
-                          const mtx::events::collections::TimelineEvent &event);
-        std::vector<std::string> relatedEvents(const std::string &room_id,
-                                               const std::string &event_id);
-
-        struct TimelineRange
-        {
-                uint64_t first, last;
+                                 uint64_t index = std::numeric_limits<uint64_t>::max(),
+                                 bool forward   = false);
+
+    std::optional<mtx::events::collections::TimelineEvent> getEvent(const std::string &room_id,
+                                                                    const std::string &event_id);
+    void storeEvent(const std::string &room_id,
+                    const std::string &event_id,
+                    const mtx::events::collections::TimelineEvent &event);
+    void replaceEvent(const std::string &room_id,
+                      const std::string &event_id,
+                      const mtx::events::collections::TimelineEvent &event);
+    std::vector<std::string> relatedEvents(const std::string &room_id, const std::string &event_id);
+
+    struct TimelineRange
+    {
+        uint64_t first, last;
+    };
+    std::optional<TimelineRange> getTimelineRange(const std::string &room_id);
+    std::optional<uint64_t> getTimelineIndex(const std::string &room_id, std::string_view event_id);
+    std::optional<uint64_t> getEventIndex(const std::string &room_id, std::string_view event_id);
+    std::optional<std::pair<uint64_t, std::string>> lastInvisibleEventAfter(
+      const std::string &room_id,
+      std::string_view event_id);
+    std::optional<std::string> getTimelineEventId(const std::string &room_id, uint64_t index);
+    std::optional<uint64_t> getArrivalIndex(const std::string &room_id, std::string_view event_id);
+
+    std::string previousBatchToken(const std::string &room_id);
+    uint64_t saveOldMessages(const std::string &room_id, const mtx::responses::Messages &res);
+    void savePendingMessage(const std::string &room_id,
+                            const mtx::events::collections::TimelineEvent &message);
+    std::optional<mtx::events::collections::TimelineEvent> firstPendingMessage(
+      const std::string &room_id);
+    void removePendingStatus(const std::string &room_id, const std::string &txn_id);
+
+    //! clear timeline keeping only the latest batch
+    void clearTimeline(const std::string &room_id);
+
+    //! Remove old unused data.
+    void deleteOldMessages();
+    void deleteOldData() noexcept;
+    //! Retrieve all saved room ids.
+    std::vector<std::string> getRoomIds(lmdb::txn &txn);
+    std::vector<std::string> getParentRoomIds(const std::string &room_id);
+    std::vector<std::string> getChildRoomIds(const std::string &room_id);
+
+    std::vector<ImagePackInfo> getImagePacks(const std::string &room_id,
+                                             std::optional<bool> stickers);
+
+    //! Mark a room that uses e2e encryption.
+    void setEncryptedRoom(lmdb::txn &txn, const std::string &room_id);
+    bool isRoomEncrypted(const std::string &room_id);
+    std::optional<mtx::events::state::Encryption> roomEncryptionSettings(
+      const std::string &room_id);
+
+    //! Check if a user is a member of the room.
+    bool isRoomMember(const std::string &user_id, const std::string &room_id);
+
+    //
+    // Outbound Megolm Sessions
+    //
+    void saveOutboundMegolmSession(const std::string &room_id,
+                                   const GroupSessionData &data,
+                                   mtx::crypto::OutboundGroupSessionPtr &session);
+    OutboundGroupSessionDataRef getOutboundMegolmSession(const std::string &room_id);
+    bool outboundMegolmSessionExists(const std::string &room_id) noexcept;
+    void updateOutboundMegolmSession(const std::string &room_id,
+                                     const GroupSessionData &data,
+                                     mtx::crypto::OutboundGroupSessionPtr &session);
+    void dropOutboundMegolmSession(const std::string &room_id);
+
+    void importSessionKeys(const mtx::crypto::ExportedSessionKeys &keys);
+    mtx::crypto::ExportedSessionKeys exportSessionKeys();
+
+    //
+    // Inbound Megolm Sessions
+    //
+    void saveInboundMegolmSession(const MegolmSessionIndex &index,
+                                  mtx::crypto::InboundGroupSessionPtr session,
+                                  const GroupSessionData &data);
+    mtx::crypto::InboundGroupSessionPtr getInboundMegolmSession(const MegolmSessionIndex &index);
+    bool inboundMegolmSessionExists(const MegolmSessionIndex &index);
+    std::optional<GroupSessionData> getMegolmSessionData(const MegolmSessionIndex &index);
+
+    //
+    // Olm Sessions
+    //
+    void saveOlmSession(const std::string &curve25519,
+                        mtx::crypto::OlmSessionPtr session,
+                        uint64_t timestamp);
+    std::vector<std::string> getOlmSessions(const std::string &curve25519);
+    std::optional<mtx::crypto::OlmSessionPtr> getOlmSession(const std::string &curve25519,
+                                                            const std::string &session_id);
+    std::optional<mtx::crypto::OlmSessionPtr> getLatestOlmSession(const std::string &curve25519);
+
+    void saveOlmAccount(const std::string &pickled);
+    std::string restoreOlmAccount();
+
+    void saveBackupVersion(const OnlineBackupVersion &data);
+    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);
+
+    std::string pickleSecret();
+
+    template<class T>
+    constexpr static bool isStateEvent_ =
+      std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>,
+                     mtx::events::StateEvent<decltype(std::declval<T>().content)>>;
+
+    static int compare_state_key(const MDB_val *a, const MDB_val *b)
+    {
+        auto get_skey = [](const MDB_val *v) {
+            return nlohmann::json::parse(
+                     std::string_view(static_cast<const char *>(v->mv_data), v->mv_size))
+              .value("key", "");
         };
-        std::optional<TimelineRange> getTimelineRange(const std::string &room_id);
-        std::optional<uint64_t> getTimelineIndex(const std::string &room_id,
-                                                 std::string_view event_id);
-        std::optional<uint64_t> getEventIndex(const std::string &room_id,
-                                              std::string_view event_id);
-        std::optional<std::pair<uint64_t, std::string>> lastInvisibleEventAfter(
-          const std::string &room_id,
-          std::string_view event_id);
-        std::optional<std::string> getTimelineEventId(const std::string &room_id, uint64_t index);
-        std::optional<uint64_t> getArrivalIndex(const std::string &room_id,
-                                                std::string_view event_id);
-
-        std::string previousBatchToken(const std::string &room_id);
-        uint64_t saveOldMessages(const std::string &room_id, const mtx::responses::Messages &res);
-        void savePendingMessage(const std::string &room_id,
-                                const mtx::events::collections::TimelineEvent &message);
-        std::optional<mtx::events::collections::TimelineEvent> firstPendingMessage(
-          const std::string &room_id);
-        void removePendingStatus(const std::string &room_id, const std::string &txn_id);
-
-        //! clear timeline keeping only the latest batch
-        void clearTimeline(const std::string &room_id);
-
-        //! Remove old unused data.
-        void deleteOldMessages();
-        void deleteOldData() noexcept;
-        //! Retrieve all saved room ids.
-        std::vector<std::string> getRoomIds(lmdb::txn &txn);
-        std::vector<std::string> getParentRoomIds(const std::string &room_id);
-        std::vector<std::string> getChildRoomIds(const std::string &room_id);
-
-        std::vector<ImagePackInfo> getImagePacks(const std::string &room_id,
-                                                 std::optional<bool> stickers);
-
-        //! Mark a room that uses e2e encryption.
-        void setEncryptedRoom(lmdb::txn &txn, const std::string &room_id);
-        bool isRoomEncrypted(const std::string &room_id);
-        std::optional<mtx::events::state::Encryption> roomEncryptionSettings(
-          const std::string &room_id);
-
-        //! Check if a user is a member of the room.
-        bool isRoomMember(const std::string &user_id, const std::string &room_id);
-
-        //
-        // Outbound Megolm Sessions
-        //
-        void saveOutboundMegolmSession(const std::string &room_id,
-                                       const GroupSessionData &data,
-                                       mtx::crypto::OutboundGroupSessionPtr &session);
-        OutboundGroupSessionDataRef getOutboundMegolmSession(const std::string &room_id);
-        bool outboundMegolmSessionExists(const std::string &room_id) noexcept;
-        void updateOutboundMegolmSession(const std::string &room_id,
-                                         const GroupSessionData &data,
-                                         mtx::crypto::OutboundGroupSessionPtr &session);
-        void dropOutboundMegolmSession(const std::string &room_id);
-
-        void importSessionKeys(const mtx::crypto::ExportedSessionKeys &keys);
-        mtx::crypto::ExportedSessionKeys exportSessionKeys();
-
-        //
-        // Inbound Megolm Sessions
-        //
-        void saveInboundMegolmSession(const MegolmSessionIndex &index,
-                                      mtx::crypto::InboundGroupSessionPtr session,
-                                      const GroupSessionData &data);
-        mtx::crypto::InboundGroupSessionPtr getInboundMegolmSession(
-          const MegolmSessionIndex &index);
-        bool inboundMegolmSessionExists(const MegolmSessionIndex &index);
-        std::optional<GroupSessionData> getMegolmSessionData(const MegolmSessionIndex &index);
-
-        //
-        // Olm Sessions
-        //
-        void saveOlmSession(const std::string &curve25519,
-                            mtx::crypto::OlmSessionPtr session,
-                            uint64_t timestamp);
-        std::vector<std::string> getOlmSessions(const std::string &curve25519);
-        std::optional<mtx::crypto::OlmSessionPtr> getOlmSession(const std::string &curve25519,
-                                                                const std::string &session_id);
-        std::optional<mtx::crypto::OlmSessionPtr> getLatestOlmSession(
-          const std::string &curve25519);
-
-        void saveOlmAccount(const std::string &pickled);
-        std::string restoreOlmAccount();
-
-        void saveBackupVersion(const OnlineBackupVersion &data);
-        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);
-
-        std::string pickleSecret();
-
-        template<class T>
-        constexpr static bool isStateEvent_ =
-          std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>,
-                         mtx::events::StateEvent<decltype(std::declval<T>().content)>>;
-
-        static int compare_state_key(const MDB_val *a, const MDB_val *b)
-        {
-                auto get_skey = [](const MDB_val *v) {
-                        return nlohmann::json::parse(
-                                 std::string_view(static_cast<const char *>(v->mv_data),
-                                                  v->mv_size))
-                          .value("key", "");
-                };
-
-                return get_skey(a).compare(get_skey(b));
-        }
+
+        return get_skey(a).compare(get_skey(b));
+    }
 signals:
-        void newReadReceipts(const QString &room_id, const std::vector<QString> &event_ids);
-        void roomReadStatus(const std::map<QString, bool> &status);
-        void removeNotification(const QString &room_id, const QString &event_id);
-        void userKeysUpdate(const std::string &sync_token,
-                            const mtx::responses::QueryKeys &keyQuery);
-        void verificationStatusChanged(const std::string &userid);
-        void secretChanged(const std::string name);
+    void newReadReceipts(const QString &room_id, const std::vector<QString> &event_ids);
+    void roomReadStatus(const std::map<QString, bool> &status);
+    void removeNotification(const QString &room_id, const QString &event_id);
+    void userKeysUpdate(const std::string &sync_token, const mtx::responses::QueryKeys &keyQuery);
+    void verificationStatusChanged(const std::string &userid);
+    void secretChanged(const std::string name);
 
 private:
-        //! Save an invited room.
-        void saveInvite(lmdb::txn &txn,
+    //! Save an invited room.
+    void saveInvite(lmdb::txn &txn,
+                    lmdb::dbi &statesdb,
+                    lmdb::dbi &membersdb,
+                    const mtx::responses::InvitedRoom &room);
+
+    //! Add a notification containing a user mention to the db.
+    void saveTimelineMentions(lmdb::txn &txn,
+                              const std::string &room_id,
+                              const QList<mtx::responses::Notification> &res);
+
+    //! Get timeline items that a user was mentions in for a given room
+    mtx::responses::Notifications getTimelineMentionsForRoom(lmdb::txn &txn,
+                                                             const std::string &room_id);
+
+    QString getInviteRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb);
+    QString getInviteRoomTopic(lmdb::txn &txn, lmdb::dbi &statesdb);
+    QString getInviteRoomAvatarUrl(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb);
+    bool getInviteRoomIsSpace(lmdb::txn &txn, lmdb::dbi &db);
+
+    std::optional<MemberInfo> getMember(const std::string &room_id, const std::string &user_id);
+
+    std::string getLastEventId(lmdb::txn &txn, const std::string &room_id);
+    void saveTimelineMessages(lmdb::txn &txn,
+                              lmdb::dbi &eventsDb,
+                              const std::string &room_id,
+                              const mtx::responses::Timeline &res);
+
+    //! retrieve a specific event from account data
+    //! pass empty room_id for global account data
+    std::optional<mtx::events::collections::RoomAccountDataEvents>
+    getAccountData(lmdb::txn &txn, mtx::events::EventType type, const std::string &room_id);
+    bool isHiddenEvent(lmdb::txn &txn,
+                       mtx::events::collections::TimelineEvents e,
+                       const std::string &room_id);
+
+    //! Remove a room from the cache.
+    // void removeLeftRoom(lmdb::txn &txn, const std::string &room_id);
+    template<class T>
+    void saveStateEvents(lmdb::txn &txn,
+                         lmdb::dbi &statesdb,
+                         lmdb::dbi &stateskeydb,
+                         lmdb::dbi &membersdb,
+                         lmdb::dbi &eventsDb,
+                         const std::string &room_id,
+                         const std::vector<T> &events)
+    {
+        for (const auto &e : events)
+            saveStateEvent(txn, statesdb, stateskeydb, membersdb, eventsDb, room_id, e);
+    }
+
+    template<class T>
+    void saveStateEvent(lmdb::txn &txn,
                         lmdb::dbi &statesdb,
+                        lmdb::dbi &stateskeydb,
                         lmdb::dbi &membersdb,
-                        const mtx::responses::InvitedRoom &room);
-
-        //! Add a notification containing a user mention to the db.
-        void saveTimelineMentions(lmdb::txn &txn,
-                                  const std::string &room_id,
-                                  const QList<mtx::responses::Notification> &res);
-
-        //! Get timeline items that a user was mentions in for a given room
-        mtx::responses::Notifications getTimelineMentionsForRoom(lmdb::txn &txn,
-                                                                 const std::string &room_id);
-
-        QString getInviteRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb);
-        QString getInviteRoomTopic(lmdb::txn &txn, lmdb::dbi &statesdb);
-        QString getInviteRoomAvatarUrl(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb);
-        bool getInviteRoomIsSpace(lmdb::txn &txn, lmdb::dbi &db);
-
-        std::optional<MemberInfo> getMember(const std::string &room_id, const std::string &user_id);
-
-        std::string getLastEventId(lmdb::txn &txn, const std::string &room_id);
-        void saveTimelineMessages(lmdb::txn &txn,
-                                  lmdb::dbi &eventsDb,
-                                  const std::string &room_id,
-                                  const mtx::responses::Timeline &res);
-
-        //! retrieve a specific event from account data
-        //! pass empty room_id for global account data
-        std::optional<mtx::events::collections::RoomAccountDataEvents>
-        getAccountData(lmdb::txn &txn, mtx::events::EventType type, const std::string &room_id);
-        bool isHiddenEvent(lmdb::txn &txn,
-                           mtx::events::collections::TimelineEvents e,
-                           const std::string &room_id);
-
-        //! Remove a room from the cache.
-        // void removeLeftRoom(lmdb::txn &txn, const std::string &room_id);
-        template<class T>
-        void saveStateEvents(lmdb::txn &txn,
-                             lmdb::dbi &statesdb,
-                             lmdb::dbi &stateskeydb,
-                             lmdb::dbi &membersdb,
-                             lmdb::dbi &eventsDb,
-                             const std::string &room_id,
-                             const std::vector<T> &events)
-        {
-                for (const auto &e : events)
-                        saveStateEvent(txn, statesdb, stateskeydb, membersdb, eventsDb, room_id, e);
+                        lmdb::dbi &eventsDb,
+                        const std::string &room_id,
+                        const T &event)
+    {
+        using namespace mtx::events;
+        using namespace mtx::events::state;
+
+        if (auto e = std::get_if<StateEvent<Member>>(&event); e != nullptr) {
+            switch (e->content.membership) {
+            //
+            // We only keep users with invite or join membership.
+            //
+            case Membership::Invite:
+            case Membership::Join: {
+                auto display_name =
+                  e->content.display_name.empty() ? e->state_key : e->content.display_name;
+
+                // Lightweight representation of a member.
+                MemberInfo tmp{display_name, e->content.avatar_url};
+
+                membersdb.put(txn, e->state_key, json(tmp).dump());
+                break;
+            }
+            default: {
+                membersdb.del(txn, e->state_key, "");
+                break;
+            }
+            }
+
+            return;
+        } else if (std::holds_alternative<StateEvent<Encryption>>(event)) {
+            setEncryptedRoom(txn, room_id);
+            return;
         }
 
-        template<class T>
-        void saveStateEvent(lmdb::txn &txn,
-                            lmdb::dbi &statesdb,
-                            lmdb::dbi &stateskeydb,
-                            lmdb::dbi &membersdb,
-                            lmdb::dbi &eventsDb,
-                            const std::string &room_id,
-                            const T &event)
-        {
-                using namespace mtx::events;
-                using namespace mtx::events::state;
-
-                if (auto e = std::get_if<StateEvent<Member>>(&event); e != nullptr) {
-                        switch (e->content.membership) {
-                        //
-                        // We only keep users with invite or join membership.
-                        //
-                        case Membership::Invite:
-                        case Membership::Join: {
-                                auto display_name = e->content.display_name.empty()
-                                                      ? e->state_key
-                                                      : e->content.display_name;
-
-                                // Lightweight representation of a member.
-                                MemberInfo tmp{display_name, e->content.avatar_url};
-
-                                membersdb.put(txn, e->state_key, json(tmp).dump());
-                                break;
-                        }
-                        default: {
-                                membersdb.del(txn, e->state_key, "");
-                                break;
-                        }
-                        }
-
-                        return;
-                } else if (std::holds_alternative<StateEvent<Encryption>>(event)) {
-                        setEncryptedRoom(txn, room_id);
-                        return;
-                }
-
-                std::visit(
-                  [&txn, &statesdb, &stateskeydb, &eventsDb, &membersdb](const auto &e) {
-                          if constexpr (isStateEvent_<decltype(e)>) {
-                                  eventsDb.put(txn, e.event_id, json(e).dump());
-
-                                  if (e.type != EventType::Unsupported) {
-                                          if (std::is_same_v<
-                                                std::remove_cv_t<
-                                                  std::remove_reference_t<decltype(e)>>,
-                                                StateEvent<mtx::events::msg::Redacted>>) {
-                                                  if (e.type == EventType::RoomMember)
-                                                          membersdb.del(txn, e.state_key, "");
-                                                  else if (e.state_key.empty())
-                                                          statesdb.del(txn, to_string(e.type));
-                                                  else
-                                                          stateskeydb.del(
-                                                            txn,
-                                                            to_string(e.type),
-                                                            json::object({
-                                                                           {"key", e.state_key},
-                                                                           {"id", e.event_id},
-                                                                         })
-                                                              .dump());
-                                          } else if (e.state_key.empty())
-                                                  statesdb.put(
-                                                    txn, to_string(e.type), json(e).dump());
-                                          else
-                                                  stateskeydb.put(
-                                                    txn,
-                                                    to_string(e.type),
-                                                    json::object({
-                                                                   {"key", e.state_key},
-                                                                   {"id", e.event_id},
-                                                                 })
-                                                      .dump());
-                                  }
-                          }
-                  },
-                  event);
+        std::visit(
+          [&txn, &statesdb, &stateskeydb, &eventsDb, &membersdb](const auto &e) {
+              if constexpr (isStateEvent_<decltype(e)>) {
+                  eventsDb.put(txn, e.event_id, json(e).dump());
+
+                  if (e.type != EventType::Unsupported) {
+                      if (std::is_same_v<std::remove_cv_t<std::remove_reference_t<decltype(e)>>,
+                                         StateEvent<mtx::events::msg::Redacted>>) {
+                          if (e.type == EventType::RoomMember)
+                              membersdb.del(txn, e.state_key, "");
+                          else if (e.state_key.empty())
+                              statesdb.del(txn, to_string(e.type));
+                          else
+                              stateskeydb.del(txn,
+                                              to_string(e.type),
+                                              json::object({
+                                                             {"key", e.state_key},
+                                                             {"id", e.event_id},
+                                                           })
+                                                .dump());
+                      } else if (e.state_key.empty())
+                          statesdb.put(txn, to_string(e.type), json(e).dump());
+                      else
+                          stateskeydb.put(txn,
+                                          to_string(e.type),
+                                          json::object({
+                                                         {"key", e.state_key},
+                                                         {"id", e.event_id},
+                                                       })
+                                            .dump());
+                  }
+              }
+          },
+          event);
+    }
+
+    template<typename T>
+    std::optional<mtx::events::StateEvent<T>> getStateEvent(lmdb::txn &txn,
+                                                            const std::string &room_id,
+                                                            std::string_view state_key = "")
+    {
+        constexpr auto type = mtx::events::state_content_to_type<T>;
+        static_assert(type != mtx::events::EventType::Unsupported,
+                      "Not a supported type in state events.");
+
+        if (room_id.empty())
+            return std::nullopt;
+        const auto typeStr = to_string(type);
+
+        std::string_view value;
+        if (state_key.empty()) {
+            auto db = getStatesDb(txn, room_id);
+            if (!db.get(txn, typeStr, value)) {
+                return std::nullopt;
+            }
+        } else {
+            auto db                   = getStatesKeyDb(txn, room_id);
+            std::string d             = json::object({{"key", state_key}}).dump();
+            std::string_view data     = d;
+            std::string_view typeStrV = typeStr;
+
+            auto cursor = lmdb::cursor::open(txn, db);
+            if (!cursor.get(typeStrV, data, MDB_GET_BOTH))
+                return std::nullopt;
+
+            try {
+                auto eventsDb = getEventsDb(txn, room_id);
+                if (!eventsDb.get(txn, json::parse(data)["id"].get<std::string>(), value))
+                    return std::nullopt;
+            } catch (std::exception &e) {
+                return std::nullopt;
+            }
         }
 
-        template<typename T>
-        std::optional<mtx::events::StateEvent<T>> getStateEvent(lmdb::txn &txn,
-                                                                const std::string &room_id,
-                                                                std::string_view state_key = "")
-        {
-                constexpr auto type = mtx::events::state_content_to_type<T>;
-                static_assert(type != mtx::events::EventType::Unsupported,
-                              "Not a supported type in state events.");
-
-                if (room_id.empty())
-                        return std::nullopt;
-                const auto typeStr = to_string(type);
-
-                std::string_view value;
-                if (state_key.empty()) {
-                        auto db = getStatesDb(txn, room_id);
-                        if (!db.get(txn, typeStr, value)) {
-                                return std::nullopt;
-                        }
-                } else {
-                        auto db                   = getStatesKeyDb(txn, room_id);
-                        std::string d             = json::object({{"key", state_key}}).dump();
-                        std::string_view data     = d;
-                        std::string_view typeStrV = typeStr;
-
-                        auto cursor = lmdb::cursor::open(txn, db);
-                        if (!cursor.get(typeStrV, data, MDB_GET_BOTH))
-                                return std::nullopt;
-
-                        try {
-                                auto eventsDb = getEventsDb(txn, room_id);
-                                if (!eventsDb.get(
-                                      txn, json::parse(data)["id"].get<std::string>(), value))
-                                        return std::nullopt;
-                        } catch (std::exception &e) {
-                                return std::nullopt;
-                        }
-                }
-
-                try {
-                        return json::parse(value).get<mtx::events::StateEvent<T>>();
-                } catch (std::exception &e) {
-                        return std::nullopt;
-                }
+        try {
+            return json::parse(value).get<mtx::events::StateEvent<T>>();
+        } catch (std::exception &e) {
+            return std::nullopt;
         }
+    }
 
-        template<typename T>
-        std::vector<mtx::events::StateEvent<T>> getStateEventsWithType(lmdb::txn &txn,
-                                                                       const std::string &room_id)
+    template<typename T>
+    std::vector<mtx::events::StateEvent<T>> getStateEventsWithType(lmdb::txn &txn,
+                                                                   const std::string &room_id)
 
-        {
-                constexpr auto type = mtx::events::state_content_to_type<T>;
-                static_assert(type != mtx::events::EventType::Unsupported,
-                              "Not a supported type in state events.");
-
-                if (room_id.empty())
-                        return {};
-
-                std::vector<mtx::events::StateEvent<T>> events;
-
-                {
-                        auto db                   = getStatesKeyDb(txn, room_id);
-                        auto eventsDb             = getEventsDb(txn, room_id);
-                        const auto typeStr        = to_string(type);
-                        std::string_view typeStrV = typeStr;
-                        std::string_view data;
-                        std::string_view value;
-
-                        auto cursor = lmdb::cursor::open(txn, db);
-                        bool first  = true;
-                        if (cursor.get(typeStrV, data, MDB_SET)) {
-                                while (cursor.get(
-                                  typeStrV, data, first ? MDB_FIRST_DUP : MDB_NEXT_DUP)) {
-                                        first = false;
-
-                                        if (eventsDb.get(txn,
-                                                         json::parse(data)["id"].get<std::string>(),
-                                                         value))
-                                                events.push_back(
-                                                  json::parse(value)
-                                                    .get<mtx::events::StateEvent<T>>());
-                                }
-                        }
-                }
+    {
+        constexpr auto type = mtx::events::state_content_to_type<T>;
+        static_assert(type != mtx::events::EventType::Unsupported,
+                      "Not a supported type in state events.");
 
-                return events;
-        }
-        void saveInvites(lmdb::txn &txn,
-                         const std::map<std::string, mtx::responses::InvitedRoom> &rooms);
+        if (room_id.empty())
+            return {};
 
-        void savePresence(
-          lmdb::txn &txn,
-          const std::vector<mtx::events::Event<mtx::events::presence::Presence>> &presenceUpdates);
+        std::vector<mtx::events::StateEvent<T>> events;
 
-        //! Sends signals for the rooms that are removed.
-        void removeLeftRooms(lmdb::txn &txn,
-                             const std::map<std::string, mtx::responses::LeftRoom> &rooms)
         {
-                for (const auto &room : rooms) {
-                        removeRoom(txn, room.first);
-
-                        // Clean up leftover invites.
-                        removeInvite(txn, room.first);
+            auto db                   = getStatesKeyDb(txn, room_id);
+            auto eventsDb             = getEventsDb(txn, room_id);
+            const auto typeStr        = to_string(type);
+            std::string_view typeStrV = typeStr;
+            std::string_view data;
+            std::string_view value;
+
+            auto cursor = lmdb::cursor::open(txn, db);
+            bool first  = true;
+            if (cursor.get(typeStrV, data, MDB_SET)) {
+                while (cursor.get(typeStrV, data, first ? MDB_FIRST_DUP : MDB_NEXT_DUP)) {
+                    first = false;
+
+                    if (eventsDb.get(txn, json::parse(data)["id"].get<std::string>(), value))
+                        events.push_back(json::parse(value).get<mtx::events::StateEvent<T>>());
                 }
+            }
         }
 
-        void updateSpaces(lmdb::txn &txn,
-                          const std::set<std::string> &spaces_with_updates,
-                          std::set<std::string> rooms_with_updates);
-
-        lmdb::dbi getPendingReceiptsDb(lmdb::txn &txn)
-        {
-                return lmdb::dbi::open(txn, "pending_receipts", MDB_CREATE);
-        }
-
-        lmdb::dbi getEventsDb(lmdb::txn &txn, const std::string &room_id)
-        {
-                return lmdb::dbi::open(txn, std::string(room_id + "/events").c_str(), MDB_CREATE);
-        }
-
-        lmdb::dbi getEventOrderDb(lmdb::txn &txn, const std::string &room_id)
-        {
-                return lmdb::dbi::open(
-                  txn, std::string(room_id + "/event_order").c_str(), MDB_CREATE | MDB_INTEGERKEY);
-        }
-
-        // inverse of EventOrderDb
-        lmdb::dbi getEventToOrderDb(lmdb::txn &txn, const std::string &room_id)
-        {
-                return lmdb::dbi::open(
-                  txn, std::string(room_id + "/event2order").c_str(), MDB_CREATE);
-        }
-
-        lmdb::dbi getMessageToOrderDb(lmdb::txn &txn, const std::string &room_id)
-        {
-                return lmdb::dbi::open(
-                  txn, std::string(room_id + "/msg2order").c_str(), MDB_CREATE);
-        }
-
-        lmdb::dbi getOrderToMessageDb(lmdb::txn &txn, const std::string &room_id)
-        {
-                return lmdb::dbi::open(
-                  txn, std::string(room_id + "/order2msg").c_str(), MDB_CREATE | MDB_INTEGERKEY);
-        }
-
-        lmdb::dbi getPendingMessagesDb(lmdb::txn &txn, const std::string &room_id)
-        {
-                return lmdb::dbi::open(
-                  txn, std::string(room_id + "/pending").c_str(), MDB_CREATE | MDB_INTEGERKEY);
-        }
-
-        lmdb::dbi getRelationsDb(lmdb::txn &txn, const std::string &room_id)
-        {
-                return lmdb::dbi::open(
-                  txn, std::string(room_id + "/related").c_str(), MDB_CREATE | MDB_DUPSORT);
-        }
-
-        lmdb::dbi getInviteStatesDb(lmdb::txn &txn, const std::string &room_id)
-        {
-                return lmdb::dbi::open(
-                  txn, std::string(room_id + "/invite_state").c_str(), MDB_CREATE);
-        }
-
-        lmdb::dbi getInviteMembersDb(lmdb::txn &txn, const std::string &room_id)
-        {
-                return lmdb::dbi::open(
-                  txn, std::string(room_id + "/invite_members").c_str(), MDB_CREATE);
-        }
-
-        lmdb::dbi getStatesDb(lmdb::txn &txn, const std::string &room_id)
-        {
-                return lmdb::dbi::open(txn, std::string(room_id + "/state").c_str(), MDB_CREATE);
-        }
-
-        lmdb::dbi getStatesKeyDb(lmdb::txn &txn, const std::string &room_id)
-        {
-                auto db = lmdb::dbi::open(
-                  txn, std::string(room_id + "/state_by_key").c_str(), MDB_CREATE | MDB_DUPSORT);
-                lmdb::dbi_set_dupsort(txn, db, compare_state_key);
-                return db;
-        }
-
-        lmdb::dbi getAccountDataDb(lmdb::txn &txn, const std::string &room_id)
-        {
-                return lmdb::dbi::open(
-                  txn, std::string(room_id + "/account_data").c_str(), MDB_CREATE);
-        }
-
-        lmdb::dbi getMembersDb(lmdb::txn &txn, const std::string &room_id)
-        {
-                return lmdb::dbi::open(txn, std::string(room_id + "/members").c_str(), MDB_CREATE);
-        }
-
-        lmdb::dbi getMentionsDb(lmdb::txn &txn, const std::string &room_id)
-        {
-                return lmdb::dbi::open(txn, std::string(room_id + "/mentions").c_str(), MDB_CREATE);
-        }
+        return events;
+    }
+    void saveInvites(lmdb::txn &txn,
+                     const std::map<std::string, mtx::responses::InvitedRoom> &rooms);
 
-        lmdb::dbi getPresenceDb(lmdb::txn &txn)
-        {
-                return lmdb::dbi::open(txn, "presence", MDB_CREATE);
-        }
+    void savePresence(
+      lmdb::txn &txn,
+      const std::vector<mtx::events::Event<mtx::events::presence::Presence>> &presenceUpdates);
 
-        lmdb::dbi getUserKeysDb(lmdb::txn &txn)
-        {
-                return lmdb::dbi::open(txn, "user_key", MDB_CREATE);
-        }
+    //! Sends signals for the rooms that are removed.
+    void removeLeftRooms(lmdb::txn &txn,
+                         const std::map<std::string, mtx::responses::LeftRoom> &rooms)
+    {
+        for (const auto &room : rooms) {
+            removeRoom(txn, room.first);
 
-        lmdb::dbi getVerificationDb(lmdb::txn &txn)
-        {
-                return lmdb::dbi::open(txn, "verified", MDB_CREATE);
-        }
-
-        //! Retrieves or creates the database that stores the open OLM sessions between our device
-        //! and the given curve25519 key which represents another device.
-        //!
-        //! Each entry is a map from the session_id to the pickled representation of the session.
-        lmdb::dbi getOlmSessionsDb(lmdb::txn &txn, const std::string &curve25519_key)
-        {
-                return lmdb::dbi::open(
-                  txn, std::string("olm_sessions.v2/" + curve25519_key).c_str(), MDB_CREATE);
+            // Clean up leftover invites.
+            removeInvite(txn, room.first);
         }
-
-        QString getDisplayName(const mtx::events::StateEvent<mtx::events::state::Member> &event)
-        {
-                if (!event.content.display_name.empty())
-                        return QString::fromStdString(event.content.display_name);
-
-                return QString::fromStdString(event.state_key);
-        }
-
-        std::optional<VerificationCache> verificationCache(const std::string &user_id,
-                                                           lmdb::txn &txn);
-        VerificationStatus verificationStatus_(const std::string &user_id, lmdb::txn &txn);
-        std::optional<UserKeyCache> userKeys_(const std::string &user_id, lmdb::txn &txn);
-
-        void setNextBatchToken(lmdb::txn &txn, const std::string &token);
-
-        lmdb::env env_;
-        lmdb::dbi syncStateDb_;
-        lmdb::dbi roomsDb_;
-        lmdb::dbi spacesChildrenDb_, spacesParentsDb_;
-        lmdb::dbi invitesDb_;
-        lmdb::dbi readReceiptsDb_;
-        lmdb::dbi notificationsDb_;
-
-        lmdb::dbi devicesDb_;
-        lmdb::dbi deviceKeysDb_;
-
-        lmdb::dbi inboundMegolmSessionDb_;
-        lmdb::dbi outboundMegolmSessionDb_;
-        lmdb::dbi megolmSessionDataDb_;
-
-        lmdb::dbi encryptedRooms_;
-
-        QString localUserId_;
-        QString cacheDirectory_;
-
-        std::string pickle_secret_;
-
-        VerificationStorage verification_storage;
-
-        bool databaseReady_ = false;
+    }
+
+    void updateSpaces(lmdb::txn &txn,
+                      const std::set<std::string> &spaces_with_updates,
+                      std::set<std::string> rooms_with_updates);
+
+    lmdb::dbi getPendingReceiptsDb(lmdb::txn &txn)
+    {
+        return lmdb::dbi::open(txn, "pending_receipts", MDB_CREATE);
+    }
+
+    lmdb::dbi getEventsDb(lmdb::txn &txn, const std::string &room_id)
+    {
+        return lmdb::dbi::open(txn, std::string(room_id + "/events").c_str(), MDB_CREATE);
+    }
+
+    lmdb::dbi getEventOrderDb(lmdb::txn &txn, const std::string &room_id)
+    {
+        return lmdb::dbi::open(
+          txn, std::string(room_id + "/event_order").c_str(), MDB_CREATE | MDB_INTEGERKEY);
+    }
+
+    // inverse of EventOrderDb
+    lmdb::dbi getEventToOrderDb(lmdb::txn &txn, const std::string &room_id)
+    {
+        return lmdb::dbi::open(txn, std::string(room_id + "/event2order").c_str(), MDB_CREATE);
+    }
+
+    lmdb::dbi getMessageToOrderDb(lmdb::txn &txn, const std::string &room_id)
+    {
+        return lmdb::dbi::open(txn, std::string(room_id + "/msg2order").c_str(), MDB_CREATE);
+    }
+
+    lmdb::dbi getOrderToMessageDb(lmdb::txn &txn, const std::string &room_id)
+    {
+        return lmdb::dbi::open(
+          txn, std::string(room_id + "/order2msg").c_str(), MDB_CREATE | MDB_INTEGERKEY);
+    }
+
+    lmdb::dbi getPendingMessagesDb(lmdb::txn &txn, const std::string &room_id)
+    {
+        return lmdb::dbi::open(
+          txn, std::string(room_id + "/pending").c_str(), MDB_CREATE | MDB_INTEGERKEY);
+    }
+
+    lmdb::dbi getRelationsDb(lmdb::txn &txn, const std::string &room_id)
+    {
+        return lmdb::dbi::open(
+          txn, std::string(room_id + "/related").c_str(), MDB_CREATE | MDB_DUPSORT);
+    }
+
+    lmdb::dbi getInviteStatesDb(lmdb::txn &txn, const std::string &room_id)
+    {
+        return lmdb::dbi::open(txn, std::string(room_id + "/invite_state").c_str(), MDB_CREATE);
+    }
+
+    lmdb::dbi getInviteMembersDb(lmdb::txn &txn, const std::string &room_id)
+    {
+        return lmdb::dbi::open(txn, std::string(room_id + "/invite_members").c_str(), MDB_CREATE);
+    }
+
+    lmdb::dbi getStatesDb(lmdb::txn &txn, const std::string &room_id)
+    {
+        return lmdb::dbi::open(txn, std::string(room_id + "/state").c_str(), MDB_CREATE);
+    }
+
+    lmdb::dbi getStatesKeyDb(lmdb::txn &txn, const std::string &room_id)
+    {
+        auto db = lmdb::dbi::open(
+          txn, std::string(room_id + "/state_by_key").c_str(), MDB_CREATE | MDB_DUPSORT);
+        lmdb::dbi_set_dupsort(txn, db, compare_state_key);
+        return db;
+    }
+
+    lmdb::dbi getAccountDataDb(lmdb::txn &txn, const std::string &room_id)
+    {
+        return lmdb::dbi::open(txn, std::string(room_id + "/account_data").c_str(), MDB_CREATE);
+    }
+
+    lmdb::dbi getMembersDb(lmdb::txn &txn, const std::string &room_id)
+    {
+        return lmdb::dbi::open(txn, std::string(room_id + "/members").c_str(), MDB_CREATE);
+    }
+
+    lmdb::dbi getMentionsDb(lmdb::txn &txn, const std::string &room_id)
+    {
+        return lmdb::dbi::open(txn, std::string(room_id + "/mentions").c_str(), MDB_CREATE);
+    }
+
+    lmdb::dbi getPresenceDb(lmdb::txn &txn) { return lmdb::dbi::open(txn, "presence", MDB_CREATE); }
+
+    lmdb::dbi getUserKeysDb(lmdb::txn &txn) { return lmdb::dbi::open(txn, "user_key", MDB_CREATE); }
+
+    lmdb::dbi getVerificationDb(lmdb::txn &txn)
+    {
+        return lmdb::dbi::open(txn, "verified", MDB_CREATE);
+    }
+
+    //! Retrieves or creates the database that stores the open OLM sessions between our device
+    //! and the given curve25519 key which represents another device.
+    //!
+    //! Each entry is a map from the session_id to the pickled representation of the session.
+    lmdb::dbi getOlmSessionsDb(lmdb::txn &txn, const std::string &curve25519_key)
+    {
+        return lmdb::dbi::open(
+          txn, std::string("olm_sessions.v2/" + curve25519_key).c_str(), MDB_CREATE);
+    }
+
+    QString getDisplayName(const mtx::events::StateEvent<mtx::events::state::Member> &event)
+    {
+        if (!event.content.display_name.empty())
+            return QString::fromStdString(event.content.display_name);
+
+        return QString::fromStdString(event.state_key);
+    }
+
+    std::optional<VerificationCache> verificationCache(const std::string &user_id, lmdb::txn &txn);
+    VerificationStatus verificationStatus_(const std::string &user_id, lmdb::txn &txn);
+    std::optional<UserKeyCache> userKeys_(const std::string &user_id, lmdb::txn &txn);
+
+    void setNextBatchToken(lmdb::txn &txn, const std::string &token);
+
+    lmdb::env env_;
+    lmdb::dbi syncStateDb_;
+    lmdb::dbi roomsDb_;
+    lmdb::dbi spacesChildrenDb_, spacesParentsDb_;
+    lmdb::dbi invitesDb_;
+    lmdb::dbi readReceiptsDb_;
+    lmdb::dbi notificationsDb_;
+
+    lmdb::dbi devicesDb_;
+    lmdb::dbi deviceKeysDb_;
+
+    lmdb::dbi inboundMegolmSessionDb_;
+    lmdb::dbi outboundMegolmSessionDb_;
+    lmdb::dbi megolmSessionDataDb_;
+
+    lmdb::dbi encryptedRooms_;
+
+    QString localUserId_;
+    QString cacheDirectory_;
+
+    std::string pickle_secret_;
+
+    VerificationStorage verification_storage;
+
+    bool databaseReady_ = false;
 };
 
 namespace cache {
diff --git a/src/CallDevices.cpp b/src/CallDevices.cpp
index 825d2f72..be185470 100644
--- a/src/CallDevices.cpp
+++ b/src/CallDevices.cpp
@@ -27,20 +27,20 @@ namespace {
 
 struct AudioSource
 {
-        std::string name;
-        GstDevice *device;
+    std::string name;
+    GstDevice *device;
 };
 
 struct VideoSource
 {
-        struct Caps
-        {
-                std::string resolution;
-                std::vector<std::string> frameRates;
-        };
-        std::string name;
-        GstDevice *device;
-        std::vector<Caps> caps;
+    struct Caps
+    {
+        std::string resolution;
+        std::vector<std::string> frameRates;
+    };
+    std::string name;
+    GstDevice *device;
+    std::vector<Caps> caps;
 };
 
 std::vector<AudioSource> audioSources_;
@@ -50,315 +50,304 @@ using FrameRate = std::pair<int, int>;
 std::optional<FrameRate>
 getFrameRate(const GValue *value)
 {
-        if (GST_VALUE_HOLDS_FRACTION(value)) {
-                gint num = gst_value_get_fraction_numerator(value);
-                gint den = gst_value_get_fraction_denominator(value);
-                return FrameRate{num, den};
-        }
-        return std::nullopt;
+    if (GST_VALUE_HOLDS_FRACTION(value)) {
+        gint num = gst_value_get_fraction_numerator(value);
+        gint den = gst_value_get_fraction_denominator(value);
+        return FrameRate{num, den};
+    }
+    return std::nullopt;
 }
 
 void
 addFrameRate(std::vector<std::string> &rates, const FrameRate &rate)
 {
-        constexpr double minimumFrameRate = 15.0;
-        if (static_cast<double>(rate.first) / rate.second >= minimumFrameRate)
-                rates.push_back(std::to_string(rate.first) + "/" + std::to_string(rate.second));
+    constexpr double minimumFrameRate = 15.0;
+    if (static_cast<double>(rate.first) / rate.second >= minimumFrameRate)
+        rates.push_back(std::to_string(rate.first) + "/" + std::to_string(rate.second));
 }
 
 void
 setDefaultDevice(bool isVideo)
 {
-        auto settings = ChatPage::instance()->userSettings();
-        if (isVideo && settings->camera().isEmpty()) {
-                const VideoSource &camera = videoSources_.front();
-                settings->setCamera(QString::fromStdString(camera.name));
-                settings->setCameraResolution(
-                  QString::fromStdString(camera.caps.front().resolution));
-                settings->setCameraFrameRate(
-                  QString::fromStdString(camera.caps.front().frameRates.front()));
-        } else if (!isVideo && settings->microphone().isEmpty()) {
-                settings->setMicrophone(QString::fromStdString(audioSources_.front().name));
-        }
+    auto settings = ChatPage::instance()->userSettings();
+    if (isVideo && settings->camera().isEmpty()) {
+        const VideoSource &camera = videoSources_.front();
+        settings->setCamera(QString::fromStdString(camera.name));
+        settings->setCameraResolution(QString::fromStdString(camera.caps.front().resolution));
+        settings->setCameraFrameRate(
+          QString::fromStdString(camera.caps.front().frameRates.front()));
+    } else if (!isVideo && settings->microphone().isEmpty()) {
+        settings->setMicrophone(QString::fromStdString(audioSources_.front().name));
+    }
 }
 
 void
 addDevice(GstDevice *device)
 {
-        if (!device)
-                return;
-
-        gchar *name  = gst_device_get_display_name(device);
-        gchar *type  = gst_device_get_device_class(device);
-        bool isVideo = !std::strncmp(type, "Video", 5);
-        g_free(type);
-        nhlog::ui()->debug("WebRTC: {} device added: {}", isVideo ? "video" : "audio", name);
-        if (!isVideo) {
-                audioSources_.push_back({name, device});
-                g_free(name);
-                setDefaultDevice(false);
-                return;
-        }
-
-        GstCaps *gstcaps = gst_device_get_caps(device);
-        if (!gstcaps) {
-                nhlog::ui()->debug("WebRTC: unable to get caps for {}", name);
-                g_free(name);
-                return;
-        }
+    if (!device)
+        return;
+
+    gchar *name  = gst_device_get_display_name(device);
+    gchar *type  = gst_device_get_device_class(device);
+    bool isVideo = !std::strncmp(type, "Video", 5);
+    g_free(type);
+    nhlog::ui()->debug("WebRTC: {} device added: {}", isVideo ? "video" : "audio", name);
+    if (!isVideo) {
+        audioSources_.push_back({name, device});
+        g_free(name);
+        setDefaultDevice(false);
+        return;
+    }
 
-        VideoSource source{name, device, {}};
+    GstCaps *gstcaps = gst_device_get_caps(device);
+    if (!gstcaps) {
+        nhlog::ui()->debug("WebRTC: unable to get caps for {}", name);
         g_free(name);
-        guint nCaps = gst_caps_get_size(gstcaps);
-        for (guint i = 0; i < nCaps; ++i) {
-                GstStructure *structure  = gst_caps_get_structure(gstcaps, i);
-                const gchar *struct_name = gst_structure_get_name(structure);
-                if (!std::strcmp(struct_name, "video/x-raw")) {
-                        gint widthpx, heightpx;
-                        if (gst_structure_get(structure,
-                                              "width",
-                                              G_TYPE_INT,
-                                              &widthpx,
-                                              "height",
-                                              G_TYPE_INT,
-                                              &heightpx,
-                                              nullptr)) {
-                                VideoSource::Caps caps;
-                                caps.resolution =
-                                  std::to_string(widthpx) + "x" + std::to_string(heightpx);
-                                const GValue *value =
-                                  gst_structure_get_value(structure, "framerate");
-                                if (auto fr = getFrameRate(value); fr)
-                                        addFrameRate(caps.frameRates, *fr);
-                                else if (GST_VALUE_HOLDS_FRACTION_RANGE(value)) {
-                                        addFrameRate(
-                                          caps.frameRates,
-                                          *getFrameRate(gst_value_get_fraction_range_min(value)));
-                                        addFrameRate(
-                                          caps.frameRates,
-                                          *getFrameRate(gst_value_get_fraction_range_max(value)));
-                                } else if (GST_VALUE_HOLDS_LIST(value)) {
-                                        guint nRates = gst_value_list_get_size(value);
-                                        for (guint j = 0; j < nRates; ++j) {
-                                                const GValue *rate =
-                                                  gst_value_list_get_value(value, j);
-                                                if (auto frate = getFrameRate(rate); frate)
-                                                        addFrameRate(caps.frameRates, *frate);
-                                        }
-                                }
-                                if (!caps.frameRates.empty())
-                                        source.caps.push_back(std::move(caps));
-                        }
+        return;
+    }
+
+    VideoSource source{name, device, {}};
+    g_free(name);
+    guint nCaps = gst_caps_get_size(gstcaps);
+    for (guint i = 0; i < nCaps; ++i) {
+        GstStructure *structure  = gst_caps_get_structure(gstcaps, i);
+        const gchar *struct_name = gst_structure_get_name(structure);
+        if (!std::strcmp(struct_name, "video/x-raw")) {
+            gint widthpx, heightpx;
+            if (gst_structure_get(structure,
+                                  "width",
+                                  G_TYPE_INT,
+                                  &widthpx,
+                                  "height",
+                                  G_TYPE_INT,
+                                  &heightpx,
+                                  nullptr)) {
+                VideoSource::Caps caps;
+                caps.resolution     = std::to_string(widthpx) + "x" + std::to_string(heightpx);
+                const GValue *value = gst_structure_get_value(structure, "framerate");
+                if (auto fr = getFrameRate(value); fr)
+                    addFrameRate(caps.frameRates, *fr);
+                else if (GST_VALUE_HOLDS_FRACTION_RANGE(value)) {
+                    addFrameRate(caps.frameRates,
+                                 *getFrameRate(gst_value_get_fraction_range_min(value)));
+                    addFrameRate(caps.frameRates,
+                                 *getFrameRate(gst_value_get_fraction_range_max(value)));
+                } else if (GST_VALUE_HOLDS_LIST(value)) {
+                    guint nRates = gst_value_list_get_size(value);
+                    for (guint j = 0; j < nRates; ++j) {
+                        const GValue *rate = gst_value_list_get_value(value, j);
+                        if (auto frate = getFrameRate(rate); frate)
+                            addFrameRate(caps.frameRates, *frate);
+                    }
                 }
+                if (!caps.frameRates.empty())
+                    source.caps.push_back(std::move(caps));
+            }
         }
-        gst_caps_unref(gstcaps);
-        videoSources_.push_back(std::move(source));
-        setDefaultDevice(true);
+    }
+    gst_caps_unref(gstcaps);
+    videoSources_.push_back(std::move(source));
+    setDefaultDevice(true);
 }
 
 template<typename T>
 bool
 removeDevice(T &sources, GstDevice *device, bool changed)
 {
-        if (auto it = std::find_if(sources.begin(),
-                                   sources.end(),
-                                   [device](const auto &s) { return s.device == device; });
-            it != sources.end()) {
-                nhlog::ui()->debug(std::string("WebRTC: device ") +
-                                     (changed ? "changed: " : "removed: ") + "{}",
-                                   it->name);
-                gst_object_unref(device);
-                sources.erase(it);
-                return true;
-        }
-        return false;
+    if (auto it = std::find_if(
+          sources.begin(), sources.end(), [device](const auto &s) { return s.device == device; });
+        it != sources.end()) {
+        nhlog::ui()->debug(
+          std::string("WebRTC: device ") + (changed ? "changed: " : "removed: ") + "{}", it->name);
+        gst_object_unref(device);
+        sources.erase(it);
+        return true;
+    }
+    return false;
 }
 
 void
 removeDevice(GstDevice *device, bool changed)
 {
-        if (device) {
-                if (removeDevice(audioSources_, device, changed) ||
-                    removeDevice(videoSources_, device, changed))
-                        return;
-        }
+    if (device) {
+        if (removeDevice(audioSources_, device, changed) ||
+            removeDevice(videoSources_, device, changed))
+            return;
+    }
 }
 
 gboolean
 newBusMessage(GstBus *bus G_GNUC_UNUSED, GstMessage *msg, gpointer user_data G_GNUC_UNUSED)
 {
-        switch (GST_MESSAGE_TYPE(msg)) {
-        case GST_MESSAGE_DEVICE_ADDED: {
-                GstDevice *device;
-                gst_message_parse_device_added(msg, &device);
-                addDevice(device);
-                emit CallDevices::instance().devicesChanged();
-                break;
-        }
-        case GST_MESSAGE_DEVICE_REMOVED: {
-                GstDevice *device;
-                gst_message_parse_device_removed(msg, &device);
-                removeDevice(device, false);
-                emit CallDevices::instance().devicesChanged();
-                break;
-        }
-        case GST_MESSAGE_DEVICE_CHANGED: {
-                GstDevice *device;
-                GstDevice *oldDevice;
-                gst_message_parse_device_changed(msg, &device, &oldDevice);
-                removeDevice(oldDevice, true);
-                addDevice(device);
-                break;
-        }
-        default:
-                break;
-        }
-        return TRUE;
+    switch (GST_MESSAGE_TYPE(msg)) {
+    case GST_MESSAGE_DEVICE_ADDED: {
+        GstDevice *device;
+        gst_message_parse_device_added(msg, &device);
+        addDevice(device);
+        emit CallDevices::instance().devicesChanged();
+        break;
+    }
+    case GST_MESSAGE_DEVICE_REMOVED: {
+        GstDevice *device;
+        gst_message_parse_device_removed(msg, &device);
+        removeDevice(device, false);
+        emit CallDevices::instance().devicesChanged();
+        break;
+    }
+    case GST_MESSAGE_DEVICE_CHANGED: {
+        GstDevice *device;
+        GstDevice *oldDevice;
+        gst_message_parse_device_changed(msg, &device, &oldDevice);
+        removeDevice(oldDevice, true);
+        addDevice(device);
+        break;
+    }
+    default:
+        break;
+    }
+    return TRUE;
 }
 
 template<typename T>
 std::vector<std::string>
 deviceNames(T &sources, const std::string &defaultDevice)
 {
-        std::vector<std::string> ret;
-        ret.reserve(sources.size());
-        for (const auto &s : sources)
-                ret.push_back(s.name);
+    std::vector<std::string> ret;
+    ret.reserve(sources.size());
+    for (const auto &s : sources)
+        ret.push_back(s.name);
 
-        // move default device to top of the list
-        if (auto it = std::find(ret.begin(), ret.end(), defaultDevice); it != ret.end())
-                std::swap(ret.front(), *it);
+    // move default device to top of the list
+    if (auto it = std::find(ret.begin(), ret.end(), defaultDevice); it != ret.end())
+        std::swap(ret.front(), *it);
 
-        return ret;
+    return ret;
 }
 
 std::optional<VideoSource>
 getVideoSource(const std::string &cameraName)
 {
-        if (auto it = std::find_if(videoSources_.cbegin(),
-                                   videoSources_.cend(),
-                                   [&cameraName](const auto &s) { return s.name == cameraName; });
-            it != videoSources_.cend()) {
-                return *it;
-        }
-        return std::nullopt;
+    if (auto it = std::find_if(videoSources_.cbegin(),
+                               videoSources_.cend(),
+                               [&cameraName](const auto &s) { return s.name == cameraName; });
+        it != videoSources_.cend()) {
+        return *it;
+    }
+    return std::nullopt;
 }
 
 std::pair<int, int>
 tokenise(std::string_view str, char delim)
 {
-        std::pair<int, int> ret;
-        ret.first  = std::atoi(str.data());
-        auto pos   = str.find_first_of(delim);
-        ret.second = std::atoi(str.data() + pos + 1);
-        return ret;
+    std::pair<int, int> ret;
+    ret.first  = std::atoi(str.data());
+    auto pos   = str.find_first_of(delim);
+    ret.second = std::atoi(str.data() + pos + 1);
+    return ret;
 }
 }
 
 void
 CallDevices::init()
 {
-        static GstDeviceMonitor *monitor = nullptr;
-        if (!monitor) {
-                monitor       = gst_device_monitor_new();
-                GstCaps *caps = gst_caps_new_empty_simple("audio/x-raw");
-                gst_device_monitor_add_filter(monitor, "Audio/Source", caps);
-                gst_device_monitor_add_filter(monitor, "Audio/Duplex", caps);
-                gst_caps_unref(caps);
-                caps = gst_caps_new_empty_simple("video/x-raw");
-                gst_device_monitor_add_filter(monitor, "Video/Source", caps);
-                gst_device_monitor_add_filter(monitor, "Video/Duplex", caps);
-                gst_caps_unref(caps);
-
-                GstBus *bus = gst_device_monitor_get_bus(monitor);
-                gst_bus_add_watch(bus, newBusMessage, nullptr);
-                gst_object_unref(bus);
-                if (!gst_device_monitor_start(monitor)) {
-                        nhlog::ui()->error("WebRTC: failed to start device monitor");
-                        return;
-                }
+    static GstDeviceMonitor *monitor = nullptr;
+    if (!monitor) {
+        monitor       = gst_device_monitor_new();
+        GstCaps *caps = gst_caps_new_empty_simple("audio/x-raw");
+        gst_device_monitor_add_filter(monitor, "Audio/Source", caps);
+        gst_device_monitor_add_filter(monitor, "Audio/Duplex", caps);
+        gst_caps_unref(caps);
+        caps = gst_caps_new_empty_simple("video/x-raw");
+        gst_device_monitor_add_filter(monitor, "Video/Source", caps);
+        gst_device_monitor_add_filter(monitor, "Video/Duplex", caps);
+        gst_caps_unref(caps);
+
+        GstBus *bus = gst_device_monitor_get_bus(monitor);
+        gst_bus_add_watch(bus, newBusMessage, nullptr);
+        gst_object_unref(bus);
+        if (!gst_device_monitor_start(monitor)) {
+            nhlog::ui()->error("WebRTC: failed to start device monitor");
+            return;
         }
+    }
 }
 
 bool
 CallDevices::haveMic() const
 {
-        return !audioSources_.empty();
+    return !audioSources_.empty();
 }
 
 bool
 CallDevices::haveCamera() const
 {
-        return !videoSources_.empty();
+    return !videoSources_.empty();
 }
 
 std::vector<std::string>
 CallDevices::names(bool isVideo, const std::string &defaultDevice) const
 {
-        return isVideo ? deviceNames(videoSources_, defaultDevice)
-                       : deviceNames(audioSources_, defaultDevice);
+    return isVideo ? deviceNames(videoSources_, defaultDevice)
+                   : deviceNames(audioSources_, defaultDevice);
 }
 
 std::vector<std::string>
 CallDevices::resolutions(const std::string &cameraName) const
 {
-        std::vector<std::string> ret;
-        if (auto s = getVideoSource(cameraName); s) {
-                ret.reserve(s->caps.size());
-                for (const auto &c : s->caps)
-                        ret.push_back(c.resolution);
-        }
-        return ret;
+    std::vector<std::string> ret;
+    if (auto s = getVideoSource(cameraName); s) {
+        ret.reserve(s->caps.size());
+        for (const auto &c : s->caps)
+            ret.push_back(c.resolution);
+    }
+    return ret;
 }
 
 std::vector<std::string>
 CallDevices::frameRates(const std::string &cameraName, const std::string &resolution) const
 {
-        if (auto s = getVideoSource(cameraName); s) {
-                if (auto it =
-                      std::find_if(s->caps.cbegin(),
+    if (auto s = getVideoSource(cameraName); s) {
+        if (auto it = std::find_if(s->caps.cbegin(),
                                    s->caps.cend(),
                                    [&](const auto &c) { return c.resolution == resolution; });
-                    it != s->caps.cend())
-                        return it->frameRates;
-        }
-        return {};
+            it != s->caps.cend())
+            return it->frameRates;
+    }
+    return {};
 }
 
 GstDevice *
 CallDevices::audioDevice() const
 {
-        std::string name = ChatPage::instance()->userSettings()->microphone().toStdString();
-        if (auto it = std::find_if(audioSources_.cbegin(),
-                                   audioSources_.cend(),
-                                   [&name](const auto &s) { return s.name == name; });
-            it != audioSources_.cend()) {
-                nhlog::ui()->debug("WebRTC: microphone: {}", name);
-                return it->device;
-        } else {
-                nhlog::ui()->error("WebRTC: unknown microphone: {}", name);
-                return nullptr;
-        }
+    std::string name = ChatPage::instance()->userSettings()->microphone().toStdString();
+    if (auto it = std::find_if(audioSources_.cbegin(),
+                               audioSources_.cend(),
+                               [&name](const auto &s) { return s.name == name; });
+        it != audioSources_.cend()) {
+        nhlog::ui()->debug("WebRTC: microphone: {}", name);
+        return it->device;
+    } else {
+        nhlog::ui()->error("WebRTC: unknown microphone: {}", name);
+        return nullptr;
+    }
 }
 
 GstDevice *
 CallDevices::videoDevice(std::pair<int, int> &resolution, std::pair<int, int> &frameRate) const
 {
-        auto settings    = ChatPage::instance()->userSettings();
-        std::string name = settings->camera().toStdString();
-        if (auto s = getVideoSource(name); s) {
-                nhlog::ui()->debug("WebRTC: camera: {}", name);
-                resolution = tokenise(settings->cameraResolution().toStdString(), 'x');
-                frameRate  = tokenise(settings->cameraFrameRate().toStdString(), '/');
-                nhlog::ui()->debug(
-                  "WebRTC: camera resolution: {}x{}", resolution.first, resolution.second);
-                nhlog::ui()->debug(
-                  "WebRTC: camera frame rate: {}/{}", frameRate.first, frameRate.second);
-                return s->device;
-        } else {
-                nhlog::ui()->error("WebRTC: unknown camera: {}", name);
-                return nullptr;
-        }
+    auto settings    = ChatPage::instance()->userSettings();
+    std::string name = settings->camera().toStdString();
+    if (auto s = getVideoSource(name); s) {
+        nhlog::ui()->debug("WebRTC: camera: {}", name);
+        resolution = tokenise(settings->cameraResolution().toStdString(), 'x');
+        frameRate  = tokenise(settings->cameraFrameRate().toStdString(), '/');
+        nhlog::ui()->debug("WebRTC: camera resolution: {}x{}", resolution.first, resolution.second);
+        nhlog::ui()->debug("WebRTC: camera frame rate: {}/{}", frameRate.first, frameRate.second);
+        return s->device;
+    } else {
+        nhlog::ui()->error("WebRTC: unknown camera: {}", name);
+        return nullptr;
+    }
 }
 
 #else
@@ -366,31 +355,31 @@ CallDevices::videoDevice(std::pair<int, int> &resolution, std::pair<int, int> &f
 bool
 CallDevices::haveMic() const
 {
-        return false;
+    return false;
 }
 
 bool
 CallDevices::haveCamera() const
 {
-        return false;
+    return false;
 }
 
 std::vector<std::string>
 CallDevices::names(bool, const std::string &) const
 {
-        return {};
+    return {};
 }
 
 std::vector<std::string>
 CallDevices::resolutions(const std::string &) const
 {
-        return {};
+    return {};
 }
 
 std::vector<std::string>
 CallDevices::frameRates(const std::string &, const std::string &) const
 {
-        return {};
+    return {};
 }
 
 #endif
diff --git a/src/CallDevices.h b/src/CallDevices.h
index 69325f97..d30ce644 100644
--- a/src/CallDevices.h
+++ b/src/CallDevices.h
@@ -14,35 +14,34 @@ typedef struct _GstDevice GstDevice;
 
 class CallDevices : public QObject
 {
-        Q_OBJECT
+    Q_OBJECT
 
 public:
-        static CallDevices &instance()
-        {
-                static CallDevices instance;
-                return instance;
-        }
-
-        bool haveMic() const;
-        bool haveCamera() const;
-        std::vector<std::string> names(bool isVideo, const std::string &defaultDevice) const;
-        std::vector<std::string> resolutions(const std::string &cameraName) const;
-        std::vector<std::string> frameRates(const std::string &cameraName,
-                                            const std::string &resolution) const;
+    static CallDevices &instance()
+    {
+        static CallDevices instance;
+        return instance;
+    }
+
+    bool haveMic() const;
+    bool haveCamera() const;
+    std::vector<std::string> names(bool isVideo, const std::string &defaultDevice) const;
+    std::vector<std::string> resolutions(const std::string &cameraName) const;
+    std::vector<std::string> frameRates(const std::string &cameraName,
+                                        const std::string &resolution) const;
 
 signals:
-        void devicesChanged();
+    void devicesChanged();
 
 private:
-        CallDevices();
+    CallDevices();
 
-        friend class WebRTCSession;
-        void init();
-        GstDevice *audioDevice() const;
-        GstDevice *videoDevice(std::pair<int, int> &resolution,
-                               std::pair<int, int> &frameRate) const;
+    friend class WebRTCSession;
+    void init();
+    GstDevice *audioDevice() const;
+    GstDevice *videoDevice(std::pair<int, int> &resolution, std::pair<int, int> &frameRate) const;
 
 public:
-        CallDevices(CallDevices const &) = delete;
-        void operator=(CallDevices const &) = delete;
+    CallDevices(CallDevices const &) = delete;
+    void operator=(CallDevices const &) = delete;
 };
diff --git a/src/CallManager.cpp b/src/CallManager.cpp
index 601c9d6b..0f701b0d 100644
--- a/src/CallManager.cpp
+++ b/src/CallManager.cpp
@@ -54,206 +54,197 @@ CallManager::CallManager(QObject *parent)
   , session_(WebRTCSession::instance())
   , turnServerTimer_(this)
 {
-        qRegisterMetaType<std::vector<mtx::events::msg::CallCandidates::Candidate>>();
-        qRegisterMetaType<mtx::events::msg::CallCandidates::Candidate>();
-        qRegisterMetaType<mtx::responses::TurnServer>();
-
-        connect(
-          &session_,
-          &WebRTCSession::offerCreated,
-          this,
-          [this](const std::string &sdp, const std::vector<CallCandidates::Candidate> &candidates) {
-                  nhlog::ui()->debug("WebRTC: call id: {} - sending offer", callid_);
-                  emit newMessage(roomid_, CallInvite{callid_, sdp, "0", timeoutms_});
-                  emit newMessage(roomid_, CallCandidates{callid_, candidates, "0"});
-                  std::string callid(callid_);
-                  QTimer::singleShot(timeoutms_, this, [this, callid]() {
-                          if (session_.state() == webrtc::State::OFFERSENT && callid == callid_) {
-                                  hangUp(CallHangUp::Reason::InviteTimeOut);
-                                  emit ChatPage::instance()->showNotification(
-                                    "The remote side failed to pick up.");
-                          }
-                  });
+    qRegisterMetaType<std::vector<mtx::events::msg::CallCandidates::Candidate>>();
+    qRegisterMetaType<mtx::events::msg::CallCandidates::Candidate>();
+    qRegisterMetaType<mtx::responses::TurnServer>();
+
+    connect(
+      &session_,
+      &WebRTCSession::offerCreated,
+      this,
+      [this](const std::string &sdp, const std::vector<CallCandidates::Candidate> &candidates) {
+          nhlog::ui()->debug("WebRTC: call id: {} - sending offer", callid_);
+          emit newMessage(roomid_, CallInvite{callid_, sdp, "0", timeoutms_});
+          emit newMessage(roomid_, CallCandidates{callid_, candidates, "0"});
+          std::string callid(callid_);
+          QTimer::singleShot(timeoutms_, this, [this, callid]() {
+              if (session_.state() == webrtc::State::OFFERSENT && callid == callid_) {
+                  hangUp(CallHangUp::Reason::InviteTimeOut);
+                  emit ChatPage::instance()->showNotification("The remote side failed to pick up.");
+              }
           });
+      });
+
+    connect(
+      &session_,
+      &WebRTCSession::answerCreated,
+      this,
+      [this](const std::string &sdp, const std::vector<CallCandidates::Candidate> &candidates) {
+          nhlog::ui()->debug("WebRTC: call id: {} - sending answer", callid_);
+          emit newMessage(roomid_, CallAnswer{callid_, sdp, "0"});
+          emit newMessage(roomid_, CallCandidates{callid_, candidates, "0"});
+      });
+
+    connect(&session_,
+            &WebRTCSession::newICECandidate,
+            this,
+            [this](const CallCandidates::Candidate &candidate) {
+                nhlog::ui()->debug("WebRTC: call id: {} - sending ice candidate", callid_);
+                emit newMessage(roomid_, CallCandidates{callid_, {candidate}, "0"});
+            });
+
+    connect(&turnServerTimer_, &QTimer::timeout, this, &CallManager::retrieveTurnServer);
+
+    connect(
+      this, &CallManager::turnServerRetrieved, this, [this](const mtx::responses::TurnServer &res) {
+          nhlog::net()->info("TURN server(s) retrieved from homeserver:");
+          nhlog::net()->info("username: {}", res.username);
+          nhlog::net()->info("ttl: {} seconds", res.ttl);
+          for (const auto &u : res.uris)
+              nhlog::net()->info("uri: {}", u);
+
+          // Request new credentials close to expiry
+          // See https://tools.ietf.org/html/draft-uberti-behave-turn-rest-00
+          turnURIs_    = getTurnURIs(res);
+          uint32_t ttl = std::max(res.ttl, UINT32_C(3600));
+          if (res.ttl < 3600)
+              nhlog::net()->warn("Setting ttl to 1 hour");
+          turnServerTimer_.setInterval(ttl * 1000 * 0.9);
+      });
+
+    connect(&session_, &WebRTCSession::stateChanged, this, [this](webrtc::State state) {
+        switch (state) {
+        case webrtc::State::DISCONNECTED:
+            playRingtone(QUrl("qrc:/media/media/callend.ogg"), false);
+            clear();
+            break;
+        case webrtc::State::ICEFAILED: {
+            QString error("Call connection failed.");
+            if (turnURIs_.empty())
+                error += " Your homeserver has no configured TURN server.";
+            emit ChatPage::instance()->showNotification(error);
+            hangUp(CallHangUp::Reason::ICEFailed);
+            break;
+        }
+        default:
+            break;
+        }
+        emit newCallState();
+    });
 
-        connect(
-          &session_,
-          &WebRTCSession::answerCreated,
-          this,
-          [this](const std::string &sdp, const std::vector<CallCandidates::Candidate> &candidates) {
-                  nhlog::ui()->debug("WebRTC: call id: {} - sending answer", callid_);
-                  emit newMessage(roomid_, CallAnswer{callid_, sdp, "0"});
-                  emit newMessage(roomid_, CallCandidates{callid_, candidates, "0"});
-          });
+    connect(
+      &CallDevices::instance(), &CallDevices::devicesChanged, this, &CallManager::devicesChanged);
 
-        connect(&session_,
-                &WebRTCSession::newICECandidate,
-                this,
-                [this](const CallCandidates::Candidate &candidate) {
-                        nhlog::ui()->debug("WebRTC: call id: {} - sending ice candidate", callid_);
-                        emit newMessage(roomid_, CallCandidates{callid_, {candidate}, "0"});
-                });
-
-        connect(&turnServerTimer_, &QTimer::timeout, this, &CallManager::retrieveTurnServer);
-
-        connect(this,
-                &CallManager::turnServerRetrieved,
-                this,
-                [this](const mtx::responses::TurnServer &res) {
-                        nhlog::net()->info("TURN server(s) retrieved from homeserver:");
-                        nhlog::net()->info("username: {}", res.username);
-                        nhlog::net()->info("ttl: {} seconds", res.ttl);
-                        for (const auto &u : res.uris)
-                                nhlog::net()->info("uri: {}", u);
-
-                        // Request new credentials close to expiry
-                        // See https://tools.ietf.org/html/draft-uberti-behave-turn-rest-00
-                        turnURIs_    = getTurnURIs(res);
-                        uint32_t ttl = std::max(res.ttl, UINT32_C(3600));
-                        if (res.ttl < 3600)
-                                nhlog::net()->warn("Setting ttl to 1 hour");
-                        turnServerTimer_.setInterval(ttl * 1000 * 0.9);
-                });
-
-        connect(&session_, &WebRTCSession::stateChanged, this, [this](webrtc::State state) {
-                switch (state) {
-                case webrtc::State::DISCONNECTED:
-                        playRingtone(QUrl("qrc:/media/media/callend.ogg"), false);
-                        clear();
-                        break;
-                case webrtc::State::ICEFAILED: {
-                        QString error("Call connection failed.");
-                        if (turnURIs_.empty())
-                                error += " Your homeserver has no configured TURN server.";
-                        emit ChatPage::instance()->showNotification(error);
-                        hangUp(CallHangUp::Reason::ICEFailed);
-                        break;
-                }
+    connect(
+      &player_, &QMediaPlayer::mediaStatusChanged, this, [this](QMediaPlayer::MediaStatus status) {
+          if (status == QMediaPlayer::LoadedMedia)
+              player_.play();
+      });
+
+    connect(&player_,
+            QOverload<QMediaPlayer::Error>::of(&QMediaPlayer::error),
+            [this](QMediaPlayer::Error error) {
+                stopRingtone();
+                switch (error) {
+                case QMediaPlayer::FormatError:
+                case QMediaPlayer::ResourceError:
+                    nhlog::ui()->error("WebRTC: valid ringtone file not found");
+                    break;
+                case QMediaPlayer::AccessDeniedError:
+                    nhlog::ui()->error("WebRTC: access to ringtone file denied");
+                    break;
                 default:
-                        break;
+                    nhlog::ui()->error("WebRTC: unable to play ringtone");
+                    break;
                 }
-                emit newCallState();
-        });
-
-        connect(&CallDevices::instance(),
-                &CallDevices::devicesChanged,
-                this,
-                &CallManager::devicesChanged);
-
-        connect(&player_,
-                &QMediaPlayer::mediaStatusChanged,
-                this,
-                [this](QMediaPlayer::MediaStatus status) {
-                        if (status == QMediaPlayer::LoadedMedia)
-                                player_.play();
-                });
-
-        connect(&player_,
-                QOverload<QMediaPlayer::Error>::of(&QMediaPlayer::error),
-                [this](QMediaPlayer::Error error) {
-                        stopRingtone();
-                        switch (error) {
-                        case QMediaPlayer::FormatError:
-                        case QMediaPlayer::ResourceError:
-                                nhlog::ui()->error("WebRTC: valid ringtone file not found");
-                                break;
-                        case QMediaPlayer::AccessDeniedError:
-                                nhlog::ui()->error("WebRTC: access to ringtone file denied");
-                                break;
-                        default:
-                                nhlog::ui()->error("WebRTC: unable to play ringtone");
-                                break;
-                        }
-                });
+            });
 }
 
 void
 CallManager::sendInvite(const QString &roomid, CallType callType, unsigned int windowIndex)
 {
-        if (isOnCall())
-                return;
-        if (callType == CallType::SCREEN) {
-                if (!screenShareSupported())
-                        return;
-                if (windows_.empty() || windowIndex >= windows_.size()) {
-                        nhlog::ui()->error("WebRTC: window index out of range");
-                        return;
-                }
-        }
-
-        auto roomInfo = cache::singleRoomInfo(roomid.toStdString());
-        if (roomInfo.member_count != 2) {
-                emit ChatPage::instance()->showNotification("Calls are limited to 1:1 rooms.");
-                return;
-        }
-
-        std::string errorMessage;
-        if (!session_.havePlugins(false, &errorMessage) ||
-            ((callType == CallType::VIDEO || callType == CallType::SCREEN) &&
-             !session_.havePlugins(true, &errorMessage))) {
-                emit ChatPage::instance()->showNotification(QString::fromStdString(errorMessage));
-                return;
-        }
-
-        callType_ = callType;
-        roomid_   = roomid;
-        session_.setTurnServers(turnURIs_);
-        generateCallID();
-        std::string strCallType = callType_ == CallType::VOICE
-                                    ? "voice"
-                                    : (callType_ == CallType::VIDEO ? "video" : "screen");
-        nhlog::ui()->debug("WebRTC: call id: {} - creating {} invite", callid_, strCallType);
-        std::vector<RoomMember> members(cache::getMembers(roomid.toStdString()));
-        const RoomMember &callee =
-          members.front().user_id == utils::localUser() ? members.back() : members.front();
-        callParty_ = callee.user_id;
-        callPartyDisplayName_ =
-          callee.display_name.isEmpty() ? callee.user_id : callee.display_name;
-        callPartyAvatarUrl_ = QString::fromStdString(roomInfo.avatar_url);
-        emit newInviteState();
-        playRingtone(QUrl("qrc:/media/media/ringback.ogg"), true);
-        if (!session_.createOffer(
-              callType, callType == CallType::SCREEN ? windows_[windowIndex].second : 0)) {
-                emit ChatPage::instance()->showNotification("Problem setting up call.");
-                endCall();
+    if (isOnCall())
+        return;
+    if (callType == CallType::SCREEN) {
+        if (!screenShareSupported())
+            return;
+        if (windows_.empty() || windowIndex >= windows_.size()) {
+            nhlog::ui()->error("WebRTC: window index out of range");
+            return;
         }
+    }
+
+    auto roomInfo = cache::singleRoomInfo(roomid.toStdString());
+    if (roomInfo.member_count != 2) {
+        emit ChatPage::instance()->showNotification("Calls are limited to 1:1 rooms.");
+        return;
+    }
+
+    std::string errorMessage;
+    if (!session_.havePlugins(false, &errorMessage) ||
+        ((callType == CallType::VIDEO || callType == CallType::SCREEN) &&
+         !session_.havePlugins(true, &errorMessage))) {
+        emit ChatPage::instance()->showNotification(QString::fromStdString(errorMessage));
+        return;
+    }
+
+    callType_ = callType;
+    roomid_   = roomid;
+    session_.setTurnServers(turnURIs_);
+    generateCallID();
+    std::string strCallType =
+      callType_ == CallType::VOICE ? "voice" : (callType_ == CallType::VIDEO ? "video" : "screen");
+    nhlog::ui()->debug("WebRTC: call id: {} - creating {} invite", callid_, strCallType);
+    std::vector<RoomMember> members(cache::getMembers(roomid.toStdString()));
+    const RoomMember &callee =
+      members.front().user_id == utils::localUser() ? members.back() : members.front();
+    callParty_            = callee.user_id;
+    callPartyDisplayName_ = callee.display_name.isEmpty() ? callee.user_id : callee.display_name;
+    callPartyAvatarUrl_   = QString::fromStdString(roomInfo.avatar_url);
+    emit newInviteState();
+    playRingtone(QUrl("qrc:/media/media/ringback.ogg"), true);
+    if (!session_.createOffer(callType,
+                              callType == CallType::SCREEN ? windows_[windowIndex].second : 0)) {
+        emit ChatPage::instance()->showNotification("Problem setting up call.");
+        endCall();
+    }
 }
 
 namespace {
 std::string
 callHangUpReasonString(CallHangUp::Reason reason)
 {
-        switch (reason) {
-        case CallHangUp::Reason::ICEFailed:
-                return "ICE failed";
-        case CallHangUp::Reason::InviteTimeOut:
-                return "Invite time out";
-        default:
-                return "User";
-        }
+    switch (reason) {
+    case CallHangUp::Reason::ICEFailed:
+        return "ICE failed";
+    case CallHangUp::Reason::InviteTimeOut:
+        return "Invite time out";
+    default:
+        return "User";
+    }
 }
 }
 
 void
 CallManager::hangUp(CallHangUp::Reason reason)
 {
-        if (!callid_.empty()) {
-                nhlog::ui()->debug(
-                  "WebRTC: call id: {} - hanging up ({})", callid_, callHangUpReasonString(reason));
-                emit newMessage(roomid_, CallHangUp{callid_, "0", reason});
-                endCall();
-        }
+    if (!callid_.empty()) {
+        nhlog::ui()->debug(
+          "WebRTC: call id: {} - hanging up ({})", callid_, callHangUpReasonString(reason));
+        emit newMessage(roomid_, CallHangUp{callid_, "0", reason});
+        endCall();
+    }
 }
 
 void
 CallManager::syncEvent(const mtx::events::collections::TimelineEvents &event)
 {
 #ifdef GSTREAMER_AVAILABLE
-        if (handleEvent<CallInvite>(event) || handleEvent<CallCandidates>(event) ||
-            handleEvent<CallAnswer>(event) || handleEvent<CallHangUp>(event))
-                return;
+    if (handleEvent<CallInvite>(event) || handleEvent<CallCandidates>(event) ||
+        handleEvent<CallAnswer>(event) || handleEvent<CallHangUp>(event))
+        return;
 #else
-        (void)event;
+    (void)event;
 #endif
 }
 
@@ -261,325 +252,321 @@ template<typename T>
 bool
 CallManager::handleEvent(const mtx::events::collections::TimelineEvents &event)
 {
-        if (std::holds_alternative<RoomEvent<T>>(event)) {
-                handleEvent(std::get<RoomEvent<T>>(event));
-                return true;
-        }
-        return false;
+    if (std::holds_alternative<RoomEvent<T>>(event)) {
+        handleEvent(std::get<RoomEvent<T>>(event));
+        return true;
+    }
+    return false;
 }
 
 void
 CallManager::handleEvent(const RoomEvent<CallInvite> &callInviteEvent)
 {
-        const char video[]     = "m=video";
-        const std::string &sdp = callInviteEvent.content.sdp;
-        bool isVideo           = std::search(sdp.cbegin(),
-                                   sdp.cend(),
-                                   std::cbegin(video),
-                                   std::cend(video) - 1,
-                                   [](unsigned char c1, unsigned char c2) {
-                                           return std::tolower(c1) == std::tolower(c2);
-                                   }) != sdp.cend();
-
-        nhlog::ui()->debug("WebRTC: call id: {} - incoming {} CallInvite from {}",
-                           callInviteEvent.content.call_id,
-                           (isVideo ? "video" : "voice"),
-                           callInviteEvent.sender);
-
-        if (callInviteEvent.content.call_id.empty())
-                return;
-
-        auto roomInfo = cache::singleRoomInfo(callInviteEvent.room_id);
-        if (isOnCall() || roomInfo.member_count != 2) {
-                emit newMessage(QString::fromStdString(callInviteEvent.room_id),
-                                CallHangUp{callInviteEvent.content.call_id,
-                                           "0",
-                                           CallHangUp::Reason::InviteTimeOut});
-                return;
-        }
-
-        const QString &ringtone = ChatPage::instance()->userSettings()->ringtone();
-        if (ringtone != "Mute")
-                playRingtone(ringtone == "Default" ? QUrl("qrc:/media/media/ring.ogg")
-                                                   : QUrl::fromLocalFile(ringtone),
-                             true);
-        roomid_ = QString::fromStdString(callInviteEvent.room_id);
-        callid_ = callInviteEvent.content.call_id;
-        remoteICECandidates_.clear();
-
-        std::vector<RoomMember> members(cache::getMembers(callInviteEvent.room_id));
-        const RoomMember &caller =
-          members.front().user_id == utils::localUser() ? members.back() : members.front();
-        callParty_ = caller.user_id;
-        callPartyDisplayName_ =
-          caller.display_name.isEmpty() ? caller.user_id : caller.display_name;
-        callPartyAvatarUrl_ = QString::fromStdString(roomInfo.avatar_url);
-
-        haveCallInvite_ = true;
-        callType_       = isVideo ? CallType::VIDEO : CallType::VOICE;
-        inviteSDP_      = callInviteEvent.content.sdp;
-        emit newInviteState();
+    const char video[]     = "m=video";
+    const std::string &sdp = callInviteEvent.content.sdp;
+    bool isVideo           = std::search(sdp.cbegin(),
+                               sdp.cend(),
+                               std::cbegin(video),
+                               std::cend(video) - 1,
+                               [](unsigned char c1, unsigned char c2) {
+                                   return std::tolower(c1) == std::tolower(c2);
+                               }) != sdp.cend();
+
+    nhlog::ui()->debug("WebRTC: call id: {} - incoming {} CallInvite from {}",
+                       callInviteEvent.content.call_id,
+                       (isVideo ? "video" : "voice"),
+                       callInviteEvent.sender);
+
+    if (callInviteEvent.content.call_id.empty())
+        return;
+
+    auto roomInfo = cache::singleRoomInfo(callInviteEvent.room_id);
+    if (isOnCall() || roomInfo.member_count != 2) {
+        emit newMessage(
+          QString::fromStdString(callInviteEvent.room_id),
+          CallHangUp{callInviteEvent.content.call_id, "0", CallHangUp::Reason::InviteTimeOut});
+        return;
+    }
+
+    const QString &ringtone = ChatPage::instance()->userSettings()->ringtone();
+    if (ringtone != "Mute")
+        playRingtone(ringtone == "Default" ? QUrl("qrc:/media/media/ring.ogg")
+                                           : QUrl::fromLocalFile(ringtone),
+                     true);
+    roomid_ = QString::fromStdString(callInviteEvent.room_id);
+    callid_ = callInviteEvent.content.call_id;
+    remoteICECandidates_.clear();
+
+    std::vector<RoomMember> members(cache::getMembers(callInviteEvent.room_id));
+    const RoomMember &caller =
+      members.front().user_id == utils::localUser() ? members.back() : members.front();
+    callParty_            = caller.user_id;
+    callPartyDisplayName_ = caller.display_name.isEmpty() ? caller.user_id : caller.display_name;
+    callPartyAvatarUrl_   = QString::fromStdString(roomInfo.avatar_url);
+
+    haveCallInvite_ = true;
+    callType_       = isVideo ? CallType::VIDEO : CallType::VOICE;
+    inviteSDP_      = callInviteEvent.content.sdp;
+    emit newInviteState();
 }
 
 void
 CallManager::acceptInvite()
 {
-        if (!haveCallInvite_)
-                return;
-
-        stopRingtone();
-        std::string errorMessage;
-        if (!session_.havePlugins(false, &errorMessage) ||
-            (callType_ == CallType::VIDEO && !session_.havePlugins(true, &errorMessage))) {
-                emit ChatPage::instance()->showNotification(QString::fromStdString(errorMessage));
-                hangUp();
-                return;
-        }
-
-        session_.setTurnServers(turnURIs_);
-        if (!session_.acceptOffer(inviteSDP_)) {
-                emit ChatPage::instance()->showNotification("Problem setting up call.");
-                hangUp();
-                return;
-        }
-        session_.acceptICECandidates(remoteICECandidates_);
-        remoteICECandidates_.clear();
-        haveCallInvite_ = false;
-        emit newInviteState();
+    if (!haveCallInvite_)
+        return;
+
+    stopRingtone();
+    std::string errorMessage;
+    if (!session_.havePlugins(false, &errorMessage) ||
+        (callType_ == CallType::VIDEO && !session_.havePlugins(true, &errorMessage))) {
+        emit ChatPage::instance()->showNotification(QString::fromStdString(errorMessage));
+        hangUp();
+        return;
+    }
+
+    session_.setTurnServers(turnURIs_);
+    if (!session_.acceptOffer(inviteSDP_)) {
+        emit ChatPage::instance()->showNotification("Problem setting up call.");
+        hangUp();
+        return;
+    }
+    session_.acceptICECandidates(remoteICECandidates_);
+    remoteICECandidates_.clear();
+    haveCallInvite_ = false;
+    emit newInviteState();
 }
 
 void
 CallManager::handleEvent(const RoomEvent<CallCandidates> &callCandidatesEvent)
 {
-        if (callCandidatesEvent.sender == utils::localUser().toStdString())
-                return;
-
-        nhlog::ui()->debug("WebRTC: call id: {} - incoming CallCandidates from {}",
-                           callCandidatesEvent.content.call_id,
-                           callCandidatesEvent.sender);
-
-        if (callid_ == callCandidatesEvent.content.call_id) {
-                if (isOnCall())
-                        session_.acceptICECandidates(callCandidatesEvent.content.candidates);
-                else {
-                        // CallInvite has been received and we're awaiting localUser to accept or
-                        // reject the call
-                        for (const auto &c : callCandidatesEvent.content.candidates)
-                                remoteICECandidates_.push_back(c);
-                }
+    if (callCandidatesEvent.sender == utils::localUser().toStdString())
+        return;
+
+    nhlog::ui()->debug("WebRTC: call id: {} - incoming CallCandidates from {}",
+                       callCandidatesEvent.content.call_id,
+                       callCandidatesEvent.sender);
+
+    if (callid_ == callCandidatesEvent.content.call_id) {
+        if (isOnCall())
+            session_.acceptICECandidates(callCandidatesEvent.content.candidates);
+        else {
+            // CallInvite has been received and we're awaiting localUser to accept or
+            // reject the call
+            for (const auto &c : callCandidatesEvent.content.candidates)
+                remoteICECandidates_.push_back(c);
         }
+    }
 }
 
 void
 CallManager::handleEvent(const RoomEvent<CallAnswer> &callAnswerEvent)
 {
-        nhlog::ui()->debug("WebRTC: call id: {} - incoming CallAnswer from {}",
-                           callAnswerEvent.content.call_id,
-                           callAnswerEvent.sender);
-
-        if (callAnswerEvent.sender == utils::localUser().toStdString() &&
-            callid_ == callAnswerEvent.content.call_id) {
-                if (!isOnCall()) {
-                        emit ChatPage::instance()->showNotification(
-                          "Call answered on another device.");
-                        stopRingtone();
-                        haveCallInvite_ = false;
-                        emit newInviteState();
-                }
-                return;
+    nhlog::ui()->debug("WebRTC: call id: {} - incoming CallAnswer from {}",
+                       callAnswerEvent.content.call_id,
+                       callAnswerEvent.sender);
+
+    if (callAnswerEvent.sender == utils::localUser().toStdString() &&
+        callid_ == callAnswerEvent.content.call_id) {
+        if (!isOnCall()) {
+            emit ChatPage::instance()->showNotification("Call answered on another device.");
+            stopRingtone();
+            haveCallInvite_ = false;
+            emit newInviteState();
         }
+        return;
+    }
 
-        if (isOnCall() && callid_ == callAnswerEvent.content.call_id) {
-                stopRingtone();
-                if (!session_.acceptAnswer(callAnswerEvent.content.sdp)) {
-                        emit ChatPage::instance()->showNotification("Problem setting up call.");
-                        hangUp();
-                }
+    if (isOnCall() && callid_ == callAnswerEvent.content.call_id) {
+        stopRingtone();
+        if (!session_.acceptAnswer(callAnswerEvent.content.sdp)) {
+            emit ChatPage::instance()->showNotification("Problem setting up call.");
+            hangUp();
         }
+    }
 }
 
 void
 CallManager::handleEvent(const RoomEvent<CallHangUp> &callHangUpEvent)
 {
-        nhlog::ui()->debug("WebRTC: call id: {} - incoming CallHangUp ({}) from {}",
-                           callHangUpEvent.content.call_id,
-                           callHangUpReasonString(callHangUpEvent.content.reason),
-                           callHangUpEvent.sender);
+    nhlog::ui()->debug("WebRTC: call id: {} - incoming CallHangUp ({}) from {}",
+                       callHangUpEvent.content.call_id,
+                       callHangUpReasonString(callHangUpEvent.content.reason),
+                       callHangUpEvent.sender);
 
-        if (callid_ == callHangUpEvent.content.call_id)
-                endCall();
+    if (callid_ == callHangUpEvent.content.call_id)
+        endCall();
 }
 
 void
 CallManager::toggleMicMute()
 {
-        session_.toggleMicMute();
-        emit micMuteChanged();
+    session_.toggleMicMute();
+    emit micMuteChanged();
 }
 
 bool
 CallManager::callsSupported()
 {
 #ifdef GSTREAMER_AVAILABLE
-        return true;
+    return true;
 #else
-        return false;
+    return false;
 #endif
 }
 
 bool
 CallManager::screenShareSupported()
 {
-        return std::getenv("DISPLAY") && !std::getenv("WAYLAND_DISPLAY");
+    return std::getenv("DISPLAY") && !std::getenv("WAYLAND_DISPLAY");
 }
 
 QStringList
 CallManager::devices(bool isVideo) const
 {
-        QStringList ret;
-        const QString &defaultDevice = isVideo ? ChatPage::instance()->userSettings()->camera()
-                                               : ChatPage::instance()->userSettings()->microphone();
-        std::vector<std::string> devices =
-          CallDevices::instance().names(isVideo, defaultDevice.toStdString());
-        ret.reserve(devices.size());
-        std::transform(devices.cbegin(),
-                       devices.cend(),
-                       std::back_inserter(ret),
-                       [](const auto &d) { return QString::fromStdString(d); });
-
-        return ret;
+    QStringList ret;
+    const QString &defaultDevice = isVideo ? ChatPage::instance()->userSettings()->camera()
+                                           : ChatPage::instance()->userSettings()->microphone();
+    std::vector<std::string> devices =
+      CallDevices::instance().names(isVideo, defaultDevice.toStdString());
+    ret.reserve(devices.size());
+    std::transform(devices.cbegin(), devices.cend(), std::back_inserter(ret), [](const auto &d) {
+        return QString::fromStdString(d);
+    });
+
+    return ret;
 }
 
 void
 CallManager::generateCallID()
 {
-        using namespace std::chrono;
-        uint64_t ms = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
-        callid_     = "c" + std::to_string(ms);
+    using namespace std::chrono;
+    uint64_t ms = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
+    callid_     = "c" + std::to_string(ms);
 }
 
 void
 CallManager::clear()
 {
-        roomid_.clear();
-        callParty_.clear();
-        callPartyDisplayName_.clear();
-        callPartyAvatarUrl_.clear();
-        callid_.clear();
-        callType_       = CallType::VOICE;
-        haveCallInvite_ = false;
-        emit newInviteState();
-        inviteSDP_.clear();
-        remoteICECandidates_.clear();
+    roomid_.clear();
+    callParty_.clear();
+    callPartyDisplayName_.clear();
+    callPartyAvatarUrl_.clear();
+    callid_.clear();
+    callType_       = CallType::VOICE;
+    haveCallInvite_ = false;
+    emit newInviteState();
+    inviteSDP_.clear();
+    remoteICECandidates_.clear();
 }
 
 void
 CallManager::endCall()
 {
-        stopRingtone();
-        session_.end();
-        clear();
+    stopRingtone();
+    session_.end();
+    clear();
 }
 
 void
 CallManager::refreshTurnServer()
 {
-        turnURIs_.clear();
-        turnServerTimer_.start(2000);
+    turnURIs_.clear();
+    turnServerTimer_.start(2000);
 }
 
 void
 CallManager::retrieveTurnServer()
 {
-        http::client()->get_turn_server(
-          [this](const mtx::responses::TurnServer &res, mtx::http::RequestErr err) {
-                  if (err) {
-                          turnServerTimer_.setInterval(5000);
-                          return;
-                  }
-                  emit turnServerRetrieved(res);
-          });
+    http::client()->get_turn_server(
+      [this](const mtx::responses::TurnServer &res, mtx::http::RequestErr err) {
+          if (err) {
+              turnServerTimer_.setInterval(5000);
+              return;
+          }
+          emit turnServerRetrieved(res);
+      });
 }
 
 void
 CallManager::playRingtone(const QUrl &ringtone, bool repeat)
 {
-        static QMediaPlaylist playlist;
-        playlist.clear();
-        playlist.setPlaybackMode(repeat ? QMediaPlaylist::CurrentItemInLoop
-                                        : QMediaPlaylist::CurrentItemOnce);
-        playlist.addMedia(ringtone);
-        player_.setVolume(100);
-        player_.setPlaylist(&playlist);
+    static QMediaPlaylist playlist;
+    playlist.clear();
+    playlist.setPlaybackMode(repeat ? QMediaPlaylist::CurrentItemInLoop
+                                    : QMediaPlaylist::CurrentItemOnce);
+    playlist.addMedia(ringtone);
+    player_.setVolume(100);
+    player_.setPlaylist(&playlist);
 }
 
 void
 CallManager::stopRingtone()
 {
-        player_.setPlaylist(nullptr);
+    player_.setPlaylist(nullptr);
 }
 
 QStringList
 CallManager::windowList()
 {
-        windows_.clear();
-        windows_.push_back({tr("Entire screen"), 0});
+    windows_.clear();
+    windows_.push_back({tr("Entire screen"), 0});
 
 #ifdef XCB_AVAILABLE
-        std::unique_ptr<xcb_connection_t, std::function<void(xcb_connection_t *)>> connection(
-          xcb_connect(nullptr, nullptr), [](xcb_connection_t *c) { xcb_disconnect(c); });
-        if (xcb_connection_has_error(connection.get())) {
-                nhlog::ui()->error("Failed to connect to X server");
-                return {};
-        }
-
-        xcb_ewmh_connection_t ewmh;
-        if (!xcb_ewmh_init_atoms_replies(
-              &ewmh, xcb_ewmh_init_atoms(connection.get(), &ewmh), nullptr)) {
-                nhlog::ui()->error("Failed to connect to EWMH server");
-                return {};
+    std::unique_ptr<xcb_connection_t, std::function<void(xcb_connection_t *)>> connection(
+      xcb_connect(nullptr, nullptr), [](xcb_connection_t *c) { xcb_disconnect(c); });
+    if (xcb_connection_has_error(connection.get())) {
+        nhlog::ui()->error("Failed to connect to X server");
+        return {};
+    }
+
+    xcb_ewmh_connection_t ewmh;
+    if (!xcb_ewmh_init_atoms_replies(
+          &ewmh, xcb_ewmh_init_atoms(connection.get(), &ewmh), nullptr)) {
+        nhlog::ui()->error("Failed to connect to EWMH server");
+        return {};
+    }
+    std::unique_ptr<xcb_ewmh_connection_t, std::function<void(xcb_ewmh_connection_t *)>>
+      ewmhconnection(&ewmh, [](xcb_ewmh_connection_t *c) { xcb_ewmh_connection_wipe(c); });
+
+    for (int i = 0; i < ewmh.nb_screens; i++) {
+        xcb_ewmh_get_windows_reply_t clients;
+        if (!xcb_ewmh_get_client_list_reply(
+              &ewmh, xcb_ewmh_get_client_list(&ewmh, i), &clients, nullptr)) {
+            nhlog::ui()->error("Failed to request window list");
+            return {};
         }
-        std::unique_ptr<xcb_ewmh_connection_t, std::function<void(xcb_ewmh_connection_t *)>>
-          ewmhconnection(&ewmh, [](xcb_ewmh_connection_t *c) { xcb_ewmh_connection_wipe(c); });
-
-        for (int i = 0; i < ewmh.nb_screens; i++) {
-                xcb_ewmh_get_windows_reply_t clients;
-                if (!xcb_ewmh_get_client_list_reply(
-                      &ewmh, xcb_ewmh_get_client_list(&ewmh, i), &clients, nullptr)) {
-                        nhlog::ui()->error("Failed to request window list");
-                        return {};
-                }
 
-                for (uint32_t w = 0; w < clients.windows_len; w++) {
-                        xcb_window_t window = clients.windows[w];
+        for (uint32_t w = 0; w < clients.windows_len; w++) {
+            xcb_window_t window = clients.windows[w];
 
-                        std::string name;
-                        xcb_ewmh_get_utf8_strings_reply_t data;
-                        auto getName = [](xcb_ewmh_get_utf8_strings_reply_t *r) {
-                                std::string name(r->strings, r->strings_len);
-                                xcb_ewmh_get_utf8_strings_reply_wipe(r);
-                                return name;
-                        };
+            std::string name;
+            xcb_ewmh_get_utf8_strings_reply_t data;
+            auto getName = [](xcb_ewmh_get_utf8_strings_reply_t *r) {
+                std::string name(r->strings, r->strings_len);
+                xcb_ewmh_get_utf8_strings_reply_wipe(r);
+                return name;
+            };
 
-                        xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_name(&ewmh, window);
-                        if (xcb_ewmh_get_wm_name_reply(&ewmh, cookie, &data, nullptr))
-                                name = getName(&data);
+            xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_name(&ewmh, window);
+            if (xcb_ewmh_get_wm_name_reply(&ewmh, cookie, &data, nullptr))
+                name = getName(&data);
 
-                        cookie = xcb_ewmh_get_wm_visible_name(&ewmh, window);
-                        if (xcb_ewmh_get_wm_visible_name_reply(&ewmh, cookie, &data, nullptr))
-                                name = getName(&data);
+            cookie = xcb_ewmh_get_wm_visible_name(&ewmh, window);
+            if (xcb_ewmh_get_wm_visible_name_reply(&ewmh, cookie, &data, nullptr))
+                name = getName(&data);
 
-                        windows_.push_back({QString::fromStdString(name), window});
-                }
-                xcb_ewmh_get_windows_reply_wipe(&clients);
+            windows_.push_back({QString::fromStdString(name), window});
         }
+        xcb_ewmh_get_windows_reply_wipe(&clients);
+    }
 #endif
-        QStringList ret;
-        ret.reserve(windows_.size());
-        for (const auto &w : windows_)
-                ret.append(w.first);
+    QStringList ret;
+    ret.reserve(windows_.size());
+    for (const auto &w : windows_)
+        ret.append(w.first);
 
-        return ret;
+    return ret;
 }
 
 #ifdef GSTREAMER_AVAILABLE
@@ -591,22 +578,22 @@ unsigned int busWatchId_ = 0;
 gboolean
 newBusMessage(GstBus *bus G_GNUC_UNUSED, GstMessage *msg, gpointer G_GNUC_UNUSED)
 {
-        switch (GST_MESSAGE_TYPE(msg)) {
-        case GST_MESSAGE_EOS:
-                if (pipe_) {
-                        gst_element_set_state(GST_ELEMENT(pipe_), GST_STATE_NULL);
-                        gst_object_unref(pipe_);
-                        pipe_ = nullptr;
-                }
-                if (busWatchId_) {
-                        g_source_remove(busWatchId_);
-                        busWatchId_ = 0;
-                }
-                break;
-        default:
-                break;
+    switch (GST_MESSAGE_TYPE(msg)) {
+    case GST_MESSAGE_EOS:
+        if (pipe_) {
+            gst_element_set_state(GST_ELEMENT(pipe_), GST_STATE_NULL);
+            gst_object_unref(pipe_);
+            pipe_ = nullptr;
+        }
+        if (busWatchId_) {
+            g_source_remove(busWatchId_);
+            busWatchId_ = 0;
         }
-        return TRUE;
+        break;
+    default:
+        break;
+    }
+    return TRUE;
 }
 }
 #endif
@@ -615,50 +602,50 @@ void
 CallManager::previewWindow(unsigned int index) const
 {
 #ifdef GSTREAMER_AVAILABLE
-        if (windows_.empty() || index >= windows_.size() || !gst_is_initialized())
-                return;
-
-        GstElement *ximagesrc = gst_element_factory_make("ximagesrc", nullptr);
-        if (!ximagesrc) {
-                nhlog::ui()->error("Failed to create ximagesrc");
-                return;
-        }
-        GstElement *videoconvert = gst_element_factory_make("videoconvert", nullptr);
-        GstElement *videoscale   = gst_element_factory_make("videoscale", nullptr);
-        GstElement *capsfilter   = gst_element_factory_make("capsfilter", nullptr);
-        GstElement *ximagesink   = gst_element_factory_make("ximagesink", nullptr);
-
-        g_object_set(ximagesrc, "use-damage", FALSE, nullptr);
-        g_object_set(ximagesrc, "show-pointer", FALSE, nullptr);
-        g_object_set(ximagesrc, "xid", windows_[index].second, nullptr);
-
-        GstCaps *caps = gst_caps_new_simple(
-          "video/x-raw", "width", G_TYPE_INT, 480, "height", G_TYPE_INT, 360, nullptr);
-        g_object_set(capsfilter, "caps", caps, nullptr);
-        gst_caps_unref(caps);
-
-        pipe_ = gst_pipeline_new(nullptr);
-        gst_bin_add_many(
-          GST_BIN(pipe_), ximagesrc, videoconvert, videoscale, capsfilter, ximagesink, nullptr);
-        if (!gst_element_link_many(
-              ximagesrc, videoconvert, videoscale, capsfilter, ximagesink, nullptr)) {
-                nhlog::ui()->error("Failed to link preview window elements");
-                gst_object_unref(pipe_);
-                pipe_ = nullptr;
-                return;
-        }
-        if (gst_element_set_state(pipe_, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
-                nhlog::ui()->error("Unable to start preview pipeline");
-                gst_object_unref(pipe_);
-                pipe_ = nullptr;
-                return;
-        }
-
-        GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(pipe_));
-        busWatchId_ = gst_bus_add_watch(bus, newBusMessage, nullptr);
-        gst_object_unref(bus);
+    if (windows_.empty() || index >= windows_.size() || !gst_is_initialized())
+        return;
+
+    GstElement *ximagesrc = gst_element_factory_make("ximagesrc", nullptr);
+    if (!ximagesrc) {
+        nhlog::ui()->error("Failed to create ximagesrc");
+        return;
+    }
+    GstElement *videoconvert = gst_element_factory_make("videoconvert", nullptr);
+    GstElement *videoscale   = gst_element_factory_make("videoscale", nullptr);
+    GstElement *capsfilter   = gst_element_factory_make("capsfilter", nullptr);
+    GstElement *ximagesink   = gst_element_factory_make("ximagesink", nullptr);
+
+    g_object_set(ximagesrc, "use-damage", FALSE, nullptr);
+    g_object_set(ximagesrc, "show-pointer", FALSE, nullptr);
+    g_object_set(ximagesrc, "xid", windows_[index].second, nullptr);
+
+    GstCaps *caps = gst_caps_new_simple(
+      "video/x-raw", "width", G_TYPE_INT, 480, "height", G_TYPE_INT, 360, nullptr);
+    g_object_set(capsfilter, "caps", caps, nullptr);
+    gst_caps_unref(caps);
+
+    pipe_ = gst_pipeline_new(nullptr);
+    gst_bin_add_many(
+      GST_BIN(pipe_), ximagesrc, videoconvert, videoscale, capsfilter, ximagesink, nullptr);
+    if (!gst_element_link_many(
+          ximagesrc, videoconvert, videoscale, capsfilter, ximagesink, nullptr)) {
+        nhlog::ui()->error("Failed to link preview window elements");
+        gst_object_unref(pipe_);
+        pipe_ = nullptr;
+        return;
+    }
+    if (gst_element_set_state(pipe_, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
+        nhlog::ui()->error("Unable to start preview pipeline");
+        gst_object_unref(pipe_);
+        pipe_ = nullptr;
+        return;
+    }
+
+    GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(pipe_));
+    busWatchId_ = gst_bus_add_watch(bus, newBusMessage, nullptr);
+    gst_object_unref(bus);
 #else
-        (void)index;
+    (void)index;
 #endif
 }
 
@@ -666,29 +653,28 @@ namespace {
 std::vector<std::string>
 getTurnURIs(const mtx::responses::TurnServer &turnServer)
 {
-        // gstreamer expects: turn(s)://username:password@host:port?transport=udp(tcp)
-        // where username and password are percent-encoded
-        std::vector<std::string> ret;
-        for (const auto &uri : turnServer.uris) {
-                if (auto c = uri.find(':'); c == std::string::npos) {
-                        nhlog::ui()->error("Invalid TURN server uri: {}", uri);
-                        continue;
-                } else {
-                        std::string scheme = std::string(uri, 0, c);
-                        if (scheme != "turn" && scheme != "turns") {
-                                nhlog::ui()->error("Invalid TURN server uri: {}", uri);
-                                continue;
-                        }
-
-                        QString encodedUri =
-                          QString::fromStdString(scheme) + "://" +
-                          QUrl::toPercentEncoding(QString::fromStdString(turnServer.username)) +
-                          ":" +
-                          QUrl::toPercentEncoding(QString::fromStdString(turnServer.password)) +
-                          "@" + QString::fromStdString(std::string(uri, ++c));
-                        ret.push_back(encodedUri.toStdString());
-                }
+    // gstreamer expects: turn(s)://username:password@host:port?transport=udp(tcp)
+    // where username and password are percent-encoded
+    std::vector<std::string> ret;
+    for (const auto &uri : turnServer.uris) {
+        if (auto c = uri.find(':'); c == std::string::npos) {
+            nhlog::ui()->error("Invalid TURN server uri: {}", uri);
+            continue;
+        } else {
+            std::string scheme = std::string(uri, 0, c);
+            if (scheme != "turn" && scheme != "turns") {
+                nhlog::ui()->error("Invalid TURN server uri: {}", uri);
+                continue;
+            }
+
+            QString encodedUri =
+              QString::fromStdString(scheme) + "://" +
+              QUrl::toPercentEncoding(QString::fromStdString(turnServer.username)) + ":" +
+              QUrl::toPercentEncoding(QString::fromStdString(turnServer.password)) + "@" +
+              QString::fromStdString(std::string(uri, ++c));
+            ret.push_back(encodedUri.toStdString());
         }
-        return ret;
+    }
+    return ret;
 }
 }
diff --git a/src/CallManager.h b/src/CallManager.h
index 407b8366..22f31814 100644
--- a/src/CallManager.h
+++ b/src/CallManager.h
@@ -26,93 +26,92 @@ class QUrl;
 
 class CallManager : public QObject
 {
-        Q_OBJECT
-        Q_PROPERTY(bool haveCallInvite READ haveCallInvite NOTIFY newInviteState)
-        Q_PROPERTY(bool isOnCall READ isOnCall NOTIFY newCallState)
-        Q_PROPERTY(webrtc::CallType callType READ callType NOTIFY newInviteState)
-        Q_PROPERTY(webrtc::State callState READ callState NOTIFY newCallState)
-        Q_PROPERTY(QString callParty READ callParty NOTIFY newInviteState)
-        Q_PROPERTY(QString callPartyDisplayName READ callPartyDisplayName NOTIFY newInviteState)
-        Q_PROPERTY(QString callPartyAvatarUrl READ callPartyAvatarUrl NOTIFY newInviteState)
-        Q_PROPERTY(bool isMicMuted READ isMicMuted NOTIFY micMuteChanged)
-        Q_PROPERTY(bool haveLocalPiP READ haveLocalPiP NOTIFY newCallState)
-        Q_PROPERTY(QStringList mics READ mics NOTIFY devicesChanged)
-        Q_PROPERTY(QStringList cameras READ cameras NOTIFY devicesChanged)
-        Q_PROPERTY(bool callsSupported READ callsSupported CONSTANT)
-        Q_PROPERTY(bool screenShareSupported READ screenShareSupported CONSTANT)
+    Q_OBJECT
+    Q_PROPERTY(bool haveCallInvite READ haveCallInvite NOTIFY newInviteState)
+    Q_PROPERTY(bool isOnCall READ isOnCall NOTIFY newCallState)
+    Q_PROPERTY(webrtc::CallType callType READ callType NOTIFY newInviteState)
+    Q_PROPERTY(webrtc::State callState READ callState NOTIFY newCallState)
+    Q_PROPERTY(QString callParty READ callParty NOTIFY newInviteState)
+    Q_PROPERTY(QString callPartyDisplayName READ callPartyDisplayName NOTIFY newInviteState)
+    Q_PROPERTY(QString callPartyAvatarUrl READ callPartyAvatarUrl NOTIFY newInviteState)
+    Q_PROPERTY(bool isMicMuted READ isMicMuted NOTIFY micMuteChanged)
+    Q_PROPERTY(bool haveLocalPiP READ haveLocalPiP NOTIFY newCallState)
+    Q_PROPERTY(QStringList mics READ mics NOTIFY devicesChanged)
+    Q_PROPERTY(QStringList cameras READ cameras NOTIFY devicesChanged)
+    Q_PROPERTY(bool callsSupported READ callsSupported CONSTANT)
+    Q_PROPERTY(bool screenShareSupported READ screenShareSupported CONSTANT)
 
 public:
-        CallManager(QObject *);
+    CallManager(QObject *);
 
-        bool haveCallInvite() const { return haveCallInvite_; }
-        bool isOnCall() const { return session_.state() != webrtc::State::DISCONNECTED; }
-        webrtc::CallType callType() const { return callType_; }
-        webrtc::State callState() const { return session_.state(); }
-        QString callParty() const { return callParty_; }
-        QString callPartyDisplayName() const { return callPartyDisplayName_; }
-        QString callPartyAvatarUrl() const { return callPartyAvatarUrl_; }
-        bool isMicMuted() const { return session_.isMicMuted(); }
-        bool haveLocalPiP() const { return session_.haveLocalPiP(); }
-        QStringList mics() const { return devices(false); }
-        QStringList cameras() const { return devices(true); }
-        void refreshTurnServer();
+    bool haveCallInvite() const { return haveCallInvite_; }
+    bool isOnCall() const { return session_.state() != webrtc::State::DISCONNECTED; }
+    webrtc::CallType callType() const { return callType_; }
+    webrtc::State callState() const { return session_.state(); }
+    QString callParty() const { return callParty_; }
+    QString callPartyDisplayName() const { return callPartyDisplayName_; }
+    QString callPartyAvatarUrl() const { return callPartyAvatarUrl_; }
+    bool isMicMuted() const { return session_.isMicMuted(); }
+    bool haveLocalPiP() const { return session_.haveLocalPiP(); }
+    QStringList mics() const { return devices(false); }
+    QStringList cameras() const { return devices(true); }
+    void refreshTurnServer();
 
-        static bool callsSupported();
-        static bool screenShareSupported();
+    static bool callsSupported();
+    static bool screenShareSupported();
 
 public slots:
-        void sendInvite(const QString &roomid, webrtc::CallType, unsigned int windowIndex = 0);
-        void syncEvent(const mtx::events::collections::TimelineEvents &event);
-        void toggleMicMute();
-        void toggleLocalPiP() { session_.toggleLocalPiP(); }
-        void acceptInvite();
-        void hangUp(
-          mtx::events::msg::CallHangUp::Reason = mtx::events::msg::CallHangUp::Reason::User);
-        QStringList windowList();
-        void previewWindow(unsigned int windowIndex) const;
+    void sendInvite(const QString &roomid, webrtc::CallType, unsigned int windowIndex = 0);
+    void syncEvent(const mtx::events::collections::TimelineEvents &event);
+    void toggleMicMute();
+    void toggleLocalPiP() { session_.toggleLocalPiP(); }
+    void acceptInvite();
+    void hangUp(mtx::events::msg::CallHangUp::Reason = mtx::events::msg::CallHangUp::Reason::User);
+    QStringList windowList();
+    void previewWindow(unsigned int windowIndex) const;
 
 signals:
-        void newMessage(const QString &roomid, const mtx::events::msg::CallInvite &);
-        void newMessage(const QString &roomid, const mtx::events::msg::CallCandidates &);
-        void newMessage(const QString &roomid, const mtx::events::msg::CallAnswer &);
-        void newMessage(const QString &roomid, const mtx::events::msg::CallHangUp &);
-        void newInviteState();
-        void newCallState();
-        void micMuteChanged();
-        void devicesChanged();
-        void turnServerRetrieved(const mtx::responses::TurnServer &);
+    void newMessage(const QString &roomid, const mtx::events::msg::CallInvite &);
+    void newMessage(const QString &roomid, const mtx::events::msg::CallCandidates &);
+    void newMessage(const QString &roomid, const mtx::events::msg::CallAnswer &);
+    void newMessage(const QString &roomid, const mtx::events::msg::CallHangUp &);
+    void newInviteState();
+    void newCallState();
+    void micMuteChanged();
+    void devicesChanged();
+    void turnServerRetrieved(const mtx::responses::TurnServer &);
 
 private slots:
-        void retrieveTurnServer();
+    void retrieveTurnServer();
 
 private:
-        WebRTCSession &session_;
-        QString roomid_;
-        QString callParty_;
-        QString callPartyDisplayName_;
-        QString callPartyAvatarUrl_;
-        std::string callid_;
-        const uint32_t timeoutms_  = 120000;
-        webrtc::CallType callType_ = webrtc::CallType::VOICE;
-        bool haveCallInvite_       = false;
-        std::string inviteSDP_;
-        std::vector<mtx::events::msg::CallCandidates::Candidate> remoteICECandidates_;
-        std::vector<std::string> turnURIs_;
-        QTimer turnServerTimer_;
-        QMediaPlayer player_;
-        std::vector<std::pair<QString, uint32_t>> windows_;
+    WebRTCSession &session_;
+    QString roomid_;
+    QString callParty_;
+    QString callPartyDisplayName_;
+    QString callPartyAvatarUrl_;
+    std::string callid_;
+    const uint32_t timeoutms_  = 120000;
+    webrtc::CallType callType_ = webrtc::CallType::VOICE;
+    bool haveCallInvite_       = false;
+    std::string inviteSDP_;
+    std::vector<mtx::events::msg::CallCandidates::Candidate> remoteICECandidates_;
+    std::vector<std::string> turnURIs_;
+    QTimer turnServerTimer_;
+    QMediaPlayer player_;
+    std::vector<std::pair<QString, uint32_t>> windows_;
 
-        template<typename T>
-        bool handleEvent(const mtx::events::collections::TimelineEvents &event);
-        void handleEvent(const mtx::events::RoomEvent<mtx::events::msg::CallInvite> &);
-        void handleEvent(const mtx::events::RoomEvent<mtx::events::msg::CallCandidates> &);
-        void handleEvent(const mtx::events::RoomEvent<mtx::events::msg::CallAnswer> &);
-        void handleEvent(const mtx::events::RoomEvent<mtx::events::msg::CallHangUp> &);
-        void answerInvite(const mtx::events::msg::CallInvite &, bool isVideo);
-        void generateCallID();
-        QStringList devices(bool isVideo) const;
-        void clear();
-        void endCall();
-        void playRingtone(const QUrl &ringtone, bool repeat);
-        void stopRingtone();
+    template<typename T>
+    bool handleEvent(const mtx::events::collections::TimelineEvents &event);
+    void handleEvent(const mtx::events::RoomEvent<mtx::events::msg::CallInvite> &);
+    void handleEvent(const mtx::events::RoomEvent<mtx::events::msg::CallCandidates> &);
+    void handleEvent(const mtx::events::RoomEvent<mtx::events::msg::CallAnswer> &);
+    void handleEvent(const mtx::events::RoomEvent<mtx::events::msg::CallHangUp> &);
+    void answerInvite(const mtx::events::msg::CallInvite &, bool isVideo);
+    void generateCallID();
+    QStringList devices(bool isVideo) const;
+    void clear();
+    void endCall();
+    void playRingtone(const QUrl &ringtone, bool repeat);
+    void stopRingtone();
 };
diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp
index 3887f8b8..673f39ee 100644
--- a/src/ChatPage.cpp
+++ b/src/ChatPage.cpp
@@ -50,660 +50,641 @@ ChatPage::ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent)
   , notificationsManager(this)
   , callManager_(new CallManager(this))
 {
-        setObjectName("chatPage");
-
-        instance_ = this;
-
-        qRegisterMetaType<std::optional<mtx::crypto::EncryptedFile>>();
-        qRegisterMetaType<std::optional<RelatedInfo>>();
-        qRegisterMetaType<mtx::presence::PresenceState>();
-        qRegisterMetaType<mtx::secret_storage::AesHmacSha2KeyDescription>();
-        qRegisterMetaType<SecretsToDecrypt>();
-
-        topLayout_ = new QHBoxLayout(this);
-        topLayout_->setSpacing(0);
-        topLayout_->setMargin(0);
-
-        view_manager_ = new TimelineViewManager(callManager_, this);
-
-        topLayout_->addWidget(view_manager_->getWidget());
-
-        connect(this,
-                &ChatPage::downloadedSecrets,
-                this,
-                &ChatPage::decryptDownloadedSecrets,
-                Qt::QueuedConnection);
-
-        connect(this, &ChatPage::connectionLost, this, [this]() {
-                nhlog::net()->info("connectivity lost");
-                isConnected_ = false;
-                http::client()->shutdown();
-        });
-        connect(this, &ChatPage::connectionRestored, this, [this]() {
-                nhlog::net()->info("trying to re-connect");
-                isConnected_ = true;
-
-                // Drop all pending connections.
-                http::client()->shutdown();
-                trySync();
-        });
-
-        connectivityTimer_.setInterval(CHECK_CONNECTIVITY_INTERVAL);
-        connect(&connectivityTimer_, &QTimer::timeout, this, [=]() {
-                if (http::client()->access_token().empty()) {
-                        connectivityTimer_.stop();
-                        return;
-                }
+    setObjectName("chatPage");
 
-                http::client()->versions(
-                  [this](const mtx::responses::Versions &, mtx::http::RequestErr err) {
-                          if (err) {
-                                  emit connectionLost();
-                                  return;
-                          }
+    instance_ = this;
 
-                          if (!isConnected_)
-                                  emit connectionRestored();
-                  });
-        });
+    qRegisterMetaType<std::optional<mtx::crypto::EncryptedFile>>();
+    qRegisterMetaType<std::optional<RelatedInfo>>();
+    qRegisterMetaType<mtx::presence::PresenceState>();
+    qRegisterMetaType<mtx::secret_storage::AesHmacSha2KeyDescription>();
+    qRegisterMetaType<SecretsToDecrypt>();
 
-        connect(this, &ChatPage::loggedOut, this, &ChatPage::logout);
+    topLayout_ = new QHBoxLayout(this);
+    topLayout_->setSpacing(0);
+    topLayout_->setMargin(0);
 
-        connect(
-          view_manager_,
-          &TimelineViewManager::inviteUsers,
-          this,
-          [this](QString roomId, QStringList users) {
-                  for (int ii = 0; ii < users.size(); ++ii) {
-                          QTimer::singleShot(ii * 500, this, [this, roomId, ii, users]() {
-                                  const auto user = users.at(ii);
-
-                                  http::client()->invite_user(
-                                    roomId.toStdString(),
-                                    user.toStdString(),
-                                    [this, user](const mtx::responses::RoomInvite &,
-                                                 mtx::http::RequestErr err) {
-                                            if (err) {
-                                                    emit showNotification(
-                                                      tr("Failed to invite user: %1").arg(user));
-                                                    return;
-                                            }
-
-                                            emit showNotification(tr("Invited user: %1").arg(user));
-                                    });
-                          });
-                  }
-          });
+    view_manager_ = new TimelineViewManager(callManager_, this);
+
+    topLayout_->addWidget(view_manager_->getWidget());
+
+    connect(this,
+            &ChatPage::downloadedSecrets,
+            this,
+            &ChatPage::decryptDownloadedSecrets,
+            Qt::QueuedConnection);
+
+    connect(this, &ChatPage::connectionLost, this, [this]() {
+        nhlog::net()->info("connectivity lost");
+        isConnected_ = false;
+        http::client()->shutdown();
+    });
+    connect(this, &ChatPage::connectionRestored, this, [this]() {
+        nhlog::net()->info("trying to re-connect");
+        isConnected_ = true;
 
-        connect(this, &ChatPage::leftRoom, this, &ChatPage::removeRoom);
-        connect(this, &ChatPage::changeToRoom, this, &ChatPage::changeRoom, Qt::QueuedConnection);
-        connect(this, &ChatPage::notificationsRetrieved, this, &ChatPage::sendNotifications);
-        connect(this,
-                &ChatPage::highlightedNotifsRetrieved,
-                this,
-                [](const mtx::responses::Notifications &notif) {
-                        try {
-                                cache::saveTimelineMentions(notif);
-                        } catch (const lmdb::error &e) {
-                                nhlog::db()->error("failed to save mentions: {}", e.what());
+        // Drop all pending connections.
+        http::client()->shutdown();
+        trySync();
+    });
+
+    connectivityTimer_.setInterval(CHECK_CONNECTIVITY_INTERVAL);
+    connect(&connectivityTimer_, &QTimer::timeout, this, [=]() {
+        if (http::client()->access_token().empty()) {
+            connectivityTimer_.stop();
+            return;
+        }
+
+        http::client()->versions(
+          [this](const mtx::responses::Versions &, mtx::http::RequestErr err) {
+              if (err) {
+                  emit connectionLost();
+                  return;
+              }
+
+              if (!isConnected_)
+                  emit connectionRestored();
+          });
+    });
+
+    connect(this, &ChatPage::loggedOut, this, &ChatPage::logout);
+
+    connect(
+      view_manager_,
+      &TimelineViewManager::inviteUsers,
+      this,
+      [this](QString roomId, QStringList users) {
+          for (int ii = 0; ii < users.size(); ++ii) {
+              QTimer::singleShot(ii * 500, this, [this, roomId, ii, users]() {
+                  const auto user = users.at(ii);
+
+                  http::client()->invite_user(
+                    roomId.toStdString(),
+                    user.toStdString(),
+                    [this, user](const mtx::responses::RoomInvite &, mtx::http::RequestErr err) {
+                        if (err) {
+                            emit showNotification(tr("Failed to invite user: %1").arg(user));
+                            return;
                         }
-                });
-
-        connect(&notificationsManager,
-                &NotificationsManager::notificationClicked,
-                this,
-                [this](const QString &roomid, const QString &eventid) {
-                        Q_UNUSED(eventid)
-                        view_manager_->rooms()->setCurrentRoom(roomid);
-                        activateWindow();
-                });
-        connect(&notificationsManager,
-                &NotificationsManager::sendNotificationReply,
-                this,
-                [this](const QString &roomid, const QString &eventid, const QString &body) {
-                        view_manager_->rooms()->setCurrentRoom(roomid);
-                        view_manager_->queueReply(roomid, eventid, body);
-                        activateWindow();
-                });
-
-        connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, [this]() {
-                // ensure the qml context is shutdown before we destroy all other singletons
-                // Otherwise Qml will try to access the room list or settings, after they have been
-                // destroyed
-                topLayout_->removeWidget(view_manager_->getWidget());
-                delete view_manager_->getWidget();
-        });
-
-        connect(
-          this,
-          &ChatPage::initializeViews,
-          view_manager_,
-          [this](const mtx::responses::Rooms &rooms) { view_manager_->sync(rooms); },
-          Qt::QueuedConnection);
-        connect(this,
-                &ChatPage::initializeEmptyViews,
-                view_manager_,
-                &TimelineViewManager::initializeRoomlist);
-        connect(
-          this, &ChatPage::chatFocusChanged, view_manager_, &TimelineViewManager::chatFocusChanged);
-        connect(this, &ChatPage::syncUI, this, [this](const mtx::responses::Rooms &rooms) {
-                view_manager_->sync(rooms);
-
-                static unsigned int prevNotificationCount = 0;
-                unsigned int notificationCount            = 0;
-                for (const auto &room : rooms.join) {
-                        notificationCount += room.second.unread_notifications.notification_count;
-                }
 
-                // HACK: If we had less notifications last time we checked, send an alert if the
-                // user wanted one. Technically, this may cause an alert to be missed if new ones
-                // come in while you are reading old ones. Since the window is almost certainly open
-                // in this edge case, that's probably a non-issue.
-                // TODO: Replace this once we have proper pushrules support. This is a horrible hack
-                if (prevNotificationCount < notificationCount) {
-                        if (userSettings_->hasAlertOnNotification())
-                                QApplication::alert(this);
+                        emit showNotification(tr("Invited user: %1").arg(user));
+                    });
+              });
+          }
+      });
+
+    connect(this, &ChatPage::leftRoom, this, &ChatPage::removeRoom);
+    connect(this, &ChatPage::changeToRoom, this, &ChatPage::changeRoom, Qt::QueuedConnection);
+    connect(this, &ChatPage::notificationsRetrieved, this, &ChatPage::sendNotifications);
+    connect(this,
+            &ChatPage::highlightedNotifsRetrieved,
+            this,
+            [](const mtx::responses::Notifications &notif) {
+                try {
+                    cache::saveTimelineMentions(notif);
+                } catch (const lmdb::error &e) {
+                    nhlog::db()->error("failed to save mentions: {}", e.what());
                 }
-                prevNotificationCount = notificationCount;
-
-                // No need to check amounts for this section, as this function internally checks for
-                // duplicates.
-                if (notificationCount && userSettings_->hasNotifications())
-                        http::client()->notifications(
-                          5,
-                          "",
-                          "",
-                          [this](const mtx::responses::Notifications &res,
-                                 mtx::http::RequestErr err) {
-                                  if (err) {
-                                          nhlog::net()->warn(
-                                            "failed to retrieve notifications: {} ({})",
-                                            err->matrix_error.error,
-                                            static_cast<int>(err->status_code));
-                                          return;
-                                  }
-
-                                  emit notificationsRetrieved(std::move(res));
-                          });
-        });
-
-        connect(
-          this, &ChatPage::tryInitialSyncCb, this, &ChatPage::tryInitialSync, Qt::QueuedConnection);
-        connect(this, &ChatPage::trySyncCb, this, &ChatPage::trySync, Qt::QueuedConnection);
-        connect(
-          this,
-          &ChatPage::tryDelayedSyncCb,
-          this,
-          [this]() { QTimer::singleShot(RETRY_TIMEOUT, this, &ChatPage::trySync); },
-          Qt::QueuedConnection);
-
-        connect(this,
-                &ChatPage::newSyncResponse,
-                this,
-                &ChatPage::handleSyncResponse,
-                Qt::QueuedConnection);
+            });
+
+    connect(&notificationsManager,
+            &NotificationsManager::notificationClicked,
+            this,
+            [this](const QString &roomid, const QString &eventid) {
+                Q_UNUSED(eventid)
+                view_manager_->rooms()->setCurrentRoom(roomid);
+                activateWindow();
+            });
+    connect(&notificationsManager,
+            &NotificationsManager::sendNotificationReply,
+            this,
+            [this](const QString &roomid, const QString &eventid, const QString &body) {
+                view_manager_->rooms()->setCurrentRoom(roomid);
+                view_manager_->queueReply(roomid, eventid, body);
+                activateWindow();
+            });
+
+    connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, [this]() {
+        // ensure the qml context is shutdown before we destroy all other singletons
+        // Otherwise Qml will try to access the room list or settings, after they have been
+        // destroyed
+        topLayout_->removeWidget(view_manager_->getWidget());
+        delete view_manager_->getWidget();
+    });
+
+    connect(
+      this,
+      &ChatPage::initializeViews,
+      view_manager_,
+      [this](const mtx::responses::Rooms &rooms) { view_manager_->sync(rooms); },
+      Qt::QueuedConnection);
+    connect(this,
+            &ChatPage::initializeEmptyViews,
+            view_manager_,
+            &TimelineViewManager::initializeRoomlist);
+    connect(
+      this, &ChatPage::chatFocusChanged, view_manager_, &TimelineViewManager::chatFocusChanged);
+    connect(this, &ChatPage::syncUI, this, [this](const mtx::responses::Rooms &rooms) {
+        view_manager_->sync(rooms);
+
+        static unsigned int prevNotificationCount = 0;
+        unsigned int notificationCount            = 0;
+        for (const auto &room : rooms.join) {
+            notificationCount += room.second.unread_notifications.notification_count;
+        }
 
-        connect(this, &ChatPage::dropToLoginPageCb, this, &ChatPage::dropToLoginPage);
+        // HACK: If we had less notifications last time we checked, send an alert if the
+        // user wanted one. Technically, this may cause an alert to be missed if new ones
+        // come in while you are reading old ones. Since the window is almost certainly open
+        // in this edge case, that's probably a non-issue.
+        // TODO: Replace this once we have proper pushrules support. This is a horrible hack
+        if (prevNotificationCount < notificationCount) {
+            if (userSettings_->hasAlertOnNotification())
+                QApplication::alert(this);
+        }
+        prevNotificationCount = notificationCount;
+
+        // No need to check amounts for this section, as this function internally checks for
+        // duplicates.
+        if (notificationCount && userSettings_->hasNotifications())
+            http::client()->notifications(
+              5,
+              "",
+              "",
+              [this](const mtx::responses::Notifications &res, mtx::http::RequestErr err) {
+                  if (err) {
+                      nhlog::net()->warn("failed to retrieve notifications: {} ({})",
+                                         err->matrix_error.error,
+                                         static_cast<int>(err->status_code));
+                      return;
+                  }
 
-        connectCallMessage<mtx::events::msg::CallInvite>();
-        connectCallMessage<mtx::events::msg::CallCandidates>();
-        connectCallMessage<mtx::events::msg::CallAnswer>();
-        connectCallMessage<mtx::events::msg::CallHangUp>();
+                  emit notificationsRetrieved(std::move(res));
+              });
+    });
+
+    connect(
+      this, &ChatPage::tryInitialSyncCb, this, &ChatPage::tryInitialSync, Qt::QueuedConnection);
+    connect(this, &ChatPage::trySyncCb, this, &ChatPage::trySync, Qt::QueuedConnection);
+    connect(
+      this,
+      &ChatPage::tryDelayedSyncCb,
+      this,
+      [this]() { QTimer::singleShot(RETRY_TIMEOUT, this, &ChatPage::trySync); },
+      Qt::QueuedConnection);
+
+    connect(
+      this, &ChatPage::newSyncResponse, this, &ChatPage::handleSyncResponse, Qt::QueuedConnection);
+
+    connect(this, &ChatPage::dropToLoginPageCb, this, &ChatPage::dropToLoginPage);
+
+    connectCallMessage<mtx::events::msg::CallInvite>();
+    connectCallMessage<mtx::events::msg::CallCandidates>();
+    connectCallMessage<mtx::events::msg::CallAnswer>();
+    connectCallMessage<mtx::events::msg::CallHangUp>();
 }
 
 void
 ChatPage::logout()
 {
-        resetUI();
-        deleteConfigs();
+    resetUI();
+    deleteConfigs();
 
-        emit closing();
-        connectivityTimer_.stop();
+    emit closing();
+    connectivityTimer_.stop();
 }
 
 void
 ChatPage::dropToLoginPage(const QString &msg)
 {
-        nhlog::ui()->info("dropping to the login page: {}", msg.toStdString());
+    nhlog::ui()->info("dropping to the login page: {}", msg.toStdString());
 
-        http::client()->shutdown();
-        connectivityTimer_.stop();
+    http::client()->shutdown();
+    connectivityTimer_.stop();
 
-        resetUI();
-        deleteConfigs();
+    resetUI();
+    deleteConfigs();
 
-        emit showLoginPage(msg);
+    emit showLoginPage(msg);
 }
 
 void
 ChatPage::resetUI()
 {
-        view_manager_->clearAll();
+    view_manager_->clearAll();
 
-        emit unreadMessages(0);
+    emit unreadMessages(0);
 }
 
 void
 ChatPage::deleteConfigs()
 {
-        auto settings = UserSettings::instance()->qsettings();
-
-        if (UserSettings::instance()->profile() != "") {
-                settings->beginGroup("profile");
-                settings->beginGroup(UserSettings::instance()->profile());
-        }
-        settings->beginGroup("auth");
-        settings->remove("");
-        settings->endGroup(); // auth
-
-        http::client()->shutdown();
-        cache::deleteData();
+    auto settings = UserSettings::instance()->qsettings();
+
+    if (UserSettings::instance()->profile() != "") {
+        settings->beginGroup("profile");
+        settings->beginGroup(UserSettings::instance()->profile());
+    }
+    settings->beginGroup("auth");
+    settings->remove("");
+    settings->endGroup(); // auth
+
+    http::client()->shutdown();
+    cache::deleteData();
 }
 
 void
 ChatPage::bootstrap(QString userid, QString homeserver, QString token)
 {
-        using namespace mtx::identifiers;
+    using namespace mtx::identifiers;
 
-        try {
-                http::client()->set_user(parse<User>(userid.toStdString()));
-        } catch (const std::invalid_argument &) {
-                nhlog::ui()->critical("bootstrapped with invalid user_id: {}",
-                                      userid.toStdString());
-        }
+    try {
+        http::client()->set_user(parse<User>(userid.toStdString()));
+    } catch (const std::invalid_argument &) {
+        nhlog::ui()->critical("bootstrapped with invalid user_id: {}", userid.toStdString());
+    }
 
-        http::client()->set_server(homeserver.toStdString());
-        http::client()->set_access_token(token.toStdString());
-        http::client()->verify_certificates(
-          !UserSettings::instance()->disableCertificateValidation());
+    http::client()->set_server(homeserver.toStdString());
+    http::client()->set_access_token(token.toStdString());
+    http::client()->verify_certificates(!UserSettings::instance()->disableCertificateValidation());
 
-        // The Olm client needs the user_id & device_id that will be included
-        // in the generated payloads & keys.
-        olm::client()->set_user_id(http::client()->user_id().to_string());
-        olm::client()->set_device_id(http::client()->device_id());
+    // The Olm client needs the user_id & device_id that will be included
+    // in the generated payloads & keys.
+    olm::client()->set_user_id(http::client()->user_id().to_string());
+    olm::client()->set_device_id(http::client()->device_id());
 
-        try {
-                cache::init(userid);
-
-                connect(cache::client(),
-                        &Cache::newReadReceipts,
-                        view_manager_,
-                        &TimelineViewManager::updateReadReceipts);
-
-                connect(cache::client(),
-                        &Cache::removeNotification,
-                        &notificationsManager,
-                        &NotificationsManager::removeNotification);
-
-                const bool isInitialized = cache::isInitialized();
-                const auto cacheVersion  = cache::formatVersion();
-
-                callManager_->refreshTurnServer();
-
-                if (!isInitialized) {
-                        cache::setCurrentFormat();
-                } else {
-                        if (cacheVersion == cache::CacheVersion::Current) {
-                                loadStateFromCache();
-                                return;
-                        } else if (cacheVersion == cache::CacheVersion::Older) {
-                                if (!cache::runMigrations()) {
-                                        QMessageBox::critical(
-                                          this,
+    try {
+        cache::init(userid);
+
+        connect(cache::client(),
+                &Cache::newReadReceipts,
+                view_manager_,
+                &TimelineViewManager::updateReadReceipts);
+
+        connect(cache::client(),
+                &Cache::removeNotification,
+                &notificationsManager,
+                &NotificationsManager::removeNotification);
+
+        const bool isInitialized = cache::isInitialized();
+        const auto cacheVersion  = cache::formatVersion();
+
+        callManager_->refreshTurnServer();
+
+        if (!isInitialized) {
+            cache::setCurrentFormat();
+        } else {
+            if (cacheVersion == cache::CacheVersion::Current) {
+                loadStateFromCache();
+                return;
+            } else if (cacheVersion == cache::CacheVersion::Older) {
+                if (!cache::runMigrations()) {
+                    QMessageBox::critical(this,
                                           tr("Cache migration failed!"),
                                           tr("Migrating the cache to the current version failed. "
                                              "This can have different reasons. Please open an "
                                              "issue and try to use an older version in the mean "
                                              "time. Alternatively you can try deleting the cache "
                                              "manually."));
-                                        QCoreApplication::quit();
-                                }
-                                loadStateFromCache();
-                                return;
-                        } else if (cacheVersion == cache::CacheVersion::Newer) {
-                                QMessageBox::critical(
-                                  this,
-                                  tr("Incompatible cache version"),
-                                  tr("The cache on your disk is newer than this version of Nheko "
-                                     "supports. Please update or clear your cache."));
-                                QCoreApplication::quit();
-                                return;
-                        }
+                    QCoreApplication::quit();
                 }
-
-        } catch (const lmdb::error &e) {
-                nhlog::db()->critical("failure during boot: {}", e.what());
-                cache::deleteData();
-                nhlog::net()->info("falling back to initial sync");
-        }
-
-        try {
-                // It's the first time syncing with this device
-                // There isn't a saved olm account to restore.
-                nhlog::crypto()->info("creating new olm account");
-                olm::client()->create_new_account();
-                cache::saveOlmAccount(olm::client()->save(cache::client()->pickleSecret()));
-        } catch (const lmdb::error &e) {
-                nhlog::crypto()->critical("failed to save olm account {}", e.what());
-                emit dropToLoginPageCb(QString::fromStdString(e.what()));
+                loadStateFromCache();
                 return;
-        } catch (const mtx::crypto::olm_exception &e) {
-                nhlog::crypto()->critical("failed to create new olm account {}", e.what());
-                emit dropToLoginPageCb(QString::fromStdString(e.what()));
+            } else if (cacheVersion == cache::CacheVersion::Newer) {
+                QMessageBox::critical(
+                  this,
+                  tr("Incompatible cache version"),
+                  tr("The cache on your disk is newer than this version of Nheko "
+                     "supports. Please update or clear your cache."));
+                QCoreApplication::quit();
                 return;
+            }
         }
 
-        getProfileInfo();
-        getBackupVersion();
-        tryInitialSync();
+    } catch (const lmdb::error &e) {
+        nhlog::db()->critical("failure during boot: {}", e.what());
+        cache::deleteData();
+        nhlog::net()->info("falling back to initial sync");
+    }
+
+    try {
+        // It's the first time syncing with this device
+        // There isn't a saved olm account to restore.
+        nhlog::crypto()->info("creating new olm account");
+        olm::client()->create_new_account();
+        cache::saveOlmAccount(olm::client()->save(cache::client()->pickleSecret()));
+    } catch (const lmdb::error &e) {
+        nhlog::crypto()->critical("failed to save olm account {}", e.what());
+        emit dropToLoginPageCb(QString::fromStdString(e.what()));
+        return;
+    } catch (const mtx::crypto::olm_exception &e) {
+        nhlog::crypto()->critical("failed to create new olm account {}", e.what());
+        emit dropToLoginPageCb(QString::fromStdString(e.what()));
+        return;
+    }
+
+    getProfileInfo();
+    getBackupVersion();
+    tryInitialSync();
 }
 
 void
 ChatPage::loadStateFromCache()
 {
-        nhlog::db()->info("restoring state from cache");
-
-        try {
-                olm::client()->load(cache::restoreOlmAccount(), cache::client()->pickleSecret());
-
-                emit initializeEmptyViews();
-                emit initializeMentions(cache::getTimelineMentions());
-
-                cache::calculateRoomReadStatus();
-
-        } catch (const mtx::crypto::olm_exception &e) {
-                nhlog::crypto()->critical("failed to restore olm account: {}", e.what());
-                emit dropToLoginPageCb(tr("Failed to restore OLM account. Please login again."));
-                return;
-        } catch (const lmdb::error &e) {
-                nhlog::db()->critical("failed to restore cache: {}", e.what());
-                emit dropToLoginPageCb(tr("Failed to restore save data. Please login again."));
-                return;
-        } catch (const json::exception &e) {
-                nhlog::db()->critical("failed to parse cache data: {}", e.what());
-                emit dropToLoginPageCb(tr("Failed to restore save data. Please login again."));
-                return;
-        } catch (const std::exception &e) {
-                nhlog::db()->critical("failed to load cache data: {}", e.what());
-                emit dropToLoginPageCb(tr("Failed to restore save data. Please login again."));
-                return;
-        }
-
-        nhlog::crypto()->info("ed25519   : {}", olm::client()->identity_keys().ed25519);
-        nhlog::crypto()->info("curve25519: {}", olm::client()->identity_keys().curve25519);
-
-        getProfileInfo();
-        getBackupVersion();
-        verifyOneTimeKeyCountAfterStartup();
-
-        emit contentLoaded();
-
-        // Start receiving events.
-        emit trySyncCb();
+    nhlog::db()->info("restoring state from cache");
+
+    try {
+        olm::client()->load(cache::restoreOlmAccount(), cache::client()->pickleSecret());
+
+        emit initializeEmptyViews();
+        emit initializeMentions(cache::getTimelineMentions());
+
+        cache::calculateRoomReadStatus();
+
+    } catch (const mtx::crypto::olm_exception &e) {
+        nhlog::crypto()->critical("failed to restore olm account: {}", e.what());
+        emit dropToLoginPageCb(tr("Failed to restore OLM account. Please login again."));
+        return;
+    } catch (const lmdb::error &e) {
+        nhlog::db()->critical("failed to restore cache: {}", e.what());
+        emit dropToLoginPageCb(tr("Failed to restore save data. Please login again."));
+        return;
+    } catch (const json::exception &e) {
+        nhlog::db()->critical("failed to parse cache data: {}", e.what());
+        emit dropToLoginPageCb(tr("Failed to restore save data. Please login again."));
+        return;
+    } catch (const std::exception &e) {
+        nhlog::db()->critical("failed to load cache data: {}", e.what());
+        emit dropToLoginPageCb(tr("Failed to restore save data. Please login again."));
+        return;
+    }
+
+    nhlog::crypto()->info("ed25519   : {}", olm::client()->identity_keys().ed25519);
+    nhlog::crypto()->info("curve25519: {}", olm::client()->identity_keys().curve25519);
+
+    getProfileInfo();
+    getBackupVersion();
+    verifyOneTimeKeyCountAfterStartup();
+
+    emit contentLoaded();
+
+    // Start receiving events.
+    emit trySyncCb();
 }
 
 void
 ChatPage::removeRoom(const QString &room_id)
 {
-        try {
-                cache::removeRoom(room_id);
-                cache::removeInvite(room_id.toStdString());
-        } catch (const lmdb::error &e) {
-                nhlog::db()->critical("failure while removing room: {}", e.what());
-                // TODO: Notify the user.
-        }
+    try {
+        cache::removeRoom(room_id);
+        cache::removeInvite(room_id.toStdString());
+    } catch (const lmdb::error &e) {
+        nhlog::db()->critical("failure while removing room: {}", e.what());
+        // TODO: Notify the user.
+    }
 }
 
 void
 ChatPage::sendNotifications(const mtx::responses::Notifications &res)
 {
-        for (const auto &item : res.notifications) {
-                const auto event_id = mtx::accessors::event_id(item.event);
-
-                try {
-                        if (item.read) {
-                                cache::removeReadNotification(event_id);
-                                continue;
-                        }
-
-                        if (!cache::isNotificationSent(event_id)) {
-                                const auto room_id = QString::fromStdString(item.room_id);
-
-                                // We should only sent one notification per event.
-                                cache::markSentNotification(event_id);
-
-                                // Don't send a notification when the current room is opened.
-                                if (isRoomActive(room_id))
-                                        continue;
-
-                                if (userSettings_->hasDesktopNotifications()) {
-                                        auto info = cache::singleRoomInfo(item.room_id);
+    for (const auto &item : res.notifications) {
+        const auto event_id = mtx::accessors::event_id(item.event);
 
-                                        AvatarProvider::resolve(
-                                          QString::fromStdString(info.avatar_url),
-                                          96,
-                                          this,
-                                          [this, item](QPixmap image) {
-                                                  notificationsManager.postNotification(
-                                                    item, image.toImage());
-                                          });
-                                }
-                        }
-                } catch (const lmdb::error &e) {
-                        nhlog::db()->warn("error while sending notification: {}", e.what());
+        try {
+            if (item.read) {
+                cache::removeReadNotification(event_id);
+                continue;
+            }
+
+            if (!cache::isNotificationSent(event_id)) {
+                const auto room_id = QString::fromStdString(item.room_id);
+
+                // We should only sent one notification per event.
+                cache::markSentNotification(event_id);
+
+                // Don't send a notification when the current room is opened.
+                if (isRoomActive(room_id))
+                    continue;
+
+                if (userSettings_->hasDesktopNotifications()) {
+                    auto info = cache::singleRoomInfo(item.room_id);
+
+                    AvatarProvider::resolve(QString::fromStdString(info.avatar_url),
+                                            96,
+                                            this,
+                                            [this, item](QPixmap image) {
+                                                notificationsManager.postNotification(
+                                                  item, image.toImage());
+                                            });
                 }
+            }
+        } catch (const lmdb::error &e) {
+            nhlog::db()->warn("error while sending notification: {}", e.what());
         }
+    }
 }
 
 void
 ChatPage::tryInitialSync()
 {
-        nhlog::crypto()->info("ed25519   : {}", olm::client()->identity_keys().ed25519);
-        nhlog::crypto()->info("curve25519: {}", olm::client()->identity_keys().curve25519);
+    nhlog::crypto()->info("ed25519   : {}", olm::client()->identity_keys().ed25519);
+    nhlog::crypto()->info("curve25519: {}", olm::client()->identity_keys().curve25519);
 
-        // Upload one time keys for the device.
-        nhlog::crypto()->info("generating one time keys");
-        olm::client()->generate_one_time_keys(MAX_ONETIME_KEYS);
+    // Upload one time keys for the device.
+    nhlog::crypto()->info("generating one time keys");
+    olm::client()->generate_one_time_keys(MAX_ONETIME_KEYS);
 
-        http::client()->upload_keys(
-          olm::client()->create_upload_keys_request(),
-          [this](const mtx::responses::UploadKeys &res, mtx::http::RequestErr err) {
-                  if (err) {
-                          const int status_code = static_cast<int>(err->status_code);
+    http::client()->upload_keys(
+      olm::client()->create_upload_keys_request(),
+      [this](const mtx::responses::UploadKeys &res, mtx::http::RequestErr err) {
+          if (err) {
+              const int status_code = static_cast<int>(err->status_code);
 
-                          if (status_code == 404) {
-                                  nhlog::net()->warn(
-                                    "skipping key uploading. server doesn't provide /keys/upload");
-                                  return startInitialSync();
-                          }
+              if (status_code == 404) {
+                  nhlog::net()->warn("skipping key uploading. server doesn't provide /keys/upload");
+                  return startInitialSync();
+              }
 
-                          nhlog::crypto()->critical("failed to upload one time keys: {} {}",
-                                                    err->matrix_error.error,
-                                                    status_code);
+              nhlog::crypto()->critical(
+                "failed to upload one time keys: {} {}", err->matrix_error.error, status_code);
 
-                          QString errorMsg(tr("Failed to setup encryption keys. Server response: "
-                                              "%1 %2. Please try again later.")
-                                             .arg(QString::fromStdString(err->matrix_error.error))
-                                             .arg(status_code));
+              QString errorMsg(tr("Failed to setup encryption keys. Server response: "
+                                  "%1 %2. Please try again later.")
+                                 .arg(QString::fromStdString(err->matrix_error.error))
+                                 .arg(status_code));
 
-                          emit dropToLoginPageCb(errorMsg);
-                          return;
-                  }
+              emit dropToLoginPageCb(errorMsg);
+              return;
+          }
 
-                  olm::mark_keys_as_published();
+          olm::mark_keys_as_published();
 
-                  for (const auto &entry : res.one_time_key_counts)
-                          nhlog::net()->info(
-                            "uploaded {} {} one-time keys", entry.second, entry.first);
+          for (const auto &entry : res.one_time_key_counts)
+              nhlog::net()->info("uploaded {} {} one-time keys", entry.second, entry.first);
 
-                  startInitialSync();
-          });
+          startInitialSync();
+      });
 }
 
 void
 ChatPage::startInitialSync()
 {
-        nhlog::net()->info("trying initial sync");
-
-        mtx::http::SyncOpts opts;
-        opts.timeout      = 0;
-        opts.set_presence = currentPresence();
-
-        http::client()->sync(
-          opts, [this](const mtx::responses::Sync &res, mtx::http::RequestErr err) {
-                  // TODO: Initial Sync should include mentions as well...
+    nhlog::net()->info("trying initial sync");
+
+    mtx::http::SyncOpts opts;
+    opts.timeout      = 0;
+    opts.set_presence = currentPresence();
+
+    http::client()->sync(opts, [this](const mtx::responses::Sync &res, mtx::http::RequestErr err) {
+        // TODO: Initial Sync should include mentions as well...
+
+        if (err) {
+            const auto error      = QString::fromStdString(err->matrix_error.error);
+            const auto msg        = tr("Please try to login again: %1").arg(error);
+            const auto err_code   = mtx::errors::to_string(err->matrix_error.errcode);
+            const int status_code = static_cast<int>(err->status_code);
+
+            nhlog::net()->error("initial sync error: {} {} {} {}",
+                                err->parse_error,
+                                status_code,
+                                err->error_code,
+                                err_code);
+
+            // non http related errors
+            if (status_code <= 0 || status_code >= 600) {
+                startInitialSync();
+                return;
+            }
 
-                  if (err) {
-                          const auto error      = QString::fromStdString(err->matrix_error.error);
-                          const auto msg        = tr("Please try to login again: %1").arg(error);
-                          const auto err_code   = mtx::errors::to_string(err->matrix_error.errcode);
-                          const int status_code = static_cast<int>(err->status_code);
-
-                          nhlog::net()->error("initial sync error: {} {} {} {}",
-                                              err->parse_error,
-                                              status_code,
-                                              err->error_code,
-                                              err_code);
-
-                          // non http related errors
-                          if (status_code <= 0 || status_code >= 600) {
-                                  startInitialSync();
-                                  return;
-                          }
-
-                          switch (status_code) {
-                          case 502:
-                          case 504:
-                          case 524: {
-                                  startInitialSync();
-                                  return;
-                          }
-                          default: {
-                                  emit dropToLoginPageCb(msg);
-                                  return;
-                          }
-                          }
-                  }
+            switch (status_code) {
+            case 502:
+            case 504:
+            case 524: {
+                startInitialSync();
+                return;
+            }
+            default: {
+                emit dropToLoginPageCb(msg);
+                return;
+            }
+            }
+        }
 
-                  nhlog::net()->info("initial sync completed");
+        nhlog::net()->info("initial sync completed");
 
-                  try {
-                          cache::client()->saveState(res);
+        try {
+            cache::client()->saveState(res);
 
-                          olm::handle_to_device_messages(res.to_device.events);
+            olm::handle_to_device_messages(res.to_device.events);
 
-                          emit initializeViews(std::move(res.rooms));
-                          emit initializeMentions(cache::getTimelineMentions());
+            emit initializeViews(std::move(res.rooms));
+            emit initializeMentions(cache::getTimelineMentions());
 
-                          cache::calculateRoomReadStatus();
-                  } catch (const lmdb::error &e) {
-                          nhlog::db()->error("failed to save state after initial sync: {}",
-                                             e.what());
-                          startInitialSync();
-                          return;
-                  }
+            cache::calculateRoomReadStatus();
+        } catch (const lmdb::error &e) {
+            nhlog::db()->error("failed to save state after initial sync: {}", e.what());
+            startInitialSync();
+            return;
+        }
 
-                  emit trySyncCb();
-                  emit contentLoaded();
-          });
+        emit trySyncCb();
+        emit contentLoaded();
+    });
 }
 
 void
 ChatPage::handleSyncResponse(const mtx::responses::Sync &res, const std::string &prev_batch_token)
 {
-        try {
-                if (prev_batch_token != cache::nextBatchToken()) {
-                        nhlog::net()->warn("Duplicate sync, dropping");
-                        return;
-                }
-        } catch (const lmdb::error &e) {
-                nhlog::db()->warn("Logged out in the mean time, dropping sync");
+    try {
+        if (prev_batch_token != cache::nextBatchToken()) {
+            nhlog::net()->warn("Duplicate sync, dropping");
+            return;
         }
+    } catch (const lmdb::error &e) {
+        nhlog::db()->warn("Logged out in the mean time, dropping sync");
+    }
 
-        nhlog::net()->debug("sync completed: {}", res.next_batch);
+    nhlog::net()->debug("sync completed: {}", res.next_batch);
 
-        // Ensure that we have enough one-time keys available.
-        ensureOneTimeKeyCount(res.device_one_time_keys_count);
+    // Ensure that we have enough one-time keys available.
+    ensureOneTimeKeyCount(res.device_one_time_keys_count);
 
-        // TODO: fine grained error handling
-        try {
-                cache::client()->saveState(res);
-                olm::handle_to_device_messages(res.to_device.events);
+    // TODO: fine grained error handling
+    try {
+        cache::client()->saveState(res);
+        olm::handle_to_device_messages(res.to_device.events);
 
-                auto updates = cache::getRoomInfo(cache::client()->roomsWithStateUpdates(res));
+        auto updates = cache::getRoomInfo(cache::client()->roomsWithStateUpdates(res));
 
-                emit syncUI(res.rooms);
+        emit syncUI(res.rooms);
 
-                // if we process a lot of syncs (1 every 200ms), this means we clean the
-                // db every 100s
-                static int syncCounter = 0;
-                if (syncCounter++ >= 500) {
-                        cache::deleteOldData();
-                        syncCounter = 0;
-                }
-        } catch (const lmdb::map_full_error &e) {
-                nhlog::db()->error("lmdb is full: {}", e.what());
-                cache::deleteOldData();
-        } catch (const lmdb::error &e) {
-                nhlog::db()->error("saving sync response: {}", e.what());
+        // if we process a lot of syncs (1 every 200ms), this means we clean the
+        // db every 100s
+        static int syncCounter = 0;
+        if (syncCounter++ >= 500) {
+            cache::deleteOldData();
+            syncCounter = 0;
         }
-
-        emit trySyncCb();
+    } catch (const lmdb::map_full_error &e) {
+        nhlog::db()->error("lmdb is full: {}", e.what());
+        cache::deleteOldData();
+    } catch (const lmdb::error &e) {
+        nhlog::db()->error("saving sync response: {}", e.what());
+    }
+
+    emit trySyncCb();
 }
 
 void
 ChatPage::trySync()
 {
-        mtx::http::SyncOpts opts;
-        opts.set_presence = currentPresence();
-
-        if (!connectivityTimer_.isActive())
-                connectivityTimer_.start();
-
-        try {
-                opts.since = cache::nextBatchToken();
-        } catch (const lmdb::error &e) {
-                nhlog::db()->error("failed to retrieve next batch token: {}", e.what());
-                return;
-        }
-
-        http::client()->sync(
-          opts,
-          [this, since = opts.since](const mtx::responses::Sync &res, mtx::http::RequestErr err) {
-                  if (err) {
-                          const auto error      = QString::fromStdString(err->matrix_error.error);
-                          const auto msg        = tr("Please try to login again: %1").arg(error);
-                          const auto err_code   = mtx::errors::to_string(err->matrix_error.errcode);
-                          const int status_code = static_cast<int>(err->status_code);
-
-                          if ((http::is_logged_in() &&
-                               (err->matrix_error.errcode ==
-                                  mtx::errors::ErrorCode::M_UNKNOWN_TOKEN ||
-                                err->matrix_error.errcode ==
-                                  mtx::errors::ErrorCode::M_MISSING_TOKEN)) ||
-                              !http::is_logged_in()) {
-                                  emit dropToLoginPageCb(msg);
-                                  return;
-                          }
-
-                          nhlog::net()->error("sync error: {} {} {} {}",
-                                              err->parse_error,
-                                              status_code,
-                                              err->error_code,
-                                              err_code);
-                          emit tryDelayedSyncCb();
-                          return;
-                  }
-
-                  emit newSyncResponse(res, since);
-          });
+    mtx::http::SyncOpts opts;
+    opts.set_presence = currentPresence();
+
+    if (!connectivityTimer_.isActive())
+        connectivityTimer_.start();
+
+    try {
+        opts.since = cache::nextBatchToken();
+    } catch (const lmdb::error &e) {
+        nhlog::db()->error("failed to retrieve next batch token: {}", e.what());
+        return;
+    }
+
+    http::client()->sync(
+      opts, [this, since = opts.since](const mtx::responses::Sync &res, mtx::http::RequestErr err) {
+          if (err) {
+              const auto error      = QString::fromStdString(err->matrix_error.error);
+              const auto msg        = tr("Please try to login again: %1").arg(error);
+              const auto err_code   = mtx::errors::to_string(err->matrix_error.errcode);
+              const int status_code = static_cast<int>(err->status_code);
+
+              if ((http::is_logged_in() &&
+                   (err->matrix_error.errcode == mtx::errors::ErrorCode::M_UNKNOWN_TOKEN ||
+                    err->matrix_error.errcode == mtx::errors::ErrorCode::M_MISSING_TOKEN)) ||
+                  !http::is_logged_in()) {
+                  emit dropToLoginPageCb(msg);
+                  return;
+              }
+
+              nhlog::net()->error("sync error: {} {} {} {}",
+                                  err->parse_error,
+                                  status_code,
+                                  err->error_code,
+                                  err_code);
+              emit tryDelayedSyncCb();
+              return;
+          }
+
+          emit newSyncResponse(res, since);
+      });
 }
 
 void
 ChatPage::joinRoom(const QString &room)
 {
-        const auto room_id = room.toStdString();
-        joinRoomVia(room_id, {}, false);
+    const auto room_id = room.toStdString();
+    joinRoomVia(room_id, {}, false);
 }
 
 void
@@ -711,692 +692,662 @@ ChatPage::joinRoomVia(const std::string &room_id,
                       const std::vector<std::string> &via,
                       bool promptForConfirmation)
 {
-        if (promptForConfirmation &&
-            QMessageBox::Yes !=
-              QMessageBox::question(
-                this,
-                tr("Confirm join"),
-                tr("Do you really want to join %1?").arg(QString::fromStdString(room_id))))
-                return;
-
-        http::client()->join_room(
-          room_id, via, [this, room_id](const mtx::responses::RoomId &, mtx::http::RequestErr err) {
-                  if (err) {
-                          emit showNotification(
-                            tr("Failed to join room: %1")
-                              .arg(QString::fromStdString(err->matrix_error.error)));
-                          return;
-                  }
-
-                  emit tr("You joined the room");
-
-                  // We remove any invites with the same room_id.
-                  try {
-                          cache::removeInvite(room_id);
-                  } catch (const lmdb::error &e) {
-                          emit showNotification(tr("Failed to remove invite: %1").arg(e.what()));
-                  }
-
-                  view_manager_->rooms()->setCurrentRoom(QString::fromStdString(room_id));
-          });
+    if (promptForConfirmation &&
+        QMessageBox::Yes !=
+          QMessageBox::question(
+            this,
+            tr("Confirm join"),
+            tr("Do you really want to join %1?").arg(QString::fromStdString(room_id))))
+        return;
+
+    http::client()->join_room(
+      room_id, via, [this, room_id](const mtx::responses::RoomId &, mtx::http::RequestErr err) {
+          if (err) {
+              emit showNotification(
+                tr("Failed to join room: %1").arg(QString::fromStdString(err->matrix_error.error)));
+              return;
+          }
+
+          emit tr("You joined the room");
+
+          // We remove any invites with the same room_id.
+          try {
+              cache::removeInvite(room_id);
+          } catch (const lmdb::error &e) {
+              emit showNotification(tr("Failed to remove invite: %1").arg(e.what()));
+          }
+
+          view_manager_->rooms()->setCurrentRoom(QString::fromStdString(room_id));
+      });
 }
 
 void
 ChatPage::createRoom(const mtx::requests::CreateRoom &req)
 {
-        http::client()->create_room(
-          req, [this](const mtx::responses::CreateRoom &res, mtx::http::RequestErr err) {
-                  if (err) {
-                          const auto err_code   = mtx::errors::to_string(err->matrix_error.errcode);
-                          const auto error      = err->matrix_error.error;
-                          const int status_code = static_cast<int>(err->status_code);
-
-                          nhlog::net()->warn(
-                            "failed to create room: {} {} ({})", error, err_code, status_code);
-
-                          emit showNotification(
-                            tr("Room creation failed: %1").arg(QString::fromStdString(error)));
-                          return;
-                  }
-
-                  QString newRoomId = QString::fromStdString(res.room_id.to_string());
-                  emit showNotification(tr("Room %1 created.").arg(newRoomId));
-                  emit newRoom(newRoomId);
-                  emit changeToRoom(newRoomId);
-          });
+    http::client()->create_room(
+      req, [this](const mtx::responses::CreateRoom &res, mtx::http::RequestErr err) {
+          if (err) {
+              const auto err_code   = mtx::errors::to_string(err->matrix_error.errcode);
+              const auto error      = err->matrix_error.error;
+              const int status_code = static_cast<int>(err->status_code);
+
+              nhlog::net()->warn("failed to create room: {} {} ({})", error, err_code, status_code);
+
+              emit showNotification(
+                tr("Room creation failed: %1").arg(QString::fromStdString(error)));
+              return;
+          }
+
+          QString newRoomId = QString::fromStdString(res.room_id.to_string());
+          emit showNotification(tr("Room %1 created.").arg(newRoomId));
+          emit newRoom(newRoomId);
+          emit changeToRoom(newRoomId);
+      });
 }
 
 void
 ChatPage::leaveRoom(const QString &room_id)
 {
-        http::client()->leave_room(
-          room_id.toStdString(),
-          [this, room_id](const mtx::responses::Empty &, mtx::http::RequestErr err) {
-                  if (err) {
-                          emit showNotification(
-                            tr("Failed to leave room: %1")
-                              .arg(QString::fromStdString(err->matrix_error.error)));
-                          return;
-                  }
-
-                  emit leftRoom(room_id);
-          });
+    http::client()->leave_room(
+      room_id.toStdString(),
+      [this, room_id](const mtx::responses::Empty &, mtx::http::RequestErr err) {
+          if (err) {
+              emit showNotification(tr("Failed to leave room: %1")
+                                      .arg(QString::fromStdString(err->matrix_error.error)));
+              return;
+          }
+
+          emit leftRoom(room_id);
+      });
 }
 
 void
 ChatPage::changeRoom(const QString &room_id)
 {
-        view_manager_->rooms()->setCurrentRoom(room_id);
+    view_manager_->rooms()->setCurrentRoom(room_id);
 }
 
 void
 ChatPage::inviteUser(QString userid, QString reason)
 {
-        auto room = currentRoom();
-
-        if (QMessageBox::question(this,
-                                  tr("Confirm invite"),
-                                  tr("Do you really want to invite %1 (%2)?")
-                                    .arg(cache::displayName(room, userid))
-                                    .arg(userid)) != QMessageBox::Yes)
-                return;
-
-        http::client()->invite_user(
-          room.toStdString(),
-          userid.toStdString(),
-          [this, userid, room](const mtx::responses::Empty &, mtx::http::RequestErr err) {
-                  if (err) {
-                          emit showNotification(
-                            tr("Failed to invite %1 to %2: %3")
-                              .arg(userid)
-                              .arg(room)
-                              .arg(QString::fromStdString(err->matrix_error.error)));
-                  } else
-                          emit showNotification(tr("Invited user: %1").arg(userid));
-          },
-          reason.trimmed().toStdString());
+    auto room = currentRoom();
+
+    if (QMessageBox::question(this,
+                              tr("Confirm invite"),
+                              tr("Do you really want to invite %1 (%2)?")
+                                .arg(cache::displayName(room, userid))
+                                .arg(userid)) != QMessageBox::Yes)
+        return;
+
+    http::client()->invite_user(
+      room.toStdString(),
+      userid.toStdString(),
+      [this, userid, room](const mtx::responses::Empty &, mtx::http::RequestErr err) {
+          if (err) {
+              emit showNotification(tr("Failed to invite %1 to %2: %3")
+                                      .arg(userid)
+                                      .arg(room)
+                                      .arg(QString::fromStdString(err->matrix_error.error)));
+          } else
+              emit showNotification(tr("Invited user: %1").arg(userid));
+      },
+      reason.trimmed().toStdString());
 }
 void
 ChatPage::kickUser(QString userid, QString reason)
 {
-        auto room = currentRoom();
-
-        if (QMessageBox::question(this,
-                                  tr("Confirm kick"),
-                                  tr("Do you really want to kick %1 (%2)?")
-                                    .arg(cache::displayName(room, userid))
-                                    .arg(userid)) != QMessageBox::Yes)
-                return;
-
-        http::client()->kick_user(
-          room.toStdString(),
-          userid.toStdString(),
-          [this, userid, room](const mtx::responses::Empty &, mtx::http::RequestErr err) {
-                  if (err) {
-                          emit showNotification(
-                            tr("Failed to kick %1 from %2: %3")
-                              .arg(userid)
-                              .arg(room)
-                              .arg(QString::fromStdString(err->matrix_error.error)));
-                  } else
-                          emit showNotification(tr("Kicked user: %1").arg(userid));
-          },
-          reason.trimmed().toStdString());
+    auto room = currentRoom();
+
+    if (QMessageBox::question(this,
+                              tr("Confirm kick"),
+                              tr("Do you really want to kick %1 (%2)?")
+                                .arg(cache::displayName(room, userid))
+                                .arg(userid)) != QMessageBox::Yes)
+        return;
+
+    http::client()->kick_user(
+      room.toStdString(),
+      userid.toStdString(),
+      [this, userid, room](const mtx::responses::Empty &, mtx::http::RequestErr err) {
+          if (err) {
+              emit showNotification(tr("Failed to kick %1 from %2: %3")
+                                      .arg(userid)
+                                      .arg(room)
+                                      .arg(QString::fromStdString(err->matrix_error.error)));
+          } else
+              emit showNotification(tr("Kicked user: %1").arg(userid));
+      },
+      reason.trimmed().toStdString());
 }
 void
 ChatPage::banUser(QString userid, QString reason)
 {
-        auto room = currentRoom();
-
-        if (QMessageBox::question(this,
-                                  tr("Confirm ban"),
-                                  tr("Do you really want to ban %1 (%2)?")
-                                    .arg(cache::displayName(room, userid))
-                                    .arg(userid)) != QMessageBox::Yes)
-                return;
-
-        http::client()->ban_user(
-          room.toStdString(),
-          userid.toStdString(),
-          [this, userid, room](const mtx::responses::Empty &, mtx::http::RequestErr err) {
-                  if (err) {
-                          emit showNotification(
-                            tr("Failed to ban %1 in %2: %3")
-                              .arg(userid)
-                              .arg(room)
-                              .arg(QString::fromStdString(err->matrix_error.error)));
-                  } else
-                          emit showNotification(tr("Banned user: %1").arg(userid));
-          },
-          reason.trimmed().toStdString());
+    auto room = currentRoom();
+
+    if (QMessageBox::question(this,
+                              tr("Confirm ban"),
+                              tr("Do you really want to ban %1 (%2)?")
+                                .arg(cache::displayName(room, userid))
+                                .arg(userid)) != QMessageBox::Yes)
+        return;
+
+    http::client()->ban_user(
+      room.toStdString(),
+      userid.toStdString(),
+      [this, userid, room](const mtx::responses::Empty &, mtx::http::RequestErr err) {
+          if (err) {
+              emit showNotification(tr("Failed to ban %1 in %2: %3")
+                                      .arg(userid)
+                                      .arg(room)
+                                      .arg(QString::fromStdString(err->matrix_error.error)));
+          } else
+              emit showNotification(tr("Banned user: %1").arg(userid));
+      },
+      reason.trimmed().toStdString());
 }
 void
 ChatPage::unbanUser(QString userid, QString reason)
 {
-        auto room = currentRoom();
-
-        if (QMessageBox::question(this,
-                                  tr("Confirm unban"),
-                                  tr("Do you really want to unban %1 (%2)?")
-                                    .arg(cache::displayName(room, userid))
-                                    .arg(userid)) != QMessageBox::Yes)
-                return;
-
-        http::client()->unban_user(
-          room.toStdString(),
-          userid.toStdString(),
-          [this, userid, room](const mtx::responses::Empty &, mtx::http::RequestErr err) {
-                  if (err) {
-                          emit showNotification(
-                            tr("Failed to unban %1 in %2: %3")
-                              .arg(userid)
-                              .arg(room)
-                              .arg(QString::fromStdString(err->matrix_error.error)));
-                  } else
-                          emit showNotification(tr("Unbanned user: %1").arg(userid));
-          },
-          reason.trimmed().toStdString());
+    auto room = currentRoom();
+
+    if (QMessageBox::question(this,
+                              tr("Confirm unban"),
+                              tr("Do you really want to unban %1 (%2)?")
+                                .arg(cache::displayName(room, userid))
+                                .arg(userid)) != QMessageBox::Yes)
+        return;
+
+    http::client()->unban_user(
+      room.toStdString(),
+      userid.toStdString(),
+      [this, userid, room](const mtx::responses::Empty &, mtx::http::RequestErr err) {
+          if (err) {
+              emit showNotification(tr("Failed to unban %1 in %2: %3")
+                                      .arg(userid)
+                                      .arg(room)
+                                      .arg(QString::fromStdString(err->matrix_error.error)));
+          } else
+              emit showNotification(tr("Unbanned user: %1").arg(userid));
+      },
+      reason.trimmed().toStdString());
 }
 
 void
 ChatPage::receivedSessionKey(const std::string &room_id, const std::string &session_id)
 {
-        view_manager_->receivedSessionKey(room_id, session_id);
+    view_manager_->receivedSessionKey(room_id, session_id);
 }
 
 QString
 ChatPage::status() const
 {
-        return QString::fromStdString(cache::statusMessage(utils::localUser().toStdString()));
+    return QString::fromStdString(cache::statusMessage(utils::localUser().toStdString()));
 }
 
 void
 ChatPage::setStatus(const QString &status)
 {
-        http::client()->put_presence_status(
-          currentPresence(), status.toStdString(), [](mtx::http::RequestErr err) {
-                  if (err) {
-                          nhlog::net()->warn("failed to set presence status_msg: {}",
-                                             err->matrix_error.error);
-                  }
-          });
+    http::client()->put_presence_status(
+      currentPresence(), status.toStdString(), [](mtx::http::RequestErr err) {
+          if (err) {
+              nhlog::net()->warn("failed to set presence status_msg: {}", err->matrix_error.error);
+          }
+      });
 }
 
 mtx::presence::PresenceState
 ChatPage::currentPresence() const
 {
-        switch (userSettings_->presence()) {
-        case UserSettings::Presence::Online:
-                return mtx::presence::online;
-        case UserSettings::Presence::Unavailable:
-                return mtx::presence::unavailable;
-        case UserSettings::Presence::Offline:
-                return mtx::presence::offline;
-        default:
-                return mtx::presence::online;
-        }
+    switch (userSettings_->presence()) {
+    case UserSettings::Presence::Online:
+        return mtx::presence::online;
+    case UserSettings::Presence::Unavailable:
+        return mtx::presence::unavailable;
+    case UserSettings::Presence::Offline:
+        return mtx::presence::offline;
+    default:
+        return mtx::presence::online;
+    }
 }
 
 void
 ChatPage::verifyOneTimeKeyCountAfterStartup()
 {
-        http::client()->upload_keys(
-          olm::client()->create_upload_keys_request(),
-          [this](const mtx::responses::UploadKeys &res, mtx::http::RequestErr err) {
-                  if (err) {
-                          nhlog::crypto()->warn("failed to update one-time keys: {} {} {}",
-                                                err->matrix_error.error,
-                                                static_cast<int>(err->status_code),
-                                                static_cast<int>(err->error_code));
-
-                          if (err->status_code < 400 || err->status_code >= 500)
-                                  return;
-                  }
-
-                  std::map<std::string, uint16_t> key_counts;
-                  auto count = 0;
-                  if (auto c = res.one_time_key_counts.find(mtx::crypto::SIGNED_CURVE25519);
-                      c == res.one_time_key_counts.end()) {
-                          key_counts[mtx::crypto::SIGNED_CURVE25519] = 0;
-                  } else {
-                          key_counts[mtx::crypto::SIGNED_CURVE25519] = c->second;
-                          count                                      = c->second;
-                  }
-
-                  nhlog::crypto()->info(
-                    "Fetched server key count {} {}", count, mtx::crypto::SIGNED_CURVE25519);
-
-                  ensureOneTimeKeyCount(key_counts);
-          });
+    http::client()->upload_keys(
+      olm::client()->create_upload_keys_request(),
+      [this](const mtx::responses::UploadKeys &res, mtx::http::RequestErr err) {
+          if (err) {
+              nhlog::crypto()->warn("failed to update one-time keys: {} {} {}",
+                                    err->matrix_error.error,
+                                    static_cast<int>(err->status_code),
+                                    static_cast<int>(err->error_code));
+
+              if (err->status_code < 400 || err->status_code >= 500)
+                  return;
+          }
+
+          std::map<std::string, uint16_t> key_counts;
+          auto count = 0;
+          if (auto c = res.one_time_key_counts.find(mtx::crypto::SIGNED_CURVE25519);
+              c == res.one_time_key_counts.end()) {
+              key_counts[mtx::crypto::SIGNED_CURVE25519] = 0;
+          } else {
+              key_counts[mtx::crypto::SIGNED_CURVE25519] = c->second;
+              count                                      = c->second;
+          }
+
+          nhlog::crypto()->info(
+            "Fetched server key count {} {}", count, mtx::crypto::SIGNED_CURVE25519);
+
+          ensureOneTimeKeyCount(key_counts);
+      });
 }
 
 void
 ChatPage::ensureOneTimeKeyCount(const std::map<std::string, uint16_t> &counts)
 {
-        if (auto count = counts.find(mtx::crypto::SIGNED_CURVE25519); count != counts.end()) {
-                nhlog::crypto()->debug(
-                  "Updated server key count {} {}", count->second, mtx::crypto::SIGNED_CURVE25519);
-
-                if (count->second < MAX_ONETIME_KEYS) {
-                        const int nkeys = MAX_ONETIME_KEYS - count->second;
-
-                        nhlog::crypto()->info(
-                          "uploading {} {} keys", nkeys, mtx::crypto::SIGNED_CURVE25519);
-                        olm::client()->generate_one_time_keys(nkeys);
-
-                        http::client()->upload_keys(
-                          olm::client()->create_upload_keys_request(),
-                          [](const mtx::responses::UploadKeys &, mtx::http::RequestErr err) {
-                                  if (err) {
-                                          nhlog::crypto()->warn(
-                                            "failed to update one-time keys: {} {} {}",
+    if (auto count = counts.find(mtx::crypto::SIGNED_CURVE25519); count != counts.end()) {
+        nhlog::crypto()->debug(
+          "Updated server key count {} {}", count->second, mtx::crypto::SIGNED_CURVE25519);
+
+        if (count->second < MAX_ONETIME_KEYS) {
+            const int nkeys = MAX_ONETIME_KEYS - count->second;
+
+            nhlog::crypto()->info("uploading {} {} keys", nkeys, mtx::crypto::SIGNED_CURVE25519);
+            olm::client()->generate_one_time_keys(nkeys);
+
+            http::client()->upload_keys(
+              olm::client()->create_upload_keys_request(),
+              [](const mtx::responses::UploadKeys &, mtx::http::RequestErr err) {
+                  if (err) {
+                      nhlog::crypto()->warn("failed to update one-time keys: {} {} {}",
                                             err->matrix_error.error,
                                             static_cast<int>(err->status_code),
                                             static_cast<int>(err->error_code));
 
-                                          if (err->status_code < 400 || err->status_code >= 500)
-                                                  return;
-                                  }
-
-                                  // mark as published anyway, otherwise we may end up in a loop.
-                                  olm::mark_keys_as_published();
-                          });
-                } else if (count->second > 2 * MAX_ONETIME_KEYS) {
-                        nhlog::crypto()->warn("too many one-time keys, deleting 1");
-                        mtx::requests::ClaimKeys req;
-                        req.one_time_keys[http::client()->user_id().to_string()]
-                                         [http::client()->device_id()] =
-                          std::string(mtx::crypto::SIGNED_CURVE25519);
-                        http::client()->claim_keys(
-                          req, [](const mtx::responses::ClaimKeys &, mtx::http::RequestErr err) {
-                                  if (err)
-                                          nhlog::crypto()->warn(
-                                            "failed to clear 1 one-time key: {} {} {}",
+                      if (err->status_code < 400 || err->status_code >= 500)
+                          return;
+                  }
+
+                  // mark as published anyway, otherwise we may end up in a loop.
+                  olm::mark_keys_as_published();
+              });
+        } else if (count->second > 2 * MAX_ONETIME_KEYS) {
+            nhlog::crypto()->warn("too many one-time keys, deleting 1");
+            mtx::requests::ClaimKeys req;
+            req.one_time_keys[http::client()->user_id().to_string()][http::client()->device_id()] =
+              std::string(mtx::crypto::SIGNED_CURVE25519);
+            http::client()->claim_keys(
+              req, [](const mtx::responses::ClaimKeys &, mtx::http::RequestErr err) {
+                  if (err)
+                      nhlog::crypto()->warn("failed to clear 1 one-time key: {} {} {}",
                                             err->matrix_error.error,
                                             static_cast<int>(err->status_code),
                                             static_cast<int>(err->error_code));
-                                  else
-                                          nhlog::crypto()->info("cleared 1 one-time key");
-                          });
-                }
+                  else
+                      nhlog::crypto()->info("cleared 1 one-time key");
+              });
         }
+    }
 }
 
 void
 ChatPage::getProfileInfo()
 {
-        const auto userid = utils::localUser().toStdString();
+    const auto userid = utils::localUser().toStdString();
 
-        http::client()->get_profile(
-          userid, [this](const mtx::responses::Profile &res, mtx::http::RequestErr err) {
-                  if (err) {
-                          nhlog::net()->warn("failed to retrieve own profile info");
-                          return;
-                  }
+    http::client()->get_profile(
+      userid, [this](const mtx::responses::Profile &res, mtx::http::RequestErr err) {
+          if (err) {
+              nhlog::net()->warn("failed to retrieve own profile info");
+              return;
+          }
 
-                  emit setUserDisplayName(QString::fromStdString(res.display_name));
+          emit setUserDisplayName(QString::fromStdString(res.display_name));
 
-                  emit setUserAvatar(QString::fromStdString(res.avatar_url));
-          });
+          emit setUserAvatar(QString::fromStdString(res.avatar_url));
+      });
 }
 
 void
 ChatPage::getBackupVersion()
 {
-        if (!UserSettings::instance()->useOnlineKeyBackup()) {
-                nhlog::crypto()->info("Online key backup disabled.");
-                return;
-        }
-
-        http::client()->backup_version(
-          [this](const mtx::responses::backup::BackupVersion &res, mtx::http::RequestErr err) {
-                  if (err) {
-                          nhlog::net()->warn("Failed to retrieve backup version");
-                          if (err->status_code == 404)
-                                  cache::client()->deleteBackupVersion();
-                          return;
+    if (!UserSettings::instance()->useOnlineKeyBackup()) {
+        nhlog::crypto()->info("Online key backup disabled.");
+        return;
+    }
+
+    http::client()->backup_version(
+      [this](const mtx::responses::backup::BackupVersion &res, mtx::http::RequestErr err) {
+          if (err) {
+              nhlog::net()->warn("Failed to retrieve backup version");
+              if (err->status_code == 404)
+                  cache::client()->deleteBackupVersion();
+              return;
+          }
+
+          // switch to UI thread for secrets stuff
+          QTimer::singleShot(0, this, [res] {
+              auto auth_data = nlohmann::json::parse(res.auth_data);
+
+              if (res.algorithm == "m.megolm_backup.v1.curve25519-aes-sha2") {
+                  auto key = cache::secret(mtx::secret_storage::secrets::megolm_backup_v1);
+                  if (!key) {
+                      nhlog::crypto()->info("No key for online key backup.");
+                      cache::client()->deleteBackupVersion();
+                      return;
                   }
 
-                  // switch to UI thread for secrets stuff
-                  QTimer::singleShot(0, this, [res] {
-                          auto auth_data = nlohmann::json::parse(res.auth_data);
-
-                          if (res.algorithm == "m.megolm_backup.v1.curve25519-aes-sha2") {
-                                  auto key =
-                                    cache::secret(mtx::secret_storage::secrets::megolm_backup_v1);
-                                  if (!key) {
-                                          nhlog::crypto()->info("No key for online key backup.");
-                                          cache::client()->deleteBackupVersion();
-                                          return;
-                                  }
-
-                                  using namespace mtx::crypto;
-                                  auto pubkey = CURVE25519_public_key_from_private(
-                                    to_binary_buf(base642bin(*key)));
-
-                                  if (auth_data["public_key"].get<std::string>() != pubkey) {
-                                          nhlog::crypto()->info(
-                                            "Our backup key {} does not match the one "
+                  using namespace mtx::crypto;
+                  auto pubkey = CURVE25519_public_key_from_private(to_binary_buf(base642bin(*key)));
+
+                  if (auth_data["public_key"].get<std::string>() != pubkey) {
+                      nhlog::crypto()->info("Our backup key {} does not match the one "
                                             "used in the online backup {}",
                                             pubkey,
                                             auth_data["public_key"]);
-                                          cache::client()->deleteBackupVersion();
-                                          return;
-                                  }
-
-                                  nhlog::crypto()->info("Using online key backup.");
-                                  OnlineBackupVersion data{};
-                                  data.algorithm = res.algorithm;
-                                  data.version   = res.version;
-                                  cache::client()->saveBackupVersion(data);
-                          } else {
-                                  nhlog::crypto()->info("Unsupported key backup algorithm: {}",
-                                                        res.algorithm);
-                                  cache::client()->deleteBackupVersion();
-                          }
-                  });
+                      cache::client()->deleteBackupVersion();
+                      return;
+                  }
+
+                  nhlog::crypto()->info("Using online key backup.");
+                  OnlineBackupVersion data{};
+                  data.algorithm = res.algorithm;
+                  data.version   = res.version;
+                  cache::client()->saveBackupVersion(data);
+              } else {
+                  nhlog::crypto()->info("Unsupported key backup algorithm: {}", res.algorithm);
+                  cache::client()->deleteBackupVersion();
+              }
           });
+      });
 }
 
 void
 ChatPage::initiateLogout()
 {
-        http::client()->logout([this](const mtx::responses::Logout &, mtx::http::RequestErr err) {
-                if (err) {
-                        // TODO: handle special errors
-                        emit contentLoaded();
-                        nhlog::net()->warn("failed to logout: {} - {}",
-                                           mtx::errors::to_string(err->matrix_error.errcode),
-                                           err->matrix_error.error);
-                        return;
-                }
+    http::client()->logout([this](const mtx::responses::Logout &, mtx::http::RequestErr err) {
+        if (err) {
+            // TODO: handle special errors
+            emit contentLoaded();
+            nhlog::net()->warn("failed to logout: {} - {}",
+                               mtx::errors::to_string(err->matrix_error.errcode),
+                               err->matrix_error.error);
+            return;
+        }
 
-                emit loggedOut();
-        });
+        emit loggedOut();
+    });
 
-        emit showOverlayProgressBar();
+    emit showOverlayProgressBar();
 }
 
 template<typename T>
 void
 ChatPage::connectCallMessage()
 {
-        connect(callManager_,
-                qOverload<const QString &, const T &>(&CallManager::newMessage),
-                view_manager_,
-                qOverload<const QString &, const T &>(&TimelineViewManager::queueCallMessage));
+    connect(callManager_,
+            qOverload<const QString &, const T &>(&CallManager::newMessage),
+            view_manager_,
+            qOverload<const QString &, const T &>(&TimelineViewManager::queueCallMessage));
 }
 
 void
 ChatPage::decryptDownloadedSecrets(mtx::secret_storage::AesHmacSha2KeyDescription keyDesc,
                                    const SecretsToDecrypt &secrets)
 {
-        QString text = QInputDialog::getText(
-          ChatPage::instance(),
-          QCoreApplication::translate("CrossSigningSecrets", "Decrypt secrets"),
-          keyDesc.name.empty()
-            ? QCoreApplication::translate(
-                "CrossSigningSecrets",
-                "Enter your recovery key or passphrase to decrypt your secrets:")
-            : QCoreApplication::translate(
-                "CrossSigningSecrets",
-                "Enter your recovery key or passphrase called %1 to decrypt your secrets:")
-                .arg(QString::fromStdString(keyDesc.name)),
-          QLineEdit::Password);
-
-        if (text.isEmpty())
-                return;
-
-        auto decryptionKey = mtx::crypto::key_from_recoverykey(text.toStdString(), keyDesc);
-
-        if (!decryptionKey && keyDesc.passphrase) {
-                try {
-                        decryptionKey =
-                          mtx::crypto::key_from_passphrase(text.toStdString(), keyDesc);
-                } catch (std::exception &e) {
-                        nhlog::crypto()->error("Failed to derive secret key from passphrase: {}",
-                                               e.what());
-                }
-        }
-
-        if (!decryptionKey) {
-                QMessageBox::information(
-                  ChatPage::instance(),
-                  QCoreApplication::translate("CrossSigningSecrets", "Decryption failed"),
-                  QCoreApplication::translate("CrossSigningSecrets",
-                                              "Failed to decrypt secrets with the "
-                                              "provided recovery key or passphrase"));
-                return;
+    QString text = QInputDialog::getText(
+      ChatPage::instance(),
+      QCoreApplication::translate("CrossSigningSecrets", "Decrypt secrets"),
+      keyDesc.name.empty()
+        ? QCoreApplication::translate(
+            "CrossSigningSecrets", "Enter your recovery key or passphrase to decrypt your secrets:")
+        : QCoreApplication::translate(
+            "CrossSigningSecrets",
+            "Enter your recovery key or passphrase called %1 to decrypt your secrets:")
+            .arg(QString::fromStdString(keyDesc.name)),
+      QLineEdit::Password);
+
+    if (text.isEmpty())
+        return;
+
+    auto decryptionKey = mtx::crypto::key_from_recoverykey(text.toStdString(), keyDesc);
+
+    if (!decryptionKey && keyDesc.passphrase) {
+        try {
+            decryptionKey = mtx::crypto::key_from_passphrase(text.toStdString(), keyDesc);
+        } catch (std::exception &e) {
+            nhlog::crypto()->error("Failed to derive secret key from passphrase: {}", e.what());
         }
+    }
 
-        for (const auto &[secretName, encryptedSecret] : secrets) {
-                auto decrypted = mtx::crypto::decrypt(encryptedSecret, *decryptionKey, secretName);
-                if (!decrypted.empty())
-                        cache::storeSecret(secretName, decrypted);
-        }
+    if (!decryptionKey) {
+        QMessageBox::information(
+          ChatPage::instance(),
+          QCoreApplication::translate("CrossSigningSecrets", "Decryption failed"),
+          QCoreApplication::translate("CrossSigningSecrets",
+                                      "Failed to decrypt secrets with the "
+                                      "provided recovery key or passphrase"));
+        return;
+    }
+
+    for (const auto &[secretName, encryptedSecret] : secrets) {
+        auto decrypted = mtx::crypto::decrypt(encryptedSecret, *decryptionKey, secretName);
+        if (!decrypted.empty())
+            cache::storeSecret(secretName, decrypted);
+    }
 }
 
 void
 ChatPage::startChat(QString userid)
 {
-        auto joined_rooms = cache::joinedRooms();
-        auto room_infos   = cache::getRoomInfo(joined_rooms);
-
-        for (std::string room_id : joined_rooms) {
-                if (room_infos[QString::fromStdString(room_id)].member_count == 2) {
-                        auto room_members = cache::roomMembers(room_id);
-                        if (std::find(room_members.begin(),
-                                      room_members.end(),
-                                      (userid).toStdString()) != room_members.end()) {
-                                view_manager_->rooms()->setCurrentRoom(
-                                  QString::fromStdString(room_id));
-                                return;
-                        }
-                }
-        }
-
-        if (QMessageBox::Yes !=
-            QMessageBox::question(
-              this,
-              tr("Confirm invite"),
-              tr("Do you really want to start a private chat with %1?").arg(userid)))
+    auto joined_rooms = cache::joinedRooms();
+    auto room_infos   = cache::getRoomInfo(joined_rooms);
+
+    for (std::string room_id : joined_rooms) {
+        if (room_infos[QString::fromStdString(room_id)].member_count == 2) {
+            auto room_members = cache::roomMembers(room_id);
+            if (std::find(room_members.begin(), room_members.end(), (userid).toStdString()) !=
+                room_members.end()) {
+                view_manager_->rooms()->setCurrentRoom(QString::fromStdString(room_id));
                 return;
-
-        mtx::requests::CreateRoom req;
-        req.preset     = mtx::requests::Preset::PrivateChat;
-        req.visibility = mtx::common::RoomVisibility::Private;
-        if (utils::localUser() != userid) {
-                req.invite    = {userid.toStdString()};
-                req.is_direct = true;
+            }
         }
-        emit ChatPage::instance()->createRoom(req);
+    }
+
+    if (QMessageBox::Yes !=
+        QMessageBox::question(
+          this,
+          tr("Confirm invite"),
+          tr("Do you really want to start a private chat with %1?").arg(userid)))
+        return;
+
+    mtx::requests::CreateRoom req;
+    req.preset     = mtx::requests::Preset::PrivateChat;
+    req.visibility = mtx::common::RoomVisibility::Private;
+    if (utils::localUser() != userid) {
+        req.invite    = {userid.toStdString()};
+        req.is_direct = true;
+    }
+    emit ChatPage::instance()->createRoom(req);
 }
 
 static QString
 mxidFromSegments(QStringRef sigil, QStringRef mxid)
 {
-        if (mxid.isEmpty())
-                return "";
-
-        auto mxid_ = QUrl::fromPercentEncoding(mxid.toUtf8());
-
-        if (sigil == "u") {
-                return "@" + mxid_;
-        } else if (sigil == "roomid") {
-                return "!" + mxid_;
-        } else if (sigil == "r") {
-                return "#" + mxid_;
-                //} else if (sigil == "group") {
-                //        return "+" + mxid_;
-        } else {
-                return "";
-        }
+    if (mxid.isEmpty())
+        return "";
+
+    auto mxid_ = QUrl::fromPercentEncoding(mxid.toUtf8());
+
+    if (sigil == "u") {
+        return "@" + mxid_;
+    } else if (sigil == "roomid") {
+        return "!" + mxid_;
+    } else if (sigil == "r") {
+        return "#" + mxid_;
+        //} else if (sigil == "group") {
+        //        return "+" + mxid_;
+    } else {
+        return "";
+    }
 }
 
 bool
 ChatPage::handleMatrixUri(const QByteArray &uri)
 {
-        nhlog::ui()->info("Received uri! {}", uri.toStdString());
-        QUrl uri_{QString::fromUtf8(uri)};
-
-        // Convert matrix.to URIs to proper format
-        if (uri_.scheme() == "https" && uri_.host() == "matrix.to") {
-                QString p = uri_.fragment(QUrl::FullyEncoded);
-                if (p.startsWith("/"))
-                        p.remove(0, 1);
-
-                auto temp = p.split("?");
-                QString query;
-                if (temp.size() >= 2)
-                        query = QUrl::fromPercentEncoding(temp.takeAt(1).toUtf8());
-
-                temp            = temp.first().split("/");
-                auto identifier = QUrl::fromPercentEncoding(temp.takeFirst().toUtf8());
-                QString eventId = QUrl::fromPercentEncoding(temp.join('/').toUtf8());
-                if (!identifier.isEmpty()) {
-                        if (identifier.startsWith("@")) {
-                                QByteArray newUri =
-                                  "matrix:u/" + QUrl::toPercentEncoding(identifier.remove(0, 1));
-                                if (!query.isEmpty())
-                                        newUri.append("?" + query.toUtf8());
-                                return handleMatrixUri(QUrl::fromEncoded(newUri));
-                        } else if (identifier.startsWith("#")) {
-                                QByteArray newUri =
-                                  "matrix:r/" + QUrl::toPercentEncoding(identifier.remove(0, 1));
-                                if (!eventId.isEmpty())
-                                        newUri.append(
-                                          "/e/" + QUrl::toPercentEncoding(eventId.remove(0, 1)));
-                                if (!query.isEmpty())
-                                        newUri.append("?" + query.toUtf8());
-                                return handleMatrixUri(QUrl::fromEncoded(newUri));
-                        } else if (identifier.startsWith("!")) {
-                                QByteArray newUri = "matrix:roomid/" + QUrl::toPercentEncoding(
-                                                                         identifier.remove(0, 1));
-                                if (!eventId.isEmpty())
-                                        newUri.append(
-                                          "/e/" + QUrl::toPercentEncoding(eventId.remove(0, 1)));
-                                if (!query.isEmpty())
-                                        newUri.append("?" + query.toUtf8());
-                                return handleMatrixUri(QUrl::fromEncoded(newUri));
-                        }
-                }
+    nhlog::ui()->info("Received uri! {}", uri.toStdString());
+    QUrl uri_{QString::fromUtf8(uri)};
+
+    // Convert matrix.to URIs to proper format
+    if (uri_.scheme() == "https" && uri_.host() == "matrix.to") {
+        QString p = uri_.fragment(QUrl::FullyEncoded);
+        if (p.startsWith("/"))
+            p.remove(0, 1);
+
+        auto temp = p.split("?");
+        QString query;
+        if (temp.size() >= 2)
+            query = QUrl::fromPercentEncoding(temp.takeAt(1).toUtf8());
+
+        temp            = temp.first().split("/");
+        auto identifier = QUrl::fromPercentEncoding(temp.takeFirst().toUtf8());
+        QString eventId = QUrl::fromPercentEncoding(temp.join('/').toUtf8());
+        if (!identifier.isEmpty()) {
+            if (identifier.startsWith("@")) {
+                QByteArray newUri = "matrix:u/" + QUrl::toPercentEncoding(identifier.remove(0, 1));
+                if (!query.isEmpty())
+                    newUri.append("?" + query.toUtf8());
+                return handleMatrixUri(QUrl::fromEncoded(newUri));
+            } else if (identifier.startsWith("#")) {
+                QByteArray newUri = "matrix:r/" + QUrl::toPercentEncoding(identifier.remove(0, 1));
+                if (!eventId.isEmpty())
+                    newUri.append("/e/" + QUrl::toPercentEncoding(eventId.remove(0, 1)));
+                if (!query.isEmpty())
+                    newUri.append("?" + query.toUtf8());
+                return handleMatrixUri(QUrl::fromEncoded(newUri));
+            } else if (identifier.startsWith("!")) {
+                QByteArray newUri =
+                  "matrix:roomid/" + QUrl::toPercentEncoding(identifier.remove(0, 1));
+                if (!eventId.isEmpty())
+                    newUri.append("/e/" + QUrl::toPercentEncoding(eventId.remove(0, 1)));
+                if (!query.isEmpty())
+                    newUri.append("?" + query.toUtf8());
+                return handleMatrixUri(QUrl::fromEncoded(newUri));
+            }
         }
+    }
 
-        // non-matrix URIs are not handled by us, return false
-        if (uri_.scheme() != "matrix")
-                return false;
-
-        auto tempPath = uri_.path(QUrl::ComponentFormattingOption::FullyEncoded);
-        if (tempPath.startsWith('/'))
-                tempPath.remove(0, 1);
-        auto segments = tempPath.splitRef('/');
-
-        if (segments.size() != 2 && segments.size() != 4)
-                return false;
-
-        auto sigil1 = segments[0];
-        auto mxid1  = mxidFromSegments(sigil1, segments[1]);
-        if (mxid1.isEmpty())
-                return false;
-
-        QString mxid2;
-        if (segments.size() == 4 && segments[2] == "e") {
-                if (segments[3].isEmpty())
-                        return false;
-                else
-                        mxid2 = "$" + QUrl::fromPercentEncoding(segments[3].toUtf8());
-        }
+    // non-matrix URIs are not handled by us, return false
+    if (uri_.scheme() != "matrix")
+        return false;
 
-        std::vector<std::string> vias;
-        QString action;
+    auto tempPath = uri_.path(QUrl::ComponentFormattingOption::FullyEncoded);
+    if (tempPath.startsWith('/'))
+        tempPath.remove(0, 1);
+    auto segments = tempPath.splitRef('/');
 
-        for (QString item : uri_.query(QUrl::ComponentFormattingOption::FullyEncoded).split('&')) {
-                nhlog::ui()->info("item: {}", item.toStdString());
+    if (segments.size() != 2 && segments.size() != 4)
+        return false;
 
-                if (item.startsWith("action=")) {
-                        action = item.remove("action=");
-                } else if (item.startsWith("via=")) {
-                        vias.push_back(
-                          QUrl::fromPercentEncoding(item.remove("via=").toUtf8()).toStdString());
-                }
+    auto sigil1 = segments[0];
+    auto mxid1  = mxidFromSegments(sigil1, segments[1]);
+    if (mxid1.isEmpty())
+        return false;
+
+    QString mxid2;
+    if (segments.size() == 4 && segments[2] == "e") {
+        if (segments[3].isEmpty())
+            return false;
+        else
+            mxid2 = "$" + QUrl::fromPercentEncoding(segments[3].toUtf8());
+    }
+
+    std::vector<std::string> vias;
+    QString action;
+
+    for (QString item : uri_.query(QUrl::ComponentFormattingOption::FullyEncoded).split('&')) {
+        nhlog::ui()->info("item: {}", item.toStdString());
+
+        if (item.startsWith("action=")) {
+            action = item.remove("action=");
+        } else if (item.startsWith("via=")) {
+            vias.push_back(QUrl::fromPercentEncoding(item.remove("via=").toUtf8()).toStdString());
         }
+    }
 
-        if (sigil1 == "u") {
-                if (action.isEmpty()) {
-                        auto t = view_manager_->rooms()->currentRoom();
-                        if (t &&
-                            cache::isRoomMember(mxid1.toStdString(), t->roomId().toStdString())) {
-                                t->openUserProfile(mxid1);
-                                return true;
-                        }
-                        emit view_manager_->openGlobalUserProfile(mxid1);
-                } else if (action == "chat") {
-                        this->startChat(mxid1);
-                }
+    if (sigil1 == "u") {
+        if (action.isEmpty()) {
+            auto t = view_manager_->rooms()->currentRoom();
+            if (t && cache::isRoomMember(mxid1.toStdString(), t->roomId().toStdString())) {
+                t->openUserProfile(mxid1);
                 return true;
-        } else if (sigil1 == "roomid") {
-                auto joined_rooms = cache::joinedRooms();
-                auto targetRoomId = mxid1.toStdString();
-
-                for (auto roomid : joined_rooms) {
-                        if (roomid == targetRoomId) {
-                                view_manager_->rooms()->setCurrentRoom(mxid1);
-                                if (!mxid2.isEmpty())
-                                        view_manager_->showEvent(mxid1, mxid2);
-                                return true;
-                        }
-                }
+            }
+            emit view_manager_->openGlobalUserProfile(mxid1);
+        } else if (action == "chat") {
+            this->startChat(mxid1);
+        }
+        return true;
+    } else if (sigil1 == "roomid") {
+        auto joined_rooms = cache::joinedRooms();
+        auto targetRoomId = mxid1.toStdString();
 
-                if (action == "join" || action.isEmpty()) {
-                        joinRoomVia(targetRoomId, vias);
-                        return true;
-                }
-                return false;
-        } else if (sigil1 == "r") {
-                auto joined_rooms    = cache::joinedRooms();
-                auto targetRoomAlias = mxid1.toStdString();
-
-                for (auto roomid : joined_rooms) {
-                        auto aliases = cache::client()->getRoomAliases(roomid);
-                        if (aliases) {
-                                if (aliases->alias == targetRoomAlias) {
-                                        view_manager_->rooms()->setCurrentRoom(
-                                          QString::fromStdString(roomid));
-                                        if (!mxid2.isEmpty())
-                                                view_manager_->showEvent(
-                                                  QString::fromStdString(roomid), mxid2);
-                                        return true;
-                                }
-                        }
-                }
+        for (auto roomid : joined_rooms) {
+            if (roomid == targetRoomId) {
+                view_manager_->rooms()->setCurrentRoom(mxid1);
+                if (!mxid2.isEmpty())
+                    view_manager_->showEvent(mxid1, mxid2);
+                return true;
+            }
+        }
 
-                if (action == "join" || action.isEmpty()) {
-                        joinRoomVia(mxid1.toStdString(), vias);
-                        return true;
+        if (action == "join" || action.isEmpty()) {
+            joinRoomVia(targetRoomId, vias);
+            return true;
+        }
+        return false;
+    } else if (sigil1 == "r") {
+        auto joined_rooms    = cache::joinedRooms();
+        auto targetRoomAlias = mxid1.toStdString();
+
+        for (auto roomid : joined_rooms) {
+            auto aliases = cache::client()->getRoomAliases(roomid);
+            if (aliases) {
+                if (aliases->alias == targetRoomAlias) {
+                    view_manager_->rooms()->setCurrentRoom(QString::fromStdString(roomid));
+                    if (!mxid2.isEmpty())
+                        view_manager_->showEvent(QString::fromStdString(roomid), mxid2);
+                    return true;
                 }
-                return false;
+            }
+        }
+
+        if (action == "join" || action.isEmpty()) {
+            joinRoomVia(mxid1.toStdString(), vias);
+            return true;
         }
         return false;
+    }
+    return false;
 }
 
 bool
 ChatPage::handleMatrixUri(const QUrl &uri)
 {
-        return handleMatrixUri(
-          uri.toString(QUrl::ComponentFormattingOption::FullyEncoded).toUtf8());
+    return handleMatrixUri(uri.toString(QUrl::ComponentFormattingOption::FullyEncoded).toUtf8());
 }
 
 bool
 ChatPage::isRoomActive(const QString &room_id)
 {
-        return isActiveWindow() && currentRoom() == room_id;
+    return isActiveWindow() && currentRoom() == room_id;
 }
 
 QString
 ChatPage::currentRoom() const
 {
-        if (view_manager_->rooms()->currentRoom())
-                return view_manager_->rooms()->currentRoom()->roomId();
-        else
-                return "";
+    if (view_manager_->rooms()->currentRoom())
+        return view_manager_->rooms()->currentRoom()->roomId();
+    else
+        return "";
 }
diff --git a/src/ChatPage.h b/src/ChatPage.h
index 66e4c6ab..8f3dc53e 100644
--- a/src/ChatPage.h
+++ b/src/ChatPage.h
@@ -52,186 +52,181 @@ using SecretsToDecrypt = std::map<std::string, mtx::secret_storage::AesHmacSha2E
 
 class ChatPage : public QWidget
 {
-        Q_OBJECT
+    Q_OBJECT
 
 public:
-        ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent = nullptr);
+    ChatPage(QSharedPointer<UserSettings> userSettings, QWidget *parent = nullptr);
 
-        // Initialize all the components of the UI.
-        void bootstrap(QString userid, QString homeserver, QString token);
+    // Initialize all the components of the UI.
+    void bootstrap(QString userid, QString homeserver, QString token);
 
-        static ChatPage *instance() { return instance_; }
+    static ChatPage *instance() { return instance_; }
 
-        QSharedPointer<UserSettings> userSettings() { return userSettings_; }
-        CallManager *callManager() { return callManager_; }
-        TimelineViewManager *timelineManager() { return view_manager_; }
-        void deleteConfigs();
+    QSharedPointer<UserSettings> userSettings() { return userSettings_; }
+    CallManager *callManager() { return callManager_; }
+    TimelineViewManager *timelineManager() { return view_manager_; }
+    void deleteConfigs();
 
-        void initiateLogout();
+    void initiateLogout();
 
-        QString status() const;
-        void setStatus(const QString &status);
+    QString status() const;
+    void setStatus(const QString &status);
 
-        mtx::presence::PresenceState currentPresence() const;
+    mtx::presence::PresenceState currentPresence() const;
 
-        // TODO(Nico): Get rid of this!
-        QString currentRoom() const;
+    // TODO(Nico): Get rid of this!
+    QString currentRoom() const;
 
 public slots:
-        bool handleMatrixUri(const QByteArray &uri);
-        bool handleMatrixUri(const QUrl &uri);
-
-        void startChat(QString userid);
-        void leaveRoom(const QString &room_id);
-        void createRoom(const mtx::requests::CreateRoom &req);
-        void joinRoom(const QString &room);
-        void joinRoomVia(const std::string &room_id,
-                         const std::vector<std::string> &via,
-                         bool promptForConfirmation = true);
-
-        void inviteUser(QString userid, QString reason);
-        void kickUser(QString userid, QString reason);
-        void banUser(QString userid, QString reason);
-        void unbanUser(QString userid, QString reason);
-
-        void receivedSessionKey(const std::string &room_id, const std::string &session_id);
-        void decryptDownloadedSecrets(mtx::secret_storage::AesHmacSha2KeyDescription keyDesc,
-                                      const SecretsToDecrypt &secrets);
+    bool handleMatrixUri(const QByteArray &uri);
+    bool handleMatrixUri(const QUrl &uri);
+
+    void startChat(QString userid);
+    void leaveRoom(const QString &room_id);
+    void createRoom(const mtx::requests::CreateRoom &req);
+    void joinRoom(const QString &room);
+    void joinRoomVia(const std::string &room_id,
+                     const std::vector<std::string> &via,
+                     bool promptForConfirmation = true);
+
+    void inviteUser(QString userid, QString reason);
+    void kickUser(QString userid, QString reason);
+    void banUser(QString userid, QString reason);
+    void unbanUser(QString userid, QString reason);
+
+    void receivedSessionKey(const std::string &room_id, const std::string &session_id);
+    void decryptDownloadedSecrets(mtx::secret_storage::AesHmacSha2KeyDescription keyDesc,
+                                  const SecretsToDecrypt &secrets);
 signals:
-        void connectionLost();
-        void connectionRestored();
-
-        void notificationsRetrieved(const mtx::responses::Notifications &);
-        void highlightedNotifsRetrieved(const mtx::responses::Notifications &,
-                                        const QPoint widgetPos);
-
-        void contentLoaded();
-        void closing();
-        void changeWindowTitle(const int);
-        void unreadMessages(int count);
-        void showNotification(const QString &msg);
-        void showLoginPage(const QString &msg);
-        void showUserSettingsPage();
-        void showOverlayProgressBar();
-
-        void ownProfileOk();
-        void setUserDisplayName(const QString &name);
-        void setUserAvatar(const QString &avatar);
-        void loggedOut();
-
-        void trySyncCb();
-        void tryDelayedSyncCb();
-        void tryInitialSyncCb();
-        void newSyncResponse(const mtx::responses::Sync &res, const std::string &prev_batch_token);
-        void leftRoom(const QString &room_id);
-        void newRoom(const QString &room_id);
-        void changeToRoom(const QString &room_id);
-
-        void initializeViews(const mtx::responses::Rooms &rooms);
-        void initializeEmptyViews();
-        void initializeMentions(const QMap<QString, mtx::responses::Notifications> &notifs);
-        void syncUI(const mtx::responses::Rooms &rooms);
-        void dropToLoginPageCb(const QString &msg);
-
-        void notifyMessage(const QString &roomid,
-                           const QString &eventid,
-                           const QString &roomname,
-                           const QString &sender,
-                           const QString &message,
-                           const QImage &icon);
-
-        void retrievedPresence(const QString &statusMsg, mtx::presence::PresenceState state);
-        void themeChanged();
-        void decryptSidebarChanged();
-        void chatFocusChanged(const bool focused);
-
-        //! Signals for device verificaiton
-        void receivedDeviceVerificationAccept(
-          const mtx::events::msg::KeyVerificationAccept &message);
-        void receivedDeviceVerificationRequest(
-          const mtx::events::msg::KeyVerificationRequest &message,
-          std::string sender);
-        void receivedRoomDeviceVerificationRequest(
-          const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest> &message,
-          TimelineModel *model);
-        void receivedDeviceVerificationCancel(
-          const mtx::events::msg::KeyVerificationCancel &message);
-        void receivedDeviceVerificationKey(const mtx::events::msg::KeyVerificationKey &message);
-        void receivedDeviceVerificationMac(const mtx::events::msg::KeyVerificationMac &message);
-        void receivedDeviceVerificationStart(const mtx::events::msg::KeyVerificationStart &message,
-                                             std::string sender);
-        void receivedDeviceVerificationReady(const mtx::events::msg::KeyVerificationReady &message);
-        void receivedDeviceVerificationDone(const mtx::events::msg::KeyVerificationDone &message);
-
-        void downloadedSecrets(mtx::secret_storage::AesHmacSha2KeyDescription keyDesc,
-                               const SecretsToDecrypt &secrets);
+    void connectionLost();
+    void connectionRestored();
+
+    void notificationsRetrieved(const mtx::responses::Notifications &);
+    void highlightedNotifsRetrieved(const mtx::responses::Notifications &, const QPoint widgetPos);
+
+    void contentLoaded();
+    void closing();
+    void changeWindowTitle(const int);
+    void unreadMessages(int count);
+    void showNotification(const QString &msg);
+    void showLoginPage(const QString &msg);
+    void showUserSettingsPage();
+    void showOverlayProgressBar();
+
+    void ownProfileOk();
+    void setUserDisplayName(const QString &name);
+    void setUserAvatar(const QString &avatar);
+    void loggedOut();
+
+    void trySyncCb();
+    void tryDelayedSyncCb();
+    void tryInitialSyncCb();
+    void newSyncResponse(const mtx::responses::Sync &res, const std::string &prev_batch_token);
+    void leftRoom(const QString &room_id);
+    void newRoom(const QString &room_id);
+    void changeToRoom(const QString &room_id);
+
+    void initializeViews(const mtx::responses::Rooms &rooms);
+    void initializeEmptyViews();
+    void initializeMentions(const QMap<QString, mtx::responses::Notifications> &notifs);
+    void syncUI(const mtx::responses::Rooms &rooms);
+    void dropToLoginPageCb(const QString &msg);
+
+    void notifyMessage(const QString &roomid,
+                       const QString &eventid,
+                       const QString &roomname,
+                       const QString &sender,
+                       const QString &message,
+                       const QImage &icon);
+
+    void retrievedPresence(const QString &statusMsg, mtx::presence::PresenceState state);
+    void themeChanged();
+    void decryptSidebarChanged();
+    void chatFocusChanged(const bool focused);
+
+    //! Signals for device verificaiton
+    void receivedDeviceVerificationAccept(const mtx::events::msg::KeyVerificationAccept &message);
+    void receivedDeviceVerificationRequest(const mtx::events::msg::KeyVerificationRequest &message,
+                                           std::string sender);
+    void receivedRoomDeviceVerificationRequest(
+      const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest> &message,
+      TimelineModel *model);
+    void receivedDeviceVerificationCancel(const mtx::events::msg::KeyVerificationCancel &message);
+    void receivedDeviceVerificationKey(const mtx::events::msg::KeyVerificationKey &message);
+    void receivedDeviceVerificationMac(const mtx::events::msg::KeyVerificationMac &message);
+    void receivedDeviceVerificationStart(const mtx::events::msg::KeyVerificationStart &message,
+                                         std::string sender);
+    void receivedDeviceVerificationReady(const mtx::events::msg::KeyVerificationReady &message);
+    void receivedDeviceVerificationDone(const mtx::events::msg::KeyVerificationDone &message);
+
+    void downloadedSecrets(mtx::secret_storage::AesHmacSha2KeyDescription keyDesc,
+                           const SecretsToDecrypt &secrets);
 
 private slots:
-        void logout();
-        void removeRoom(const QString &room_id);
-        void changeRoom(const QString &room_id);
-        void dropToLoginPage(const QString &msg);
+    void logout();
+    void removeRoom(const QString &room_id);
+    void changeRoom(const QString &room_id);
+    void dropToLoginPage(const QString &msg);
 
-        void handleSyncResponse(const mtx::responses::Sync &res,
-                                const std::string &prev_batch_token);
+    void handleSyncResponse(const mtx::responses::Sync &res, const std::string &prev_batch_token);
 
 private:
-        static ChatPage *instance_;
+    static ChatPage *instance_;
 
-        void startInitialSync();
-        void tryInitialSync();
-        void trySync();
-        void verifyOneTimeKeyCountAfterStartup();
-        void ensureOneTimeKeyCount(const std::map<std::string, uint16_t> &counts);
-        void getProfileInfo();
-        void getBackupVersion();
+    void startInitialSync();
+    void tryInitialSync();
+    void trySync();
+    void verifyOneTimeKeyCountAfterStartup();
+    void ensureOneTimeKeyCount(const std::map<std::string, uint16_t> &counts);
+    void getProfileInfo();
+    void getBackupVersion();
 
-        //! Check if the given room is currently open.
-        bool isRoomActive(const QString &room_id);
+    //! Check if the given room is currently open.
+    bool isRoomActive(const QString &room_id);
 
-        using UserID      = QString;
-        using Membership  = mtx::events::StateEvent<mtx::events::state::Member>;
-        using Memberships = std::map<std::string, Membership>;
+    using UserID      = QString;
+    using Membership  = mtx::events::StateEvent<mtx::events::state::Member>;
+    using Memberships = std::map<std::string, Membership>;
 
-        void loadStateFromCache();
-        void resetUI();
+    void loadStateFromCache();
+    void resetUI();
 
-        template<class Collection>
-        Memberships getMemberships(const std::vector<Collection> &events) const;
+    template<class Collection>
+    Memberships getMemberships(const std::vector<Collection> &events) const;
 
-        //! Send desktop notification for the received messages.
-        void sendNotifications(const mtx::responses::Notifications &);
+    //! Send desktop notification for the received messages.
+    void sendNotifications(const mtx::responses::Notifications &);
 
-        template<typename T>
-        void connectCallMessage();
+    template<typename T>
+    void connectCallMessage();
 
-        QHBoxLayout *topLayout_;
+    QHBoxLayout *topLayout_;
 
-        TimelineViewManager *view_manager_;
+    TimelineViewManager *view_manager_;
 
-        QTimer connectivityTimer_;
-        std::atomic_bool isConnected_;
+    QTimer connectivityTimer_;
+    std::atomic_bool isConnected_;
 
-        // Global user settings.
-        QSharedPointer<UserSettings> userSettings_;
+    // Global user settings.
+    QSharedPointer<UserSettings> userSettings_;
 
-        NotificationsManager notificationsManager;
-        CallManager *callManager_;
+    NotificationsManager notificationsManager;
+    CallManager *callManager_;
 };
 
 template<class Collection>
 std::map<std::string, mtx::events::StateEvent<mtx::events::state::Member>>
 ChatPage::getMemberships(const std::vector<Collection> &collection) const
 {
-        std::map<std::string, mtx::events::StateEvent<mtx::events::state::Member>> memberships;
+    std::map<std::string, mtx::events::StateEvent<mtx::events::state::Member>> memberships;
 
-        using Member = mtx::events::StateEvent<mtx::events::state::Member>;
+    using Member = mtx::events::StateEvent<mtx::events::state::Member>;
 
-        for (const auto &event : collection) {
-                if (auto member = std::get_if<Member>(event)) {
-                        memberships.emplace(member->state_key, *member);
-                }
+    for (const auto &event : collection) {
+        if (auto member = std::get_if<Member>(event)) {
+            memberships.emplace(member->state_key, *member);
         }
+    }
 
-        return memberships;
+    return memberships;
 }
diff --git a/src/Clipboard.cpp b/src/Clipboard.cpp
index d4d5bab7..93d913be 100644
--- a/src/Clipboard.cpp
+++ b/src/Clipboard.cpp
@@ -10,18 +10,17 @@
 Clipboard::Clipboard(QObject *parent)
   : QObject(parent)
 {
-        connect(
-          QGuiApplication::clipboard(), &QClipboard::dataChanged, this, &Clipboard::textChanged);
+    connect(QGuiApplication::clipboard(), &QClipboard::dataChanged, this, &Clipboard::textChanged);
 }
 
 void
 Clipboard::setText(QString text)
 {
-        QGuiApplication::clipboard()->setText(text);
+    QGuiApplication::clipboard()->setText(text);
 }
 
 QString
 Clipboard::text() const
 {
-        return QGuiApplication::clipboard()->text();
+    return QGuiApplication::clipboard()->text();
 }
diff --git a/src/Clipboard.h b/src/Clipboard.h
index fa74da22..1a6584ca 100644
--- a/src/Clipboard.h
+++ b/src/Clipboard.h
@@ -9,14 +9,14 @@
 
 class Clipboard : public QObject
 {
-        Q_OBJECT
-        Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
+    Q_OBJECT
+    Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
 
 public:
-        Clipboard(QObject *parent = nullptr);
+    Clipboard(QObject *parent = nullptr);
 
-        QString text() const;
-        void setText(QString text_);
+    QString text() const;
+    void setText(QString text_);
 signals:
-        void textChanged();
+    void textChanged();
 };
diff --git a/src/ColorImageProvider.cpp b/src/ColorImageProvider.cpp
index 41fd5d8f..9c371c8c 100644
--- a/src/ColorImageProvider.cpp
+++ b/src/ColorImageProvider.cpp
@@ -9,23 +9,23 @@
 QPixmap
 ColorImageProvider::requestPixmap(const QString &id, QSize *size, const QSize &)
 {
-        auto args = id.split('?');
+    auto args = id.split('?');
 
-        QPixmap source(args[0]);
+    QPixmap source(args[0]);
 
-        if (size)
-                *size = QSize(source.width(), source.height());
+    if (size)
+        *size = QSize(source.width(), source.height());
 
-        if (args.size() < 2)
-                return source;
+    if (args.size() < 2)
+        return source;
 
-        QColor color(args[1]);
+    QColor color(args[1]);
 
-        QPixmap colorized = source;
-        QPainter painter(&colorized);
-        painter.setCompositionMode(QPainter::CompositionMode_SourceIn);
-        painter.fillRect(colorized.rect(), color);
-        painter.end();
+    QPixmap colorized = source;
+    QPainter painter(&colorized);
+    painter.setCompositionMode(QPainter::CompositionMode_SourceIn);
+    painter.fillRect(colorized.rect(), color);
+    painter.end();
 
-        return colorized;
+    return colorized;
 }
diff --git a/src/ColorImageProvider.h b/src/ColorImageProvider.h
index 9ae8c85e..f2997e0a 100644
--- a/src/ColorImageProvider.h
+++ b/src/ColorImageProvider.h
@@ -7,9 +7,9 @@
 class ColorImageProvider : public QQuickImageProvider
 {
 public:
-        ColorImageProvider()
-          : QQuickImageProvider(QQuickImageProvider::Pixmap)
-        {}
+    ColorImageProvider()
+      : QQuickImageProvider(QQuickImageProvider::Pixmap)
+    {}
 
-        QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) override;
+    QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize) override;
 };
diff --git a/src/CombinedImagePackModel.cpp b/src/CombinedImagePackModel.cpp
index 341a34ec..9a52f810 100644
--- a/src/CombinedImagePackModel.cpp
+++ b/src/CombinedImagePackModel.cpp
@@ -13,65 +13,65 @@ CombinedImagePackModel::CombinedImagePackModel(const std::string &roomId,
   : QAbstractListModel(parent)
   , room_id(roomId)
 {
-        auto packs = cache::client()->getImagePacks(room_id, stickers);
+    auto packs = cache::client()->getImagePacks(room_id, stickers);
 
-        for (const auto &pack : packs) {
-                QString packname =
-                  pack.pack.pack ? QString::fromStdString(pack.pack.pack->display_name) : "";
+    for (const auto &pack : packs) {
+        QString packname =
+          pack.pack.pack ? QString::fromStdString(pack.pack.pack->display_name) : "";
 
-                for (const auto &img : pack.pack.images) {
-                        ImageDesc i{};
-                        i.shortcode = QString::fromStdString(img.first);
-                        i.packname  = packname;
-                        i.image     = img.second;
-                        images.push_back(std::move(i));
-                }
+        for (const auto &img : pack.pack.images) {
+            ImageDesc i{};
+            i.shortcode = QString::fromStdString(img.first);
+            i.packname  = packname;
+            i.image     = img.second;
+            images.push_back(std::move(i));
         }
+    }
 }
 
 int
 CombinedImagePackModel::rowCount(const QModelIndex &) const
 {
-        return (int)images.size();
+    return (int)images.size();
 }
 
 QHash<int, QByteArray>
 CombinedImagePackModel::roleNames() const
 {
-        return {
-          {CompletionModel::CompletionRole, "completionRole"},
-          {CompletionModel::SearchRole, "searchRole"},
-          {CompletionModel::SearchRole2, "searchRole2"},
-          {Roles::Url, "url"},
-          {Roles::ShortCode, "shortcode"},
-          {Roles::Body, "body"},
-          {Roles::PackName, "packname"},
-          {Roles::OriginalRow, "originalRow"},
-        };
+    return {
+      {CompletionModel::CompletionRole, "completionRole"},
+      {CompletionModel::SearchRole, "searchRole"},
+      {CompletionModel::SearchRole2, "searchRole2"},
+      {Roles::Url, "url"},
+      {Roles::ShortCode, "shortcode"},
+      {Roles::Body, "body"},
+      {Roles::PackName, "packname"},
+      {Roles::OriginalRow, "originalRow"},
+    };
 }
 
 QVariant
 CombinedImagePackModel::data(const QModelIndex &index, int role) const
 {
-        if (hasIndex(index.row(), index.column(), index.parent())) {
-                switch (role) {
-                case CompletionModel::CompletionRole:
-                        return QString::fromStdString(images[index.row()].image.url);
-                case Roles::Url:
-                        return QString::fromStdString(images[index.row()].image.url);
-                case CompletionModel::SearchRole:
-                case Roles::ShortCode:
-                        return images[index.row()].shortcode;
-                case CompletionModel::SearchRole2:
-                case Roles::Body:
-                        return QString::fromStdString(images[index.row()].image.body);
-                case Roles::PackName:
-                        return images[index.row()].packname;
-                case Roles::OriginalRow:
-                        return index.row();
-                default:
-                        return {};
-                }
+    if (hasIndex(index.row(), index.column(), index.parent())) {
+        switch (role) {
+        case CompletionModel::CompletionRole:
+            return QString::fromStdString(images[index.row()].image.url);
+        case Roles::Url:
+            return QString::fromStdString(images[index.row()].image.url);
+        case CompletionModel::SearchRole:
+        case Roles::ShortCode:
+            return images[index.row()].shortcode;
+        case CompletionModel::SearchRole2:
+        case Roles::Body:
+            return QString::fromStdString(images[index.row()].image.body);
+        case Roles::PackName:
+            return images[index.row()].packname;
+        case Roles::OriginalRow:
+            return index.row();
+        default:
+            return {};
         }
-        return {};
+    }
+    return {};
 }
diff --git a/src/CombinedImagePackModel.h b/src/CombinedImagePackModel.h
index f0f69799..ec49b325 100644
--- a/src/CombinedImagePackModel.h
+++ b/src/CombinedImagePackModel.h
@@ -10,39 +10,39 @@
 
 class CombinedImagePackModel : public QAbstractListModel
 {
-        Q_OBJECT
+    Q_OBJECT
 public:
-        enum Roles
-        {
-                Url = Qt::UserRole,
-                ShortCode,
-                Body,
-                PackName,
-                OriginalRow,
-        };
-
-        CombinedImagePackModel(const std::string &roomId, bool stickers, QObject *parent = nullptr);
-        QHash<int, QByteArray> roleNames() const override;
-        int rowCount(const QModelIndex &parent = QModelIndex()) const override;
-        QVariant data(const QModelIndex &index, int role) const override;
-
-        mtx::events::msc2545::PackImage imageAt(int row)
-        {
-                if (row < 0 || static_cast<size_t>(row) >= images.size())
-                        return {};
-                return images.at(static_cast<size_t>(row)).image;
-        }
+    enum Roles
+    {
+        Url = Qt::UserRole,
+        ShortCode,
+        Body,
+        PackName,
+        OriginalRow,
+    };
+
+    CombinedImagePackModel(const std::string &roomId, bool stickers, QObject *parent = nullptr);
+    QHash<int, QByteArray> roleNames() const override;
+    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+    QVariant data(const QModelIndex &index, int role) const override;
+
+    mtx::events::msc2545::PackImage imageAt(int row)
+    {
+        if (row < 0 || static_cast<size_t>(row) >= images.size())
+            return {};
+        return images.at(static_cast<size_t>(row)).image;
+    }
 
 private:
-        std::string room_id;
+    std::string room_id;
 
-        struct ImageDesc
-        {
-                QString shortcode;
-                QString packname;
+    struct ImageDesc
+    {
+        QString shortcode;
+        QString packname;
 
-                mtx::events::msc2545::PackImage image;
-        };
+        mtx::events::msc2545::PackImage image;
+    };
 
-        std::vector<ImageDesc> images;
+    std::vector<ImageDesc> images;
 };
diff --git a/src/CompletionModelRoles.h b/src/CompletionModelRoles.h
index 8505e761..9a735d60 100644
--- a/src/CompletionModelRoles.h
+++ b/src/CompletionModelRoles.h
@@ -12,8 +12,8 @@ namespace CompletionModel {
 // Start at Qt::UserRole * 2 to prevent clashes
 enum Roles
 {
-        CompletionRole = Qt::UserRole * 2, // The string to replace the active completion
-        SearchRole,                        // String completer uses for search
-        SearchRole2,                       // Secondary string completer uses for search
+    CompletionRole = Qt::UserRole * 2, // The string to replace the active completion
+    SearchRole,                        // String completer uses for search
+    SearchRole2,                       // Secondary string completer uses for search
 };
 }
diff --git a/src/CompletionProxyModel.cpp b/src/CompletionProxyModel.cpp
index e68944c7..454f54b7 100644
--- a/src/CompletionProxyModel.cpp
+++ b/src/CompletionProxyModel.cpp
@@ -18,154 +18,154 @@ CompletionProxyModel::CompletionProxyModel(QAbstractItemModel *model,
   , maxMistakes_(max_mistakes)
   , max_completions_(max_completions)
 {
-        setSourceModel(model);
-        QChar splitPoints(' ');
-
-        // insert all the full texts
-        for (int i = 0; i < sourceModel()->rowCount(); i++) {
-                if (static_cast<size_t>(i) < max_completions_)
-                        mapping.push_back(i);
-
-                auto string1 = sourceModel()
-                                 ->data(sourceModel()->index(i, 0), CompletionModel::SearchRole)
-                                 .toString()
-                                 .toLower();
-                if (!string1.isEmpty())
-                        trie_.insert(string1.toUcs4(), i);
-
-                auto string2 = sourceModel()
-                                 ->data(sourceModel()->index(i, 0), CompletionModel::SearchRole2)
-                                 .toString()
-                                 .toLower();
-                if (!string2.isEmpty())
-                        trie_.insert(string2.toUcs4(), i);
+    setSourceModel(model);
+    QChar splitPoints(' ');
+
+    // insert all the full texts
+    for (int i = 0; i < sourceModel()->rowCount(); i++) {
+        if (static_cast<size_t>(i) < max_completions_)
+            mapping.push_back(i);
+
+        auto string1 = sourceModel()
+                         ->data(sourceModel()->index(i, 0), CompletionModel::SearchRole)
+                         .toString()
+                         .toLower();
+        if (!string1.isEmpty())
+            trie_.insert(string1.toUcs4(), i);
+
+        auto string2 = sourceModel()
+                         ->data(sourceModel()->index(i, 0), CompletionModel::SearchRole2)
+                         .toString()
+                         .toLower();
+        if (!string2.isEmpty())
+            trie_.insert(string2.toUcs4(), i);
+    }
+
+    // insert the partial matches
+    for (int i = 0; i < sourceModel()->rowCount(); i++) {
+        auto string1 = sourceModel()
+                         ->data(sourceModel()->index(i, 0), CompletionModel::SearchRole)
+                         .toString()
+                         .toLower();
+
+        for (const auto &e : string1.splitRef(splitPoints)) {
+            if (!e.isEmpty()) // NOTE(Nico): Use Qt::SkipEmptyParts in Qt 5.14
+                trie_.insert(e.toUcs4(), i);
         }
 
-        // insert the partial matches
-        for (int i = 0; i < sourceModel()->rowCount(); i++) {
-                auto string1 = sourceModel()
-                                 ->data(sourceModel()->index(i, 0), CompletionModel::SearchRole)
-                                 .toString()
-                                 .toLower();
-
-                for (const auto &e : string1.splitRef(splitPoints)) {
-                        if (!e.isEmpty()) // NOTE(Nico): Use Qt::SkipEmptyParts in Qt 5.14
-                                trie_.insert(e.toUcs4(), i);
-                }
-
-                auto string2 = sourceModel()
-                                 ->data(sourceModel()->index(i, 0), CompletionModel::SearchRole2)
-                                 .toString()
-                                 .toLower();
-
-                if (!string2.isEmpty()) {
-                        for (const auto &e : string2.splitRef(splitPoints)) {
-                                if (!e.isEmpty()) // NOTE(Nico): Use Qt::SkipEmptyParts in Qt 5.14
-                                        trie_.insert(e.toUcs4(), i);
-                        }
-                }
-        }
+        auto string2 = sourceModel()
+                         ->data(sourceModel()->index(i, 0), CompletionModel::SearchRole2)
+                         .toString()
+                         .toLower();
 
-        connect(
-          this,
-          &CompletionProxyModel::newSearchString,
-          this,
-          [this](QString s) {
-                  s.remove(":");
-                  s.remove("@");
-                  searchString_ = s.toLower();
-                  invalidate();
-          },
-          Qt::QueuedConnection);
+        if (!string2.isEmpty()) {
+            for (const auto &e : string2.splitRef(splitPoints)) {
+                if (!e.isEmpty()) // NOTE(Nico): Use Qt::SkipEmptyParts in Qt 5.14
+                    trie_.insert(e.toUcs4(), i);
+            }
+        }
+    }
+
+    connect(
+      this,
+      &CompletionProxyModel::newSearchString,
+      this,
+      [this](QString s) {
+          s.remove(":");
+          s.remove("@");
+          searchString_ = s.toLower();
+          invalidate();
+      },
+      Qt::QueuedConnection);
 }
 
 void
 CompletionProxyModel::invalidate()
 {
-        auto key = searchString_.toUcs4();
-        beginResetModel();
-        if (!key.empty()) // return default model data, if no search string
-                mapping = trie_.search(key, max_completions_, maxMistakes_);
-        endResetModel();
+    auto key = searchString_.toUcs4();
+    beginResetModel();
+    if (!key.empty()) // return default model data, if no search string
+        mapping = trie_.search(key, max_completions_, maxMistakes_);
+    endResetModel();
 }
 
 QHash<int, QByteArray>
 CompletionProxyModel::roleNames() const
 {
-        return this->sourceModel()->roleNames();
+    return this->sourceModel()->roleNames();
 }
 
 int
 CompletionProxyModel::rowCount(const QModelIndex &) const
 {
-        if (searchString_.isEmpty())
-                return std::min(static_cast<int>(std::min<size_t>(max_completions_,
-                                                                  std::numeric_limits<int>::max())),
-                                sourceModel()->rowCount());
-        else
-                return (int)mapping.size();
+    if (searchString_.isEmpty())
+        return std::min(
+          static_cast<int>(std::min<size_t>(max_completions_, std::numeric_limits<int>::max())),
+          sourceModel()->rowCount());
+    else
+        return (int)mapping.size();
 }
 
 QModelIndex
 CompletionProxyModel::mapFromSource(const QModelIndex &sourceIndex) const
 {
-        // return default model data, if no search string
-        if (searchString_.isEmpty()) {
-                return index(sourceIndex.row(), 0);
-        }
-
-        for (int i = 0; i < (int)mapping.size(); i++) {
-                if (mapping[i] == sourceIndex.row()) {
-                        return index(i, 0);
-                }
+    // return default model data, if no search string
+    if (searchString_.isEmpty()) {
+        return index(sourceIndex.row(), 0);
+    }
+
+    for (int i = 0; i < (int)mapping.size(); i++) {
+        if (mapping[i] == sourceIndex.row()) {
+            return index(i, 0);
         }
-        return QModelIndex();
+    }
+    return QModelIndex();
 }
 
 QModelIndex
 CompletionProxyModel::mapToSource(const QModelIndex &proxyIndex) const
 {
-        auto row = proxyIndex.row();
+    auto row = proxyIndex.row();
 
-        // return default model data, if no search string
-        if (searchString_.isEmpty()) {
-                return index(row, 0);
-        }
+    // return default model data, if no search string
+    if (searchString_.isEmpty()) {
+        return index(row, 0);
+    }
 
-        if (row < 0 || row >= (int)mapping.size())
-                return QModelIndex();
+    if (row < 0 || row >= (int)mapping.size())
+        return QModelIndex();
 
-        return sourceModel()->index(mapping[row], 0);
+    return sourceModel()->index(mapping[row], 0);
 }
 
 QModelIndex
 CompletionProxyModel::index(int row, int column, const QModelIndex &) const
 {
-        return createIndex(row, column);
+    return createIndex(row, column);
 }
 
 QModelIndex
 CompletionProxyModel::parent(const QModelIndex &) const
 {
-        return QModelIndex{};
+    return QModelIndex{};
 }
 int
 CompletionProxyModel::columnCount(const QModelIndex &) const
 {
-        return sourceModel()->columnCount();
+    return sourceModel()->columnCount();
 }
 
 QVariant
 CompletionProxyModel::completionAt(int i) const
 {
-        if (i >= 0 && i < rowCount())
-                return data(index(i, 0), CompletionModel::CompletionRole);
-        else
-                return {};
+    if (i >= 0 && i < rowCount())
+        return data(index(i, 0), CompletionModel::CompletionRole);
+    else
+        return {};
 }
 
 void
 CompletionProxyModel::setSearchString(QString s)
 {
-        emit newSearchString(s);
+    emit newSearchString(s);
 }
diff --git a/src/CompletionProxyModel.h b/src/CompletionProxyModel.h
index d85d9343..c6331a2d 100644
--- a/src/CompletionProxyModel.h
+++ b/src/CompletionProxyModel.h
@@ -11,179 +11,176 @@
 template<typename Key, typename Value>
 struct trie
 {
-        std::vector<Value> values;
-        std::map<Key, trie> next;
-
-        void insert(const QVector<Key> &keys, const Value &v)
-        {
-                auto t = this;
-                for (const auto k : keys) {
-                        t = &t->next[k];
-                }
-
-                t->values.push_back(v);
+    std::vector<Value> values;
+    std::map<Key, trie> next;
+
+    void insert(const QVector<Key> &keys, const Value &v)
+    {
+        auto t = this;
+        for (const auto k : keys) {
+            t = &t->next[k];
         }
 
-        std::vector<Value> valuesAndSubvalues(size_t limit = -1) const
-        {
-                std::vector<Value> ret;
-                if (limit < 200)
-                        ret.reserve(limit);
-
-                for (const auto &v : values) {
-                        if (ret.size() >= limit)
-                                return ret;
-                        else
-                                ret.push_back(v);
-                }
+        t->values.push_back(v);
+    }
 
-                for (const auto &[k, t] : next) {
-                        (void)k;
-                        if (ret.size() >= limit)
-                                return ret;
-                        else {
-                                auto temp = t.valuesAndSubvalues(limit - ret.size());
-                                for (auto &&v : temp) {
-                                        if (ret.size() >= limit)
-                                                return ret;
-
-                                        if (std::find(ret.begin(), ret.end(), v) == ret.end()) {
-                                                ret.push_back(std::move(v));
-                                        }
-                                }
-                        }
-                }
+    std::vector<Value> valuesAndSubvalues(size_t limit = -1) const
+    {
+        std::vector<Value> ret;
+        if (limit < 200)
+            ret.reserve(limit);
 
+        for (const auto &v : values) {
+            if (ret.size() >= limit)
                 return ret;
+            else
+                ret.push_back(v);
         }
 
-        std::vector<Value> search(const QVector<Key> &keys, //< TODO(Nico): replace this with a span
-                                  size_t result_count_limit,
-                                  size_t max_edit_distance_ = 2) const
-        {
-                std::vector<Value> ret;
-                if (!result_count_limit)
+        for (const auto &[k, t] : next) {
+            (void)k;
+            if (ret.size() >= limit)
+                return ret;
+            else {
+                auto temp = t.valuesAndSubvalues(limit - ret.size());
+                for (auto &&v : temp) {
+                    if (ret.size() >= limit)
                         return ret;
 
-                if (keys.isEmpty())
-                        return valuesAndSubvalues(result_count_limit);
+                    if (std::find(ret.begin(), ret.end(), v) == ret.end()) {
+                        ret.push_back(std::move(v));
+                    }
+                }
+            }
+        }
 
-                auto append = [&ret, result_count_limit](std::vector<Value> &&in) {
-                        for (auto &&v : in) {
-                                if (ret.size() >= result_count_limit)
-                                        return;
+        return ret;
+    }
 
-                                if (std::find(ret.begin(), ret.end(), v) == ret.end()) {
-                                        ret.push_back(std::move(v));
-                                }
-                        }
-                };
-
-                auto limit = [&ret, result_count_limit] {
-                        return std::min(result_count_limit, (result_count_limit - ret.size()) * 2);
-                };
-
-                // Try first exact matches, then with maximum errors
-                for (size_t max_edit_distance = 0;
-                     max_edit_distance <= max_edit_distance_ && ret.size() < result_count_limit;
-                     max_edit_distance += 1) {
-                        if (max_edit_distance && ret.size() < result_count_limit) {
-                                max_edit_distance -= 1;
-
-                                // swap chars case
-                                if (keys.size() >= 2) {
-                                        auto t = this;
-                                        for (int i = 1; i >= 0; i--) {
-                                                if (auto e = t->next.find(keys[i]);
-                                                    e != t->next.end()) {
-                                                        t = &e->second;
-                                                } else {
-                                                        t = nullptr;
-                                                        break;
-                                                }
-                                        }
-
-                                        if (t) {
-                                                append(t->search(
-                                                  keys.mid(2), limit(), max_edit_distance));
-                                        }
-                                }
-
-                                // insert case
-                                for (const auto &[k, t] : this->next) {
-                                        if (k == keys[0])
-                                                continue;
-                                        if (ret.size() >= limit())
-                                                break;
-
-                                        // insert
-                                        append(t.search(keys, limit(), max_edit_distance));
-                                }
-
-                                // delete character case
-                                append(this->search(keys.mid(1), limit(), max_edit_distance));
-
-                                // substitute case
-                                for (const auto &[k, t] : this->next) {
-                                        if (k == keys[0])
-                                                continue;
-                                        if (ret.size() >= limit())
-                                                break;
-
-                                        // substitute
-                                        append(t.search(keys.mid(1), limit(), max_edit_distance));
-                                }
-
-                                max_edit_distance += 1;
-                        }
+    std::vector<Value> search(const QVector<Key> &keys, //< TODO(Nico): replace this with a span
+                              size_t result_count_limit,
+                              size_t max_edit_distance_ = 2) const
+    {
+        std::vector<Value> ret;
+        if (!result_count_limit)
+            return ret;
+
+        if (keys.isEmpty())
+            return valuesAndSubvalues(result_count_limit);
+
+        auto append = [&ret, result_count_limit](std::vector<Value> &&in) {
+            for (auto &&v : in) {
+                if (ret.size() >= result_count_limit)
+                    return;
 
-                        if (auto e = this->next.find(keys[0]); e != this->next.end()) {
-                                append(e->second.search(keys.mid(1), limit(), max_edit_distance));
+                if (std::find(ret.begin(), ret.end(), v) == ret.end()) {
+                    ret.push_back(std::move(v));
+                }
+            }
+        };
+
+        auto limit = [&ret, result_count_limit] {
+            return std::min(result_count_limit, (result_count_limit - ret.size()) * 2);
+        };
+
+        // Try first exact matches, then with maximum errors
+        for (size_t max_edit_distance = 0;
+             max_edit_distance <= max_edit_distance_ && ret.size() < result_count_limit;
+             max_edit_distance += 1) {
+            if (max_edit_distance && ret.size() < result_count_limit) {
+                max_edit_distance -= 1;
+
+                // swap chars case
+                if (keys.size() >= 2) {
+                    auto t = this;
+                    for (int i = 1; i >= 0; i--) {
+                        if (auto e = t->next.find(keys[i]); e != t->next.end()) {
+                            t = &e->second;
+                        } else {
+                            t = nullptr;
+                            break;
                         }
+                    }
+
+                    if (t) {
+                        append(t->search(keys.mid(2), limit(), max_edit_distance));
+                    }
                 }
 
-                return ret;
+                // insert case
+                for (const auto &[k, t] : this->next) {
+                    if (k == keys[0])
+                        continue;
+                    if (ret.size() >= limit())
+                        break;
+
+                    // insert
+                    append(t.search(keys, limit(), max_edit_distance));
+                }
+
+                // delete character case
+                append(this->search(keys.mid(1), limit(), max_edit_distance));
+
+                // substitute case
+                for (const auto &[k, t] : this->next) {
+                    if (k == keys[0])
+                        continue;
+                    if (ret.size() >= limit())
+                        break;
+
+                    // substitute
+                    append(t.search(keys.mid(1), limit(), max_edit_distance));
+                }
+
+                max_edit_distance += 1;
+            }
+
+            if (auto e = this->next.find(keys[0]); e != this->next.end()) {
+                append(e->second.search(keys.mid(1), limit(), max_edit_distance));
+            }
         }
+
+        return ret;
+    }
 };
 
 class CompletionProxyModel : public QAbstractProxyModel
 {
-        Q_OBJECT
-        Q_PROPERTY(
-          QString searchString READ searchString WRITE setSearchString NOTIFY newSearchString)
+    Q_OBJECT
+    Q_PROPERTY(QString searchString READ searchString WRITE setSearchString NOTIFY newSearchString)
 public:
-        CompletionProxyModel(QAbstractItemModel *model,
-                             int max_mistakes       = 2,
-                             size_t max_completions = 7,
-                             QObject *parent        = nullptr);
+    CompletionProxyModel(QAbstractItemModel *model,
+                         int max_mistakes       = 2,
+                         size_t max_completions = 7,
+                         QObject *parent        = nullptr);
 
-        void invalidate();
+    void invalidate();
 
-        QHash<int, QByteArray> roleNames() const override;
-        int rowCount(const QModelIndex &parent = QModelIndex()) const override;
-        int columnCount(const QModelIndex &) const override;
+    QHash<int, QByteArray> roleNames() const override;
+    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+    int columnCount(const QModelIndex &) const override;
 
-        QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override;
-        QModelIndex mapToSource(const QModelIndex &proxyIndex) const override;
+    QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override;
+    QModelIndex mapToSource(const QModelIndex &proxyIndex) const override;
 
-        QModelIndex index(int row,
-                          int column,
-                          const QModelIndex &parent = QModelIndex()) const override;
-        QModelIndex parent(const QModelIndex &) const override;
+    QModelIndex index(int row,
+                      int column,
+                      const QModelIndex &parent = QModelIndex()) const override;
+    QModelIndex parent(const QModelIndex &) const override;
 
 public slots:
-        QVariant completionAt(int i) const;
+    QVariant completionAt(int i) const;
 
-        void setSearchString(QString s);
-        QString searchString() const { return searchString_; }
+    void setSearchString(QString s);
+    QString searchString() const { return searchString_; }
 
 signals:
-        void newSearchString(QString);
+    void newSearchString(QString);
 
 private:
-        QString searchString_;
-        trie<uint, int> trie_;
-        std::vector<int> mapping;
-        int maxMistakes_;
-        size_t max_completions_;
+    QString searchString_;
+    trie<uint, int> trie_;
+    std::vector<int> mapping;
+    int maxMistakes_;
+    size_t max_completions_;
 };
diff --git a/src/DeviceVerificationFlow.cpp b/src/DeviceVerificationFlow.cpp
index 1760ea9a..d4e27022 100644
--- a/src/DeviceVerificationFlow.cpp
+++ b/src/DeviceVerificationFlow.cpp
@@ -38,685 +38,653 @@ DeviceVerificationFlow::DeviceVerificationFlow(QObject *,
   , deviceId(deviceId_)
   , model_(model)
 {
-        timeout = new QTimer(this);
-        timeout->setSingleShot(true);
-        this->sas           = olm::client()->sas_init();
-        this->isMacVerified = false;
-
-        auto user_id   = userID.toStdString();
-        this->toClient = mtx::identifiers::parse<mtx::identifiers::User>(user_id);
-        cache::client()->query_keys(
-          user_id, [user_id, this](const UserKeyCache &res, mtx::http::RequestErr err) {
-                  if (err) {
-                          nhlog::net()->warn("failed to query device keys: {},{}",
-                                             mtx::errors::to_string(err->matrix_error.errcode),
-                                             static_cast<int>(err->status_code));
-                          return;
-                  }
-
-                  if (!this->deviceId.isEmpty() &&
-                      (res.device_keys.find(deviceId.toStdString()) == res.device_keys.end())) {
-                          nhlog::net()->warn("no devices retrieved {}", user_id);
-                          return;
-                  }
-
-                  this->their_keys = res;
-          });
-
-        cache::client()->query_keys(
-          http::client()->user_id().to_string(),
-          [this](const UserKeyCache &res, mtx::http::RequestErr err) {
-                  if (err) {
-                          nhlog::net()->warn("failed to query device keys: {},{}",
-                                             mtx::errors::to_string(err->matrix_error.errcode),
-                                             static_cast<int>(err->status_code));
-                          return;
-                  }
-
-                  if (res.master_keys.keys.empty())
-                          return;
-
-                  if (auto status =
-                        cache::verificationStatus(http::client()->user_id().to_string());
-                      status && status->user_verified == crypto::Trust::Verified)
-                          this->our_trusted_master_key = res.master_keys.keys.begin()->second;
-          });
-
-        if (model) {
-                connect(this->model_,
-                        &TimelineModel::updateFlowEventId,
-                        this,
-                        [this](std::string event_id_) {
-                                this->relation.rel_type = mtx::common::RelationType::Reference;
-                                this->relation.event_id = event_id_;
-                                this->transaction_id    = event_id_;
-                        });
-        }
-
-        connect(timeout, &QTimer::timeout, this, [this]() {
-                nhlog::crypto()->info("verification: timeout");
-                if (state_ != Success && state_ != Failed)
-                        this->cancelVerification(DeviceVerificationFlow::Error::Timeout);
-        });
-
-        connect(ChatPage::instance(),
-                &ChatPage::receivedDeviceVerificationStart,
-                this,
-                &DeviceVerificationFlow::handleStartMessage);
-        connect(ChatPage::instance(),
-                &ChatPage::receivedDeviceVerificationAccept,
-                this,
-                [this](const mtx::events::msg::KeyVerificationAccept &msg) {
-                        nhlog::crypto()->info("verification: received accept");
-                        if (msg.transaction_id.has_value()) {
-                                if (msg.transaction_id.value() != this->transaction_id)
-                                        return;
-                        } else if (msg.relations.references()) {
-                                if (msg.relations.references() != this->relation.event_id)
-                                        return;
-                        }
-                        if ((msg.key_agreement_protocol == "curve25519-hkdf-sha256") &&
-                            (msg.hash == "sha256") &&
-                            (msg.message_authentication_code == "hkdf-hmac-sha256")) {
-                                this->commitment = msg.commitment;
-                                if (std::find(msg.short_authentication_string.begin(),
-                                              msg.short_authentication_string.end(),
-                                              mtx::events::msg::SASMethods::Emoji) !=
-                                    msg.short_authentication_string.end()) {
-                                        this->method = mtx::events::msg::SASMethods::Emoji;
-                                } else {
-                                        this->method = mtx::events::msg::SASMethods::Decimal;
-                                }
-                                this->mac_method = msg.message_authentication_code;
-                                this->sendVerificationKey();
-                        } else {
-                                this->cancelVerification(
-                                  DeviceVerificationFlow::Error::UnknownMethod);
-                        }
-                });
-
-        connect(ChatPage::instance(),
-                &ChatPage::receivedDeviceVerificationCancel,
-                this,
-                [this](const mtx::events::msg::KeyVerificationCancel &msg) {
-                        nhlog::crypto()->info("verification: received cancel");
-                        if (msg.transaction_id.has_value()) {
-                                if (msg.transaction_id.value() != this->transaction_id)
-                                        return;
-                        } else if (msg.relations.references()) {
-                                if (msg.relations.references() != this->relation.event_id)
-                                        return;
-                        }
-                        error_ = User;
-                        emit errorChanged();
-                        setState(Failed);
-                });
-
-        connect(ChatPage::instance(),
-                &ChatPage::receivedDeviceVerificationKey,
-                this,
-                [this](const mtx::events::msg::KeyVerificationKey &msg) {
-                        nhlog::crypto()->info("verification: received key");
-                        if (msg.transaction_id.has_value()) {
-                                if (msg.transaction_id.value() != this->transaction_id)
-                                        return;
-                        } else if (msg.relations.references()) {
-                                if (msg.relations.references() != this->relation.event_id)
-                                        return;
-                        }
-
-                        if (sender) {
-                                if (state_ != WaitingForOtherToAccept) {
-                                        this->cancelVerification(OutOfOrder);
-                                        return;
-                                }
-                        } else {
-                                if (state_ != WaitingForKeys) {
-                                        this->cancelVerification(OutOfOrder);
-                                        return;
-                                }
-                        }
-
-                        this->sas->set_their_key(msg.key);
-                        std::string info;
-                        if (this->sender == true) {
-                                info = "MATRIX_KEY_VERIFICATION_SAS|" +
-                                       http::client()->user_id().to_string() + "|" +
-                                       http::client()->device_id() + "|" + this->sas->public_key() +
-                                       "|" + this->toClient.to_string() + "|" +
-                                       this->deviceId.toStdString() + "|" + msg.key + "|" +
-                                       this->transaction_id;
-                        } else {
-                                info = "MATRIX_KEY_VERIFICATION_SAS|" + this->toClient.to_string() +
-                                       "|" + this->deviceId.toStdString() + "|" + msg.key + "|" +
-                                       http::client()->user_id().to_string() + "|" +
-                                       http::client()->device_id() + "|" + this->sas->public_key() +
-                                       "|" + this->transaction_id;
-                        }
-
-                        nhlog::ui()->info("Info is: '{}'", info);
-
-                        if (this->sender == false) {
-                                this->sendVerificationKey();
-                        } else {
-                                if (this->commitment !=
-                                    mtx::crypto::bin2base64_unpadded(
-                                      mtx::crypto::sha256(msg.key + this->canonical_json.dump()))) {
-                                        this->cancelVerification(
-                                          DeviceVerificationFlow::Error::MismatchedCommitment);
-                                        return;
-                                }
-                        }
-
-                        if (this->method == mtx::events::msg::SASMethods::Emoji) {
-                                this->sasList = this->sas->generate_bytes_emoji(info);
-                                setState(CompareEmoji);
-                        } else if (this->method == mtx::events::msg::SASMethods::Decimal) {
-                                this->sasList = this->sas->generate_bytes_decimal(info);
-                                setState(CompareNumber);
-                        }
-                });
-
+    timeout = new QTimer(this);
+    timeout->setSingleShot(true);
+    this->sas           = olm::client()->sas_init();
+    this->isMacVerified = false;
+
+    auto user_id   = userID.toStdString();
+    this->toClient = mtx::identifiers::parse<mtx::identifiers::User>(user_id);
+    cache::client()->query_keys(
+      user_id, [user_id, this](const UserKeyCache &res, mtx::http::RequestErr err) {
+          if (err) {
+              nhlog::net()->warn("failed to query device keys: {},{}",
+                                 mtx::errors::to_string(err->matrix_error.errcode),
+                                 static_cast<int>(err->status_code));
+              return;
+          }
+
+          if (!this->deviceId.isEmpty() &&
+              (res.device_keys.find(deviceId.toStdString()) == res.device_keys.end())) {
+              nhlog::net()->warn("no devices retrieved {}", user_id);
+              return;
+          }
+
+          this->their_keys = res;
+      });
+
+    cache::client()->query_keys(
+      http::client()->user_id().to_string(),
+      [this](const UserKeyCache &res, mtx::http::RequestErr err) {
+          if (err) {
+              nhlog::net()->warn("failed to query device keys: {},{}",
+                                 mtx::errors::to_string(err->matrix_error.errcode),
+                                 static_cast<int>(err->status_code));
+              return;
+          }
+
+          if (res.master_keys.keys.empty())
+              return;
+
+          if (auto status = cache::verificationStatus(http::client()->user_id().to_string());
+              status && status->user_verified == crypto::Trust::Verified)
+              this->our_trusted_master_key = res.master_keys.keys.begin()->second;
+      });
+
+    if (model) {
         connect(
-          ChatPage::instance(),
-          &ChatPage::receivedDeviceVerificationMac,
-          this,
-          [this](const mtx::events::msg::KeyVerificationMac &msg) {
-                  nhlog::crypto()->info("verification: received mac");
-                  if (msg.transaction_id.has_value()) {
-                          if (msg.transaction_id.value() != this->transaction_id)
-                                  return;
-                  } else if (msg.relations.references()) {
-                          if (msg.relations.references() != this->relation.event_id)
-                                  return;
-                  }
-
-                  std::map<std::string, std::string> key_list;
-                  std::string key_string;
+          this->model_, &TimelineModel::updateFlowEventId, this, [this](std::string event_id_) {
+              this->relation.rel_type = mtx::common::RelationType::Reference;
+              this->relation.event_id = event_id_;
+              this->transaction_id    = event_id_;
+          });
+    }
+
+    connect(timeout, &QTimer::timeout, this, [this]() {
+        nhlog::crypto()->info("verification: timeout");
+        if (state_ != Success && state_ != Failed)
+            this->cancelVerification(DeviceVerificationFlow::Error::Timeout);
+    });
+
+    connect(ChatPage::instance(),
+            &ChatPage::receivedDeviceVerificationStart,
+            this,
+            &DeviceVerificationFlow::handleStartMessage);
+    connect(ChatPage::instance(),
+            &ChatPage::receivedDeviceVerificationAccept,
+            this,
+            [this](const mtx::events::msg::KeyVerificationAccept &msg) {
+                nhlog::crypto()->info("verification: received accept");
+                if (msg.transaction_id.has_value()) {
+                    if (msg.transaction_id.value() != this->transaction_id)
+                        return;
+                } else if (msg.relations.references()) {
+                    if (msg.relations.references() != this->relation.event_id)
+                        return;
+                }
+                if ((msg.key_agreement_protocol == "curve25519-hkdf-sha256") &&
+                    (msg.hash == "sha256") &&
+                    (msg.message_authentication_code == "hkdf-hmac-sha256")) {
+                    this->commitment = msg.commitment;
+                    if (std::find(msg.short_authentication_string.begin(),
+                                  msg.short_authentication_string.end(),
+                                  mtx::events::msg::SASMethods::Emoji) !=
+                        msg.short_authentication_string.end()) {
+                        this->method = mtx::events::msg::SASMethods::Emoji;
+                    } else {
+                        this->method = mtx::events::msg::SASMethods::Decimal;
+                    }
+                    this->mac_method = msg.message_authentication_code;
+                    this->sendVerificationKey();
+                } else {
+                    this->cancelVerification(DeviceVerificationFlow::Error::UnknownMethod);
+                }
+            });
+
+    connect(ChatPage::instance(),
+            &ChatPage::receivedDeviceVerificationCancel,
+            this,
+            [this](const mtx::events::msg::KeyVerificationCancel &msg) {
+                nhlog::crypto()->info("verification: received cancel");
+                if (msg.transaction_id.has_value()) {
+                    if (msg.transaction_id.value() != this->transaction_id)
+                        return;
+                } else if (msg.relations.references()) {
+                    if (msg.relations.references() != this->relation.event_id)
+                        return;
+                }
+                error_ = User;
+                emit errorChanged();
+                setState(Failed);
+            });
+
+    connect(
+      ChatPage::instance(),
+      &ChatPage::receivedDeviceVerificationKey,
+      this,
+      [this](const mtx::events::msg::KeyVerificationKey &msg) {
+          nhlog::crypto()->info("verification: received key");
+          if (msg.transaction_id.has_value()) {
+              if (msg.transaction_id.value() != this->transaction_id)
+                  return;
+          } else if (msg.relations.references()) {
+              if (msg.relations.references() != this->relation.event_id)
+                  return;
+          }
+
+          if (sender) {
+              if (state_ != WaitingForOtherToAccept) {
+                  this->cancelVerification(OutOfOrder);
+                  return;
+              }
+          } else {
+              if (state_ != WaitingForKeys) {
+                  this->cancelVerification(OutOfOrder);
+                  return;
+              }
+          }
+
+          this->sas->set_their_key(msg.key);
+          std::string info;
+          if (this->sender == true) {
+              info = "MATRIX_KEY_VERIFICATION_SAS|" + http::client()->user_id().to_string() + "|" +
+                     http::client()->device_id() + "|" + this->sas->public_key() + "|" +
+                     this->toClient.to_string() + "|" + this->deviceId.toStdString() + "|" +
+                     msg.key + "|" + this->transaction_id;
+          } else {
+              info = "MATRIX_KEY_VERIFICATION_SAS|" + this->toClient.to_string() + "|" +
+                     this->deviceId.toStdString() + "|" + msg.key + "|" +
+                     http::client()->user_id().to_string() + "|" + http::client()->device_id() +
+                     "|" + this->sas->public_key() + "|" + this->transaction_id;
+          }
+
+          nhlog::ui()->info("Info is: '{}'", info);
+
+          if (this->sender == false) {
+              this->sendVerificationKey();
+          } else {
+              if (this->commitment != mtx::crypto::bin2base64_unpadded(mtx::crypto::sha256(
+                                        msg.key + this->canonical_json.dump()))) {
+                  this->cancelVerification(DeviceVerificationFlow::Error::MismatchedCommitment);
+                  return;
+              }
+          }
+
+          if (this->method == mtx::events::msg::SASMethods::Emoji) {
+              this->sasList = this->sas->generate_bytes_emoji(info);
+              setState(CompareEmoji);
+          } else if (this->method == mtx::events::msg::SASMethods::Decimal) {
+              this->sasList = this->sas->generate_bytes_decimal(info);
+              setState(CompareNumber);
+          }
+      });
+
+    connect(
+      ChatPage::instance(),
+      &ChatPage::receivedDeviceVerificationMac,
+      this,
+      [this](const mtx::events::msg::KeyVerificationMac &msg) {
+          nhlog::crypto()->info("verification: received mac");
+          if (msg.transaction_id.has_value()) {
+              if (msg.transaction_id.value() != this->transaction_id)
+                  return;
+          } else if (msg.relations.references()) {
+              if (msg.relations.references() != this->relation.event_id)
+                  return;
+          }
+
+          std::map<std::string, std::string> key_list;
+          std::string key_string;
+          for (const auto &mac : msg.mac) {
+              for (const auto &[deviceid, key] : their_keys.device_keys) {
+                  (void)deviceid;
+                  if (key.keys.count(mac.first))
+                      key_list[mac.first] = key.keys.at(mac.first);
+              }
+
+              if (their_keys.master_keys.keys.count(mac.first))
+                  key_list[mac.first] = their_keys.master_keys.keys[mac.first];
+              if (their_keys.user_signing_keys.keys.count(mac.first))
+                  key_list[mac.first] = their_keys.user_signing_keys.keys[mac.first];
+              if (their_keys.self_signing_keys.keys.count(mac.first))
+                  key_list[mac.first] = their_keys.self_signing_keys.keys[mac.first];
+          }
+          auto macs = key_verification_mac(sas.get(),
+                                           toClient,
+                                           this->deviceId.toStdString(),
+                                           http::client()->user_id(),
+                                           http::client()->device_id(),
+                                           this->transaction_id,
+                                           key_list);
+
+          for (const auto &[key, mac] : macs.mac) {
+              if (mac != msg.mac.at(key)) {
+                  this->cancelVerification(DeviceVerificationFlow::Error::KeyMismatch);
+                  return;
+              }
+          }
+
+          if (msg.keys == macs.keys) {
+              mtx::requests::KeySignaturesUpload req;
+              if (utils::localUser().toStdString() == this->toClient.to_string()) {
+                  // self verification, sign master key with device key, if we
+                  // verified it
                   for (const auto &mac : msg.mac) {
-                          for (const auto &[deviceid, key] : their_keys.device_keys) {
-                                  (void)deviceid;
-                                  if (key.keys.count(mac.first))
-                                          key_list[mac.first] = key.keys.at(mac.first);
+                      if (their_keys.master_keys.keys.count(mac.first)) {
+                          json j = their_keys.master_keys;
+                          j.erase("signatures");
+                          j.erase("unsigned");
+                          mtx::crypto::CrossSigningKeys master_key = j;
+                          master_key.signatures[utils::localUser().toStdString()]
+                                               ["ed25519:" + http::client()->device_id()] =
+                            olm::client()->sign_message(j.dump());
+                          req.signatures[utils::localUser().toStdString()]
+                                        [master_key.keys.at(mac.first)] = master_key;
+                      } else if (mac.first == "ed25519:" + this->deviceId.toStdString()) {
+                          // Sign their device key with self signing key
+
+                          auto device_id = this->deviceId.toStdString();
+
+                          if (their_keys.device_keys.count(device_id)) {
+                              json j = their_keys.device_keys.at(device_id);
+                              j.erase("signatures");
+                              j.erase("unsigned");
+
+                              auto secret = cache::secret(
+                                mtx::secret_storage::secrets::cross_signing_self_signing);
+                              if (!secret)
+                                  continue;
+                              auto ssk = mtx::crypto::PkSigning::from_seed(*secret);
+
+                              mtx::crypto::DeviceKeys dev = j;
+                              dev.signatures[utils::localUser().toStdString()]
+                                            ["ed25519:" + ssk.public_key()] = ssk.sign(j.dump());
+
+                              req.signatures[utils::localUser().toStdString()][device_id] = dev;
                           }
-
-                          if (their_keys.master_keys.keys.count(mac.first))
-                                  key_list[mac.first] = their_keys.master_keys.keys[mac.first];
-                          if (their_keys.user_signing_keys.keys.count(mac.first))
-                                  key_list[mac.first] =
-                                    their_keys.user_signing_keys.keys[mac.first];
-                          if (their_keys.self_signing_keys.keys.count(mac.first))
-                                  key_list[mac.first] =
-                                    their_keys.self_signing_keys.keys[mac.first];
+                      }
                   }
-                  auto macs = key_verification_mac(sas.get(),
-                                                   toClient,
-                                                   this->deviceId.toStdString(),
-                                                   http::client()->user_id(),
-                                                   http::client()->device_id(),
-                                                   this->transaction_id,
-                                                   key_list);
-
-                  for (const auto &[key, mac] : macs.mac) {
-                          if (mac != msg.mac.at(key)) {
-                                  this->cancelVerification(
-                                    DeviceVerificationFlow::Error::KeyMismatch);
-                                  return;
-                          }
+              } else {
+                  // Sign their master key with user signing key
+                  for (const auto &mac : msg.mac) {
+                      if (their_keys.master_keys.keys.count(mac.first)) {
+                          json j = their_keys.master_keys;
+                          j.erase("signatures");
+                          j.erase("unsigned");
+
+                          auto secret =
+                            cache::secret(mtx::secret_storage::secrets::cross_signing_user_signing);
+                          if (!secret)
+                              continue;
+                          auto usk = mtx::crypto::PkSigning::from_seed(*secret);
+
+                          mtx::crypto::CrossSigningKeys master_key = j;
+                          master_key.signatures[utils::localUser().toStdString()]
+                                               ["ed25519:" + usk.public_key()] = usk.sign(j.dump());
+
+                          req.signatures[toClient.to_string()][master_key.keys.at(mac.first)] =
+                            master_key;
+                      }
                   }
+              }
+
+              if (!req.signatures.empty()) {
+                  http::client()->keys_signatures_upload(
+                    req,
+                    [](const mtx::responses::KeySignaturesUpload &res, mtx::http::RequestErr err) {
+                        if (err) {
+                            nhlog::net()->error("failed to upload signatures: {},{}",
+                                                mtx::errors::to_string(err->matrix_error.errcode),
+                                                static_cast<int>(err->status_code));
+                        }
 
-                  if (msg.keys == macs.keys) {
-                          mtx::requests::KeySignaturesUpload req;
-                          if (utils::localUser().toStdString() == this->toClient.to_string()) {
-                                  // self verification, sign master key with device key, if we
-                                  // verified it
-                                  for (const auto &mac : msg.mac) {
-                                          if (their_keys.master_keys.keys.count(mac.first)) {
-                                                  json j = their_keys.master_keys;
-                                                  j.erase("signatures");
-                                                  j.erase("unsigned");
-                                                  mtx::crypto::CrossSigningKeys master_key = j;
-                                                  master_key
-                                                    .signatures[utils::localUser().toStdString()]
-                                                               ["ed25519:" +
-                                                                http::client()->device_id()] =
-                                                    olm::client()->sign_message(j.dump());
-                                                  req.signatures[utils::localUser().toStdString()]
-                                                                [master_key.keys.at(mac.first)] =
-                                                    master_key;
-                                          } else if (mac.first ==
-                                                     "ed25519:" + this->deviceId.toStdString()) {
-                                                  // Sign their device key with self signing key
-
-                                                  auto device_id = this->deviceId.toStdString();
-
-                                                  if (their_keys.device_keys.count(device_id)) {
-                                                          json j =
-                                                            their_keys.device_keys.at(device_id);
-                                                          j.erase("signatures");
-                                                          j.erase("unsigned");
-
-                                                          auto secret = cache::secret(
-                                                            mtx::secret_storage::secrets::
-                                                              cross_signing_self_signing);
-                                                          if (!secret)
-                                                                  continue;
-                                                          auto ssk =
-                                                            mtx::crypto::PkSigning::from_seed(
-                                                              *secret);
-
-                                                          mtx::crypto::DeviceKeys dev = j;
-                                                          dev.signatures
-                                                            [utils::localUser().toStdString()]
-                                                            ["ed25519:" + ssk.public_key()] =
-                                                            ssk.sign(j.dump());
-
-                                                          req.signatures[utils::localUser()
-                                                                           .toStdString()]
-                                                                        [device_id] = dev;
-                                                  }
-                                          }
-                                  }
-                          } else {
-                                  // Sign their master key with user signing key
-                                  for (const auto &mac : msg.mac) {
-                                          if (their_keys.master_keys.keys.count(mac.first)) {
-                                                  json j = their_keys.master_keys;
-                                                  j.erase("signatures");
-                                                  j.erase("unsigned");
-
-                                                  auto secret =
-                                                    cache::secret(mtx::secret_storage::secrets::
-                                                                    cross_signing_user_signing);
-                                                  if (!secret)
-                                                          continue;
-                                                  auto usk =
-                                                    mtx::crypto::PkSigning::from_seed(*secret);
-
-                                                  mtx::crypto::CrossSigningKeys master_key = j;
-                                                  master_key
-                                                    .signatures[utils::localUser().toStdString()]
-                                                               ["ed25519:" + usk.public_key()] =
-                                                    usk.sign(j.dump());
-
-                                                  req.signatures[toClient.to_string()]
-                                                                [master_key.keys.at(mac.first)] =
-                                                    master_key;
-                                          }
-                                  }
-                          }
-
-                          if (!req.signatures.empty()) {
-                                  http::client()->keys_signatures_upload(
-                                    req,
-                                    [](const mtx::responses::KeySignaturesUpload &res,
-                                       mtx::http::RequestErr err) {
-                                            if (err) {
-                                                    nhlog::net()->error(
-                                                      "failed to upload signatures: {},{}",
-                                                      mtx::errors::to_string(
-                                                        err->matrix_error.errcode),
-                                                      static_cast<int>(err->status_code));
-                                            }
-
-                                            for (const auto &[user_id, tmp] : res.errors)
-                                                    for (const auto &[key_id, e] : tmp)
-                                                            nhlog::net()->error(
-                                                              "signature error for user {} and key "
-                                                              "id {}: {}, {}",
-                                                              user_id,
-                                                              key_id,
-                                                              mtx::errors::to_string(e.errcode),
-                                                              e.error);
-                                    });
-                          }
-
-                          this->isMacVerified = true;
-                          this->acceptDevice();
-                  } else {
-                          this->cancelVerification(DeviceVerificationFlow::Error::KeyMismatch);
-                  }
-          });
+                        for (const auto &[user_id, tmp] : res.errors)
+                            for (const auto &[key_id, e] : tmp)
+                                nhlog::net()->error("signature error for user {} and key "
+                                                    "id {}: {}, {}",
+                                                    user_id,
+                                                    key_id,
+                                                    mtx::errors::to_string(e.errcode),
+                                                    e.error);
+                    });
+              }
+
+              this->isMacVerified = true;
+              this->acceptDevice();
+          } else {
+              this->cancelVerification(DeviceVerificationFlow::Error::KeyMismatch);
+          }
+      });
+
+    connect(ChatPage::instance(),
+            &ChatPage::receivedDeviceVerificationReady,
+            this,
+            [this](const mtx::events::msg::KeyVerificationReady &msg) {
+                nhlog::crypto()->info("verification: received ready");
+                if (!sender) {
+                    if (msg.from_device != http::client()->device_id()) {
+                        error_ = User;
+                        emit errorChanged();
+                        setState(Failed);
+                    }
 
-        connect(ChatPage::instance(),
-                &ChatPage::receivedDeviceVerificationReady,
-                this,
-                [this](const mtx::events::msg::KeyVerificationReady &msg) {
-                        nhlog::crypto()->info("verification: received ready");
-                        if (!sender) {
-                                if (msg.from_device != http::client()->device_id()) {
-                                        error_ = User;
-                                        emit errorChanged();
-                                        setState(Failed);
-                                }
-
-                                return;
-                        }
+                    return;
+                }
 
-                        if (msg.transaction_id.has_value()) {
-                                if (msg.transaction_id.value() != this->transaction_id)
-                                        return;
-                        } else if (msg.relations.references()) {
-                                if (msg.relations.references() != this->relation.event_id)
-                                        return;
-                                else {
-                                        this->deviceId = QString::fromStdString(msg.from_device);
-                                }
-                        }
-                        this->startVerificationRequest();
-                });
-
-        connect(ChatPage::instance(),
-                &ChatPage::receivedDeviceVerificationDone,
-                this,
-                [this](const mtx::events::msg::KeyVerificationDone &msg) {
-                        nhlog::crypto()->info("verification: receoved done");
-                        if (msg.transaction_id.has_value()) {
-                                if (msg.transaction_id.value() != this->transaction_id)
-                                        return;
-                        } else if (msg.relations.references()) {
-                                if (msg.relations.references() != this->relation.event_id)
-                                        return;
-                        }
-                        nhlog::ui()->info("Flow done on other side");
-                });
+                if (msg.transaction_id.has_value()) {
+                    if (msg.transaction_id.value() != this->transaction_id)
+                        return;
+                } else if (msg.relations.references()) {
+                    if (msg.relations.references() != this->relation.event_id)
+                        return;
+                    else {
+                        this->deviceId = QString::fromStdString(msg.from_device);
+                    }
+                }
+                this->startVerificationRequest();
+            });
+
+    connect(ChatPage::instance(),
+            &ChatPage::receivedDeviceVerificationDone,
+            this,
+            [this](const mtx::events::msg::KeyVerificationDone &msg) {
+                nhlog::crypto()->info("verification: receoved done");
+                if (msg.transaction_id.has_value()) {
+                    if (msg.transaction_id.value() != this->transaction_id)
+                        return;
+                } else if (msg.relations.references()) {
+                    if (msg.relations.references() != this->relation.event_id)
+                        return;
+                }
+                nhlog::ui()->info("Flow done on other side");
+            });
 
-        timeout->start(TIMEOUT);
+    timeout->start(TIMEOUT);
 }
 
 QString
 DeviceVerificationFlow::state()
 {
+    switch (state_) {
+    case PromptStartVerification:
+        return "PromptStartVerification";
+    case CompareEmoji:
+        return "CompareEmoji";
+    case CompareNumber:
+        return "CompareNumber";
+    case WaitingForKeys:
+        return "WaitingForKeys";
+    case WaitingForOtherToAccept:
+        return "WaitingForOtherToAccept";
+    case WaitingForMac:
+        return "WaitingForMac";
+    case Success:
+        return "Success";
+    case Failed:
+        return "Failed";
+    default:
+        return "";
+    }
+}
+
+void
+DeviceVerificationFlow::next()
+{
+    if (sender) {
         switch (state_) {
         case PromptStartVerification:
-                return "PromptStartVerification";
+            sendVerificationRequest();
+            break;
         case CompareEmoji:
-                return "CompareEmoji";
         case CompareNumber:
-                return "CompareNumber";
+            sendVerificationMac();
+            break;
         case WaitingForKeys:
-                return "WaitingForKeys";
         case WaitingForOtherToAccept:
-                return "WaitingForOtherToAccept";
         case WaitingForMac:
-                return "WaitingForMac";
         case Success:
-                return "Success";
         case Failed:
-                return "Failed";
-        default:
-                return "";
+            nhlog::db()->error("verification: Invalid state transition!");
+            break;
         }
-}
-
-void
-DeviceVerificationFlow::next()
-{
-        if (sender) {
-                switch (state_) {
-                case PromptStartVerification:
-                        sendVerificationRequest();
-                        break;
-                case CompareEmoji:
-                case CompareNumber:
-                        sendVerificationMac();
-                        break;
-                case WaitingForKeys:
-                case WaitingForOtherToAccept:
-                case WaitingForMac:
-                case Success:
-                case Failed:
-                        nhlog::db()->error("verification: Invalid state transition!");
-                        break;
-                }
-        } else {
-                switch (state_) {
-                case PromptStartVerification:
-                        if (canonical_json.is_null())
-                                sendVerificationReady();
-                        else // legacy path without request and ready
-                                acceptVerificationRequest();
-                        break;
-                case CompareEmoji:
-                        [[fallthrough]];
-                case CompareNumber:
-                        sendVerificationMac();
-                        break;
-                case WaitingForKeys:
-                case WaitingForOtherToAccept:
-                case WaitingForMac:
-                case Success:
-                case Failed:
-                        nhlog::db()->error("verification: Invalid state transition!");
-                        break;
-                }
+    } else {
+        switch (state_) {
+        case PromptStartVerification:
+            if (canonical_json.is_null())
+                sendVerificationReady();
+            else // legacy path without request and ready
+                acceptVerificationRequest();
+            break;
+        case CompareEmoji:
+            [[fallthrough]];
+        case CompareNumber:
+            sendVerificationMac();
+            break;
+        case WaitingForKeys:
+        case WaitingForOtherToAccept:
+        case WaitingForMac:
+        case Success:
+        case Failed:
+            nhlog::db()->error("verification: Invalid state transition!");
+            break;
         }
+    }
 }
 
 QString
 DeviceVerificationFlow::getUserId()
 {
-        return QString::fromStdString(this->toClient.to_string());
+    return QString::fromStdString(this->toClient.to_string());
 }
 
 QString
 DeviceVerificationFlow::getDeviceId()
 {
-        return this->deviceId;
+    return this->deviceId;
 }
 
 bool
 DeviceVerificationFlow::getSender()
 {
-        return this->sender;
+    return this->sender;
 }
 
 std::vector<int>
 DeviceVerificationFlow::getSasList()
 {
-        return this->sasList;
+    return this->sasList;
 }
 
 bool
 DeviceVerificationFlow::isSelfVerification() const
 {
-        return this->toClient.to_string() == http::client()->user_id().to_string();
+    return this->toClient.to_string() == http::client()->user_id().to_string();
 }
 
 void
 DeviceVerificationFlow::setEventId(std::string event_id_)
 {
-        this->relation.rel_type = mtx::common::RelationType::Reference;
-        this->relation.event_id = event_id_;
-        this->transaction_id    = event_id_;
+    this->relation.rel_type = mtx::common::RelationType::Reference;
+    this->relation.event_id = event_id_;
+    this->transaction_id    = event_id_;
 }
 
 void
 DeviceVerificationFlow::handleStartMessage(const mtx::events::msg::KeyVerificationStart &msg,
                                            std::string)
 {
-        if (msg.transaction_id.has_value()) {
-                if (msg.transaction_id.value() != this->transaction_id)
-                        return;
-        } else if (msg.relations.references()) {
-                if (msg.relations.references() != this->relation.event_id)
-                        return;
-        }
-        if ((std::find(msg.key_agreement_protocols.begin(),
-                       msg.key_agreement_protocols.end(),
-                       "curve25519-hkdf-sha256") != msg.key_agreement_protocols.end()) &&
-            (std::find(msg.hashes.begin(), msg.hashes.end(), "sha256") != msg.hashes.end()) &&
-            (std::find(msg.message_authentication_codes.begin(),
-                       msg.message_authentication_codes.end(),
-                       "hkdf-hmac-sha256") != msg.message_authentication_codes.end())) {
-                if (std::find(msg.short_authentication_string.begin(),
-                              msg.short_authentication_string.end(),
-                              mtx::events::msg::SASMethods::Emoji) !=
-                    msg.short_authentication_string.end()) {
-                        this->method = mtx::events::msg::SASMethods::Emoji;
-                } else if (std::find(msg.short_authentication_string.begin(),
-                                     msg.short_authentication_string.end(),
-                                     mtx::events::msg::SASMethods::Decimal) !=
-                           msg.short_authentication_string.end()) {
-                        this->method = mtx::events::msg::SASMethods::Decimal;
-                } else {
-                        this->cancelVerification(DeviceVerificationFlow::Error::UnknownMethod);
-                        return;
-                }
-                if (!sender)
-                        this->canonical_json = nlohmann::json(msg);
-                else {
-                        if (utils::localUser().toStdString() < this->toClient.to_string()) {
-                                this->canonical_json = nlohmann::json(msg);
-                        }
-                }
-
-                if (state_ != PromptStartVerification)
-                        this->acceptVerificationRequest();
+    if (msg.transaction_id.has_value()) {
+        if (msg.transaction_id.value() != this->transaction_id)
+            return;
+    } else if (msg.relations.references()) {
+        if (msg.relations.references() != this->relation.event_id)
+            return;
+    }
+    if ((std::find(msg.key_agreement_protocols.begin(),
+                   msg.key_agreement_protocols.end(),
+                   "curve25519-hkdf-sha256") != msg.key_agreement_protocols.end()) &&
+        (std::find(msg.hashes.begin(), msg.hashes.end(), "sha256") != msg.hashes.end()) &&
+        (std::find(msg.message_authentication_codes.begin(),
+                   msg.message_authentication_codes.end(),
+                   "hkdf-hmac-sha256") != msg.message_authentication_codes.end())) {
+        if (std::find(msg.short_authentication_string.begin(),
+                      msg.short_authentication_string.end(),
+                      mtx::events::msg::SASMethods::Emoji) !=
+            msg.short_authentication_string.end()) {
+            this->method = mtx::events::msg::SASMethods::Emoji;
+        } else if (std::find(msg.short_authentication_string.begin(),
+                             msg.short_authentication_string.end(),
+                             mtx::events::msg::SASMethods::Decimal) !=
+                   msg.short_authentication_string.end()) {
+            this->method = mtx::events::msg::SASMethods::Decimal;
         } else {
-                this->cancelVerification(DeviceVerificationFlow::Error::UnknownMethod);
+            this->cancelVerification(DeviceVerificationFlow::Error::UnknownMethod);
+            return;
+        }
+        if (!sender)
+            this->canonical_json = nlohmann::json(msg);
+        else {
+            if (utils::localUser().toStdString() < this->toClient.to_string()) {
+                this->canonical_json = nlohmann::json(msg);
+            }
         }
+
+        if (state_ != PromptStartVerification)
+            this->acceptVerificationRequest();
+    } else {
+        this->cancelVerification(DeviceVerificationFlow::Error::UnknownMethod);
+    }
 }
 
 //! accepts a verification
 void
 DeviceVerificationFlow::acceptVerificationRequest()
 {
-        mtx::events::msg::KeyVerificationAccept req;
-
-        req.method                      = mtx::events::msg::VerificationMethods::SASv1;
-        req.key_agreement_protocol      = "curve25519-hkdf-sha256";
-        req.hash                        = "sha256";
-        req.message_authentication_code = "hkdf-hmac-sha256";
-        if (this->method == mtx::events::msg::SASMethods::Emoji)
-                req.short_authentication_string = {mtx::events::msg::SASMethods::Emoji};
-        else if (this->method == mtx::events::msg::SASMethods::Decimal)
-                req.short_authentication_string = {mtx::events::msg::SASMethods::Decimal};
-        req.commitment = mtx::crypto::bin2base64_unpadded(
-          mtx::crypto::sha256(this->sas->public_key() + this->canonical_json.dump()));
-
-        send(req);
-        setState(WaitingForKeys);
+    mtx::events::msg::KeyVerificationAccept req;
+
+    req.method                      = mtx::events::msg::VerificationMethods::SASv1;
+    req.key_agreement_protocol      = "curve25519-hkdf-sha256";
+    req.hash                        = "sha256";
+    req.message_authentication_code = "hkdf-hmac-sha256";
+    if (this->method == mtx::events::msg::SASMethods::Emoji)
+        req.short_authentication_string = {mtx::events::msg::SASMethods::Emoji};
+    else if (this->method == mtx::events::msg::SASMethods::Decimal)
+        req.short_authentication_string = {mtx::events::msg::SASMethods::Decimal};
+    req.commitment = mtx::crypto::bin2base64_unpadded(
+      mtx::crypto::sha256(this->sas->public_key() + this->canonical_json.dump()));
+
+    send(req);
+    setState(WaitingForKeys);
 }
 //! responds verification request
 void
 DeviceVerificationFlow::sendVerificationReady()
 {
-        mtx::events::msg::KeyVerificationReady req;
+    mtx::events::msg::KeyVerificationReady req;
 
-        req.from_device = http::client()->device_id();
-        req.methods     = {mtx::events::msg::VerificationMethods::SASv1};
+    req.from_device = http::client()->device_id();
+    req.methods     = {mtx::events::msg::VerificationMethods::SASv1};
 
-        send(req);
-        setState(WaitingForKeys);
+    send(req);
+    setState(WaitingForKeys);
 }
 //! accepts a verification
 void
 DeviceVerificationFlow::sendVerificationDone()
 {
-        mtx::events::msg::KeyVerificationDone req;
+    mtx::events::msg::KeyVerificationDone req;
 
-        send(req);
+    send(req);
 }
 //! starts the verification flow
 void
 DeviceVerificationFlow::startVerificationRequest()
 {
-        mtx::events::msg::KeyVerificationStart req;
-
-        req.from_device                  = http::client()->device_id();
-        req.method                       = mtx::events::msg::VerificationMethods::SASv1;
-        req.key_agreement_protocols      = {"curve25519-hkdf-sha256"};
-        req.hashes                       = {"sha256"};
-        req.message_authentication_codes = {"hkdf-hmac-sha256"};
-        req.short_authentication_string  = {mtx::events::msg::SASMethods::Decimal,
-                                           mtx::events::msg::SASMethods::Emoji};
-
-        if (this->type == DeviceVerificationFlow::Type::ToDevice) {
-                mtx::requests::ToDeviceMessages<mtx::events::msg::KeyVerificationStart> body;
-                req.transaction_id   = this->transaction_id;
-                this->canonical_json = nlohmann::json(req);
-        } else if (this->type == DeviceVerificationFlow::Type::RoomMsg && model_) {
-                req.relations.relations.push_back(this->relation);
-                // Set synthesized to surpress the nheko relation extensions
-                req.relations.synthesized = true;
-                this->canonical_json      = nlohmann::json(req);
-        }
-        send(req);
-        setState(WaitingForOtherToAccept);
+    mtx::events::msg::KeyVerificationStart req;
+
+    req.from_device                  = http::client()->device_id();
+    req.method                       = mtx::events::msg::VerificationMethods::SASv1;
+    req.key_agreement_protocols      = {"curve25519-hkdf-sha256"};
+    req.hashes                       = {"sha256"};
+    req.message_authentication_codes = {"hkdf-hmac-sha256"};
+    req.short_authentication_string  = {mtx::events::msg::SASMethods::Decimal,
+                                       mtx::events::msg::SASMethods::Emoji};
+
+    if (this->type == DeviceVerificationFlow::Type::ToDevice) {
+        mtx::requests::ToDeviceMessages<mtx::events::msg::KeyVerificationStart> body;
+        req.transaction_id   = this->transaction_id;
+        this->canonical_json = nlohmann::json(req);
+    } else if (this->type == DeviceVerificationFlow::Type::RoomMsg && model_) {
+        req.relations.relations.push_back(this->relation);
+        // Set synthesized to surpress the nheko relation extensions
+        req.relations.synthesized = true;
+        this->canonical_json      = nlohmann::json(req);
+    }
+    send(req);
+    setState(WaitingForOtherToAccept);
 }
 //! sends a verification request
 void
 DeviceVerificationFlow::sendVerificationRequest()
 {
-        mtx::events::msg::KeyVerificationRequest req;
+    mtx::events::msg::KeyVerificationRequest req;
 
-        req.from_device = http::client()->device_id();
-        req.methods     = {mtx::events::msg::VerificationMethods::SASv1};
+    req.from_device = http::client()->device_id();
+    req.methods     = {mtx::events::msg::VerificationMethods::SASv1};
 
-        if (this->type == DeviceVerificationFlow::Type::ToDevice) {
-                QDateTime currentTime = QDateTime::currentDateTimeUtc();
+    if (this->type == DeviceVerificationFlow::Type::ToDevice) {
+        QDateTime currentTime = QDateTime::currentDateTimeUtc();
 
-                req.timestamp = (uint64_t)currentTime.toMSecsSinceEpoch();
+        req.timestamp = (uint64_t)currentTime.toMSecsSinceEpoch();
 
-        } else if (this->type == DeviceVerificationFlow::Type::RoomMsg && model_) {
-                req.to      = this->toClient.to_string();
-                req.msgtype = "m.key.verification.request";
-                req.body = "User is requesting to verify keys with you. However, your client does "
-                           "not support this method, so you will need to use the legacy method of "
-                           "key verification.";
-        }
+    } else if (this->type == DeviceVerificationFlow::Type::RoomMsg && model_) {
+        req.to      = this->toClient.to_string();
+        req.msgtype = "m.key.verification.request";
+        req.body    = "User is requesting to verify keys with you. However, your client does "
+                   "not support this method, so you will need to use the legacy method of "
+                   "key verification.";
+    }
 
-        send(req);
-        setState(WaitingForOtherToAccept);
+    send(req);
+    setState(WaitingForOtherToAccept);
 }
 //! cancels a verification flow
 void
 DeviceVerificationFlow::cancelVerification(DeviceVerificationFlow::Error error_code)
 {
-        if (state_ == State::Success || state_ == State::Failed)
-                return;
-
-        mtx::events::msg::KeyVerificationCancel req;
-
-        if (error_code == DeviceVerificationFlow::Error::UnknownMethod) {
-                req.code   = "m.unknown_method";
-                req.reason = "unknown method received";
-        } else if (error_code == DeviceVerificationFlow::Error::MismatchedCommitment) {
-                req.code   = "m.mismatched_commitment";
-                req.reason = "commitment didn't match";
-        } else if (error_code == DeviceVerificationFlow::Error::MismatchedSAS) {
-                req.code   = "m.mismatched_sas";
-                req.reason = "sas didn't match";
-        } else if (error_code == DeviceVerificationFlow::Error::KeyMismatch) {
-                req.code   = "m.key_match";
-                req.reason = "keys did not match";
-        } else if (error_code == DeviceVerificationFlow::Error::Timeout) {
-                req.code   = "m.timeout";
-                req.reason = "timed out";
-        } else if (error_code == DeviceVerificationFlow::Error::User) {
-                req.code   = "m.user";
-                req.reason = "user cancelled the verification";
-        } else if (error_code == DeviceVerificationFlow::Error::OutOfOrder) {
-                req.code   = "m.unexpected_message";
-                req.reason = "received messages out of order";
-        }
-
-        this->error_ = error_code;
-        emit errorChanged();
-        this->setState(Failed);
-
-        send(req);
+    if (state_ == State::Success || state_ == State::Failed)
+        return;
+
+    mtx::events::msg::KeyVerificationCancel req;
+
+    if (error_code == DeviceVerificationFlow::Error::UnknownMethod) {
+        req.code   = "m.unknown_method";
+        req.reason = "unknown method received";
+    } else if (error_code == DeviceVerificationFlow::Error::MismatchedCommitment) {
+        req.code   = "m.mismatched_commitment";
+        req.reason = "commitment didn't match";
+    } else if (error_code == DeviceVerificationFlow::Error::MismatchedSAS) {
+        req.code   = "m.mismatched_sas";
+        req.reason = "sas didn't match";
+    } else if (error_code == DeviceVerificationFlow::Error::KeyMismatch) {
+        req.code   = "m.key_match";
+        req.reason = "keys did not match";
+    } else if (error_code == DeviceVerificationFlow::Error::Timeout) {
+        req.code   = "m.timeout";
+        req.reason = "timed out";
+    } else if (error_code == DeviceVerificationFlow::Error::User) {
+        req.code   = "m.user";
+        req.reason = "user cancelled the verification";
+    } else if (error_code == DeviceVerificationFlow::Error::OutOfOrder) {
+        req.code   = "m.unexpected_message";
+        req.reason = "received messages out of order";
+    }
+
+    this->error_ = error_code;
+    emit errorChanged();
+    this->setState(Failed);
+
+    send(req);
 }
 //! sends the verification key
 void
 DeviceVerificationFlow::sendVerificationKey()
 {
-        mtx::events::msg::KeyVerificationKey req;
+    mtx::events::msg::KeyVerificationKey req;
 
-        req.key = this->sas->public_key();
+    req.key = this->sas->public_key();
 
-        send(req);
+    send(req);
 }
 
 mtx::events::msg::KeyVerificationMac
@@ -728,79 +696,78 @@ key_verification_mac(mtx::crypto::SAS *sas,
                      const std::string &transactionId,
                      std::map<std::string, std::string> keys)
 {
-        mtx::events::msg::KeyVerificationMac req;
+    mtx::events::msg::KeyVerificationMac req;
 
-        std::string info = "MATRIX_KEY_VERIFICATION_MAC" + sender.to_string() + senderDevice +
-                           receiver.to_string() + receiverDevice + transactionId;
+    std::string info = "MATRIX_KEY_VERIFICATION_MAC" + sender.to_string() + senderDevice +
+                       receiver.to_string() + receiverDevice + transactionId;
 
-        std::string key_list;
-        bool first = true;
-        for (const auto &[key_id, key] : keys) {
-                req.mac[key_id] = sas->calculate_mac(key, info + key_id);
+    std::string key_list;
+    bool first = true;
+    for (const auto &[key_id, key] : keys) {
+        req.mac[key_id] = sas->calculate_mac(key, info + key_id);
 
-                if (!first)
-                        key_list += ",";
-                key_list += key_id;
-                first = false;
-        }
+        if (!first)
+            key_list += ",";
+        key_list += key_id;
+        first = false;
+    }
 
-        req.keys = sas->calculate_mac(key_list, info + "KEY_IDS");
+    req.keys = sas->calculate_mac(key_list, info + "KEY_IDS");
 
-        return req;
+    return req;
 }
 
 //! sends the mac of the keys
 void
 DeviceVerificationFlow::sendVerificationMac()
 {
-        std::map<std::string, std::string> key_list;
-        key_list["ed25519:" + http::client()->device_id()] = olm::client()->identity_keys().ed25519;
+    std::map<std::string, std::string> key_list;
+    key_list["ed25519:" + http::client()->device_id()] = olm::client()->identity_keys().ed25519;
 
-        // send our master key, if we trust it
-        if (!this->our_trusted_master_key.empty())
-                key_list["ed25519:" + our_trusted_master_key] = our_trusted_master_key;
+    // send our master key, if we trust it
+    if (!this->our_trusted_master_key.empty())
+        key_list["ed25519:" + our_trusted_master_key] = our_trusted_master_key;
 
-        mtx::events::msg::KeyVerificationMac req =
-          key_verification_mac(sas.get(),
-                               http::client()->user_id(),
-                               http::client()->device_id(),
-                               this->toClient,
-                               this->deviceId.toStdString(),
-                               this->transaction_id,
-                               key_list);
+    mtx::events::msg::KeyVerificationMac req = key_verification_mac(sas.get(),
+                                                                    http::client()->user_id(),
+                                                                    http::client()->device_id(),
+                                                                    this->toClient,
+                                                                    this->deviceId.toStdString(),
+                                                                    this->transaction_id,
+                                                                    key_list);
 
-        send(req);
+    send(req);
 
-        setState(WaitingForMac);
-        acceptDevice();
+    setState(WaitingForMac);
+    acceptDevice();
 }
 //! Completes the verification flow
 void
 DeviceVerificationFlow::acceptDevice()
 {
-        if (!isMacVerified) {
-                setState(WaitingForMac);
-        } else if (state_ == WaitingForMac) {
-                cache::markDeviceVerified(this->toClient.to_string(), this->deviceId.toStdString());
-                this->sendVerificationDone();
-                setState(Success);
-
-                // Request secrets. We should probably check somehow, if a device knowns about the
-                // secrets.
-                if (utils::localUser().toStdString() == this->toClient.to_string() &&
-                    (!cache::secret(mtx::secret_storage::secrets::cross_signing_self_signing) ||
-                     !cache::secret(mtx::secret_storage::secrets::cross_signing_user_signing))) {
-                        olm::request_cross_signing_keys();
-                }
+    if (!isMacVerified) {
+        setState(WaitingForMac);
+    } else if (state_ == WaitingForMac) {
+        cache::markDeviceVerified(this->toClient.to_string(), this->deviceId.toStdString());
+        this->sendVerificationDone();
+        setState(Success);
+
+        // Request secrets. We should probably check somehow, if a device knowns about the
+        // secrets.
+        if (utils::localUser().toStdString() == this->toClient.to_string() &&
+            (!cache::secret(mtx::secret_storage::secrets::cross_signing_self_signing) ||
+             !cache::secret(mtx::secret_storage::secrets::cross_signing_user_signing))) {
+            olm::request_cross_signing_keys();
         }
+    }
 }
 
 void
 DeviceVerificationFlow::unverify()
 {
-        cache::markDeviceUnverified(this->toClient.to_string(), this->deviceId.toStdString());
+    cache::markDeviceUnverified(this->toClient.to_string(), this->deviceId.toStdString());
 
-        emit refreshProfile();
+    emit refreshProfile();
 }
 
 QSharedPointer<DeviceVerificationFlow>
@@ -810,22 +777,22 @@ DeviceVerificationFlow::NewInRoomVerification(QObject *parent_,
                                               QString other_user_,
                                               QString event_id_)
 {
-        QSharedPointer<DeviceVerificationFlow> flow(
-          new DeviceVerificationFlow(parent_,
-                                     Type::RoomMsg,
-                                     timelineModel_,
-                                     other_user_,
-                                     QString::fromStdString(msg.from_device)));
-
-        flow->setEventId(event_id_.toStdString());
-
-        if (std::find(msg.methods.begin(),
-                      msg.methods.end(),
-                      mtx::events::msg::VerificationMethods::SASv1) == msg.methods.end()) {
-                flow->cancelVerification(UnknownMethod);
-        }
-
-        return flow;
+    QSharedPointer<DeviceVerificationFlow> flow(
+      new DeviceVerificationFlow(parent_,
+                                 Type::RoomMsg,
+                                 timelineModel_,
+                                 other_user_,
+                                 QString::fromStdString(msg.from_device)));
+
+    flow->setEventId(event_id_.toStdString());
+
+    if (std::find(msg.methods.begin(),
+                  msg.methods.end(),
+                  mtx::events::msg::VerificationMethods::SASv1) == msg.methods.end()) {
+        flow->cancelVerification(UnknownMethod);
+    }
+
+    return flow;
 }
 QSharedPointer<DeviceVerificationFlow>
 DeviceVerificationFlow::NewToDeviceVerification(QObject *parent_,
@@ -833,17 +800,17 @@ DeviceVerificationFlow::NewToDeviceVerification(QObject *parent_,
                                                 QString other_user_,
                                                 QString txn_id_)
 {
-        QSharedPointer<DeviceVerificationFlow> flow(new DeviceVerificationFlow(
-          parent_, Type::ToDevice, nullptr, other_user_, QString::fromStdString(msg.from_device)));
-        flow->transaction_id = txn_id_.toStdString();
-
-        if (std::find(msg.methods.begin(),
-                      msg.methods.end(),
-                      mtx::events::msg::VerificationMethods::SASv1) == msg.methods.end()) {
-                flow->cancelVerification(UnknownMethod);
-        }
+    QSharedPointer<DeviceVerificationFlow> flow(new DeviceVerificationFlow(
+      parent_, Type::ToDevice, nullptr, other_user_, QString::fromStdString(msg.from_device)));
+    flow->transaction_id = txn_id_.toStdString();
+
+    if (std::find(msg.methods.begin(),
+                  msg.methods.end(),
+                  mtx::events::msg::VerificationMethods::SASv1) == msg.methods.end()) {
+        flow->cancelVerification(UnknownMethod);
+    }
 
-        return flow;
+    return flow;
 }
 QSharedPointer<DeviceVerificationFlow>
 DeviceVerificationFlow::NewToDeviceVerification(QObject *parent_,
@@ -851,32 +818,32 @@ DeviceVerificationFlow::NewToDeviceVerification(QObject *parent_,
                                                 QString other_user_,
                                                 QString txn_id_)
 {
-        QSharedPointer<DeviceVerificationFlow> flow(new DeviceVerificationFlow(
-          parent_, Type::ToDevice, nullptr, other_user_, QString::fromStdString(msg.from_device)));
-        flow->transaction_id = txn_id_.toStdString();
+    QSharedPointer<DeviceVerificationFlow> flow(new DeviceVerificationFlow(
+      parent_, Type::ToDevice, nullptr, other_user_, QString::fromStdString(msg.from_device)));
+    flow->transaction_id = txn_id_.toStdString();
 
-        flow->handleStartMessage(msg, "");
+    flow->handleStartMessage(msg, "");
 
-        return flow;
+    return flow;
 }
 QSharedPointer<DeviceVerificationFlow>
 DeviceVerificationFlow::InitiateUserVerification(QObject *parent_,
                                                  TimelineModel *timelineModel_,
                                                  QString userid)
 {
-        QSharedPointer<DeviceVerificationFlow> flow(
-          new DeviceVerificationFlow(parent_, Type::RoomMsg, timelineModel_, userid, ""));
-        flow->sender = true;
-        return flow;
+    QSharedPointer<DeviceVerificationFlow> flow(
+      new DeviceVerificationFlow(parent_, Type::RoomMsg, timelineModel_, userid, ""));
+    flow->sender = true;
+    return flow;
 }
 QSharedPointer<DeviceVerificationFlow>
 DeviceVerificationFlow::InitiateDeviceVerification(QObject *parent_, QString userid, QString device)
 {
-        QSharedPointer<DeviceVerificationFlow> flow(
-          new DeviceVerificationFlow(parent_, Type::ToDevice, nullptr, userid, device));
+    QSharedPointer<DeviceVerificationFlow> flow(
+      new DeviceVerificationFlow(parent_, Type::ToDevice, nullptr, userid, device));
 
-        flow->sender         = true;
-        flow->transaction_id = http::client()->generate_txn_id();
+    flow->sender         = true;
+    flow->transaction_id = http::client()->generate_txn_id();
 
-        return flow;
+    return flow;
 }
diff --git a/src/DeviceVerificationFlow.h b/src/DeviceVerificationFlow.h
index 4685a450..f71fa337 100644
--- a/src/DeviceVerificationFlow.h
+++ b/src/DeviceVerificationFlow.h
@@ -60,192 +60,189 @@ using sas_ptr = std::unique_ptr<mtx::crypto::SAS>;
 // clang-format on
 class DeviceVerificationFlow : public QObject
 {
-        Q_OBJECT
-        Q_PROPERTY(QString state READ state NOTIFY stateChanged)
-        Q_PROPERTY(Error error READ error NOTIFY errorChanged)
-        Q_PROPERTY(QString userId READ getUserId CONSTANT)
-        Q_PROPERTY(QString deviceId READ getDeviceId CONSTANT)
-        Q_PROPERTY(bool sender READ getSender CONSTANT)
-        Q_PROPERTY(std::vector<int> sasList READ getSasList CONSTANT)
-        Q_PROPERTY(bool isDeviceVerification READ isDeviceVerification CONSTANT)
-        Q_PROPERTY(bool isSelfVerification READ isSelfVerification CONSTANT)
+    Q_OBJECT
+    Q_PROPERTY(QString state READ state NOTIFY stateChanged)
+    Q_PROPERTY(Error error READ error NOTIFY errorChanged)
+    Q_PROPERTY(QString userId READ getUserId CONSTANT)
+    Q_PROPERTY(QString deviceId READ getDeviceId CONSTANT)
+    Q_PROPERTY(bool sender READ getSender CONSTANT)
+    Q_PROPERTY(std::vector<int> sasList READ getSasList CONSTANT)
+    Q_PROPERTY(bool isDeviceVerification READ isDeviceVerification CONSTANT)
+    Q_PROPERTY(bool isSelfVerification READ isSelfVerification CONSTANT)
 
 public:
-        enum State
-        {
-                PromptStartVerification,
-                WaitingForOtherToAccept,
-                WaitingForKeys,
-                CompareEmoji,
-                CompareNumber,
-                WaitingForMac,
-                Success,
-                Failed,
-        };
-        Q_ENUM(State)
-
-        enum Type
-        {
-                ToDevice,
-                RoomMsg
-        };
-
-        enum Error
-        {
-                UnknownMethod,
-                MismatchedCommitment,
-                MismatchedSAS,
-                KeyMismatch,
-                Timeout,
-                User,
-                OutOfOrder,
-        };
-        Q_ENUM(Error)
-
-        static QSharedPointer<DeviceVerificationFlow> NewInRoomVerification(
-          QObject *parent_,
-          TimelineModel *timelineModel_,
-          const mtx::events::msg::KeyVerificationRequest &msg,
-          QString other_user_,
-          QString event_id_);
-        static QSharedPointer<DeviceVerificationFlow> NewToDeviceVerification(
-          QObject *parent_,
-          const mtx::events::msg::KeyVerificationRequest &msg,
-          QString other_user_,
-          QString txn_id_);
-        static QSharedPointer<DeviceVerificationFlow> NewToDeviceVerification(
-          QObject *parent_,
-          const mtx::events::msg::KeyVerificationStart &msg,
-          QString other_user_,
-          QString txn_id_);
-        static QSharedPointer<DeviceVerificationFlow>
-        InitiateUserVerification(QObject *parent_, TimelineModel *timelineModel_, QString userid);
-        static QSharedPointer<DeviceVerificationFlow> InitiateDeviceVerification(QObject *parent,
-                                                                                 QString userid,
-                                                                                 QString device);
-
-        // getters
-        QString state();
-        Error error() { return error_; }
-        QString getUserId();
-        QString getDeviceId();
-        bool getSender();
-        std::vector<int> getSasList();
-        QString transactionId() { return QString::fromStdString(this->transaction_id); }
-        // setters
-        void setDeviceId(QString deviceID);
-        void setEventId(std::string event_id);
-        bool isDeviceVerification() const
-        {
-                return this->type == DeviceVerificationFlow::Type::ToDevice;
-        }
-        bool isSelfVerification() const;
-
-        void callback_fn(const UserKeyCache &res, mtx::http::RequestErr err, std::string user_id);
+    enum State
+    {
+        PromptStartVerification,
+        WaitingForOtherToAccept,
+        WaitingForKeys,
+        CompareEmoji,
+        CompareNumber,
+        WaitingForMac,
+        Success,
+        Failed,
+    };
+    Q_ENUM(State)
+
+    enum Type
+    {
+        ToDevice,
+        RoomMsg
+    };
+
+    enum Error
+    {
+        UnknownMethod,
+        MismatchedCommitment,
+        MismatchedSAS,
+        KeyMismatch,
+        Timeout,
+        User,
+        OutOfOrder,
+    };
+    Q_ENUM(Error)
+
+    static QSharedPointer<DeviceVerificationFlow> NewInRoomVerification(
+      QObject *parent_,
+      TimelineModel *timelineModel_,
+      const mtx::events::msg::KeyVerificationRequest &msg,
+      QString other_user_,
+      QString event_id_);
+    static QSharedPointer<DeviceVerificationFlow> NewToDeviceVerification(
+      QObject *parent_,
+      const mtx::events::msg::KeyVerificationRequest &msg,
+      QString other_user_,
+      QString txn_id_);
+    static QSharedPointer<DeviceVerificationFlow> NewToDeviceVerification(
+      QObject *parent_,
+      const mtx::events::msg::KeyVerificationStart &msg,
+      QString other_user_,
+      QString txn_id_);
+    static QSharedPointer<DeviceVerificationFlow>
+    InitiateUserVerification(QObject *parent_, TimelineModel *timelineModel_, QString userid);
+    static QSharedPointer<DeviceVerificationFlow> InitiateDeviceVerification(QObject *parent,
+                                                                             QString userid,
+                                                                             QString device);
+
+    // getters
+    QString state();
+    Error error() { return error_; }
+    QString getUserId();
+    QString getDeviceId();
+    bool getSender();
+    std::vector<int> getSasList();
+    QString transactionId() { return QString::fromStdString(this->transaction_id); }
+    // setters
+    void setDeviceId(QString deviceID);
+    void setEventId(std::string event_id);
+    bool isDeviceVerification() const
+    {
+        return this->type == DeviceVerificationFlow::Type::ToDevice;
+    }
+    bool isSelfVerification() const;
+
+    void callback_fn(const UserKeyCache &res, mtx::http::RequestErr err, std::string user_id);
 
 public slots:
-        //! unverifies a device
-        void unverify();
-        //! Continues the flow
-        void next();
-        //! Cancel the flow
-        void cancel() { cancelVerification(User); }
+    //! unverifies a device
+    void unverify();
+    //! Continues the flow
+    void next();
+    //! Cancel the flow
+    void cancel() { cancelVerification(User); }
 
 signals:
-        void refreshProfile();
-        void stateChanged();
-        void errorChanged();
+    void refreshProfile();
+    void stateChanged();
+    void errorChanged();
 
 private:
-        DeviceVerificationFlow(QObject *,
-                               DeviceVerificationFlow::Type flow_type,
-                               TimelineModel *model,
-                               QString userID,
-                               QString deviceId_);
-        void setState(State state)
-        {
-                if (state != state_) {
-                        state_ = state;
-                        emit stateChanged();
-                }
+    DeviceVerificationFlow(QObject *,
+                           DeviceVerificationFlow::Type flow_type,
+                           TimelineModel *model,
+                           QString userID,
+                           QString deviceId_);
+    void setState(State state)
+    {
+        if (state != state_) {
+            state_ = state;
+            emit stateChanged();
         }
-
-        void handleStartMessage(const mtx::events::msg::KeyVerificationStart &msg, std::string);
-        //! sends a verification request
-        void sendVerificationRequest();
-        //! accepts a verification request
-        void sendVerificationReady();
-        //! completes the verification flow();
-        void sendVerificationDone();
-        //! accepts a verification
-        void acceptVerificationRequest();
-        //! starts the verification flow
-        void startVerificationRequest();
-        //! cancels a verification flow
-        void cancelVerification(DeviceVerificationFlow::Error error_code);
-        //! sends the verification key
-        void sendVerificationKey();
-        //! sends the mac of the keys
-        void sendVerificationMac();
-        //! Completes the verification flow
-        void acceptDevice();
-
-        std::string transaction_id;
-
-        bool sender;
-        Type type;
-        mtx::identifiers::User toClient;
-        QString deviceId;
-
-        // public part of our master key, when trusted or empty
-        std::string our_trusted_master_key;
-
-        mtx::events::msg::SASMethods method = mtx::events::msg::SASMethods::Emoji;
-        QTimer *timeout                     = nullptr;
-        sas_ptr sas;
-        std::string mac_method;
-        std::string commitment;
-        nlohmann::json canonical_json;
-
-        std::vector<int> sasList;
-        UserKeyCache their_keys;
-        TimelineModel *model_;
-        mtx::common::Relation relation;
-
-        State state_ = PromptStartVerification;
-        Error error_ = UnknownMethod;
-
-        bool isMacVerified = 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;
-                        body[this->toClient][deviceId.toStdString()] = msg;
-
-                        http::client()->send_to_device<T>(
-                          this->transaction_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 handleStartMessage(const mtx::events::msg::KeyVerificationStart &msg, std::string);
+    //! sends a verification request
+    void sendVerificationRequest();
+    //! accepts a verification request
+    void sendVerificationReady();
+    //! completes the verification flow();
+    void sendVerificationDone();
+    //! accepts a verification
+    void acceptVerificationRequest();
+    //! starts the verification flow
+    void startVerificationRequest();
+    //! cancels a verification flow
+    void cancelVerification(DeviceVerificationFlow::Error error_code);
+    //! sends the verification key
+    void sendVerificationKey();
+    //! sends the mac of the keys
+    void sendVerificationMac();
+    //! Completes the verification flow
+    void acceptDevice();
+
+    std::string transaction_id;
+
+    bool sender;
+    Type type;
+    mtx::identifiers::User toClient;
+    QString deviceId;
+
+    // public part of our master key, when trusted or empty
+    std::string our_trusted_master_key;
+
+    mtx::events::msg::SASMethods method = mtx::events::msg::SASMethods::Emoji;
+    QTimer *timeout                     = nullptr;
+    sas_ptr sas;
+    std::string mac_method;
+    std::string commitment;
+    nlohmann::json canonical_json;
+
+    std::vector<int> sasList;
+    UserKeyCache their_keys;
+    TimelineModel *model_;
+    mtx::common::Relation relation;
+
+    State state_ = PromptStartVerification;
+    Error error_ = UnknownMethod;
+
+    bool isMacVerified = 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;
+            body[this->toClient][deviceId.toStdString()] = msg;
+
+            http::client()->send_to_device<T>(
+              this->transaction_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/EventAccessors.cpp b/src/EventAccessors.cpp
index 362bf4e9..d794a384 100644
--- a/src/EventAccessors.cpp
+++ b/src/EventAccessors.cpp
@@ -16,463 +16,460 @@ using is_detected = typename nheko::detail::detector<nheko::nonesuch, void, Op,
 
 struct IsStateEvent
 {
-        template<class T>
-        bool operator()(const mtx::events::StateEvent<T> &)
-        {
-                return true;
-        }
-        template<class T>
-        bool operator()(const mtx::events::Event<T> &)
-        {
-                return false;
-        }
+    template<class T>
+    bool operator()(const mtx::events::StateEvent<T> &)
+    {
+        return true;
+    }
+    template<class T>
+    bool operator()(const mtx::events::Event<T> &)
+    {
+        return false;
+    }
 };
 
 struct EventMsgType
 {
-        template<class E>
-        using msgtype_t = decltype(E::msgtype);
-        template<class T>
-        mtx::events::MessageType operator()(const mtx::events::Event<T> &e)
-        {
-                if constexpr (is_detected<msgtype_t, T>::value) {
-                        if constexpr (std::is_same_v<std::optional<std::string>,
-                                                     std::remove_cv_t<decltype(e.content.msgtype)>>)
-                                return mtx::events::getMessageType(e.content.msgtype.value());
-                        else if constexpr (std::is_same_v<
-                                             std::string,
-                                             std::remove_cv_t<decltype(e.content.msgtype)>>)
-                                return mtx::events::getMessageType(e.content.msgtype);
-                }
-                return mtx::events::MessageType::Unknown;
+    template<class E>
+    using msgtype_t = decltype(E::msgtype);
+    template<class T>
+    mtx::events::MessageType operator()(const mtx::events::Event<T> &e)
+    {
+        if constexpr (is_detected<msgtype_t, T>::value) {
+            if constexpr (std::is_same_v<std::optional<std::string>,
+                                         std::remove_cv_t<decltype(e.content.msgtype)>>)
+                return mtx::events::getMessageType(e.content.msgtype.value());
+            else if constexpr (std::is_same_v<std::string,
+                                              std::remove_cv_t<decltype(e.content.msgtype)>>)
+                return mtx::events::getMessageType(e.content.msgtype);
         }
+        return mtx::events::MessageType::Unknown;
+    }
 };
 
 struct EventRoomName
 {
-        template<class T>
-        std::string operator()(const T &e)
-        {
-                if constexpr (std::is_same_v<mtx::events::StateEvent<mtx::events::state::Name>, T>)
-                        return e.content.name;
-                return "";
-        }
+    template<class T>
+    std::string operator()(const T &e)
+    {
+        if constexpr (std::is_same_v<mtx::events::StateEvent<mtx::events::state::Name>, T>)
+            return e.content.name;
+        return "";
+    }
 };
 
 struct EventRoomTopic
 {
-        template<class T>
-        std::string operator()(const T &e)
-        {
-                if constexpr (std::is_same_v<mtx::events::StateEvent<mtx::events::state::Topic>, T>)
-                        return e.content.topic;
-                return "";
-        }
+    template<class T>
+    std::string operator()(const T &e)
+    {
+        if constexpr (std::is_same_v<mtx::events::StateEvent<mtx::events::state::Topic>, T>)
+            return e.content.topic;
+        return "";
+    }
 };
 
 struct CallType
 {
-        template<class T>
-        std::string operator()(const T &e)
-        {
-                if constexpr (std::is_same_v<mtx::events::RoomEvent<mtx::events::msg::CallInvite>,
-                                             T>) {
-                        const char video[]     = "m=video";
-                        const std::string &sdp = e.content.sdp;
-                        return std::search(sdp.cbegin(),
-                                           sdp.cend(),
-                                           std::cbegin(video),
-                                           std::cend(video) - 1,
-                                           [](unsigned char c1, unsigned char c2) {
-                                                   return std::tolower(c1) == std::tolower(c2);
-                                           }) != sdp.cend()
-                                 ? "video"
-                                 : "voice";
-                }
-                return std::string();
+    template<class T>
+    std::string operator()(const T &e)
+    {
+        if constexpr (std::is_same_v<mtx::events::RoomEvent<mtx::events::msg::CallInvite>, T>) {
+            const char video[]     = "m=video";
+            const std::string &sdp = e.content.sdp;
+            return std::search(sdp.cbegin(),
+                               sdp.cend(),
+                               std::cbegin(video),
+                               std::cend(video) - 1,
+                               [](unsigned char c1, unsigned char c2) {
+                                   return std::tolower(c1) == std::tolower(c2);
+                               }) != sdp.cend()
+                     ? "video"
+                     : "voice";
         }
+        return std::string();
+    }
 };
 
 struct EventBody
 {
-        template<class C>
-        using body_t = decltype(C::body);
-        template<class T>
-        std::string operator()(const 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)>>)
-                                return e.content.body ? e.content.body.value() : "";
-                        else if constexpr (std::is_same_v<
-                                             std::string,
-                                             std::remove_cv_t<decltype(e.content.body)>>)
-                                return e.content.body;
-                }
-                return "";
+    template<class C>
+    using body_t = decltype(C::body);
+    template<class T>
+    std::string operator()(const 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)>>)
+                return e.content.body ? e.content.body.value() : "";
+            else if constexpr (std::is_same_v<std::string,
+                                              std::remove_cv_t<decltype(e.content.body)>>)
+                return e.content.body;
         }
+        return "";
+    }
 };
 
 struct EventFormattedBody
 {
-        template<class C>
-        using formatted_body_t = decltype(C::formatted_body);
-        template<class T>
-        std::string operator()(const mtx::events::RoomEvent<T> &e)
-        {
-                if constexpr (is_detected<formatted_body_t, T>::value) {
-                        if (e.content.format == "org.matrix.custom.html")
-                                return e.content.formatted_body;
-                }
-                return "";
+    template<class C>
+    using formatted_body_t = decltype(C::formatted_body);
+    template<class T>
+    std::string operator()(const mtx::events::RoomEvent<T> &e)
+    {
+        if constexpr (is_detected<formatted_body_t, T>::value) {
+            if (e.content.format == "org.matrix.custom.html")
+                return e.content.formatted_body;
         }
+        return "";
+    }
 };
 
 struct EventFile
 {
-        template<class Content>
-        using file_t = decltype(Content::file);
-        template<class T>
-        std::optional<mtx::crypto::EncryptedFile> operator()(const mtx::events::Event<T> &e)
-        {
-                if constexpr (is_detected<file_t, T>::value)
-                        return e.content.file;
-                return std::nullopt;
-        }
+    template<class Content>
+    using file_t = decltype(Content::file);
+    template<class T>
+    std::optional<mtx::crypto::EncryptedFile> operator()(const mtx::events::Event<T> &e)
+    {
+        if constexpr (is_detected<file_t, T>::value)
+            return e.content.file;
+        return std::nullopt;
+    }
 };
 
 struct EventUrl
 {
-        template<class Content>
-        using url_t = decltype(Content::url);
-        template<class T>
-        std::string operator()(const mtx::events::Event<T> &e)
-        {
-                if constexpr (is_detected<url_t, T>::value) {
-                        if (auto file = EventFile{}(e))
-                                return file->url;
-                        return e.content.url;
-                }
-                return "";
+    template<class Content>
+    using url_t = decltype(Content::url);
+    template<class T>
+    std::string operator()(const mtx::events::Event<T> &e)
+    {
+        if constexpr (is_detected<url_t, T>::value) {
+            if (auto file = EventFile{}(e))
+                return file->url;
+            return e.content.url;
         }
+        return "";
+    }
 };
 
 struct EventThumbnailUrl
 {
-        template<class Content>
-        using thumbnail_url_t = decltype(Content::info.thumbnail_url);
-        template<class T>
-        std::string operator()(const mtx::events::Event<T> &e)
-        {
-                if constexpr (is_detected<thumbnail_url_t, T>::value) {
-                        return e.content.info.thumbnail_url;
-                }
-                return "";
+    template<class Content>
+    using thumbnail_url_t = decltype(Content::info.thumbnail_url);
+    template<class T>
+    std::string operator()(const mtx::events::Event<T> &e)
+    {
+        if constexpr (is_detected<thumbnail_url_t, T>::value) {
+            return e.content.info.thumbnail_url;
         }
+        return "";
+    }
 };
 
 struct EventBlurhash
 {
-        template<class Content>
-        using blurhash_t = decltype(Content::info.blurhash);
-        template<class T>
-        std::string operator()(const mtx::events::Event<T> &e)
-        {
-                if constexpr (is_detected<blurhash_t, T>::value) {
-                        return e.content.info.blurhash;
-                }
-                return "";
+    template<class Content>
+    using blurhash_t = decltype(Content::info.blurhash);
+    template<class T>
+    std::string operator()(const mtx::events::Event<T> &e)
+    {
+        if constexpr (is_detected<blurhash_t, T>::value) {
+            return e.content.info.blurhash;
         }
+        return "";
+    }
 };
 
 struct EventFilename
 {
-        template<class T>
-        std::string operator()(const mtx::events::Event<T> &)
-        {
-                return "";
-        }
-        std::string operator()(const mtx::events::RoomEvent<mtx::events::msg::Audio> &e)
-        {
-                // body may be the original filename
-                return e.content.body;
-        }
-        std::string operator()(const mtx::events::RoomEvent<mtx::events::msg::Video> &e)
-        {
-                // body may be the original filename
-                return e.content.body;
-        }
-        std::string operator()(const mtx::events::RoomEvent<mtx::events::msg::Image> &e)
-        {
-                // body may be the original filename
-                return e.content.body;
-        }
-        std::string operator()(const mtx::events::RoomEvent<mtx::events::msg::File> &e)
-        {
-                // body may be the original filename
-                if (!e.content.filename.empty())
-                        return e.content.filename;
-                return e.content.body;
-        }
+    template<class T>
+    std::string operator()(const mtx::events::Event<T> &)
+    {
+        return "";
+    }
+    std::string operator()(const mtx::events::RoomEvent<mtx::events::msg::Audio> &e)
+    {
+        // body may be the original filename
+        return e.content.body;
+    }
+    std::string operator()(const mtx::events::RoomEvent<mtx::events::msg::Video> &e)
+    {
+        // body may be the original filename
+        return e.content.body;
+    }
+    std::string operator()(const mtx::events::RoomEvent<mtx::events::msg::Image> &e)
+    {
+        // body may be the original filename
+        return e.content.body;
+    }
+    std::string operator()(const mtx::events::RoomEvent<mtx::events::msg::File> &e)
+    {
+        // body may be the original filename
+        if (!e.content.filename.empty())
+            return e.content.filename;
+        return e.content.body;
+    }
 };
 
 struct EventMimeType
 {
-        template<class Content>
-        using mimetype_t = decltype(Content::info.mimetype);
-        template<class T>
-        std::string operator()(const mtx::events::Event<T> &e)
-        {
-                if constexpr (is_detected<mimetype_t, T>::value) {
-                        return e.content.info.mimetype;
-                }
-                return "";
+    template<class Content>
+    using mimetype_t = decltype(Content::info.mimetype);
+    template<class T>
+    std::string operator()(const mtx::events::Event<T> &e)
+    {
+        if constexpr (is_detected<mimetype_t, T>::value) {
+            return e.content.info.mimetype;
         }
+        return "";
+    }
 };
 
 struct EventFilesize
 {
-        template<class Content>
-        using filesize_t = decltype(Content::info.size);
-        template<class T>
-        int64_t operator()(const mtx::events::RoomEvent<T> &e)
-        {
-                if constexpr (is_detected<filesize_t, T>::value) {
-                        return e.content.info.size;
-                }
-                return 0;
+    template<class Content>
+    using filesize_t = decltype(Content::info.size);
+    template<class T>
+    int64_t operator()(const mtx::events::RoomEvent<T> &e)
+    {
+        if constexpr (is_detected<filesize_t, T>::value) {
+            return e.content.info.size;
         }
+        return 0;
+    }
 };
 
 struct EventRelations
 {
-        template<class Content>
-        using related_ev_id_t = decltype(Content::relations);
-        template<class T>
-        mtx::common::Relations operator()(const mtx::events::Event<T> &e)
-        {
-                if constexpr (is_detected<related_ev_id_t, T>::value) {
-                        return e.content.relations;
-                }
-                return {};
+    template<class Content>
+    using related_ev_id_t = decltype(Content::relations);
+    template<class T>
+    mtx::common::Relations operator()(const mtx::events::Event<T> &e)
+    {
+        if constexpr (is_detected<related_ev_id_t, T>::value) {
+            return e.content.relations;
         }
+        return {};
+    }
 };
 
 struct SetEventRelations
 {
-        mtx::common::Relations new_relations;
-        template<class Content>
-        using related_ev_id_t = decltype(Content::relations);
-        template<class T>
-        void operator()(mtx::events::Event<T> &e)
-        {
-                if constexpr (is_detected<related_ev_id_t, T>::value) {
-                        e.content.relations = std::move(new_relations);
-                }
+    mtx::common::Relations new_relations;
+    template<class Content>
+    using related_ev_id_t = decltype(Content::relations);
+    template<class T>
+    void operator()(mtx::events::Event<T> &e)
+    {
+        if constexpr (is_detected<related_ev_id_t, T>::value) {
+            e.content.relations = std::move(new_relations);
         }
+    }
 };
 
 struct EventTransactionId
 {
-        template<class T>
-        std::string operator()(const mtx::events::RoomEvent<T> &e)
-        {
-                return e.unsigned_data.transaction_id;
-        }
-        template<class T>
-        std::string operator()(const mtx::events::Event<T> &e)
-        {
-                return e.unsigned_data.transaction_id;
-        }
+    template<class T>
+    std::string operator()(const mtx::events::RoomEvent<T> &e)
+    {
+        return e.unsigned_data.transaction_id;
+    }
+    template<class T>
+    std::string operator()(const mtx::events::Event<T> &e)
+    {
+        return e.unsigned_data.transaction_id;
+    }
 };
 
 struct EventMediaHeight
 {
-        template<class Content>
-        using h_t = decltype(Content::info.h);
-        template<class T>
-        uint64_t operator()(const mtx::events::Event<T> &e)
-        {
-                if constexpr (is_detected<h_t, T>::value) {
-                        return e.content.info.h;
-                }
-                return -1;
+    template<class Content>
+    using h_t = decltype(Content::info.h);
+    template<class T>
+    uint64_t operator()(const mtx::events::Event<T> &e)
+    {
+        if constexpr (is_detected<h_t, T>::value) {
+            return e.content.info.h;
         }
+        return -1;
+    }
 };
 
 struct EventMediaWidth
 {
-        template<class Content>
-        using w_t = decltype(Content::info.w);
-        template<class T>
-        uint64_t operator()(const mtx::events::Event<T> &e)
-        {
-                if constexpr (is_detected<w_t, T>::value) {
-                        return e.content.info.w;
-                }
-                return -1;
+    template<class Content>
+    using w_t = decltype(Content::info.w);
+    template<class T>
+    uint64_t operator()(const mtx::events::Event<T> &e)
+    {
+        if constexpr (is_detected<w_t, T>::value) {
+            return e.content.info.w;
         }
+        return -1;
+    }
 };
 
 template<class T>
 double
 eventPropHeight(const mtx::events::RoomEvent<T> &e)
 {
-        auto w = eventWidth(e);
-        if (w == 0)
-                w = 1;
+    auto w = eventWidth(e);
+    if (w == 0)
+        w = 1;
 
-        double prop = eventHeight(e) / (double)w;
+    double prop = eventHeight(e) / (double)w;
 
-        return prop > 0 ? prop : 1.;
+    return prop > 0 ? prop : 1.;
 }
 }
 
 std::string
 mtx::accessors::event_id(const mtx::events::collections::TimelineEvents &event)
 {
-        return std::visit([](const auto e) { return e.event_id; }, event);
+    return std::visit([](const auto e) { return e.event_id; }, event);
 }
 std::string
 mtx::accessors::room_id(const mtx::events::collections::TimelineEvents &event)
 {
-        return std::visit([](const auto e) { return e.room_id; }, event);
+    return std::visit([](const auto e) { return e.room_id; }, event);
 }
 
 std::string
 mtx::accessors::sender(const mtx::events::collections::TimelineEvents &event)
 {
-        return std::visit([](const auto e) { return e.sender; }, event);
+    return std::visit([](const auto e) { return e.sender; }, event);
 }
 
 QDateTime
 mtx::accessors::origin_server_ts(const mtx::events::collections::TimelineEvents &event)
 {
-        return QDateTime::fromMSecsSinceEpoch(
-          std::visit([](const auto e) { return e.origin_server_ts; }, event));
+    return QDateTime::fromMSecsSinceEpoch(
+      std::visit([](const auto e) { return e.origin_server_ts; }, event));
 }
 
 std::string
 mtx::accessors::filename(const mtx::events::collections::TimelineEvents &event)
 {
-        return std::visit(EventFilename{}, event);
+    return std::visit(EventFilename{}, event);
 }
 
 mtx::events::MessageType
 mtx::accessors::msg_type(const mtx::events::collections::TimelineEvents &event)
 {
-        return std::visit(EventMsgType{}, event);
+    return std::visit(EventMsgType{}, event);
 }
 std::string
 mtx::accessors::room_name(const mtx::events::collections::TimelineEvents &event)
 {
-        return std::visit(EventRoomName{}, event);
+    return std::visit(EventRoomName{}, event);
 }
 std::string
 mtx::accessors::room_topic(const mtx::events::collections::TimelineEvents &event)
 {
-        return std::visit(EventRoomTopic{}, event);
+    return std::visit(EventRoomTopic{}, event);
 }
 
 std::string
 mtx::accessors::call_type(const mtx::events::collections::TimelineEvents &event)
 {
-        return std::visit(CallType{}, event);
+    return std::visit(CallType{}, event);
 }
 
 std::string
 mtx::accessors::body(const mtx::events::collections::TimelineEvents &event)
 {
-        return std::visit(EventBody{}, event);
+    return std::visit(EventBody{}, event);
 }
 
 std::string
 mtx::accessors::formatted_body(const mtx::events::collections::TimelineEvents &event)
 {
-        return std::visit(EventFormattedBody{}, event);
+    return std::visit(EventFormattedBody{}, event);
 }
 
 QString
 mtx::accessors::formattedBodyWithFallback(const mtx::events::collections::TimelineEvents &event)
 {
-        auto formatted = formatted_body(event);
-        if (!formatted.empty())
-                return QString::fromStdString(formatted);
-        else
-                return QString::fromStdString(body(event)).toHtmlEscaped().replace("\n", "<br>");
+    auto formatted = formatted_body(event);
+    if (!formatted.empty())
+        return QString::fromStdString(formatted);
+    else
+        return QString::fromStdString(body(event)).toHtmlEscaped().replace("\n", "<br>");
 }
 
 std::optional<mtx::crypto::EncryptedFile>
 mtx::accessors::file(const mtx::events::collections::TimelineEvents &event)
 {
-        return std::visit(EventFile{}, event);
+    return std::visit(EventFile{}, event);
 }
 
 std::string
 mtx::accessors::url(const mtx::events::collections::TimelineEvents &event)
 {
-        return std::visit(EventUrl{}, event);
+    return std::visit(EventUrl{}, event);
 }
 std::string
 mtx::accessors::thumbnail_url(const mtx::events::collections::TimelineEvents &event)
 {
-        return std::visit(EventThumbnailUrl{}, event);
+    return std::visit(EventThumbnailUrl{}, event);
 }
 std::string
 mtx::accessors::blurhash(const mtx::events::collections::TimelineEvents &event)
 {
-        return std::visit(EventBlurhash{}, event);
+    return std::visit(EventBlurhash{}, event);
 }
 std::string
 mtx::accessors::mimetype(const mtx::events::collections::TimelineEvents &event)
 {
-        return std::visit(EventMimeType{}, event);
+    return std::visit(EventMimeType{}, event);
 }
 mtx::common::Relations
 mtx::accessors::relations(const mtx::events::collections::TimelineEvents &event)
 {
-        return std::visit(EventRelations{}, event);
+    return std::visit(EventRelations{}, event);
 }
 
 void
 mtx::accessors::set_relations(mtx::events::collections::TimelineEvents &event,
                               mtx::common::Relations relations)
 {
-        std::visit(SetEventRelations{std::move(relations)}, event);
+    std::visit(SetEventRelations{std::move(relations)}, event);
 }
 
 std::string
 mtx::accessors::transaction_id(const mtx::events::collections::TimelineEvents &event)
 {
-        return std::visit(EventTransactionId{}, event);
+    return std::visit(EventTransactionId{}, event);
 }
 
 int64_t
 mtx::accessors::filesize(const mtx::events::collections::TimelineEvents &event)
 {
-        return std::visit(EventFilesize{}, event);
+    return std::visit(EventFilesize{}, event);
 }
 
 uint64_t
 mtx::accessors::media_height(const mtx::events::collections::TimelineEvents &event)
 {
-        return std::visit(EventMediaHeight{}, event);
+    return std::visit(EventMediaHeight{}, event);
 }
 
 uint64_t
 mtx::accessors::media_width(const mtx::events::collections::TimelineEvents &event)
 {
-        return std::visit(EventMediaWidth{}, event);
+    return std::visit(EventMediaWidth{}, event);
 }
 
 nlohmann::json
 mtx::accessors::serialize_event(const mtx::events::collections::TimelineEvents &event)
 {
-        return std::visit([](const auto &e) { return nlohmann::json(e); }, event);
+    return std::visit([](const auto &e) { return nlohmann::json(e); }, event);
 }
 
 bool
 mtx::accessors::is_state_event(const mtx::events::collections::TimelineEvents &event)
 {
-        return std::visit(IsStateEvent{}, event);
+    return std::visit(IsStateEvent{}, event);
 }
diff --git a/src/EventAccessors.h b/src/EventAccessors.h
index a58c7de0..c6b8e854 100644
--- a/src/EventAccessors.h
+++ b/src/EventAccessors.h
@@ -14,24 +14,24 @@
 namespace nheko {
 struct nonesuch
 {
-        ~nonesuch()                = delete;
-        nonesuch(nonesuch const &) = delete;
-        void operator=(nonesuch const &) = delete;
+    ~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;
+    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...>;
+    using value_t = std::true_type;
+    using type    = Op<Args...>;
 };
 
 } // namespace detail
diff --git a/src/ImagePackListModel.cpp b/src/ImagePackListModel.cpp
index 6392de22..39e46f01 100644
--- a/src/ImagePackListModel.cpp
+++ b/src/ImagePackListModel.cpp
@@ -13,82 +13,81 @@ ImagePackListModel::ImagePackListModel(const std::string &roomId, QObject *paren
   : QAbstractListModel(parent)
   , room_id(roomId)
 {
-        auto packs_ = cache::client()->getImagePacks(room_id, std::nullopt);
+    auto packs_ = cache::client()->getImagePacks(room_id, std::nullopt);
 
-        for (const auto &pack : packs_) {
-                packs.push_back(
-                  QSharedPointer<SingleImagePackModel>(new SingleImagePackModel(pack)));
-        }
+    for (const auto &pack : packs_) {
+        packs.push_back(QSharedPointer<SingleImagePackModel>(new SingleImagePackModel(pack)));
+    }
 }
 
 int
 ImagePackListModel::rowCount(const QModelIndex &) const
 {
-        return (int)packs.size();
+    return (int)packs.size();
 }
 
 QHash<int, QByteArray>
 ImagePackListModel::roleNames() const
 {
-        return {
-          {Roles::DisplayName, "displayName"},
-          {Roles::AvatarUrl, "avatarUrl"},
-          {Roles::FromAccountData, "fromAccountData"},
-          {Roles::FromCurrentRoom, "fromCurrentRoom"},
-          {Roles::StateKey, "statekey"},
-          {Roles::RoomId, "roomid"},
-        };
+    return {
+      {Roles::DisplayName, "displayName"},
+      {Roles::AvatarUrl, "avatarUrl"},
+      {Roles::FromAccountData, "fromAccountData"},
+      {Roles::FromCurrentRoom, "fromCurrentRoom"},
+      {Roles::StateKey, "statekey"},
+      {Roles::RoomId, "roomid"},
+    };
 }
 
 QVariant
 ImagePackListModel::data(const QModelIndex &index, int role) const
 {
-        if (hasIndex(index.row(), index.column(), index.parent())) {
-                const auto &pack = packs.at(index.row());
-                switch (role) {
-                case Roles::DisplayName:
-                        return pack->packname();
-                case Roles::AvatarUrl:
-                        return pack->avatarUrl();
-                case Roles::FromAccountData:
-                        return pack->roomid().isEmpty();
-                case Roles::FromCurrentRoom:
-                        return pack->roomid().toStdString() == this->room_id;
-                case Roles::StateKey:
-                        return pack->statekey();
-                case Roles::RoomId:
-                        return pack->roomid();
-                default:
-                        return {};
-                }
+    if (hasIndex(index.row(), index.column(), index.parent())) {
+        const auto &pack = packs.at(index.row());
+        switch (role) {
+        case Roles::DisplayName:
+            return pack->packname();
+        case Roles::AvatarUrl:
+            return pack->avatarUrl();
+        case Roles::FromAccountData:
+            return pack->roomid().isEmpty();
+        case Roles::FromCurrentRoom:
+            return pack->roomid().toStdString() == this->room_id;
+        case Roles::StateKey:
+            return pack->statekey();
+        case Roles::RoomId:
+            return pack->roomid();
+        default:
+            return {};
         }
-        return {};
+    }
+    return {};
 }
 
 SingleImagePackModel *
 ImagePackListModel::packAt(int row)
 {
-        if (row < 0 || static_cast<size_t>(row) >= packs.size())
-                return {};
-        auto e = packs.at(row).get();
-        QQmlEngine::setObjectOwnership(e, QQmlEngine::CppOwnership);
-        return e;
+    if (row < 0 || static_cast<size_t>(row) >= packs.size())
+        return {};
+    auto e = packs.at(row).get();
+    QQmlEngine::setObjectOwnership(e, QQmlEngine::CppOwnership);
+    return e;
 }
 
 SingleImagePackModel *
 ImagePackListModel::newPack(bool inRoom)
 {
-        ImagePackInfo info{};
-        if (inRoom)
-                info.source_room = room_id;
-        return new SingleImagePackModel(info);
+    ImagePackInfo info{};
+    if (inRoom)
+        info.source_room = room_id;
+    return new SingleImagePackModel(info);
 }
 
 bool
 ImagePackListModel::containsAccountPack() const
 {
-        for (const auto &p : packs)
-                if (p->roomid().isEmpty())
-                        return true;
-        return false;
+    for (const auto &p : packs)
+        if (p->roomid().isEmpty())
+            return true;
+    return false;
 }
diff --git a/src/ImagePackListModel.h b/src/ImagePackListModel.h
index 2aa5abb2..0b39729a 100644
--- a/src/ImagePackListModel.h
+++ b/src/ImagePackListModel.h
@@ -11,31 +11,31 @@
 class SingleImagePackModel;
 class ImagePackListModel : public QAbstractListModel
 {
-        Q_OBJECT
-        Q_PROPERTY(bool containsAccountPack READ containsAccountPack CONSTANT)
+    Q_OBJECT
+    Q_PROPERTY(bool containsAccountPack READ containsAccountPack CONSTANT)
 public:
-        enum Roles
-        {
-                DisplayName = Qt::UserRole,
-                AvatarUrl,
-                FromAccountData,
-                FromCurrentRoom,
-                StateKey,
-                RoomId,
-        };
-
-        ImagePackListModel(const std::string &roomId, QObject *parent = nullptr);
-        QHash<int, QByteArray> roleNames() const override;
-        int rowCount(const QModelIndex &parent = QModelIndex()) const override;
-        QVariant data(const QModelIndex &index, int role) const override;
-
-        Q_INVOKABLE SingleImagePackModel *packAt(int row);
-        Q_INVOKABLE SingleImagePackModel *newPack(bool inRoom);
-
-        bool containsAccountPack() const;
+    enum Roles
+    {
+        DisplayName = Qt::UserRole,
+        AvatarUrl,
+        FromAccountData,
+        FromCurrentRoom,
+        StateKey,
+        RoomId,
+    };
+
+    ImagePackListModel(const std::string &roomId, QObject *parent = nullptr);
+    QHash<int, QByteArray> roleNames() const override;
+    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+    QVariant data(const QModelIndex &index, int role) const override;
+
+    Q_INVOKABLE SingleImagePackModel *packAt(int row);
+    Q_INVOKABLE SingleImagePackModel *newPack(bool inRoom);
+
+    bool containsAccountPack() const;
 
 private:
-        std::string room_id;
+    std::string room_id;
 
-        std::vector<QSharedPointer<SingleImagePackModel>> packs;
+    std::vector<QSharedPointer<SingleImagePackModel>> packs;
 };
diff --git a/src/InviteesModel.cpp b/src/InviteesModel.cpp
index 27b2116f..e045581a 100644
--- a/src/InviteesModel.cpp
+++ b/src/InviteesModel.cpp
@@ -16,69 +16,68 @@ InviteesModel::InviteesModel(QObject *parent)
 void
 InviteesModel::addUser(QString mxid)
 {
-        beginInsertRows(QModelIndex(), invitees_.count(), invitees_.count());
+    beginInsertRows(QModelIndex(), invitees_.count(), invitees_.count());
 
-        auto invitee        = new Invitee{mxid, this};
-        auto indexOfInvitee = invitees_.count();
-        connect(invitee, &Invitee::userInfoLoaded, this, [this, indexOfInvitee]() {
-                emit dataChanged(index(indexOfInvitee), index(indexOfInvitee));
-        });
+    auto invitee        = new Invitee{mxid, this};
+    auto indexOfInvitee = invitees_.count();
+    connect(invitee, &Invitee::userInfoLoaded, this, [this, indexOfInvitee]() {
+        emit dataChanged(index(indexOfInvitee), index(indexOfInvitee));
+    });
 
-        invitees_.push_back(invitee);
+    invitees_.push_back(invitee);
 
-        endInsertRows();
-        emit countChanged();
+    endInsertRows();
+    emit countChanged();
 }
 
 QHash<int, QByteArray>
 InviteesModel::roleNames() const
 {
-        return {{Mxid, "mxid"}, {DisplayName, "displayName"}, {AvatarUrl, "avatarUrl"}};
+    return {{Mxid, "mxid"}, {DisplayName, "displayName"}, {AvatarUrl, "avatarUrl"}};
 }
 
 QVariant
 InviteesModel::data(const QModelIndex &index, int role) const
 {
-        if (!index.isValid() || index.row() >= (int)invitees_.size() || index.row() < 0)
-                return {};
+    if (!index.isValid() || index.row() >= (int)invitees_.size() || index.row() < 0)
+        return {};
 
-        switch (role) {
-        case Mxid:
-                return invitees_[index.row()]->mxid_;
-        case DisplayName:
-                return invitees_[index.row()]->displayName_;
-        case AvatarUrl:
-                return invitees_[index.row()]->avatarUrl_;
-        default:
-                return {};
-        }
+    switch (role) {
+    case Mxid:
+        return invitees_[index.row()]->mxid_;
+    case DisplayName:
+        return invitees_[index.row()]->displayName_;
+    case AvatarUrl:
+        return invitees_[index.row()]->avatarUrl_;
+    default:
+        return {};
+    }
 }
 
 QStringList
 InviteesModel::mxids()
 {
-        QStringList mxidList;
-        for (int i = 0; i < invitees_.length(); ++i)
-                mxidList.push_back(invitees_[i]->mxid_);
-        return mxidList;
+    QStringList mxidList;
+    for (int i = 0; i < invitees_.length(); ++i)
+        mxidList.push_back(invitees_[i]->mxid_);
+    return mxidList;
 }
 
 Invitee::Invitee(const QString &mxid, QObject *parent)
   : QObject{parent}
   , mxid_{mxid}
 {
-        http::client()->get_profile(
-          mxid_.toStdString(),
-          [this](const mtx::responses::Profile &res, mtx::http::RequestErr err) {
-                  if (err) {
-                          nhlog::net()->warn("failed to retrieve profile info");
-                          emit userInfoLoaded();
-                          return;
-                  }
+    http::client()->get_profile(
+      mxid_.toStdString(), [this](const mtx::responses::Profile &res, mtx::http::RequestErr err) {
+          if (err) {
+              nhlog::net()->warn("failed to retrieve profile info");
+              emit userInfoLoaded();
+              return;
+          }
 
-                  displayName_ = QString::fromStdString(res.display_name);
-                  avatarUrl_   = QString::fromStdString(res.avatar_url);
+          displayName_ = QString::fromStdString(res.display_name);
+          avatarUrl_   = QString::fromStdString(res.avatar_url);
 
-                  emit userInfoLoaded();
-          });
+          emit userInfoLoaded();
+      });
 }
diff --git a/src/InviteesModel.h b/src/InviteesModel.h
index a4e19ebb..fd64116b 100644
--- a/src/InviteesModel.h
+++ b/src/InviteesModel.h
@@ -10,54 +10,54 @@
 
 class Invitee : public QObject
 {
-        Q_OBJECT
+    Q_OBJECT
 
 public:
-        Invitee(const QString &mxid, QObject *parent = nullptr);
+    Invitee(const QString &mxid, QObject *parent = nullptr);
 
 signals:
-        void userInfoLoaded();
+    void userInfoLoaded();
 
 private:
-        const QString mxid_;
-        QString displayName_;
-        QString avatarUrl_;
+    const QString mxid_;
+    QString displayName_;
+    QString avatarUrl_;
 
-        friend class InviteesModel;
+    friend class InviteesModel;
 };
 
 class InviteesModel : public QAbstractListModel
 {
-        Q_OBJECT
+    Q_OBJECT
 
-        Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
+    Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
 
 public:
-        enum Roles
-        {
-                Mxid,
-                DisplayName,
-                AvatarUrl,
-        };
+    enum Roles
+    {
+        Mxid,
+        DisplayName,
+        AvatarUrl,
+    };
 
-        InviteesModel(QObject *parent = nullptr);
+    InviteesModel(QObject *parent = nullptr);
 
-        Q_INVOKABLE void addUser(QString mxid);
+    Q_INVOKABLE void addUser(QString mxid);
 
-        QHash<int, QByteArray> roleNames() const override;
-        int rowCount(const QModelIndex & = QModelIndex()) const override
-        {
-                return (int)invitees_.size();
-        }
-        QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
-        QStringList mxids();
+    QHash<int, QByteArray> roleNames() const override;
+    int rowCount(const QModelIndex & = QModelIndex()) const override
+    {
+        return (int)invitees_.size();
+    }
+    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+    QStringList mxids();
 
 signals:
-        void accept();
-        void countChanged();
+    void accept();
+    void countChanged();
 
 private:
-        QVector<Invitee *> invitees_;
+    QVector<Invitee *> invitees_;
 };
 
 #endif // INVITEESMODEL_H
diff --git a/src/JdenticonProvider.cpp b/src/JdenticonProvider.cpp
index 23b601fc..e2828286 100644
--- a/src/JdenticonProvider.cpp
+++ b/src/JdenticonProvider.cpp
@@ -22,20 +22,20 @@
 static QPixmap
 clipRadius(QPixmap img, double radius)
 {
-        QPixmap out(img.size());
-        out.fill(Qt::transparent);
+    QPixmap out(img.size());
+    out.fill(Qt::transparent);
 
-        QPainter painter(&out);
-        painter.setRenderHint(QPainter::Antialiasing, true);
-        painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
+    QPainter painter(&out);
+    painter.setRenderHint(QPainter::Antialiasing, true);
+    painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
 
-        QPainterPath ppath;
-        ppath.addRoundedRect(img.rect(), radius, radius, Qt::SizeMode::RelativeSize);
+    QPainterPath ppath;
+    ppath.addRoundedRect(img.rect(), radius, radius, Qt::SizeMode::RelativeSize);
 
-        painter.setClipPath(ppath);
-        painter.drawPixmap(img.rect(), img);
+    painter.setClipPath(ppath);
+    painter.drawPixmap(img.rect(), img);
 
-        return out;
+    return out;
 }
 
 JdenticonResponse::JdenticonResponse(const QString &key,
@@ -49,64 +49,64 @@ JdenticonResponse::JdenticonResponse(const QString &key,
   , m_pixmap{m_requestedSize}
   , jdenticonInterface_{Jdenticon::getJdenticonInterface()}
 {
-        setAutoDelete(false);
+    setAutoDelete(false);
 }
 
 void
 JdenticonResponse::run()
 {
-        m_pixmap.fill(Qt::transparent);
-
-        QPainter painter;
-        painter.begin(&m_pixmap);
-        painter.setRenderHint(QPainter::Antialiasing, true);
-        painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
-
-        try {
-                QSvgRenderer renderer{
-                  jdenticonInterface_->generate(m_key, m_requestedSize.width()).toUtf8()};
-                renderer.render(&painter);
-        } catch (std::exception &e) {
-                nhlog::ui()->error(
-                  "caught {} in jdenticonprovider, key '{}'", e.what(), m_key.toStdString());
-        }
+    m_pixmap.fill(Qt::transparent);
+
+    QPainter painter;
+    painter.begin(&m_pixmap);
+    painter.setRenderHint(QPainter::Antialiasing, true);
+    painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
+
+    try {
+        QSvgRenderer renderer{
+          jdenticonInterface_->generate(m_key, m_requestedSize.width()).toUtf8()};
+        renderer.render(&painter);
+    } catch (std::exception &e) {
+        nhlog::ui()->error(
+          "caught {} in jdenticonprovider, key '{}'", e.what(), m_key.toStdString());
+    }
 
-        painter.end();
+    painter.end();
 
-        m_pixmap = clipRadius(m_pixmap, m_radius);
+    m_pixmap = clipRadius(m_pixmap, m_radius);
 
-        emit finished();
+    emit finished();
 }
 
 namespace Jdenticon {
 JdenticonInterface *
 getJdenticonInterface()
 {
-        static JdenticonInterface *interface = nullptr;
-        static bool interfaceExists{true};
-
-        if (interface == nullptr && interfaceExists) {
-                QDir pluginsDir(qApp->applicationDirPath());
-
-                bool plugins = pluginsDir.cd("plugins");
-                if (plugins) {
-                        for (const QString &fileName : pluginsDir.entryList(QDir::Files)) {
-                                QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
-                                QObject *plugin = pluginLoader.instance();
-                                if (plugin) {
-                                        interface = qobject_cast<JdenticonInterface *>(plugin);
-                                        if (interface) {
-                                                nhlog::ui()->info("Loaded jdenticon plugin.");
-                                                break;
-                                        }
-                                }
-                        }
-                } else {
-                        nhlog::ui()->info("jdenticon plugin not found.");
-                        interfaceExists = false;
+    static JdenticonInterface *interface = nullptr;
+    static bool interfaceExists{true};
+
+    if (interface == nullptr && interfaceExists) {
+        QDir pluginsDir(qApp->applicationDirPath());
+
+        bool plugins = pluginsDir.cd("plugins");
+        if (plugins) {
+            for (const QString &fileName : pluginsDir.entryList(QDir::Files)) {
+                QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
+                QObject *plugin = pluginLoader.instance();
+                if (plugin) {
+                    interface = qobject_cast<JdenticonInterface *>(plugin);
+                    if (interface) {
+                        nhlog::ui()->info("Loaded jdenticon plugin.");
+                        break;
+                    }
                 }
+            }
+        } else {
+            nhlog::ui()->info("jdenticon plugin not found.");
+            interfaceExists = false;
         }
+    }
 
-        return interface;
+    return interface;
 }
 }
diff --git a/src/JdenticonProvider.h b/src/JdenticonProvider.h
index bcda29c8..f4ef6d10 100644
--- a/src/JdenticonProvider.h
+++ b/src/JdenticonProvider.h
@@ -23,59 +23,58 @@ class JdenticonResponse
   , public QRunnable
 {
 public:
-        JdenticonResponse(const QString &key, bool crop, double radius, const QSize &requestedSize);
+    JdenticonResponse(const QString &key, bool crop, double radius, const QSize &requestedSize);
 
-        QQuickTextureFactory *textureFactory() const override
-        {
-                return QQuickTextureFactory::textureFactoryForImage(m_pixmap.toImage());
-        }
+    QQuickTextureFactory *textureFactory() const override
+    {
+        return QQuickTextureFactory::textureFactoryForImage(m_pixmap.toImage());
+    }
 
-        void run() override;
+    void run() override;
 
-        QString m_key;
-        bool m_crop;
-        double m_radius;
-        QSize m_requestedSize;
-        QPixmap m_pixmap;
-        JdenticonInterface *jdenticonInterface_ = nullptr;
+    QString m_key;
+    bool m_crop;
+    double m_radius;
+    QSize m_requestedSize;
+    QPixmap m_pixmap;
+    JdenticonInterface *jdenticonInterface_ = nullptr;
 };
 
 class JdenticonProvider
   : public QObject
   , public QQuickAsyncImageProvider
 {
-        Q_OBJECT
+    Q_OBJECT
 
 public:
-        static bool isAvailable() { return Jdenticon::getJdenticonInterface() != nullptr; }
+    static bool isAvailable() { return Jdenticon::getJdenticonInterface() != nullptr; }
 
 public slots:
-        QQuickImageResponse *requestImageResponse(const QString &id,
-                                                  const QSize &requestedSize) override
-        {
-                auto id_      = id;
-                bool crop     = true;
-                double radius = 0;
-
-                auto queryStart = id.lastIndexOf('?');
-                if (queryStart != -1) {
-                        id_            = id.left(queryStart);
-                        auto query     = id.midRef(queryStart + 1);
-                        auto queryBits = query.split('&');
-
-                        for (auto b : queryBits) {
-                                if (b.startsWith("radius=")) {
-                                        radius = b.mid(7).toDouble();
-                                }
-                        }
+    QQuickImageResponse *requestImageResponse(const QString &id,
+                                              const QSize &requestedSize) override
+    {
+        auto id_      = id;
+        bool crop     = true;
+        double radius = 0;
+
+        auto queryStart = id.lastIndexOf('?');
+        if (queryStart != -1) {
+            id_            = id.left(queryStart);
+            auto query     = id.midRef(queryStart + 1);
+            auto queryBits = query.split('&');
+
+            for (auto b : queryBits) {
+                if (b.startsWith("radius=")) {
+                    radius = b.mid(7).toDouble();
                 }
-
-                JdenticonResponse *response =
-                  new JdenticonResponse(id_, crop, radius, requestedSize);
-                pool.start(response);
-                return response;
+            }
         }
 
+        JdenticonResponse *response = new JdenticonResponse(id_, crop, radius, requestedSize);
+        pool.start(response);
+        return response;
+    }
+
 private:
-        QThreadPool pool;
+    QThreadPool pool;
 };
diff --git a/src/Logging.cpp b/src/Logging.cpp
index 67bcaf7a..a18a1cee 100644
--- a/src/Logging.cpp
+++ b/src/Logging.cpp
@@ -25,35 +25,35 @@ constexpr auto MAX_LOG_FILES = 3;
 void
 qmlMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
 {
-        std::string localMsg = msg.toStdString();
-        const char *file     = context.file ? context.file : "";
-        const char *function = context.function ? context.function : "";
-
-        if (
-          // The default style has the point size set. If you use pixel size anywhere, you get
-          // that warning, which is useless, since sometimes you need the pixel size to match the
-          // text to the size of the outer element for example. This is done in the avatar and
-          // without that you get one warning for every Avatar displayed, which is stupid!
-          msg.endsWith(QStringLiteral("Both point size and pixel size set. Using pixel size.")))
-                return;
-
-        switch (type) {
-        case QtDebugMsg:
-                nhlog::qml()->debug("{} ({}:{}, {})", localMsg, file, context.line, function);
-                break;
-        case QtInfoMsg:
-                nhlog::qml()->info("{} ({}:{}, {})", localMsg, file, context.line, function);
-                break;
-        case QtWarningMsg:
-                nhlog::qml()->warn("{} ({}:{}, {})", localMsg, file, context.line, function);
-                break;
-        case QtCriticalMsg:
-                nhlog::qml()->critical("{} ({}:{}, {})", localMsg, file, context.line, function);
-                break;
-        case QtFatalMsg:
-                nhlog::qml()->critical("{} ({}:{}, {})", localMsg, file, context.line, function);
-                break;
-        }
+    std::string localMsg = msg.toStdString();
+    const char *file     = context.file ? context.file : "";
+    const char *function = context.function ? context.function : "";
+
+    if (
+      // The default style has the point size set. If you use pixel size anywhere, you get
+      // that warning, which is useless, since sometimes you need the pixel size to match the
+      // text to the size of the outer element for example. This is done in the avatar and
+      // without that you get one warning for every Avatar displayed, which is stupid!
+      msg.endsWith(QStringLiteral("Both point size and pixel size set. Using pixel size.")))
+        return;
+
+    switch (type) {
+    case QtDebugMsg:
+        nhlog::qml()->debug("{} ({}:{}, {})", localMsg, file, context.line, function);
+        break;
+    case QtInfoMsg:
+        nhlog::qml()->info("{} ({}:{}, {})", localMsg, file, context.line, function);
+        break;
+    case QtWarningMsg:
+        nhlog::qml()->warn("{} ({}:{}, {})", localMsg, file, context.line, function);
+        break;
+    case QtCriticalMsg:
+        nhlog::qml()->critical("{} ({}:{}, {})", localMsg, file, context.line, function);
+        break;
+    case QtFatalMsg:
+        nhlog::qml()->critical("{} ({}:{}, {})", localMsg, file, context.line, function);
+        break;
+    }
 }
 }
 
@@ -63,60 +63,59 @@ bool enable_debug_log_from_commandline = false;
 void
 init(const std::string &file_path)
 {
-        auto file_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(
-          file_path, MAX_FILE_SIZE, MAX_LOG_FILES);
-
-        auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
-
-        std::vector<spdlog::sink_ptr> sinks;
-        sinks.push_back(file_sink);
-        sinks.push_back(console_sink);
-
-        net_logger = std::make_shared<spdlog::logger>("net", std::begin(sinks), std::end(sinks));
-        ui_logger  = std::make_shared<spdlog::logger>("ui", std::begin(sinks), std::end(sinks));
-        db_logger  = std::make_shared<spdlog::logger>("db", std::begin(sinks), std::end(sinks));
-        crypto_logger =
-          std::make_shared<spdlog::logger>("crypto", std::begin(sinks), std::end(sinks));
-        qml_logger = std::make_shared<spdlog::logger>("qml", std::begin(sinks), std::end(sinks));
-
-        if (nheko::enable_debug_log || enable_debug_log_from_commandline) {
-                db_logger->set_level(spdlog::level::trace);
-                ui_logger->set_level(spdlog::level::trace);
-                crypto_logger->set_level(spdlog::level::trace);
-                net_logger->set_level(spdlog::level::trace);
-                qml_logger->set_level(spdlog::level::trace);
-        }
-
-        qInstallMessageHandler(qmlMessageHandler);
+    auto file_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(
+      file_path, MAX_FILE_SIZE, MAX_LOG_FILES);
+
+    auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
+
+    std::vector<spdlog::sink_ptr> sinks;
+    sinks.push_back(file_sink);
+    sinks.push_back(console_sink);
+
+    net_logger    = std::make_shared<spdlog::logger>("net", std::begin(sinks), std::end(sinks));
+    ui_logger     = std::make_shared<spdlog::logger>("ui", std::begin(sinks), std::end(sinks));
+    db_logger     = std::make_shared<spdlog::logger>("db", std::begin(sinks), std::end(sinks));
+    crypto_logger = std::make_shared<spdlog::logger>("crypto", std::begin(sinks), std::end(sinks));
+    qml_logger    = std::make_shared<spdlog::logger>("qml", std::begin(sinks), std::end(sinks));
+
+    if (nheko::enable_debug_log || enable_debug_log_from_commandline) {
+        db_logger->set_level(spdlog::level::trace);
+        ui_logger->set_level(spdlog::level::trace);
+        crypto_logger->set_level(spdlog::level::trace);
+        net_logger->set_level(spdlog::level::trace);
+        qml_logger->set_level(spdlog::level::trace);
+    }
+
+    qInstallMessageHandler(qmlMessageHandler);
 }
 
 std::shared_ptr<spdlog::logger>
 ui()
 {
-        return ui_logger;
+    return ui_logger;
 }
 
 std::shared_ptr<spdlog::logger>
 net()
 {
-        return net_logger;
+    return net_logger;
 }
 
 std::shared_ptr<spdlog::logger>
 db()
 {
-        return db_logger;
+    return db_logger;
 }
 
 std::shared_ptr<spdlog::logger>
 crypto()
 {
-        return crypto_logger;
+    return crypto_logger;
 }
 
 std::shared_ptr<spdlog::logger>
 qml()
 {
-        return qml_logger;
+    return qml_logger;
 }
 }
diff --git a/src/LoginPage.cpp b/src/LoginPage.cpp
index f53d81ba..64e9c865 100644
--- a/src/LoginPage.cpp
+++ b/src/LoginPage.cpp
@@ -34,477 +34,468 @@ LoginPage::LoginPage(QWidget *parent)
   : QWidget(parent)
   , inferredServerAddress_()
 {
-        qRegisterMetaType<LoginPage::LoginMethod>("LoginPage::LoginMethod");
+    qRegisterMetaType<LoginPage::LoginMethod>("LoginPage::LoginMethod");
 
-        top_layout_ = new QVBoxLayout();
+    top_layout_ = new QVBoxLayout();
+
+    top_bar_layout_ = new QHBoxLayout();
+    top_bar_layout_->setSpacing(0);
+    top_bar_layout_->setMargin(0);
+
+    back_button_ = new FlatButton(this);
+    back_button_->setMinimumSize(QSize(30, 30));
 
-        top_bar_layout_ = new QHBoxLayout();
-        top_bar_layout_->setSpacing(0);
-        top_bar_layout_->setMargin(0);
-
-        back_button_ = new FlatButton(this);
-        back_button_->setMinimumSize(QSize(30, 30));
-
-        top_bar_layout_->addWidget(back_button_, 0, Qt::AlignLeft | Qt::AlignVCenter);
-        top_bar_layout_->addStretch(1);
-
-        QIcon icon;
-        icon.addFile(":/icons/icons/ui/angle-pointing-to-left.png");
-
-        back_button_->setIcon(icon);
-        back_button_->setIconSize(QSize(32, 32));
-
-        QIcon logo;
-        logo.addFile(":/logos/login.png");
-
-        logo_ = new QLabel(this);
-        logo_->setPixmap(logo.pixmap(128));
-
-        logo_layout_ = new QHBoxLayout();
-        logo_layout_->setContentsMargins(0, 0, 0, 20);
-        logo_layout_->addWidget(logo_, 0, Qt::AlignHCenter);
-
-        form_wrapper_ = new QHBoxLayout();
-        form_widget_  = new QWidget();
-        form_widget_->setMinimumSize(QSize(350, 200));
-
-        form_layout_ = new QVBoxLayout();
-        form_layout_->setSpacing(20);
-        form_layout_->setContentsMargins(0, 0, 0, 30);
-        form_widget_->setLayout(form_layout_);
-
-        form_wrapper_->addStretch(1);
-        form_wrapper_->addWidget(form_widget_);
-        form_wrapper_->addStretch(1);
-
-        matrixid_input_ = new TextField(this);
-        matrixid_input_->setLabel(tr("Matrix ID"));
-        matrixid_input_->setRegexp(QRegularExpression("@.+?:.{3,}"));
-        matrixid_input_->setPlaceholderText(tr("e.g @joe:matrix.org"));
-        matrixid_input_->setToolTip(
-          tr("Your login name. A mxid should start with @ followed by the user id. After the user "
-             "id you need to include your server name after a :.\nYou can also put your homeserver "
-             "address there, if your server doesn't support .well-known lookup.\nExample: "
-             "@user:server.my\nIf Nheko fails to discover your homeserver, it will show you a "
-             "field to enter the server manually."));
-
-        spinner_ = new LoadingIndicator(this);
-        spinner_->setFixedHeight(40);
-        spinner_->setFixedWidth(40);
-        spinner_->hide();
-
-        errorIcon_ = new QLabel(this);
-        errorIcon_->setPixmap(QPixmap(":/icons/icons/error.png"));
-        errorIcon_->hide();
-
-        matrixidLayout_ = new QHBoxLayout();
-        matrixidLayout_->addWidget(matrixid_input_, 0, Qt::AlignVCenter);
-
-        QFont font;
-
-        error_matrixid_label_ = new QLabel(this);
-        error_matrixid_label_->setFont(font);
-        error_matrixid_label_->setWordWrap(true);
-
-        password_input_ = new TextField(this);
-        password_input_->setLabel(tr("Password"));
-        password_input_->setEchoMode(QLineEdit::Password);
-        password_input_->setToolTip(tr("Your password."));
-
-        deviceName_ = new TextField(this);
-        deviceName_->setLabel(tr("Device name"));
-        deviceName_->setToolTip(
-          tr("A name for this device, which will be shown to others, when verifying your devices. "
-             "If none is provided a default is used."));
-
-        serverInput_ = new TextField(this);
-        serverInput_->setLabel(tr("Homeserver address"));
-        serverInput_->setPlaceholderText(tr("server.my:8787"));
-        serverInput_->setToolTip(tr("The address that can be used to contact you homeservers "
-                                    "client API.\nExample: https://server.my:8787"));
-        serverInput_->hide();
-
-        serverLayout_ = new QHBoxLayout();
-        serverLayout_->addWidget(serverInput_, 0, Qt::AlignVCenter);
-
-        form_layout_->addLayout(matrixidLayout_);
-        form_layout_->addWidget(error_matrixid_label_, 0, Qt::AlignHCenter);
-        form_layout_->addWidget(password_input_);
-        form_layout_->addWidget(deviceName_, Qt::AlignHCenter);
-        form_layout_->addLayout(serverLayout_);
-
-        error_matrixid_label_->hide();
-
-        button_layout_ = new QHBoxLayout();
-        button_layout_->setSpacing(20);
-        button_layout_->setContentsMargins(0, 0, 0, 30);
-
-        login_button_ = new RaisedButton(tr("LOGIN"), this);
-        login_button_->setMinimumSize(150, 65);
-        login_button_->setFontSize(20);
-        login_button_->setCornerRadius(3);
-
-        sso_login_button_ = new RaisedButton(tr("SSO LOGIN"), this);
-        sso_login_button_->setMinimumSize(150, 65);
-        sso_login_button_->setFontSize(20);
-        sso_login_button_->setCornerRadius(3);
-        sso_login_button_->setVisible(false);
-
-        button_layout_->addStretch(1);
-        button_layout_->addWidget(login_button_);
-        button_layout_->addWidget(sso_login_button_);
-        button_layout_->addStretch(1);
-
-        error_label_ = new QLabel(this);
-        error_label_->setFont(font);
-        error_label_->setWordWrap(true);
-
-        top_layout_->addLayout(top_bar_layout_);
-        top_layout_->addStretch(1);
-        top_layout_->addLayout(logo_layout_);
-        top_layout_->addLayout(form_wrapper_);
-        top_layout_->addStretch(1);
-        top_layout_->addLayout(button_layout_);
-        top_layout_->addWidget(error_label_, 0, Qt::AlignHCenter);
-        top_layout_->addStretch(1);
-
-        setLayout(top_layout_);
-
-        connect(this, &LoginPage::versionOkCb, this, &LoginPage::versionOk, Qt::QueuedConnection);
-        connect(
-          this, &LoginPage::versionErrorCb, this, &LoginPage::versionError, Qt::QueuedConnection);
-
-        connect(back_button_, SIGNAL(clicked()), this, SLOT(onBackButtonClicked()));
-        connect(login_button_, &RaisedButton::clicked, this, [this]() {
-                onLoginButtonClicked(passwordSupported ? LoginMethod::Password : LoginMethod::SSO);
-        });
-        connect(sso_login_button_, &RaisedButton::clicked, this, [this]() {
-                onLoginButtonClicked(LoginMethod::SSO);
-        });
-        connect(this,
-                &LoginPage::showErrorMessage,
-                this,
-                static_cast<void (LoginPage::*)(QLabel *, const QString &)>(&LoginPage::showError),
-                Qt::QueuedConnection);
-        connect(matrixid_input_, SIGNAL(returnPressed()), login_button_, SLOT(click()));
-        connect(password_input_, SIGNAL(returnPressed()), login_button_, SLOT(click()));
-        connect(deviceName_, SIGNAL(returnPressed()), login_button_, SLOT(click()));
-        connect(serverInput_, SIGNAL(returnPressed()), login_button_, SLOT(click()));
-        connect(matrixid_input_, SIGNAL(editingFinished()), this, SLOT(onMatrixIdEntered()));
-        connect(serverInput_, SIGNAL(editingFinished()), this, SLOT(onServerAddressEntered()));
+    top_bar_layout_->addWidget(back_button_, 0, Qt::AlignLeft | Qt::AlignVCenter);
+    top_bar_layout_->addStretch(1);
+
+    QIcon icon;
+    icon.addFile(":/icons/icons/ui/angle-pointing-to-left.png");
+
+    back_button_->setIcon(icon);
+    back_button_->setIconSize(QSize(32, 32));
+
+    QIcon logo;
+    logo.addFile(":/logos/login.png");
+
+    logo_ = new QLabel(this);
+    logo_->setPixmap(logo.pixmap(128));
+
+    logo_layout_ = new QHBoxLayout();
+    logo_layout_->setContentsMargins(0, 0, 0, 20);
+    logo_layout_->addWidget(logo_, 0, Qt::AlignHCenter);
+
+    form_wrapper_ = new QHBoxLayout();
+    form_widget_  = new QWidget();
+    form_widget_->setMinimumSize(QSize(350, 200));
+
+    form_layout_ = new QVBoxLayout();
+    form_layout_->setSpacing(20);
+    form_layout_->setContentsMargins(0, 0, 0, 30);
+    form_widget_->setLayout(form_layout_);
+
+    form_wrapper_->addStretch(1);
+    form_wrapper_->addWidget(form_widget_);
+    form_wrapper_->addStretch(1);
+
+    matrixid_input_ = new TextField(this);
+    matrixid_input_->setLabel(tr("Matrix ID"));
+    matrixid_input_->setRegexp(QRegularExpression("@.+?:.{3,}"));
+    matrixid_input_->setPlaceholderText(tr("e.g @joe:matrix.org"));
+    matrixid_input_->setToolTip(
+      tr("Your login name. A mxid should start with @ followed by the user id. After the user "
+         "id you need to include your server name after a :.\nYou can also put your homeserver "
+         "address there, if your server doesn't support .well-known lookup.\nExample: "
+         "@user:server.my\nIf Nheko fails to discover your homeserver, it will show you a "
+         "field to enter the server manually."));
+
+    spinner_ = new LoadingIndicator(this);
+    spinner_->setFixedHeight(40);
+    spinner_->setFixedWidth(40);
+    spinner_->hide();
+
+    errorIcon_ = new QLabel(this);
+    errorIcon_->setPixmap(QPixmap(":/icons/icons/error.png"));
+    errorIcon_->hide();
+
+    matrixidLayout_ = new QHBoxLayout();
+    matrixidLayout_->addWidget(matrixid_input_, 0, Qt::AlignVCenter);
+
+    QFont font;
+
+    error_matrixid_label_ = new QLabel(this);
+    error_matrixid_label_->setFont(font);
+    error_matrixid_label_->setWordWrap(true);
+
+    password_input_ = new TextField(this);
+    password_input_->setLabel(tr("Password"));
+    password_input_->setEchoMode(QLineEdit::Password);
+    password_input_->setToolTip(tr("Your password."));
+
+    deviceName_ = new TextField(this);
+    deviceName_->setLabel(tr("Device name"));
+    deviceName_->setToolTip(
+      tr("A name for this device, which will be shown to others, when verifying your devices. "
+         "If none is provided a default is used."));
+
+    serverInput_ = new TextField(this);
+    serverInput_->setLabel(tr("Homeserver address"));
+    serverInput_->setPlaceholderText(tr("server.my:8787"));
+    serverInput_->setToolTip(tr("The address that can be used to contact you homeservers "
+                                "client API.\nExample: https://server.my:8787"));
+    serverInput_->hide();
+
+    serverLayout_ = new QHBoxLayout();
+    serverLayout_->addWidget(serverInput_, 0, Qt::AlignVCenter);
+
+    form_layout_->addLayout(matrixidLayout_);
+    form_layout_->addWidget(error_matrixid_label_, 0, Qt::AlignHCenter);
+    form_layout_->addWidget(password_input_);
+    form_layout_->addWidget(deviceName_, Qt::AlignHCenter);
+    form_layout_->addLayout(serverLayout_);
+
+    error_matrixid_label_->hide();
+
+    button_layout_ = new QHBoxLayout();
+    button_layout_->setSpacing(20);
+    button_layout_->setContentsMargins(0, 0, 0, 30);
+
+    login_button_ = new RaisedButton(tr("LOGIN"), this);
+    login_button_->setMinimumSize(150, 65);
+    login_button_->setFontSize(20);
+    login_button_->setCornerRadius(3);
+
+    sso_login_button_ = new RaisedButton(tr("SSO LOGIN"), this);
+    sso_login_button_->setMinimumSize(150, 65);
+    sso_login_button_->setFontSize(20);
+    sso_login_button_->setCornerRadius(3);
+    sso_login_button_->setVisible(false);
+
+    button_layout_->addStretch(1);
+    button_layout_->addWidget(login_button_);
+    button_layout_->addWidget(sso_login_button_);
+    button_layout_->addStretch(1);
+
+    error_label_ = new QLabel(this);
+    error_label_->setFont(font);
+    error_label_->setWordWrap(true);
+
+    top_layout_->addLayout(top_bar_layout_);
+    top_layout_->addStretch(1);
+    top_layout_->addLayout(logo_layout_);
+    top_layout_->addLayout(form_wrapper_);
+    top_layout_->addStretch(1);
+    top_layout_->addLayout(button_layout_);
+    top_layout_->addWidget(error_label_, 0, Qt::AlignHCenter);
+    top_layout_->addStretch(1);
+
+    setLayout(top_layout_);
+
+    connect(this, &LoginPage::versionOkCb, this, &LoginPage::versionOk, Qt::QueuedConnection);
+    connect(this, &LoginPage::versionErrorCb, this, &LoginPage::versionError, Qt::QueuedConnection);
+
+    connect(back_button_, SIGNAL(clicked()), this, SLOT(onBackButtonClicked()));
+    connect(login_button_, &RaisedButton::clicked, this, [this]() {
+        onLoginButtonClicked(passwordSupported ? LoginMethod::Password : LoginMethod::SSO);
+    });
+    connect(sso_login_button_, &RaisedButton::clicked, this, [this]() {
+        onLoginButtonClicked(LoginMethod::SSO);
+    });
+    connect(this,
+            &LoginPage::showErrorMessage,
+            this,
+            static_cast<void (LoginPage::*)(QLabel *, const QString &)>(&LoginPage::showError),
+            Qt::QueuedConnection);
+    connect(matrixid_input_, SIGNAL(returnPressed()), login_button_, SLOT(click()));
+    connect(password_input_, SIGNAL(returnPressed()), login_button_, SLOT(click()));
+    connect(deviceName_, SIGNAL(returnPressed()), login_button_, SLOT(click()));
+    connect(serverInput_, SIGNAL(returnPressed()), login_button_, SLOT(click()));
+    connect(matrixid_input_, SIGNAL(editingFinished()), this, SLOT(onMatrixIdEntered()));
+    connect(serverInput_, SIGNAL(editingFinished()), this, SLOT(onServerAddressEntered()));
 }
 void
 LoginPage::showError(const QString &msg)
 {
-        auto rect  = QFontMetrics(font()).boundingRect(msg);
-        int width  = rect.width();
-        int height = rect.height();
-        error_label_->setFixedHeight((int)qCeil(width / 200.0) * height);
-        error_label_->setText(msg);
+    auto rect  = QFontMetrics(font()).boundingRect(msg);
+    int width  = rect.width();
+    int height = rect.height();
+    error_label_->setFixedHeight((int)qCeil(width / 200.0) * height);
+    error_label_->setText(msg);
 }
 
 void
 LoginPage::showError(QLabel *label, const QString &msg)
 {
-        auto rect  = QFontMetrics(font()).boundingRect(msg);
-        int width  = rect.width();
-        int height = rect.height();
-        label->setFixedHeight((int)qCeil(width / 200.0) * height);
-        label->setText(msg);
+    auto rect  = QFontMetrics(font()).boundingRect(msg);
+    int width  = rect.width();
+    int height = rect.height();
+    label->setFixedHeight((int)qCeil(width / 200.0) * height);
+    label->setText(msg);
 }
 
 void
 LoginPage::onMatrixIdEntered()
 {
-        error_label_->setText("");
+    error_label_->setText("");
 
-        User user;
+    User user;
 
-        if (!matrixid_input_->isValid()) {
-                error_matrixid_label_->show();
-                showError(error_matrixid_label_,
-                          tr("You have entered an invalid Matrix ID  e.g @joe:matrix.org"));
-                return;
+    if (!matrixid_input_->isValid()) {
+        error_matrixid_label_->show();
+        showError(error_matrixid_label_,
+                  tr("You have entered an invalid Matrix ID  e.g @joe:matrix.org"));
+        return;
+    } else {
+        error_matrixid_label_->setText("");
+        error_matrixid_label_->hide();
+    }
+
+    try {
+        user = parse<User>(matrixid_input_->text().toStdString());
+    } catch (const std::exception &) {
+        showError(error_matrixid_label_,
+                  tr("You have entered an invalid Matrix ID  e.g @joe:matrix.org"));
+        return;
+    }
+
+    QString homeServer = QString::fromStdString(user.hostname());
+    if (homeServer != inferredServerAddress_) {
+        serverInput_->hide();
+        serverLayout_->removeWidget(errorIcon_);
+        errorIcon_->hide();
+        if (serverInput_->isVisible()) {
+            matrixidLayout_->removeWidget(spinner_);
+            serverLayout_->addWidget(spinner_, 0, Qt::AlignVCenter | Qt::AlignRight);
+            spinner_->start();
         } else {
-                error_matrixid_label_->setText("");
-                error_matrixid_label_->hide();
+            serverLayout_->removeWidget(spinner_);
+            matrixidLayout_->addWidget(spinner_, 0, Qt::AlignVCenter | Qt::AlignRight);
+            spinner_->start();
         }
 
-        try {
-                user = parse<User>(matrixid_input_->text().toStdString());
-        } catch (const std::exception &) {
-                showError(error_matrixid_label_,
-                          tr("You have entered an invalid Matrix ID  e.g @joe:matrix.org"));
-                return;
-        }
+        inferredServerAddress_ = homeServer;
+        serverInput_->setText(homeServer);
 
-        QString homeServer = QString::fromStdString(user.hostname());
-        if (homeServer != inferredServerAddress_) {
-                serverInput_->hide();
-                serverLayout_->removeWidget(errorIcon_);
-                errorIcon_->hide();
-                if (serverInput_->isVisible()) {
-                        matrixidLayout_->removeWidget(spinner_);
-                        serverLayout_->addWidget(spinner_, 0, Qt::AlignVCenter | Qt::AlignRight);
-                        spinner_->start();
-                } else {
-                        serverLayout_->removeWidget(spinner_);
-                        matrixidLayout_->addWidget(spinner_, 0, Qt::AlignVCenter | Qt::AlignRight);
-                        spinner_->start();
-                }
-
-                inferredServerAddress_ = homeServer;
-                serverInput_->setText(homeServer);
-
-                http::client()->set_server(user.hostname());
-                http::client()->verify_certificates(
-                  !UserSettings::instance()->disableCertificateValidation());
-
-                http::client()->well_known([this](const mtx::responses::WellKnown &res,
-                                                  mtx::http::RequestErr err) {
-                        if (err) {
-                                if (err->status_code == 404) {
-                                        nhlog::net()->info("Autodiscovery: No .well-known.");
-                                        checkHomeserverVersion();
-                                        return;
-                                }
-
-                                if (!err->parse_error.empty()) {
-                                        emit versionErrorCb(
-                                          tr("Autodiscovery failed. Received malformed response."));
-                                        nhlog::net()->error(
-                                          "Autodiscovery failed. Received malformed response.");
-                                        return;
-                                }
-
-                                emit versionErrorCb(tr("Autodiscovery failed. Unknown error when "
-                                                       "requesting .well-known."));
-                                nhlog::net()->error("Autodiscovery failed. Unknown error when "
-                                                    "requesting .well-known. {} {}",
-                                                    err->status_code,
-                                                    err->error_code);
-                                return;
-                        }
-
-                        nhlog::net()->info("Autodiscovery: Discovered '" + res.homeserver.base_url +
-                                           "'");
-                        http::client()->set_server(res.homeserver.base_url);
-                        checkHomeserverVersion();
-                });
-        }
+        http::client()->set_server(user.hostname());
+        http::client()->verify_certificates(
+          !UserSettings::instance()->disableCertificateValidation());
+
+        http::client()->well_known(
+          [this](const mtx::responses::WellKnown &res, mtx::http::RequestErr err) {
+              if (err) {
+                  if (err->status_code == 404) {
+                      nhlog::net()->info("Autodiscovery: No .well-known.");
+                      checkHomeserverVersion();
+                      return;
+                  }
+
+                  if (!err->parse_error.empty()) {
+                      emit versionErrorCb(tr("Autodiscovery failed. Received malformed response."));
+                      nhlog::net()->error("Autodiscovery failed. Received malformed response.");
+                      return;
+                  }
+
+                  emit versionErrorCb(tr("Autodiscovery failed. Unknown error when "
+                                         "requesting .well-known."));
+                  nhlog::net()->error("Autodiscovery failed. Unknown error when "
+                                      "requesting .well-known. {} {}",
+                                      err->status_code,
+                                      err->error_code);
+                  return;
+              }
+
+              nhlog::net()->info("Autodiscovery: Discovered '" + res.homeserver.base_url + "'");
+              http::client()->set_server(res.homeserver.base_url);
+              checkHomeserverVersion();
+          });
+    }
 }
 
 void
 LoginPage::checkHomeserverVersion()
 {
-        http::client()->versions(
-          [this](const mtx::responses::Versions &, mtx::http::RequestErr err) {
-                  if (err) {
-                          if (err->status_code == 404) {
-                                  emit versionErrorCb(tr("The required endpoints were not found. "
-                                                         "Possibly not a Matrix server."));
-                                  return;
-                          }
-
-                          if (!err->parse_error.empty()) {
-                                  emit versionErrorCb(tr("Received malformed response. Make sure "
-                                                         "the homeserver domain is valid."));
-                                  return;
-                          }
-
-                          emit versionErrorCb(tr(
-                            "An unknown error occured. Make sure the homeserver domain is valid."));
-                          return;
-                  }
+    http::client()->versions([this](const mtx::responses::Versions &, mtx::http::RequestErr err) {
+        if (err) {
+            if (err->status_code == 404) {
+                emit versionErrorCb(tr("The required endpoints were not found. "
+                                       "Possibly not a Matrix server."));
+                return;
+            }
 
-                  http::client()->get_login(
-                    [this](mtx::responses::LoginFlows flows, mtx::http::RequestErr err) {
-                            if (err || flows.flows.empty())
-                                    emit versionOkCb(true, false);
-
-                            bool ssoSupported_      = false;
-                            bool passwordSupported_ = false;
-                            for (const auto &flow : flows.flows) {
-                                    if (flow.type == mtx::user_interactive::auth_types::sso) {
-                                            ssoSupported_ = true;
-                                    } else if (flow.type ==
-                                               mtx::user_interactive::auth_types::password) {
-                                            passwordSupported_ = true;
-                                    }
-                            }
-                            emit versionOkCb(passwordSupported_, ssoSupported_);
-                    });
+            if (!err->parse_error.empty()) {
+                emit versionErrorCb(tr("Received malformed response. Make sure "
+                                       "the homeserver domain is valid."));
+                return;
+            }
+
+            emit versionErrorCb(
+              tr("An unknown error occured. Make sure the homeserver domain is valid."));
+            return;
+        }
+
+        http::client()->get_login(
+          [this](mtx::responses::LoginFlows flows, mtx::http::RequestErr err) {
+              if (err || flows.flows.empty())
+                  emit versionOkCb(true, false);
+
+              bool ssoSupported_      = false;
+              bool passwordSupported_ = false;
+              for (const auto &flow : flows.flows) {
+                  if (flow.type == mtx::user_interactive::auth_types::sso) {
+                      ssoSupported_ = true;
+                  } else if (flow.type == mtx::user_interactive::auth_types::password) {
+                      passwordSupported_ = true;
+                  }
+              }
+              emit versionOkCb(passwordSupported_, ssoSupported_);
           });
+    });
 }
 
 void
 LoginPage::onServerAddressEntered()
 {
-        error_label_->setText("");
-        http::client()->verify_certificates(
-          !UserSettings::instance()->disableCertificateValidation());
-        http::client()->set_server(serverInput_->text().toStdString());
-        checkHomeserverVersion();
-
-        serverLayout_->removeWidget(errorIcon_);
-        errorIcon_->hide();
-        serverLayout_->addWidget(spinner_, 0, Qt::AlignVCenter | Qt::AlignRight);
-        spinner_->start();
+    error_label_->setText("");
+    http::client()->verify_certificates(!UserSettings::instance()->disableCertificateValidation());
+    http::client()->set_server(serverInput_->text().toStdString());
+    checkHomeserverVersion();
+
+    serverLayout_->removeWidget(errorIcon_);
+    errorIcon_->hide();
+    serverLayout_->addWidget(spinner_, 0, Qt::AlignVCenter | Qt::AlignRight);
+    spinner_->start();
 }
 
 void
 LoginPage::versionError(const QString &error)
 {
-        showError(error_label_, error);
-        serverInput_->show();
-
-        spinner_->stop();
-        serverLayout_->removeWidget(spinner_);
-        serverLayout_->addWidget(errorIcon_, 0, Qt::AlignVCenter | Qt::AlignRight);
-        errorIcon_->show();
-        matrixidLayout_->removeWidget(spinner_);
+    showError(error_label_, error);
+    serverInput_->show();
+
+    spinner_->stop();
+    serverLayout_->removeWidget(spinner_);
+    serverLayout_->addWidget(errorIcon_, 0, Qt::AlignVCenter | Qt::AlignRight);
+    errorIcon_->show();
+    matrixidLayout_->removeWidget(spinner_);
 }
 
 void
 LoginPage::versionOk(bool passwordSupported_, bool ssoSupported_)
 {
-        passwordSupported = passwordSupported_;
-        ssoSupported      = ssoSupported_;
+    passwordSupported = passwordSupported_;
+    ssoSupported      = ssoSupported_;
 
-        serverLayout_->removeWidget(spinner_);
-        matrixidLayout_->removeWidget(spinner_);
-        spinner_->stop();
+    serverLayout_->removeWidget(spinner_);
+    matrixidLayout_->removeWidget(spinner_);
+    spinner_->stop();
 
-        sso_login_button_->setVisible(ssoSupported);
-        login_button_->setVisible(passwordSupported);
+    sso_login_button_->setVisible(ssoSupported);
+    login_button_->setVisible(passwordSupported);
 
-        if (serverInput_->isVisible())
-                serverInput_->hide();
+    if (serverInput_->isVisible())
+        serverInput_->hide();
 }
 
 void
 LoginPage::onLoginButtonClicked(LoginMethod loginMethod)
 {
-        error_label_->setText("");
-        User user;
+    error_label_->setText("");
+    User user;
+
+    if (!matrixid_input_->isValid()) {
+        error_matrixid_label_->show();
+        showError(error_matrixid_label_,
+                  tr("You have entered an invalid Matrix ID  e.g @joe:matrix.org"));
+        return;
+    } else {
+        error_matrixid_label_->setText("");
+        error_matrixid_label_->hide();
+    }
+
+    try {
+        user = parse<User>(matrixid_input_->text().toStdString());
+    } catch (const std::exception &) {
+        showError(error_matrixid_label_,
+                  tr("You have entered an invalid Matrix ID  e.g @joe:matrix.org"));
+        return;
+    }
+
+    if (loginMethod == LoginMethod::Password) {
+        if (password_input_->text().isEmpty())
+            return showError(error_label_, tr("Empty password"));
+
+        http::client()->login(
+          user.localpart(),
+          password_input_->text().toStdString(),
+          deviceName_->text().trimmed().isEmpty() ? initialDeviceName()
+                                                  : deviceName_->text().toStdString(),
+          [this](const mtx::responses::Login &res, mtx::http::RequestErr err) {
+              if (err) {
+                  auto error = err->matrix_error.error;
+                  if (error.empty())
+                      error = err->parse_error;
+
+                  showErrorMessage(error_label_, QString::fromStdString(error));
+                  emit errorOccurred();
+                  return;
+              }
+
+              if (res.well_known) {
+                  http::client()->set_server(res.well_known->homeserver.base_url);
+                  nhlog::net()->info("Login requested to user server: " +
+                                     res.well_known->homeserver.base_url);
+              }
+
+              emit loginOk(res);
+          });
+    } else {
+        auto sso = new SSOHandler();
+        connect(sso, &SSOHandler::ssoSuccess, this, [this, sso](std::string token) {
+            mtx::requests::Login req{};
+            req.token     = token;
+            req.type      = mtx::user_interactive::auth_types::token;
+            req.device_id = deviceName_->text().trimmed().isEmpty()
+                              ? initialDeviceName()
+                              : deviceName_->text().toStdString();
+            http::client()->login(
+              req, [this](const mtx::responses::Login &res, mtx::http::RequestErr err) {
+                  if (err) {
+                      showErrorMessage(error_label_,
+                                       QString::fromStdString(err->matrix_error.error));
+                      emit errorOccurred();
+                      return;
+                  }
 
-        if (!matrixid_input_->isValid()) {
-                error_matrixid_label_->show();
-                showError(error_matrixid_label_,
-                          tr("You have entered an invalid Matrix ID  e.g @joe:matrix.org"));
-                return;
-        } else {
-                error_matrixid_label_->setText("");
-                error_matrixid_label_->hide();
-        }
+                  if (res.well_known) {
+                      http::client()->set_server(res.well_known->homeserver.base_url);
+                      nhlog::net()->info("Login requested to user server: " +
+                                         res.well_known->homeserver.base_url);
+                  }
 
-        try {
-                user = parse<User>(matrixid_input_->text().toStdString());
-        } catch (const std::exception &) {
-                showError(error_matrixid_label_,
-                          tr("You have entered an invalid Matrix ID  e.g @joe:matrix.org"));
-                return;
-        }
+                  emit loginOk(res);
+              });
+            sso->deleteLater();
+        });
+        connect(sso, &SSOHandler::ssoFailed, this, [this, sso]() {
+            showErrorMessage(error_label_, tr("SSO login failed"));
+            emit errorOccurred();
+            sso->deleteLater();
+        });
 
-        if (loginMethod == LoginMethod::Password) {
-                if (password_input_->text().isEmpty())
-                        return showError(error_label_, tr("Empty password"));
-
-                http::client()->login(
-                  user.localpart(),
-                  password_input_->text().toStdString(),
-                  deviceName_->text().trimmed().isEmpty() ? initialDeviceName()
-                                                          : deviceName_->text().toStdString(),
-                  [this](const mtx::responses::Login &res, mtx::http::RequestErr err) {
-                          if (err) {
-                                  auto error = err->matrix_error.error;
-                                  if (error.empty())
-                                          error = err->parse_error;
-
-                                  showErrorMessage(error_label_, QString::fromStdString(error));
-                                  emit errorOccurred();
-                                  return;
-                          }
-
-                          if (res.well_known) {
-                                  http::client()->set_server(res.well_known->homeserver.base_url);
-                                  nhlog::net()->info("Login requested to user server: " +
-                                                     res.well_known->homeserver.base_url);
-                          }
-
-                          emit loginOk(res);
-                  });
-        } else {
-                auto sso = new SSOHandler();
-                connect(sso, &SSOHandler::ssoSuccess, this, [this, sso](std::string token) {
-                        mtx::requests::Login req{};
-                        req.token     = token;
-                        req.type      = mtx::user_interactive::auth_types::token;
-                        req.device_id = deviceName_->text().trimmed().isEmpty()
-                                          ? initialDeviceName()
-                                          : deviceName_->text().toStdString();
-                        http::client()->login(
-                          req, [this](const mtx::responses::Login &res, mtx::http::RequestErr err) {
-                                  if (err) {
-                                          showErrorMessage(
-                                            error_label_,
-                                            QString::fromStdString(err->matrix_error.error));
-                                          emit errorOccurred();
-                                          return;
-                                  }
-
-                                  if (res.well_known) {
-                                          http::client()->set_server(
-                                            res.well_known->homeserver.base_url);
-                                          nhlog::net()->info("Login requested to user server: " +
-                                                             res.well_known->homeserver.base_url);
-                                  }
-
-                                  emit loginOk(res);
-                          });
-                        sso->deleteLater();
-                });
-                connect(sso, &SSOHandler::ssoFailed, this, [this, sso]() {
-                        showErrorMessage(error_label_, tr("SSO login failed"));
-                        emit errorOccurred();
-                        sso->deleteLater();
-                });
-
-                QDesktopServices::openUrl(
-                  QString::fromStdString(http::client()->login_sso_redirect(sso->url())));
-        }
+        QDesktopServices::openUrl(
+          QString::fromStdString(http::client()->login_sso_redirect(sso->url())));
+    }
 
-        emit loggingIn();
+    emit loggingIn();
 }
 
 void
 LoginPage::reset()
 {
-        matrixid_input_->clear();
-        password_input_->clear();
-        password_input_->show();
-        serverInput_->clear();
-
-        spinner_->stop();
-        errorIcon_->hide();
-        serverLayout_->removeWidget(spinner_);
-        serverLayout_->removeWidget(errorIcon_);
-        matrixidLayout_->removeWidget(spinner_);
-
-        inferredServerAddress_.clear();
+    matrixid_input_->clear();
+    password_input_->clear();
+    password_input_->show();
+    serverInput_->clear();
+
+    spinner_->stop();
+    errorIcon_->hide();
+    serverLayout_->removeWidget(spinner_);
+    serverLayout_->removeWidget(errorIcon_);
+    matrixidLayout_->removeWidget(spinner_);
+
+    inferredServerAddress_.clear();
 }
 
 void
 LoginPage::onBackButtonClicked()
 {
-        emit backButtonClicked();
+    emit backButtonClicked();
 }
 
 void
 LoginPage::paintEvent(QPaintEvent *)
 {
-        QStyleOption opt;
-        opt.init(this);
-        QPainter p(this);
-        style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
+    QStyleOption opt;
+    opt.init(this);
+    QPainter p(this);
+    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
 }
diff --git a/src/LoginPage.h b/src/LoginPage.h
index 2e1eb9b9..01dd27e1 100644
--- a/src/LoginPage.h
+++ b/src/LoginPage.h
@@ -24,101 +24,101 @@ struct Login;
 
 class LoginPage : public QWidget
 {
-        Q_OBJECT
+    Q_OBJECT
 
 public:
-        enum class LoginMethod
-        {
-                Password,
-                SSO,
-        };
+    enum class LoginMethod
+    {
+        Password,
+        SSO,
+    };
 
-        LoginPage(QWidget *parent = nullptr);
+    LoginPage(QWidget *parent = nullptr);
 
-        void reset();
+    void reset();
 
 signals:
-        void backButtonClicked();
-        void loggingIn();
-        void errorOccurred();
+    void backButtonClicked();
+    void loggingIn();
+    void errorOccurred();
 
-        //! Used to trigger the corresponding slot outside of the main thread.
-        void versionErrorCb(const QString &err);
-        void versionOkCb(bool passwordSupported, bool ssoSupported);
+    //! Used to trigger the corresponding slot outside of the main thread.
+    void versionErrorCb(const QString &err);
+    void versionOkCb(bool passwordSupported, bool ssoSupported);
 
-        void loginOk(const mtx::responses::Login &res);
-        void showErrorMessage(QLabel *label, const QString &msg);
+    void loginOk(const mtx::responses::Login &res);
+    void showErrorMessage(QLabel *label, const QString &msg);
 
 protected:
-        void paintEvent(QPaintEvent *event) override;
+    void paintEvent(QPaintEvent *event) override;
 
 public slots:
-        // Displays errors produced during the login.
-        void showError(const QString &msg);
-        void showError(QLabel *label, const QString &msg);
+    // Displays errors produced during the login.
+    void showError(const QString &msg);
+    void showError(QLabel *label, const QString &msg);
 
 private slots:
-        // Callback for the back button.
-        void onBackButtonClicked();
+    // Callback for the back button.
+    void onBackButtonClicked();
 
-        // Callback for the login button.
-        void onLoginButtonClicked(LoginMethod loginMethod);
+    // Callback for the login button.
+    void onLoginButtonClicked(LoginMethod loginMethod);
 
-        // Callback for probing the server found in the mxid
-        void onMatrixIdEntered();
+    // Callback for probing the server found in the mxid
+    void onMatrixIdEntered();
 
-        // Callback for probing the manually entered server
-        void onServerAddressEntered();
+    // Callback for probing the manually entered server
+    void onServerAddressEntered();
 
-        // Callback for errors produced during server probing
-        void versionError(const QString &error_message);
-        // Callback for successful server probing
-        void versionOk(bool passwordSupported, bool ssoSupported);
+    // Callback for errors produced during server probing
+    void versionError(const QString &error_message);
+    // Callback for successful server probing
+    void versionOk(bool passwordSupported, bool ssoSupported);
 
 private:
-        void checkHomeserverVersion();
-        std::string initialDeviceName()
-        {
+    void checkHomeserverVersion();
+    std::string initialDeviceName()
+    {
 #if defined(Q_OS_MAC)
-                return "Nheko on macOS";
+        return "Nheko on macOS";
 #elif defined(Q_OS_LINUX)
-                return "Nheko on Linux";
+        return "Nheko on Linux";
 #elif defined(Q_OS_WIN)
-                return "Nheko on Windows";
+        return "Nheko on Windows";
 #elif defined(Q_OS_FREEBSD)
-                return "Nheko on FreeBSD";
+        return "Nheko on FreeBSD";
 #else
-                return "Nheko";
+        return "Nheko";
 #endif
-        }
+    }
 
-        QVBoxLayout *top_layout_;
+    QVBoxLayout *top_layout_;
 
-        QHBoxLayout *top_bar_layout_;
-        QHBoxLayout *logo_layout_;
-        QHBoxLayout *button_layout_;
+    QHBoxLayout *top_bar_layout_;
+    QHBoxLayout *logo_layout_;
+    QHBoxLayout *button_layout_;
 
-        QLabel *logo_;
-        QLabel *error_label_;
-        QLabel *error_matrixid_label_;
+    QLabel *logo_;
+    QLabel *error_label_;
+    QLabel *error_matrixid_label_;
 
-        QHBoxLayout *serverLayout_;
-        QHBoxLayout *matrixidLayout_;
-        LoadingIndicator *spinner_;
-        QLabel *errorIcon_;
-        QString inferredServerAddress_;
+    QHBoxLayout *serverLayout_;
+    QHBoxLayout *matrixidLayout_;
+    LoadingIndicator *spinner_;
+    QLabel *errorIcon_;
+    QString inferredServerAddress_;
 
-        FlatButton *back_button_;
-        RaisedButton *login_button_, *sso_login_button_;
+    FlatButton *back_button_;
+    RaisedButton *login_button_, *sso_login_button_;
 
-        QWidget *form_widget_;
-        QHBoxLayout *form_wrapper_;
-        QVBoxLayout *form_layout_;
+    QWidget *form_widget_;
+    QHBoxLayout *form_wrapper_;
+    QVBoxLayout *form_layout_;
 
-        TextField *matrixid_input_;
-        TextField *password_input_;
-        TextField *deviceName_;
-        TextField *serverInput_;
-        bool passwordSupported = true;
-        bool ssoSupported      = false;
+    TextField *matrixid_input_;
+    TextField *password_input_;
+    TextField *deviceName_;
+    TextField *serverInput_;
+    bool passwordSupported = true;
+    bool ssoSupported      = false;
 };
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index b423304f..bc53b906 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -43,415 +43,407 @@ MainWindow::MainWindow(QWidget *parent)
   : QMainWindow(parent)
   , userSettings_{UserSettings::instance()}
 {
-        instance_ = this;
-
-        setWindowTitle(0);
-        setObjectName("MainWindow");
-
-        modal_ = new OverlayModal(this);
-
-        restoreWindowSize();
-
-        QFont font;
-        font.setStyleStrategy(QFont::PreferAntialias);
-        setFont(font);
-
-        trayIcon_ = new TrayIcon(":/logos/nheko.svg", this);
-
-        welcome_page_     = new WelcomePage(this);
-        login_page_       = new LoginPage(this);
-        register_page_    = new RegisterPage(this);
-        chat_page_        = new ChatPage(userSettings_, this);
-        userSettingsPage_ = new UserSettingsPage(userSettings_, this);
-
-        // Initialize sliding widget manager.
-        pageStack_ = new QStackedWidget(this);
-        pageStack_->addWidget(welcome_page_);
-        pageStack_->addWidget(login_page_);
-        pageStack_->addWidget(register_page_);
-        pageStack_->addWidget(chat_page_);
-        pageStack_->addWidget(userSettingsPage_);
-
-        setCentralWidget(pageStack_);
-
-        connect(welcome_page_, SIGNAL(userLogin()), this, SLOT(showLoginPage()));
-        connect(welcome_page_, SIGNAL(userRegister()), this, SLOT(showRegisterPage()));
-
-        connect(login_page_, SIGNAL(backButtonClicked()), this, SLOT(showWelcomePage()));
-        connect(login_page_, &LoginPage::loggingIn, this, &MainWindow::showOverlayProgressBar);
-        connect(
-          register_page_, &RegisterPage::registering, this, &MainWindow::showOverlayProgressBar);
-        connect(
-          login_page_, &LoginPage::errorOccurred, this, [this]() { removeOverlayProgressBar(); });
-        connect(register_page_, &RegisterPage::errorOccurred, this, [this]() {
-                removeOverlayProgressBar();
-        });
-        connect(register_page_, SIGNAL(backButtonClicked()), this, SLOT(showWelcomePage()));
-
-        connect(chat_page_, &ChatPage::closing, this, &MainWindow::showWelcomePage);
-        connect(
-          chat_page_, &ChatPage::showOverlayProgressBar, this, &MainWindow::showOverlayProgressBar);
-        connect(chat_page_, &ChatPage::unreadMessages, this, &MainWindow::setWindowTitle);
-        connect(chat_page_, SIGNAL(unreadMessages(int)), trayIcon_, SLOT(setUnreadCount(int)));
-        connect(chat_page_, &ChatPage::showLoginPage, this, [this](const QString &msg) {
-                login_page_->showError(msg);
-                showLoginPage();
-        });
-
-        connect(userSettingsPage_, &UserSettingsPage::moveBack, this, [this]() {
-                pageStack_->setCurrentWidget(chat_page_);
-        });
-
-        connect(
-          userSettingsPage_, SIGNAL(trayOptionChanged(bool)), trayIcon_, SLOT(setVisible(bool)));
-        connect(
-          userSettingsPage_, &UserSettingsPage::themeChanged, chat_page_, &ChatPage::themeChanged);
-        connect(trayIcon_,
-                SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
-                this,
-                SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
-
-        connect(chat_page_, SIGNAL(contentLoaded()), this, SLOT(removeOverlayProgressBar()));
-
-        connect(this, &MainWindow::focusChanged, chat_page_, &ChatPage::chatFocusChanged);
-
-        connect(
-          chat_page_, &ChatPage::showUserSettingsPage, this, &MainWindow::showUserSettingsPage);
-
-        connect(login_page_, &LoginPage::loginOk, this, [this](const mtx::responses::Login &res) {
-                http::client()->set_user(res.user_id);
-                showChatPage();
-        });
-
-        connect(register_page_, &RegisterPage::registerOk, this, &MainWindow::showChatPage);
-
-        QShortcut *quitShortcut = new QShortcut(QKeySequence::Quit, this);
-        connect(quitShortcut, &QShortcut::activated, this, QApplication::quit);
-
-        trayIcon_->setVisible(userSettings_->tray());
-
-        // load cache on event loop
-        QTimer::singleShot(0, this, [this] {
-                if (hasActiveUser()) {
-                        QString token       = userSettings_->accessToken();
-                        QString home_server = userSettings_->homeserver();
-                        QString user_id     = userSettings_->userId();
-                        QString device_id   = userSettings_->deviceId();
-
-                        http::client()->set_access_token(token.toStdString());
-                        http::client()->set_server(home_server.toStdString());
-                        http::client()->set_device_id(device_id.toStdString());
-
-                        try {
-                                using namespace mtx::identifiers;
-                                http::client()->set_user(parse<User>(user_id.toStdString()));
-                        } catch (const std::invalid_argument &) {
-                                nhlog::ui()->critical("bootstrapped with invalid user_id: {}",
-                                                      user_id.toStdString());
-                        }
-
-                        showChatPage();
-                }
-        });
+    instance_ = this;
+
+    setWindowTitle(0);
+    setObjectName("MainWindow");
+
+    modal_ = new OverlayModal(this);
+
+    restoreWindowSize();
+
+    QFont font;
+    font.setStyleStrategy(QFont::PreferAntialias);
+    setFont(font);
+
+    trayIcon_ = new TrayIcon(":/logos/nheko.svg", this);
+
+    welcome_page_     = new WelcomePage(this);
+    login_page_       = new LoginPage(this);
+    register_page_    = new RegisterPage(this);
+    chat_page_        = new ChatPage(userSettings_, this);
+    userSettingsPage_ = new UserSettingsPage(userSettings_, this);
+
+    // Initialize sliding widget manager.
+    pageStack_ = new QStackedWidget(this);
+    pageStack_->addWidget(welcome_page_);
+    pageStack_->addWidget(login_page_);
+    pageStack_->addWidget(register_page_);
+    pageStack_->addWidget(chat_page_);
+    pageStack_->addWidget(userSettingsPage_);
+
+    setCentralWidget(pageStack_);
+
+    connect(welcome_page_, SIGNAL(userLogin()), this, SLOT(showLoginPage()));
+    connect(welcome_page_, SIGNAL(userRegister()), this, SLOT(showRegisterPage()));
+
+    connect(login_page_, SIGNAL(backButtonClicked()), this, SLOT(showWelcomePage()));
+    connect(login_page_, &LoginPage::loggingIn, this, &MainWindow::showOverlayProgressBar);
+    connect(register_page_, &RegisterPage::registering, this, &MainWindow::showOverlayProgressBar);
+    connect(login_page_, &LoginPage::errorOccurred, this, [this]() { removeOverlayProgressBar(); });
+    connect(
+      register_page_, &RegisterPage::errorOccurred, this, [this]() { removeOverlayProgressBar(); });
+    connect(register_page_, SIGNAL(backButtonClicked()), this, SLOT(showWelcomePage()));
+
+    connect(chat_page_, &ChatPage::closing, this, &MainWindow::showWelcomePage);
+    connect(
+      chat_page_, &ChatPage::showOverlayProgressBar, this, &MainWindow::showOverlayProgressBar);
+    connect(chat_page_, &ChatPage::unreadMessages, this, &MainWindow::setWindowTitle);
+    connect(chat_page_, SIGNAL(unreadMessages(int)), trayIcon_, SLOT(setUnreadCount(int)));
+    connect(chat_page_, &ChatPage::showLoginPage, this, [this](const QString &msg) {
+        login_page_->showError(msg);
+        showLoginPage();
+    });
+
+    connect(userSettingsPage_, &UserSettingsPage::moveBack, this, [this]() {
+        pageStack_->setCurrentWidget(chat_page_);
+    });
+
+    connect(userSettingsPage_, SIGNAL(trayOptionChanged(bool)), trayIcon_, SLOT(setVisible(bool)));
+    connect(
+      userSettingsPage_, &UserSettingsPage::themeChanged, chat_page_, &ChatPage::themeChanged);
+    connect(trayIcon_,
+            SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
+            this,
+            SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
+
+    connect(chat_page_, SIGNAL(contentLoaded()), this, SLOT(removeOverlayProgressBar()));
+
+    connect(this, &MainWindow::focusChanged, chat_page_, &ChatPage::chatFocusChanged);
+
+    connect(chat_page_, &ChatPage::showUserSettingsPage, this, &MainWindow::showUserSettingsPage);
+
+    connect(login_page_, &LoginPage::loginOk, this, [this](const mtx::responses::Login &res) {
+        http::client()->set_user(res.user_id);
+        showChatPage();
+    });
+
+    connect(register_page_, &RegisterPage::registerOk, this, &MainWindow::showChatPage);
+
+    QShortcut *quitShortcut = new QShortcut(QKeySequence::Quit, this);
+    connect(quitShortcut, &QShortcut::activated, this, QApplication::quit);
+
+    trayIcon_->setVisible(userSettings_->tray());
+
+    // load cache on event loop
+    QTimer::singleShot(0, this, [this] {
+        if (hasActiveUser()) {
+            QString token       = userSettings_->accessToken();
+            QString home_server = userSettings_->homeserver();
+            QString user_id     = userSettings_->userId();
+            QString device_id   = userSettings_->deviceId();
+
+            http::client()->set_access_token(token.toStdString());
+            http::client()->set_server(home_server.toStdString());
+            http::client()->set_device_id(device_id.toStdString());
+
+            try {
+                using namespace mtx::identifiers;
+                http::client()->set_user(parse<User>(user_id.toStdString()));
+            } catch (const std::invalid_argument &) {
+                nhlog::ui()->critical("bootstrapped with invalid user_id: {}",
+                                      user_id.toStdString());
+            }
+
+            showChatPage();
+        }
+    });
 }
 
 void
 MainWindow::setWindowTitle(int notificationCount)
 {
-        QString name = "nheko";
-
-        if (!userSettings_.data()->profile().isEmpty())
-                name += " | " + userSettings_.data()->profile();
-        if (notificationCount > 0) {
-                name.append(QString{" (%1)"}.arg(notificationCount));
-        }
-        QMainWindow::setWindowTitle(name);
+    QString name = "nheko";
+
+    if (!userSettings_.data()->profile().isEmpty())
+        name += " | " + userSettings_.data()->profile();
+    if (notificationCount > 0) {
+        name.append(QString{" (%1)"}.arg(notificationCount));
+    }
+    QMainWindow::setWindowTitle(name);
 }
 
 bool
 MainWindow::event(QEvent *event)
 {
-        auto type = event->type();
-        if (type == QEvent::WindowActivate) {
-                emit focusChanged(true);
-        } else if (type == QEvent::WindowDeactivate) {
-                emit focusChanged(false);
-        }
-
-        return QMainWindow::event(event);
+    auto type = event->type();
+    if (type == QEvent::WindowActivate) {
+        emit focusChanged(true);
+    } else if (type == QEvent::WindowDeactivate) {
+        emit focusChanged(false);
+    }
+
+    return QMainWindow::event(event);
 }
 
 void
 MainWindow::restoreWindowSize()
 {
-        int savedWidth  = userSettings_->qsettings()->value("window/width").toInt();
-        int savedheight = userSettings_->qsettings()->value("window/height").toInt();
+    int savedWidth  = userSettings_->qsettings()->value("window/width").toInt();
+    int savedheight = userSettings_->qsettings()->value("window/height").toInt();
 
-        nhlog::ui()->info("Restoring window size {}x{}", savedWidth, savedheight);
+    nhlog::ui()->info("Restoring window size {}x{}", savedWidth, savedheight);
 
-        if (savedWidth == 0 || savedheight == 0)
-                resize(conf::window::width, conf::window::height);
-        else
-                resize(savedWidth, savedheight);
+    if (savedWidth == 0 || savedheight == 0)
+        resize(conf::window::width, conf::window::height);
+    else
+        resize(savedWidth, savedheight);
 }
 
 void
 MainWindow::saveCurrentWindowSize()
 {
-        auto settings = userSettings_->qsettings();
-        QSize current = size();
+    auto settings = userSettings_->qsettings();
+    QSize current = size();
 
-        settings->setValue("window/width", current.width());
-        settings->setValue("window/height", current.height());
+    settings->setValue("window/width", current.width());
+    settings->setValue("window/height", current.height());
 }
 
 void
 MainWindow::removeOverlayProgressBar()
 {
-        QTimer *timer = new QTimer(this);
-        timer->setSingleShot(true);
+    QTimer *timer = new QTimer(this);
+    timer->setSingleShot(true);
 
-        connect(timer, &QTimer::timeout, [this, timer]() {
-                timer->deleteLater();
+    connect(timer, &QTimer::timeout, [this, timer]() {
+        timer->deleteLater();
 
-                if (modal_)
-                        modal_->hide();
+        if (modal_)
+            modal_->hide();
 
-                if (spinner_)
-                        spinner_->stop();
-        });
+        if (spinner_)
+            spinner_->stop();
+    });
 
-        // FIXME:  Snackbar doesn't work if it's initialized in the constructor.
-        QTimer::singleShot(0, this, [this]() {
-                snackBar_ = new SnackBar(this);
-                connect(chat_page_, &ChatPage::showNotification, snackBar_, &SnackBar::showMessage);
-        });
+    // FIXME:  Snackbar doesn't work if it's initialized in the constructor.
+    QTimer::singleShot(0, this, [this]() {
+        snackBar_ = new SnackBar(this);
+        connect(chat_page_, &ChatPage::showNotification, snackBar_, &SnackBar::showMessage);
+    });
 
-        timer->start(50);
+    timer->start(50);
 }
 
 void
 MainWindow::showChatPage()
 {
-        auto userid     = QString::fromStdString(http::client()->user_id().to_string());
-        auto device_id  = QString::fromStdString(http::client()->device_id());
-        auto homeserver = QString::fromStdString(http::client()->server() + ":" +
-                                                 std::to_string(http::client()->port()));
-        auto token      = QString::fromStdString(http::client()->access_token());
-
-        userSettings_.data()->setUserId(userid);
-        userSettings_.data()->setAccessToken(token);
-        userSettings_.data()->setDeviceId(device_id);
-        userSettings_.data()->setHomeserver(homeserver);
-
-        showOverlayProgressBar();
-
-        pageStack_->setCurrentWidget(chat_page_);
-
-        pageStack_->removeWidget(welcome_page_);
-        pageStack_->removeWidget(login_page_);
-        pageStack_->removeWidget(register_page_);
-
-        login_page_->reset();
-        chat_page_->bootstrap(userid, homeserver, token);
-        connect(cache::client(),
-                &Cache::secretChanged,
-                userSettingsPage_,
-                &UserSettingsPage::updateSecretStatus);
-        emit reload();
+    auto userid     = QString::fromStdString(http::client()->user_id().to_string());
+    auto device_id  = QString::fromStdString(http::client()->device_id());
+    auto homeserver = QString::fromStdString(http::client()->server() + ":" +
+                                             std::to_string(http::client()->port()));
+    auto token      = QString::fromStdString(http::client()->access_token());
+
+    userSettings_.data()->setUserId(userid);
+    userSettings_.data()->setAccessToken(token);
+    userSettings_.data()->setDeviceId(device_id);
+    userSettings_.data()->setHomeserver(homeserver);
+
+    showOverlayProgressBar();
+
+    pageStack_->setCurrentWidget(chat_page_);
+
+    pageStack_->removeWidget(welcome_page_);
+    pageStack_->removeWidget(login_page_);
+    pageStack_->removeWidget(register_page_);
+
+    login_page_->reset();
+    chat_page_->bootstrap(userid, homeserver, token);
+    connect(cache::client(),
+            &Cache::secretChanged,
+            userSettingsPage_,
+            &UserSettingsPage::updateSecretStatus);
+    emit reload();
 }
 
 void
 MainWindow::closeEvent(QCloseEvent *event)
 {
-        if (WebRTCSession::instance().state() != webrtc::State::DISCONNECTED) {
-                if (QMessageBox::question(this, "nheko", "A call is in progress. Quit?") !=
-                    QMessageBox::Yes) {
-                        event->ignore();
-                        return;
-                }
+    if (WebRTCSession::instance().state() != webrtc::State::DISCONNECTED) {
+        if (QMessageBox::question(this, "nheko", "A call is in progress. Quit?") !=
+            QMessageBox::Yes) {
+            event->ignore();
+            return;
         }
+    }
 
-        if (!qApp->isSavingSession() && isVisible() && pageSupportsTray() &&
-            userSettings_->tray()) {
-                event->ignore();
-                hide();
-        }
+    if (!qApp->isSavingSession() && isVisible() && pageSupportsTray() && userSettings_->tray()) {
+        event->ignore();
+        hide();
+    }
 }
 
 void
 MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason)
 {
-        switch (reason) {
-        case QSystemTrayIcon::Trigger:
-                if (!isVisible()) {
-                        show();
-                } else {
-                        hide();
-                }
-                break;
-        default:
-                break;
+    switch (reason) {
+    case QSystemTrayIcon::Trigger:
+        if (!isVisible()) {
+            show();
+        } else {
+            hide();
         }
+        break;
+    default:
+        break;
+    }
 }
 
 bool
 MainWindow::hasActiveUser()
 {
-        auto settings = userSettings_->qsettings();
-        QString prefix;
-        if (userSettings_->profile() != "")
-                prefix = "profile/" + userSettings_->profile() + "/";
-
-        return settings->contains(prefix + "auth/access_token") &&
-               settings->contains(prefix + "auth/home_server") &&
-               settings->contains(prefix + "auth/user_id");
+    auto settings = userSettings_->qsettings();
+    QString prefix;
+    if (userSettings_->profile() != "")
+        prefix = "profile/" + userSettings_->profile() + "/";
+
+    return settings->contains(prefix + "auth/access_token") &&
+           settings->contains(prefix + "auth/home_server") &&
+           settings->contains(prefix + "auth/user_id");
 }
 
 void
 MainWindow::openLeaveRoomDialog(const QString &room_id)
 {
-        auto dialog = new dialogs::LeaveRoom(this);
-        connect(dialog, &dialogs::LeaveRoom::leaving, this, [this, room_id]() {
-                chat_page_->leaveRoom(room_id);
-        });
+    auto dialog = new dialogs::LeaveRoom(this);
+    connect(dialog, &dialogs::LeaveRoom::leaving, this, [this, room_id]() {
+        chat_page_->leaveRoom(room_id);
+    });
 
-        showDialog(dialog);
+    showDialog(dialog);
 }
 
 void
 MainWindow::showOverlayProgressBar()
 {
-        spinner_ = new LoadingIndicator(this);
-        spinner_->setFixedHeight(100);
-        spinner_->setFixedWidth(100);
-        spinner_->setObjectName("ChatPageLoadSpinner");
-        spinner_->start();
+    spinner_ = new LoadingIndicator(this);
+    spinner_->setFixedHeight(100);
+    spinner_->setFixedWidth(100);
+    spinner_->setObjectName("ChatPageLoadSpinner");
+    spinner_->start();
 
-        showSolidOverlayModal(spinner_);
+    showSolidOverlayModal(spinner_);
 }
 
 void
 MainWindow::openJoinRoomDialog(std::function<void(const QString &room_id)> callback)
 {
-        auto dialog = new dialogs::JoinRoom(this);
-        connect(dialog, &dialogs::JoinRoom::joinRoom, this, [callback](const QString &room) {
-                if (!room.isEmpty())
-                        callback(room);
-        });
+    auto dialog = new dialogs::JoinRoom(this);
+    connect(dialog, &dialogs::JoinRoom::joinRoom, this, [callback](const QString &room) {
+        if (!room.isEmpty())
+            callback(room);
+    });
 
-        showDialog(dialog);
+    showDialog(dialog);
 }
 
 void
 MainWindow::openCreateRoomDialog(
   std::function<void(const mtx::requests::CreateRoom &request)> callback)
 {
-        auto dialog = new dialogs::CreateRoom(this);
-        connect(dialog,
-                &dialogs::CreateRoom::createRoom,
-                this,
-                [callback](const mtx::requests::CreateRoom &request) { callback(request); });
+    auto dialog = new dialogs::CreateRoom(this);
+    connect(dialog,
+            &dialogs::CreateRoom::createRoom,
+            this,
+            [callback](const mtx::requests::CreateRoom &request) { callback(request); });
 
-        showDialog(dialog);
+    showDialog(dialog);
 }
 
 void
 MainWindow::showTransparentOverlayModal(QWidget *content, QFlags<Qt::AlignmentFlag> flags)
 {
-        modal_->setWidget(content);
-        modal_->setColor(QColor(30, 30, 30, 150));
-        modal_->setDismissible(true);
-        modal_->setContentAlignment(flags);
-        modal_->raise();
-        modal_->show();
+    modal_->setWidget(content);
+    modal_->setColor(QColor(30, 30, 30, 150));
+    modal_->setDismissible(true);
+    modal_->setContentAlignment(flags);
+    modal_->raise();
+    modal_->show();
 }
 
 void
 MainWindow::showSolidOverlayModal(QWidget *content, QFlags<Qt::AlignmentFlag> flags)
 {
-        modal_->setWidget(content);
-        modal_->setColor(QColor(30, 30, 30));
-        modal_->setDismissible(false);
-        modal_->setContentAlignment(flags);
-        modal_->raise();
-        modal_->show();
+    modal_->setWidget(content);
+    modal_->setColor(QColor(30, 30, 30));
+    modal_->setDismissible(false);
+    modal_->setContentAlignment(flags);
+    modal_->raise();
+    modal_->show();
 }
 
 void
 MainWindow::openLogoutDialog()
 {
-        auto dialog = new dialogs::Logout(this);
-        connect(dialog, &dialogs::Logout::loggingOut, this, [this]() {
-                if (WebRTCSession::instance().state() != webrtc::State::DISCONNECTED) {
-                        if (QMessageBox::question(
-                              this, "nheko", "A call is in progress. Log out?") !=
-                            QMessageBox::Yes) {
-                                return;
-                        }
-                        WebRTCSession::instance().end();
-                }
-                chat_page_->initiateLogout();
-        });
-
-        showDialog(dialog);
+    auto dialog = new dialogs::Logout(this);
+    connect(dialog, &dialogs::Logout::loggingOut, this, [this]() {
+        if (WebRTCSession::instance().state() != webrtc::State::DISCONNECTED) {
+            if (QMessageBox::question(this, "nheko", "A call is in progress. Log out?") !=
+                QMessageBox::Yes) {
+                return;
+            }
+            WebRTCSession::instance().end();
+        }
+        chat_page_->initiateLogout();
+    });
+
+    showDialog(dialog);
 }
 
 bool
 MainWindow::hasActiveDialogs() const
 {
-        return !modal_ && modal_->isVisible();
+    return !modal_ && modal_->isVisible();
 }
 
 bool
 MainWindow::pageSupportsTray() const
 {
-        return !welcome_page_->isVisible() && !login_page_->isVisible() &&
-               !register_page_->isVisible();
+    return !welcome_page_->isVisible() && !login_page_->isVisible() && !register_page_->isVisible();
 }
 
 void
 MainWindow::hideOverlay()
 {
-        if (modal_)
-                modal_->hide();
+    if (modal_)
+        modal_->hide();
 }
 
 inline void
 MainWindow::showDialog(QWidget *dialog)
 {
-        utils::centerWidget(dialog, this);
-        dialog->raise();
-        dialog->show();
+    utils::centerWidget(dialog, this);
+    dialog->raise();
+    dialog->show();
 }
 
 void
 MainWindow::showWelcomePage()
 {
-        removeOverlayProgressBar();
-        pageStack_->addWidget(welcome_page_);
-        pageStack_->setCurrentWidget(welcome_page_);
+    removeOverlayProgressBar();
+    pageStack_->addWidget(welcome_page_);
+    pageStack_->setCurrentWidget(welcome_page_);
 }
 
 void
 MainWindow::showLoginPage()
 {
-        if (modal_)
-                modal_->hide();
+    if (modal_)
+        modal_->hide();
 
-        pageStack_->addWidget(login_page_);
-        pageStack_->setCurrentWidget(login_page_);
+    pageStack_->addWidget(login_page_);
+    pageStack_->setCurrentWidget(login_page_);
 }
 
 void
 MainWindow::showRegisterPage()
 {
-        pageStack_->addWidget(register_page_);
-        pageStack_->setCurrentWidget(register_page_);
+    pageStack_->addWidget(register_page_);
+    pageStack_->setCurrentWidget(register_page_);
 }
 
 void
 MainWindow::showUserSettingsPage()
 {
-        pageStack_->setCurrentWidget(userSettingsPage_);
+    pageStack_->setCurrentWidget(userSettingsPage_);
 }
diff --git a/src/MainWindow.h b/src/MainWindow.h
index d9ffb9b1..eff8fbe7 100644
--- a/src/MainWindow.h
+++ b/src/MainWindow.h
@@ -46,93 +46,92 @@ class ReCaptcha;
 
 class MainWindow : public QMainWindow
 {
-        Q_OBJECT
+    Q_OBJECT
 
-        Q_PROPERTY(int x READ x CONSTANT)
-        Q_PROPERTY(int y READ y CONSTANT)
-        Q_PROPERTY(int width READ width CONSTANT)
-        Q_PROPERTY(int height READ height CONSTANT)
+    Q_PROPERTY(int x READ x CONSTANT)
+    Q_PROPERTY(int y READ y CONSTANT)
+    Q_PROPERTY(int width READ width CONSTANT)
+    Q_PROPERTY(int height READ height CONSTANT)
 
 public:
-        explicit MainWindow(QWidget *parent = nullptr);
+    explicit MainWindow(QWidget *parent = nullptr);
 
-        static MainWindow *instance() { return instance_; }
-        void saveCurrentWindowSize();
+    static MainWindow *instance() { return instance_; }
+    void saveCurrentWindowSize();
 
-        void openLeaveRoomDialog(const QString &room_id);
-        void openInviteUsersDialog(std::function<void(const QStringList &invitees)> callback);
-        void openCreateRoomDialog(
-          std::function<void(const mtx::requests::CreateRoom &request)> callback);
-        void openJoinRoomDialog(std::function<void(const QString &room_id)> callback);
-        void openLogoutDialog();
+    void openLeaveRoomDialog(const QString &room_id);
+    void openInviteUsersDialog(std::function<void(const QStringList &invitees)> callback);
+    void openCreateRoomDialog(
+      std::function<void(const mtx::requests::CreateRoom &request)> callback);
+    void openJoinRoomDialog(std::function<void(const QString &room_id)> callback);
+    void openLogoutDialog();
 
-        void hideOverlay();
-        void showSolidOverlayModal(QWidget *content,
-                                   QFlags<Qt::AlignmentFlag> flags = Qt::AlignCenter);
-        void showTransparentOverlayModal(QWidget *content,
-                                         QFlags<Qt::AlignmentFlag> flags = Qt::AlignTop |
-                                                                           Qt::AlignHCenter);
+    void hideOverlay();
+    void showSolidOverlayModal(QWidget *content, QFlags<Qt::AlignmentFlag> flags = Qt::AlignCenter);
+    void showTransparentOverlayModal(QWidget *content,
+                                     QFlags<Qt::AlignmentFlag> flags = Qt::AlignTop |
+                                                                       Qt::AlignHCenter);
 
 protected:
-        void closeEvent(QCloseEvent *event) override;
-        bool event(QEvent *event) override;
+    void closeEvent(QCloseEvent *event) override;
+    bool event(QEvent *event) override;
 
 private slots:
-        //! Handle interaction with the tray icon.
-        void iconActivated(QSystemTrayIcon::ActivationReason reason);
+    //! Handle interaction with the tray icon.
+    void iconActivated(QSystemTrayIcon::ActivationReason reason);
 
-        //! Show the welcome page in the main window.
-        void showWelcomePage();
+    //! Show the welcome page in the main window.
+    void showWelcomePage();
 
-        //! Show the login page in the main window.
-        void showLoginPage();
+    //! Show the login page in the main window.
+    void showLoginPage();
 
-        //! Show the register page in the main window.
-        void showRegisterPage();
+    //! Show the register page in the main window.
+    void showRegisterPage();
 
-        //! Show user settings page.
-        void showUserSettingsPage();
+    //! Show user settings page.
+    void showUserSettingsPage();
 
-        //! Show the chat page and start communicating with the given access token.
-        void showChatPage();
+    //! Show the chat page and start communicating with the given access token.
+    void showChatPage();
 
-        void showOverlayProgressBar();
-        void removeOverlayProgressBar();
+    void showOverlayProgressBar();
+    void removeOverlayProgressBar();
 
-        virtual void setWindowTitle(int notificationCount);
+    virtual void setWindowTitle(int notificationCount);
 
 signals:
-        void focusChanged(const bool focused);
-        void reload();
+    void focusChanged(const bool focused);
+    void reload();
 
 private:
-        void showDialog(QWidget *dialog);
-        bool hasActiveUser();
-        void restoreWindowSize();
-        //! Check if there is an open dialog.
-        bool hasActiveDialogs() const;
-        //! Check if the current page supports the "minimize to tray" functionality.
-        bool pageSupportsTray() const;
-
-        static MainWindow *instance_;
-
-        //! The initial welcome screen.
-        WelcomePage *welcome_page_;
-        //! The login screen.
-        LoginPage *login_page_;
-        //! The register page.
-        RegisterPage *register_page_;
-        //! A stacked widget that handles the transitions between widgets.
-        QStackedWidget *pageStack_;
-        //! The main chat area.
-        ChatPage *chat_page_;
-        UserSettingsPage *userSettingsPage_;
-        QSharedPointer<UserSettings> userSettings_;
-        //! Tray icon that shows the unread message count.
-        TrayIcon *trayIcon_;
-        //! Notifications display.
-        SnackBar *snackBar_ = nullptr;
-        //! Overlay modal used to project other widgets.
-        OverlayModal *modal_       = nullptr;
-        LoadingIndicator *spinner_ = nullptr;
+    void showDialog(QWidget *dialog);
+    bool hasActiveUser();
+    void restoreWindowSize();
+    //! Check if there is an open dialog.
+    bool hasActiveDialogs() const;
+    //! Check if the current page supports the "minimize to tray" functionality.
+    bool pageSupportsTray() const;
+
+    static MainWindow *instance_;
+
+    //! The initial welcome screen.
+    WelcomePage *welcome_page_;
+    //! The login screen.
+    LoginPage *login_page_;
+    //! The register page.
+    RegisterPage *register_page_;
+    //! A stacked widget that handles the transitions between widgets.
+    QStackedWidget *pageStack_;
+    //! The main chat area.
+    ChatPage *chat_page_;
+    UserSettingsPage *userSettingsPage_;
+    QSharedPointer<UserSettings> userSettings_;
+    //! Tray icon that shows the unread message count.
+    TrayIcon *trayIcon_;
+    //! Notifications display.
+    SnackBar *snackBar_ = nullptr;
+    //! Overlay modal used to project other widgets.
+    OverlayModal *modal_       = nullptr;
+    LoadingIndicator *spinner_ = nullptr;
 };
diff --git a/src/MatrixClient.cpp b/src/MatrixClient.cpp
index 196a9322..2ceb53a8 100644
--- a/src/MatrixClient.cpp
+++ b/src/MatrixClient.cpp
@@ -37,31 +37,31 @@ namespace http {
 mtx::http::Client *
 client()
 {
-        return client_.get();
+    return client_.get();
 }
 
 bool
 is_logged_in()
 {
-        return !client_->access_token().empty();
+    return !client_->access_token().empty();
 }
 
 void
 init()
 {
-        qRegisterMetaType<mtx::responses::Login>();
-        qRegisterMetaType<mtx::responses::Messages>();
-        qRegisterMetaType<mtx::responses::Notifications>();
-        qRegisterMetaType<mtx::responses::Rooms>();
-        qRegisterMetaType<mtx::responses::Sync>();
-        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>");
-        qRegisterMetaType<std::set<QString>>();
+    qRegisterMetaType<mtx::responses::Login>();
+    qRegisterMetaType<mtx::responses::Messages>();
+    qRegisterMetaType<mtx::responses::Notifications>();
+    qRegisterMetaType<mtx::responses::Rooms>();
+    qRegisterMetaType<mtx::responses::Sync>();
+    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>");
+    qRegisterMetaType<std::set<QString>>();
 }
 
 } // namespace http
diff --git a/src/MemberList.cpp b/src/MemberList.cpp
index 0c0f0cdd..34730e9a 100644
--- a/src/MemberList.cpp
+++ b/src/MemberList.cpp
@@ -15,98 +15,96 @@ MemberList::MemberList(const QString &room_id, QObject *parent)
   : QAbstractListModel{parent}
   , room_id_{room_id}
 {
-        try {
-                info_ = cache::singleRoomInfo(room_id_.toStdString());
-        } catch (const lmdb::error &) {
-                nhlog::db()->warn("failed to retrieve room info from cache: {}",
-                                  room_id_.toStdString());
-        }
+    try {
+        info_ = cache::singleRoomInfo(room_id_.toStdString());
+    } catch (const lmdb::error &) {
+        nhlog::db()->warn("failed to retrieve room info from cache: {}", room_id_.toStdString());
+    }
 
-        try {
-                auto members = cache::getMembers(room_id_.toStdString());
-                addUsers(members);
-                numUsersLoaded_ = members.size();
-        } catch (const lmdb::error &e) {
-                nhlog::db()->critical("Failed to retrieve members from cache: {}", e.what());
-        }
+    try {
+        auto members = cache::getMembers(room_id_.toStdString());
+        addUsers(members);
+        numUsersLoaded_ = members.size();
+    } catch (const lmdb::error &e) {
+        nhlog::db()->critical("Failed to retrieve members from cache: {}", e.what());
+    }
 }
 
 void
 MemberList::addUsers(const std::vector<RoomMember> &members)
 {
-        beginInsertRows(
-          QModelIndex{}, m_memberList.count(), m_memberList.count() + members.size() - 1);
+    beginInsertRows(QModelIndex{}, m_memberList.count(), m_memberList.count() + members.size() - 1);
 
-        for (const auto &member : members)
-                m_memberList.push_back(
-                  {member,
-                   ChatPage::instance()->timelineManager()->rooms()->currentRoom()->avatarUrl(
-                     member.user_id)});
+    for (const auto &member : members)
+        m_memberList.push_back(
+          {member,
+           ChatPage::instance()->timelineManager()->rooms()->currentRoom()->avatarUrl(
+             member.user_id)});
 
-        endInsertRows();
+    endInsertRows();
 }
 
 QHash<int, QByteArray>
 MemberList::roleNames() const
 {
-        return {
-          {Mxid, "mxid"},
-          {DisplayName, "displayName"},
-          {AvatarUrl, "avatarUrl"},
-          {Trustlevel, "trustlevel"},
-        };
+    return {
+      {Mxid, "mxid"},
+      {DisplayName, "displayName"},
+      {AvatarUrl, "avatarUrl"},
+      {Trustlevel, "trustlevel"},
+    };
 }
 
 QVariant
 MemberList::data(const QModelIndex &index, int role) const
 {
-        if (!index.isValid() || index.row() >= (int)m_memberList.size() || index.row() < 0)
-                return {};
+    if (!index.isValid() || index.row() >= (int)m_memberList.size() || index.row() < 0)
+        return {};
 
-        switch (role) {
-        case Mxid:
-                return m_memberList[index.row()].first.user_id;
-        case DisplayName:
-                return m_memberList[index.row()].first.display_name;
-        case AvatarUrl:
-                return m_memberList[index.row()].second;
-        case Trustlevel: {
-                auto stat =
-                  cache::verificationStatus(m_memberList[index.row()].first.user_id.toStdString());
+    switch (role) {
+    case Mxid:
+        return m_memberList[index.row()].first.user_id;
+    case DisplayName:
+        return m_memberList[index.row()].first.display_name;
+    case AvatarUrl:
+        return m_memberList[index.row()].second;
+    case Trustlevel: {
+        auto stat =
+          cache::verificationStatus(m_memberList[index.row()].first.user_id.toStdString());
 
-                if (!stat)
-                        return crypto::Unverified;
-                if (stat->unverified_device_count)
-                        return crypto::Unverified;
-                else
-                        return stat->user_verified;
-        }
-        default:
-                return {};
-        }
+        if (!stat)
+            return crypto::Unverified;
+        if (stat->unverified_device_count)
+            return crypto::Unverified;
+        else
+            return stat->user_verified;
+    }
+    default:
+        return {};
+    }
 }
 
 bool
 MemberList::canFetchMore(const QModelIndex &) const
 {
-        const size_t numMembers = rowCount();
-        if (numMembers > 1 && numMembers < info_.member_count)
-                return true;
-        else
-                return false;
+    const size_t numMembers = rowCount();
+    if (numMembers > 1 && numMembers < info_.member_count)
+        return true;
+    else
+        return false;
 }
 
 void
 MemberList::fetchMore(const QModelIndex &)
 {
-        loadingMoreMembers_ = true;
-        emit loadingMoreMembersChanged();
+    loadingMoreMembers_ = true;
+    emit loadingMoreMembersChanged();
 
-        auto members = cache::getMembers(room_id_.toStdString(), rowCount());
-        addUsers(members);
-        numUsersLoaded_ += members.size();
-        emit numUsersLoadedChanged();
+    auto members = cache::getMembers(room_id_.toStdString(), rowCount());
+    addUsers(members);
+    numUsersLoaded_ += members.size();
+    emit numUsersLoadedChanged();
 
-        loadingMoreMembers_ = false;
-        emit loadingMoreMembersChanged();
+    loadingMoreMembers_ = false;
+    emit loadingMoreMembersChanged();
 }
diff --git a/src/MemberList.h b/src/MemberList.h
index cffcd83d..b16ac983 100644
--- a/src/MemberList.h
+++ b/src/MemberList.h
@@ -10,59 +10,59 @@
 
 class MemberList : public QAbstractListModel
 {
-        Q_OBJECT
+    Q_OBJECT
 
-        Q_PROPERTY(QString roomName READ roomName NOTIFY roomNameChanged)
-        Q_PROPERTY(int memberCount READ memberCount NOTIFY memberCountChanged)
-        Q_PROPERTY(QString avatarUrl READ avatarUrl NOTIFY avatarUrlChanged)
-        Q_PROPERTY(QString roomId READ roomId NOTIFY roomIdChanged)
-        Q_PROPERTY(int numUsersLoaded READ numUsersLoaded NOTIFY numUsersLoadedChanged)
-        Q_PROPERTY(bool loadingMoreMembers READ loadingMoreMembers NOTIFY loadingMoreMembersChanged)
+    Q_PROPERTY(QString roomName READ roomName NOTIFY roomNameChanged)
+    Q_PROPERTY(int memberCount READ memberCount NOTIFY memberCountChanged)
+    Q_PROPERTY(QString avatarUrl READ avatarUrl NOTIFY avatarUrlChanged)
+    Q_PROPERTY(QString roomId READ roomId NOTIFY roomIdChanged)
+    Q_PROPERTY(int numUsersLoaded READ numUsersLoaded NOTIFY numUsersLoadedChanged)
+    Q_PROPERTY(bool loadingMoreMembers READ loadingMoreMembers NOTIFY loadingMoreMembersChanged)
 
 public:
-        enum Roles
-        {
-                Mxid,
-                DisplayName,
-                AvatarUrl,
-                Trustlevel,
-        };
-        MemberList(const QString &room_id, QObject *parent = nullptr);
+    enum Roles
+    {
+        Mxid,
+        DisplayName,
+        AvatarUrl,
+        Trustlevel,
+    };
+    MemberList(const QString &room_id, QObject *parent = nullptr);
 
-        QHash<int, QByteArray> roleNames() const override;
-        int rowCount(const QModelIndex &parent = QModelIndex()) const override
-        {
-                Q_UNUSED(parent)
-                return static_cast<int>(m_memberList.size());
-        }
-        QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+    QHash<int, QByteArray> roleNames() const override;
+    int rowCount(const QModelIndex &parent = QModelIndex()) const override
+    {
+        Q_UNUSED(parent)
+        return static_cast<int>(m_memberList.size());
+    }
+    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
 
-        QString roomName() const { return QString::fromStdString(info_.name); }
-        int memberCount() const { return info_.member_count; }
-        QString avatarUrl() const { return QString::fromStdString(info_.avatar_url); }
-        QString roomId() const { return room_id_; }
-        int numUsersLoaded() const { return numUsersLoaded_; }
-        bool loadingMoreMembers() const { return loadingMoreMembers_; }
+    QString roomName() const { return QString::fromStdString(info_.name); }
+    int memberCount() const { return info_.member_count; }
+    QString avatarUrl() const { return QString::fromStdString(info_.avatar_url); }
+    QString roomId() const { return room_id_; }
+    int numUsersLoaded() const { return numUsersLoaded_; }
+    bool loadingMoreMembers() const { return loadingMoreMembers_; }
 
 signals:
-        void roomNameChanged();
-        void memberCountChanged();
-        void avatarUrlChanged();
-        void roomIdChanged();
-        void numUsersLoadedChanged();
-        void loadingMoreMembersChanged();
+    void roomNameChanged();
+    void memberCountChanged();
+    void avatarUrlChanged();
+    void roomIdChanged();
+    void numUsersLoadedChanged();
+    void loadingMoreMembersChanged();
 
 public slots:
-        void addUsers(const std::vector<RoomMember> &users);
+    void addUsers(const std::vector<RoomMember> &users);
 
 protected:
-        bool canFetchMore(const QModelIndex &) const override;
-        void fetchMore(const QModelIndex &) override;
+    bool canFetchMore(const QModelIndex &) const override;
+    void fetchMore(const QModelIndex &) override;
 
 private:
-        QVector<QPair<RoomMember, QString>> m_memberList;
-        QString room_id_;
-        RoomInfo info_;
-        int numUsersLoaded_{0};
-        bool loadingMoreMembers_{false};
+    QVector<QPair<RoomMember, QString>> m_memberList;
+    QString room_id_;
+    RoomInfo info_;
+    int numUsersLoaded_{0};
+    bool loadingMoreMembers_{false};
 };
diff --git a/src/MxcImageProvider.cpp b/src/MxcImageProvider.cpp
index 056374a9..5d0ee0be 100644
--- a/src/MxcImageProvider.cpp
+++ b/src/MxcImageProvider.cpp
@@ -24,70 +24,70 @@ QHash<QString, mtx::crypto::EncryptedFile> infos;
 QQuickImageResponse *
 MxcImageProvider::requestImageResponse(const QString &id, const QSize &requestedSize)
 {
-        auto id_      = id;
-        bool crop     = true;
-        double radius = 0;
-
-        auto queryStart = id.lastIndexOf('?');
-        if (queryStart != -1) {
-                id_            = id.left(queryStart);
-                auto query     = id.midRef(queryStart + 1);
-                auto queryBits = query.split('&');
-
-                for (auto b : queryBits) {
-                        if (b == "scale") {
-                                crop = false;
-                        } else if (b.startsWith("radius=")) {
-                                radius = b.mid(7).toDouble();
-                        }
-                }
+    auto id_      = id;
+    bool crop     = true;
+    double radius = 0;
+
+    auto queryStart = id.lastIndexOf('?');
+    if (queryStart != -1) {
+        id_            = id.left(queryStart);
+        auto query     = id.midRef(queryStart + 1);
+        auto queryBits = query.split('&');
+
+        for (auto b : queryBits) {
+            if (b == "scale") {
+                crop = false;
+            } else if (b.startsWith("radius=")) {
+                radius = b.mid(7).toDouble();
+            }
         }
+    }
 
-        MxcImageResponse *response = new MxcImageResponse(id_, crop, radius, requestedSize);
-        pool.start(response);
-        return response;
+    MxcImageResponse *response = new MxcImageResponse(id_, crop, radius, requestedSize);
+    pool.start(response);
+    return response;
 }
 
 void
 MxcImageProvider::addEncryptionInfo(mtx::crypto::EncryptedFile info)
 {
-        infos.insert(QString::fromStdString(info.url), info);
+    infos.insert(QString::fromStdString(info.url), info);
 }
 void
 MxcImageResponse::run()
 {
-        MxcImageProvider::download(
-          m_id,
-          m_requestedSize,
-          [this](QString, QSize, QImage image, QString) {
-                  if (image.isNull()) {
-                          m_error = "Failed to download image.";
-                  } else {
-                          m_image = image;
-                  }
-                  emit finished();
-          },
-          m_crop,
-          m_radius);
+    MxcImageProvider::download(
+      m_id,
+      m_requestedSize,
+      [this](QString, QSize, QImage image, QString) {
+          if (image.isNull()) {
+              m_error = "Failed to download image.";
+          } else {
+              m_image = image;
+          }
+          emit finished();
+      },
+      m_crop,
+      m_radius);
 }
 
 static QImage
 clipRadius(QImage img, double radius)
 {
-        QImage out(img.size(), QImage::Format_ARGB32_Premultiplied);
-        out.fill(Qt::transparent);
+    QImage out(img.size(), QImage::Format_ARGB32_Premultiplied);
+    out.fill(Qt::transparent);
 
-        QPainter painter(&out);
-        painter.setRenderHint(QPainter::Antialiasing, true);
-        painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
+    QPainter painter(&out);
+    painter.setRenderHint(QPainter::Antialiasing, true);
+    painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
 
-        QPainterPath ppath;
-        ppath.addRoundedRect(img.rect(), radius, radius, Qt::SizeMode::RelativeSize);
+    QPainterPath ppath;
+    ppath.addRoundedRect(img.rect(), radius, radius, Qt::SizeMode::RelativeSize);
 
-        painter.setClipPath(ppath);
-        painter.drawImage(img.rect(), img);
+    painter.setClipPath(ppath);
+    painter.drawImage(img.rect(), img);
 
-        return out;
+    return out;
 }
 
 void
@@ -97,187 +97,165 @@ MxcImageProvider::download(const QString &id,
                            bool crop,
                            double radius)
 {
-        std::optional<mtx::crypto::EncryptedFile> encryptionInfo;
-        auto temp = infos.find("mxc://" + id);
-        if (temp != infos.end())
-                encryptionInfo = *temp;
-
-        if (requestedSize.isValid() && !encryptionInfo) {
-                QString fileName =
-                  QString("%1_%2x%3_%4_radius%5")
-                    .arg(QString::fromUtf8(id.toUtf8().toBase64(QByteArray::Base64UrlEncoding |
-                                                                QByteArray::OmitTrailingEquals)))
-                    .arg(requestedSize.width())
-                    .arg(requestedSize.height())
-                    .arg(crop ? "crop" : "scale")
-                    .arg(radius);
-                QFileInfo fileInfo(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) +
-                                     "/media_cache",
-                                   fileName);
-                QDir().mkpath(fileInfo.absolutePath());
-
-                if (fileInfo.exists()) {
-                        QImage image = utils::readImageFromFile(fileInfo.absoluteFilePath());
-                        if (!image.isNull()) {
-                                image = image.scaled(
-                                  requestedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
-
-                                if (radius != 0) {
-                                        image = clipRadius(std::move(image), radius);
-                                }
-
-                                if (!image.isNull()) {
-                                        then(id, requestedSize, image, fileInfo.absoluteFilePath());
-                                        return;
-                                }
-                        }
+    std::optional<mtx::crypto::EncryptedFile> encryptionInfo;
+    auto temp = infos.find("mxc://" + id);
+    if (temp != infos.end())
+        encryptionInfo = *temp;
+
+    if (requestedSize.isValid() && !encryptionInfo) {
+        QString fileName = QString("%1_%2x%3_%4_radius%5")
+                             .arg(QString::fromUtf8(id.toUtf8().toBase64(
+                               QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals)))
+                             .arg(requestedSize.width())
+                             .arg(requestedSize.height())
+                             .arg(crop ? "crop" : "scale")
+                             .arg(radius);
+        QFileInfo fileInfo(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) +
+                             "/media_cache",
+                           fileName);
+        QDir().mkpath(fileInfo.absolutePath());
+
+        if (fileInfo.exists()) {
+            QImage image = utils::readImageFromFile(fileInfo.absoluteFilePath());
+            if (!image.isNull()) {
+                image = image.scaled(requestedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
+
+                if (radius != 0) {
+                    image = clipRadius(std::move(image), radius);
                 }
 
-                mtx::http::ThumbOpts opts;
-                opts.mxc_url = "mxc://" + id.toStdString();
-                opts.width   = requestedSize.width() > 0 ? requestedSize.width() : -1;
-                opts.height  = requestedSize.height() > 0 ? requestedSize.height() : -1;
-                opts.method  = crop ? "crop" : "scale";
-                http::client()->get_thumbnail(
-                  opts,
-                  [fileInfo, requestedSize, radius, then, id](const std::string &res,
-                                                              mtx::http::RequestErr err) {
-                          if (err || res.empty()) {
-                                  then(id, QSize(), {}, "");
-
-                                  return;
-                          }
-
-                          auto data    = QByteArray(res.data(), (int)res.size());
-                          QImage image = utils::readImage(data);
-                          if (!image.isNull()) {
-                                  image = image.scaled(
-                                    requestedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
-
-                                  if (radius != 0) {
-                                          image = clipRadius(std::move(image), radius);
-                                  }
-                          }
-                          image.setText("mxc url", "mxc://" + id);
-                          if (image.save(fileInfo.absoluteFilePath(), "png"))
-                                  nhlog::ui()->debug("Wrote: {}",
-                                                     fileInfo.absoluteFilePath().toStdString());
-                          else
-                                  nhlog::ui()->debug("Failed to write: {}",
-                                                     fileInfo.absoluteFilePath().toStdString());
-
-                          then(id, requestedSize, image, fileInfo.absoluteFilePath());
-                  });
-        } else {
-                try {
-                        QString fileName =
-                          QString("%1_radius%2")
-                            .arg(QString::fromUtf8(id.toUtf8().toBase64(
-                              QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals)))
-                            .arg(radius);
-
-                        QFileInfo fileInfo(
-                          QStandardPaths::writableLocation(QStandardPaths::CacheLocation) +
-                            "/media_cache",
-                          fileName);
-                        QDir().mkpath(fileInfo.absolutePath());
-
-                        if (fileInfo.exists()) {
-                                if (encryptionInfo) {
-                                        QFile f(fileInfo.absoluteFilePath());
-                                        f.open(QIODevice::ReadOnly);
-
-                                        QByteArray fileData = f.readAll();
-                                        auto tempData =
-                                          mtx::crypto::to_string(mtx::crypto::decrypt_file(
-                                            fileData.toStdString(), encryptionInfo.value()));
-                                        auto data =
-                                          QByteArray(tempData.data(), (int)tempData.size());
-                                        QImage image = utils::readImage(data);
-                                        image.setText("mxc url", "mxc://" + id);
-                                        if (!image.isNull()) {
-                                                if (radius != 0) {
-                                                        image =
-                                                          clipRadius(std::move(image), radius);
-                                                }
-
-                                                then(id,
-                                                     requestedSize,
-                                                     image,
-                                                     fileInfo.absoluteFilePath());
-                                                return;
-                                        }
-                                } else {
-                                        QImage image =
-                                          utils::readImageFromFile(fileInfo.absoluteFilePath());
-                                        if (!image.isNull()) {
-                                                if (radius != 0) {
-                                                        image =
-                                                          clipRadius(std::move(image), radius);
-                                                }
-
-                                                then(id,
-                                                     requestedSize,
-                                                     image,
-                                                     fileInfo.absoluteFilePath());
-                                                return;
-                                        }
-                                }
+                if (!image.isNull()) {
+                    then(id, requestedSize, image, fileInfo.absoluteFilePath());
+                    return;
+                }
+            }
+        }
+
+        mtx::http::ThumbOpts opts;
+        opts.mxc_url = "mxc://" + id.toStdString();
+        opts.width   = requestedSize.width() > 0 ? requestedSize.width() : -1;
+        opts.height  = requestedSize.height() > 0 ? requestedSize.height() : -1;
+        opts.method  = crop ? "crop" : "scale";
+        http::client()->get_thumbnail(
+          opts,
+          [fileInfo, requestedSize, radius, then, id](const std::string &res,
+                                                      mtx::http::RequestErr err) {
+              if (err || res.empty()) {
+                  then(id, QSize(), {}, "");
+
+                  return;
+              }
+
+              auto data    = QByteArray(res.data(), (int)res.size());
+              QImage image = utils::readImage(data);
+              if (!image.isNull()) {
+                  image =
+                    image.scaled(requestedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
+
+                  if (radius != 0) {
+                      image = clipRadius(std::move(image), radius);
+                  }
+              }
+              image.setText("mxc url", "mxc://" + id);
+              if (image.save(fileInfo.absoluteFilePath(), "png"))
+                  nhlog::ui()->debug("Wrote: {}", fileInfo.absoluteFilePath().toStdString());
+              else
+                  nhlog::ui()->debug("Failed to write: {}",
+                                     fileInfo.absoluteFilePath().toStdString());
+
+              then(id, requestedSize, image, fileInfo.absoluteFilePath());
+          });
+    } else {
+        try {
+            QString fileName = QString("%1_radius%2")
+                                 .arg(QString::fromUtf8(id.toUtf8().toBase64(
+                                   QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals)))
+                                 .arg(radius);
+
+            QFileInfo fileInfo(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) +
+                                 "/media_cache",
+                               fileName);
+            QDir().mkpath(fileInfo.absolutePath());
+
+            if (fileInfo.exists()) {
+                if (encryptionInfo) {
+                    QFile f(fileInfo.absoluteFilePath());
+                    f.open(QIODevice::ReadOnly);
+
+                    QByteArray fileData = f.readAll();
+                    auto tempData       = mtx::crypto::to_string(
+                      mtx::crypto::decrypt_file(fileData.toStdString(), encryptionInfo.value()));
+                    auto data    = QByteArray(tempData.data(), (int)tempData.size());
+                    QImage image = utils::readImage(data);
+                    image.setText("mxc url", "mxc://" + id);
+                    if (!image.isNull()) {
+                        if (radius != 0) {
+                            image = clipRadius(std::move(image), radius);
                         }
 
-                        http::client()->download(
-                          "mxc://" + id.toStdString(),
-                          [fileInfo, requestedSize, then, id, radius, encryptionInfo](
-                            const std::string &res,
-                            const std::string &,
-                            const std::string &originalFilename,
-                            mtx::http::RequestErr err) {
-                                  if (err) {
-                                          then(id, QSize(), {}, "");
-                                          return;
-                                  }
-
-                                  auto tempData = res;
-                                  QFile f(fileInfo.absoluteFilePath());
-                                  if (!f.open(QIODevice::Truncate | QIODevice::WriteOnly)) {
-                                          then(id, QSize(), {}, "");
-                                          return;
-                                  }
-                                  f.write(tempData.data(), tempData.size());
-                                  f.close();
-
-                                  if (encryptionInfo) {
-                                          tempData =
-                                            mtx::crypto::to_string(mtx::crypto::decrypt_file(
-                                              tempData, encryptionInfo.value()));
-                                          auto data =
-                                            QByteArray(tempData.data(), (int)tempData.size());
-                                          QImage image = utils::readImage(data);
-                                          if (radius != 0) {
-                                                  image = clipRadius(std::move(image), radius);
-                                          }
-
-                                          image.setText("original filename",
-                                                        QString::fromStdString(originalFilename));
-                                          image.setText("mxc url", "mxc://" + id);
-                                          then(
-                                            id, requestedSize, image, fileInfo.absoluteFilePath());
-                                          return;
-                                  }
-
-                                  QImage image =
-                                    utils::readImageFromFile(fileInfo.absoluteFilePath());
-                                  if (radius != 0) {
-                                          image = clipRadius(std::move(image), radius);
-                                  }
-
-                                  image.setText("original filename",
-                                                QString::fromStdString(originalFilename));
-                                  image.setText("mxc url", "mxc://" + id);
-                                  then(id, requestedSize, image, fileInfo.absoluteFilePath());
-                          });
-                } catch (std::exception &e) {
-                        nhlog::net()->error("Exception while downloading media: {}", e.what());
+                        then(id, requestedSize, image, fileInfo.absoluteFilePath());
+                        return;
+                    }
+                } else {
+                    QImage image = utils::readImageFromFile(fileInfo.absoluteFilePath());
+                    if (!image.isNull()) {
+                        if (radius != 0) {
+                            image = clipRadius(std::move(image), radius);
+                        }
+
+                        then(id, requestedSize, image, fileInfo.absoluteFilePath());
+                        return;
+                    }
                 }
+            }
+
+            http::client()->download(
+              "mxc://" + id.toStdString(),
+              [fileInfo, requestedSize, then, id, radius, encryptionInfo](
+                const std::string &res,
+                const std::string &,
+                const std::string &originalFilename,
+                mtx::http::RequestErr err) {
+                  if (err) {
+                      then(id, QSize(), {}, "");
+                      return;
+                  }
+
+                  auto tempData = res;
+                  QFile f(fileInfo.absoluteFilePath());
+                  if (!f.open(QIODevice::Truncate | QIODevice::WriteOnly)) {
+                      then(id, QSize(), {}, "");
+                      return;
+                  }
+                  f.write(tempData.data(), tempData.size());
+                  f.close();
+
+                  if (encryptionInfo) {
+                      tempData = mtx::crypto::to_string(
+                        mtx::crypto::decrypt_file(tempData, encryptionInfo.value()));
+                      auto data    = QByteArray(tempData.data(), (int)tempData.size());
+                      QImage image = utils::readImage(data);
+                      if (radius != 0) {
+                          image = clipRadius(std::move(image), radius);
+                      }
+
+                      image.setText("original filename", QString::fromStdString(originalFilename));
+                      image.setText("mxc url", "mxc://" + id);
+                      then(id, requestedSize, image, fileInfo.absoluteFilePath());
+                      return;
+                  }
+
+                  QImage image = utils::readImageFromFile(fileInfo.absoluteFilePath());
+                  if (radius != 0) {
+                      image = clipRadius(std::move(image), radius);
+                  }
+
+                  image.setText("original filename", QString::fromStdString(originalFilename));
+                  image.setText("mxc url", "mxc://" + id);
+                  then(id, requestedSize, image, fileInfo.absoluteFilePath());
+              });
+        } catch (std::exception &e) {
+            nhlog::net()->error("Exception while downloading media: {}", e.what());
         }
+    }
 }
diff --git a/src/MxcImageProvider.h b/src/MxcImageProvider.h
index 6de83c0e..3cf5bbf4 100644
--- a/src/MxcImageProvider.h
+++ b/src/MxcImageProvider.h
@@ -19,46 +19,46 @@ class MxcImageResponse
   , public QRunnable
 {
 public:
-        MxcImageResponse(const QString &id, bool crop, double radius, const QSize &requestedSize)
-          : m_id(id)
-          , m_requestedSize(requestedSize)
-          , m_crop(crop)
-          , m_radius(radius)
-        {
-                setAutoDelete(false);
-        }
+    MxcImageResponse(const QString &id, bool crop, double radius, const QSize &requestedSize)
+      : m_id(id)
+      , m_requestedSize(requestedSize)
+      , m_crop(crop)
+      , m_radius(radius)
+    {
+        setAutoDelete(false);
+    }
 
-        QQuickTextureFactory *textureFactory() const override
-        {
-                return QQuickTextureFactory::textureFactoryForImage(m_image);
-        }
-        QString errorString() const override { return m_error; }
+    QQuickTextureFactory *textureFactory() const override
+    {
+        return QQuickTextureFactory::textureFactoryForImage(m_image);
+    }
+    QString errorString() const override { return m_error; }
 
-        void run() override;
+    void run() override;
 
-        QString m_id, m_error;
-        QSize m_requestedSize;
-        QImage m_image;
-        bool m_crop;
-        double m_radius;
+    QString m_id, m_error;
+    QSize m_requestedSize;
+    QImage m_image;
+    bool m_crop;
+    double m_radius;
 };
 
 class MxcImageProvider
   : public QObject
   , public QQuickAsyncImageProvider
 {
-        Q_OBJECT
+    Q_OBJECT
 public slots:
-        QQuickImageResponse *requestImageResponse(const QString &id,
-                                                  const QSize &requestedSize) override;
+    QQuickImageResponse *requestImageResponse(const QString &id,
+                                              const QSize &requestedSize) override;
 
-        static void addEncryptionInfo(mtx::crypto::EncryptedFile info);
-        static void download(const QString &id,
-                             const QSize &requestedSize,
-                             std::function<void(QString, QSize, QImage, QString)> then,
-                             bool crop     = true,
-                             double radius = 0);
+    static void addEncryptionInfo(mtx::crypto::EncryptedFile info);
+    static void download(const QString &id,
+                         const QSize &requestedSize,
+                         std::function<void(QString, QSize, QImage, QString)> then,
+                         bool crop     = true,
+                         double radius = 0);
 
 private:
-        QThreadPool pool;
+    QThreadPool pool;
 };
diff --git a/src/Olm.cpp b/src/Olm.cpp
index 72dc582f..60460b5c 100644
--- a/src/Olm.cpp
+++ b/src/Olm.cpp
@@ -39,433 +39,385 @@ backup_session_key(const MegolmSessionIndex &idx,
 void
 from_json(const nlohmann::json &obj, OlmMessage &msg)
 {
-        if (obj.at("type") != "m.room.encrypted")
-                throw std::invalid_argument("invalid type for olm message");
+    if (obj.at("type") != "m.room.encrypted")
+        throw std::invalid_argument("invalid type for olm message");
 
-        if (obj.at("content").at("algorithm") != OLM_ALGO)
-                throw std::invalid_argument("invalid algorithm for olm message");
+    if (obj.at("content").at("algorithm") != OLM_ALGO)
+        throw std::invalid_argument("invalid algorithm for olm message");
 
-        msg.sender     = obj.at("sender");
-        msg.sender_key = obj.at("content").at("sender_key");
-        msg.ciphertext = obj.at("content")
-                           .at("ciphertext")
-                           .get<std::map<std::string, mtx::events::msg::OlmCipherContent>>();
+    msg.sender     = obj.at("sender");
+    msg.sender_key = obj.at("content").at("sender_key");
+    msg.ciphertext = obj.at("content")
+                       .at("ciphertext")
+                       .get<std::map<std::string, mtx::events::msg::OlmCipherContent>>();
 }
 
 mtx::crypto::OlmClient *
 client()
 {
-        return client_.get();
+    return client_.get();
 }
 
 static void
 handle_secret_request(const mtx::events::DeviceEvent<mtx::events::msg::SecretRequest> *e,
                       const std::string &sender)
 {
-        using namespace mtx::events;
+    using namespace mtx::events;
 
-        if (e->content.action != mtx::events::msg::RequestAction::Request)
-                return;
+    if (e->content.action != mtx::events::msg::RequestAction::Request)
+        return;
 
-        auto local_user = http::client()->user_id();
+    auto local_user = http::client()->user_id();
 
-        if (sender != local_user.to_string())
-                return;
+    if (sender != local_user.to_string())
+        return;
 
-        auto verificationStatus = cache::verificationStatus(local_user.to_string());
+    auto verificationStatus = cache::verificationStatus(local_user.to_string());
 
-        if (!verificationStatus)
-                return;
+    if (!verificationStatus)
+        return;
 
-        auto deviceKeys = cache::userKeys(local_user.to_string());
-        if (!deviceKeys)
-                return;
+    auto deviceKeys = cache::userKeys(local_user.to_string());
+    if (!deviceKeys)
+        return;
 
-        if (std::find(verificationStatus->verified_devices.begin(),
-                      verificationStatus->verified_devices.end(),
-                      e->content.requesting_device_id) ==
-            verificationStatus->verified_devices.end())
-                return;
+    if (std::find(verificationStatus->verified_devices.begin(),
+                  verificationStatus->verified_devices.end(),
+                  e->content.requesting_device_id) == verificationStatus->verified_devices.end())
+        return;
 
-        // this is a verified device
-        mtx::events::DeviceEvent<mtx::events::msg::SecretSend> secretSend;
-        secretSend.type               = EventType::SecretSend;
-        secretSend.content.request_id = e->content.request_id;
+    // this is a verified device
+    mtx::events::DeviceEvent<mtx::events::msg::SecretSend> secretSend;
+    secretSend.type               = EventType::SecretSend;
+    secretSend.content.request_id = e->content.request_id;
 
-        auto secret = cache::client()->secret(e->content.name);
-        if (!secret)
-                return;
-        secretSend.content.secret = secret.value();
+    auto secret = cache::client()->secret(e->content.name);
+    if (!secret)
+        return;
+    secretSend.content.secret = secret.value();
 
-        send_encrypted_to_device_messages(
-          {{local_user.to_string(), {{e->content.requesting_device_id}}}}, secretSend);
+    send_encrypted_to_device_messages(
+      {{local_user.to_string(), {{e->content.requesting_device_id}}}}, secretSend);
 
-        nhlog::net()->info("Sent secret '{}' to ({},{})",
-                           e->content.name,
-                           local_user.to_string(),
-                           e->content.requesting_device_id);
+    nhlog::net()->info("Sent secret '{}' to ({},{})",
+                       e->content.name,
+                       local_user.to_string(),
+                       e->content.requesting_device_id);
 }
 
 void
 handle_to_device_messages(const std::vector<mtx::events::collections::DeviceEvents> &msgs)
 {
-        if (msgs.empty())
-                return;
-        nhlog::crypto()->info("received {} to_device messages", msgs.size());
-        nlohmann::json j_msg;
-
-        for (const auto &msg : msgs) {
-                j_msg = std::visit([](auto &e) { return json(e); }, std::move(msg));
-                if (j_msg.count("type") == 0) {
-                        nhlog::crypto()->warn("received message with no type field: {}",
-                                              j_msg.dump(2));
-                        continue;
-                }
+    if (msgs.empty())
+        return;
+    nhlog::crypto()->info("received {} to_device messages", msgs.size());
+    nlohmann::json j_msg;
+
+    for (const auto &msg : msgs) {
+        j_msg = std::visit([](auto &e) { return json(e); }, std::move(msg));
+        if (j_msg.count("type") == 0) {
+            nhlog::crypto()->warn("received message with no type field: {}", j_msg.dump(2));
+            continue;
+        }
 
-                std::string msg_type = j_msg.at("type");
-
-                if (msg_type == to_string(mtx::events::EventType::RoomEncrypted)) {
-                        try {
-                                olm::OlmMessage olm_msg = j_msg;
-                                cache::client()->query_keys(
-                                  olm_msg.sender,
-                                  [olm_msg](const UserKeyCache &userKeys, mtx::http::RequestErr e) {
-                                          if (e) {
-                                                  nhlog::crypto()->error(
-                                                    "Failed to query user keys, dropping olm "
-                                                    "message");
-                                                  return;
-                                          }
-                                          handle_olm_message(std::move(olm_msg), userKeys);
-                                  });
-                        } catch (const nlohmann::json::exception &e) {
-                                nhlog::crypto()->warn(
-                                  "parsing error for olm message: {} {}", e.what(), j_msg.dump(2));
-                        } catch (const std::invalid_argument &e) {
-                                nhlog::crypto()->warn("validation error for olm message: {} {}",
-                                                      e.what(),
-                                                      j_msg.dump(2));
-                        }
+        std::string msg_type = j_msg.at("type");
 
-                } else if (msg_type == to_string(mtx::events::EventType::RoomKeyRequest)) {
-                        nhlog::crypto()->warn("handling key request event: {}", j_msg.dump(2));
-                        try {
-                                mtx::events::DeviceEvent<mtx::events::msg::KeyRequest> req = j_msg;
-                                if (req.content.action == mtx::events::msg::RequestAction::Request)
-                                        handle_key_request_message(req);
-                                else
-                                        nhlog::crypto()->warn(
-                                          "ignore key request (unhandled action): {}",
+        if (msg_type == to_string(mtx::events::EventType::RoomEncrypted)) {
+            try {
+                olm::OlmMessage olm_msg = j_msg;
+                cache::client()->query_keys(
+                  olm_msg.sender, [olm_msg](const UserKeyCache &userKeys, mtx::http::RequestErr e) {
+                      if (e) {
+                          nhlog::crypto()->error("Failed to query user keys, dropping olm "
+                                                 "message");
+                          return;
+                      }
+                      handle_olm_message(std::move(olm_msg), userKeys);
+                  });
+            } catch (const nlohmann::json::exception &e) {
+                nhlog::crypto()->warn(
+                  "parsing error for olm message: {} {}", e.what(), j_msg.dump(2));
+            } catch (const std::invalid_argument &e) {
+                nhlog::crypto()->warn(
+                  "validation error for olm message: {} {}", e.what(), j_msg.dump(2));
+            }
+
+        } else if (msg_type == to_string(mtx::events::EventType::RoomKeyRequest)) {
+            nhlog::crypto()->warn("handling key request event: {}", j_msg.dump(2));
+            try {
+                mtx::events::DeviceEvent<mtx::events::msg::KeyRequest> req = j_msg;
+                if (req.content.action == mtx::events::msg::RequestAction::Request)
+                    handle_key_request_message(req);
+                else
+                    nhlog::crypto()->warn("ignore key request (unhandled action): {}",
                                           req.content.request_id);
-                        } catch (const nlohmann::json::exception &e) {
-                                nhlog::crypto()->warn(
-                                  "parsing error for key_request message: {} {}",
-                                  e.what(),
-                                  j_msg.dump(2));
-                        }
-                } else if (msg_type == to_string(mtx::events::EventType::KeyVerificationAccept)) {
-                        auto message = std::get<
-                          mtx::events::DeviceEvent<mtx::events::msg::KeyVerificationAccept>>(msg);
-                        ChatPage::instance()->receivedDeviceVerificationAccept(message.content);
-                } else if (msg_type == to_string(mtx::events::EventType::KeyVerificationRequest)) {
-                        auto message = std::get<
-                          mtx::events::DeviceEvent<mtx::events::msg::KeyVerificationRequest>>(msg);
-                        ChatPage::instance()->receivedDeviceVerificationRequest(message.content,
-                                                                                message.sender);
-                } else if (msg_type == to_string(mtx::events::EventType::KeyVerificationCancel)) {
-                        auto message = std::get<
-                          mtx::events::DeviceEvent<mtx::events::msg::KeyVerificationCancel>>(msg);
-                        ChatPage::instance()->receivedDeviceVerificationCancel(message.content);
-                } else if (msg_type == to_string(mtx::events::EventType::KeyVerificationKey)) {
-                        auto message =
-                          std::get<mtx::events::DeviceEvent<mtx::events::msg::KeyVerificationKey>>(
-                            msg);
-                        ChatPage::instance()->receivedDeviceVerificationKey(message.content);
-                } else if (msg_type == to_string(mtx::events::EventType::KeyVerificationMac)) {
-                        auto message =
-                          std::get<mtx::events::DeviceEvent<mtx::events::msg::KeyVerificationMac>>(
-                            msg);
-                        ChatPage::instance()->receivedDeviceVerificationMac(message.content);
-                } else if (msg_type == to_string(mtx::events::EventType::KeyVerificationStart)) {
-                        auto message = std::get<
-                          mtx::events::DeviceEvent<mtx::events::msg::KeyVerificationStart>>(msg);
-                        ChatPage::instance()->receivedDeviceVerificationStart(message.content,
-                                                                              message.sender);
-                } else if (msg_type == to_string(mtx::events::EventType::KeyVerificationReady)) {
-                        auto message = std::get<
-                          mtx::events::DeviceEvent<mtx::events::msg::KeyVerificationReady>>(msg);
-                        ChatPage::instance()->receivedDeviceVerificationReady(message.content);
-                } else if (msg_type == to_string(mtx::events::EventType::KeyVerificationDone)) {
-                        auto message =
-                          std::get<mtx::events::DeviceEvent<mtx::events::msg::KeyVerificationDone>>(
-                            msg);
-                        ChatPage::instance()->receivedDeviceVerificationDone(message.content);
-                } else if (auto e =
-                             std::get_if<mtx::events::DeviceEvent<mtx::events::msg::SecretRequest>>(
-                               &msg)) {
-                        handle_secret_request(e, e->sender);
-                } else {
-                        nhlog::crypto()->warn("unhandled event: {}", j_msg.dump(2));
-                }
+            } catch (const nlohmann::json::exception &e) {
+                nhlog::crypto()->warn(
+                  "parsing error for key_request message: {} {}", e.what(), j_msg.dump(2));
+            }
+        } else if (msg_type == to_string(mtx::events::EventType::KeyVerificationAccept)) {
+            auto message =
+              std::get<mtx::events::DeviceEvent<mtx::events::msg::KeyVerificationAccept>>(msg);
+            ChatPage::instance()->receivedDeviceVerificationAccept(message.content);
+        } else if (msg_type == to_string(mtx::events::EventType::KeyVerificationRequest)) {
+            auto message =
+              std::get<mtx::events::DeviceEvent<mtx::events::msg::KeyVerificationRequest>>(msg);
+            ChatPage::instance()->receivedDeviceVerificationRequest(message.content,
+                                                                    message.sender);
+        } else if (msg_type == to_string(mtx::events::EventType::KeyVerificationCancel)) {
+            auto message =
+              std::get<mtx::events::DeviceEvent<mtx::events::msg::KeyVerificationCancel>>(msg);
+            ChatPage::instance()->receivedDeviceVerificationCancel(message.content);
+        } else if (msg_type == to_string(mtx::events::EventType::KeyVerificationKey)) {
+            auto message =
+              std::get<mtx::events::DeviceEvent<mtx::events::msg::KeyVerificationKey>>(msg);
+            ChatPage::instance()->receivedDeviceVerificationKey(message.content);
+        } else if (msg_type == to_string(mtx::events::EventType::KeyVerificationMac)) {
+            auto message =
+              std::get<mtx::events::DeviceEvent<mtx::events::msg::KeyVerificationMac>>(msg);
+            ChatPage::instance()->receivedDeviceVerificationMac(message.content);
+        } else if (msg_type == to_string(mtx::events::EventType::KeyVerificationStart)) {
+            auto message =
+              std::get<mtx::events::DeviceEvent<mtx::events::msg::KeyVerificationStart>>(msg);
+            ChatPage::instance()->receivedDeviceVerificationStart(message.content, message.sender);
+        } else if (msg_type == to_string(mtx::events::EventType::KeyVerificationReady)) {
+            auto message =
+              std::get<mtx::events::DeviceEvent<mtx::events::msg::KeyVerificationReady>>(msg);
+            ChatPage::instance()->receivedDeviceVerificationReady(message.content);
+        } else if (msg_type == to_string(mtx::events::EventType::KeyVerificationDone)) {
+            auto message =
+              std::get<mtx::events::DeviceEvent<mtx::events::msg::KeyVerificationDone>>(msg);
+            ChatPage::instance()->receivedDeviceVerificationDone(message.content);
+        } else if (auto e =
+                     std::get_if<mtx::events::DeviceEvent<mtx::events::msg::SecretRequest>>(&msg)) {
+            handle_secret_request(e, e->sender);
+        } else {
+            nhlog::crypto()->warn("unhandled event: {}", j_msg.dump(2));
         }
+    }
 }
 
 void
 handle_olm_message(const OlmMessage &msg, const UserKeyCache &otherUserDeviceKeys)
 {
-        nhlog::crypto()->info("sender    : {}", msg.sender);
-        nhlog::crypto()->info("sender_key: {}", msg.sender_key);
+    nhlog::crypto()->info("sender    : {}", msg.sender);
+    nhlog::crypto()->info("sender_key: {}", msg.sender_key);
 
-        if (msg.sender_key == olm::client()->identity_keys().ed25519) {
-                nhlog::crypto()->warn("Ignoring olm message from ourselves!");
-                return;
+    if (msg.sender_key == olm::client()->identity_keys().ed25519) {
+        nhlog::crypto()->warn("Ignoring olm message from ourselves!");
+        return;
+    }
+
+    const auto my_key = olm::client()->identity_keys().curve25519;
+
+    bool failed_decryption = false;
+
+    for (const auto &cipher : msg.ciphertext) {
+        // We skip messages not meant for the current device.
+        if (cipher.first != my_key) {
+            nhlog::crypto()->debug(
+              "Skipping message for {} since we are {}.", cipher.first, my_key);
+            continue;
         }
 
-        const auto my_key = olm::client()->identity_keys().curve25519;
+        const auto type = cipher.second.type;
+        nhlog::crypto()->info("type: {}", type == 0 ? "OLM_PRE_KEY" : "OLM_MESSAGE");
 
-        bool failed_decryption = false;
+        auto payload = try_olm_decryption(msg.sender_key, cipher.second);
 
-        for (const auto &cipher : msg.ciphertext) {
-                // We skip messages not meant for the current device.
-                if (cipher.first != my_key) {
-                        nhlog::crypto()->debug(
-                          "Skipping message for {} since we are {}.", cipher.first, my_key);
-                        continue;
-                }
+        if (payload.is_null()) {
+            // Check for PRE_KEY message
+            if (cipher.second.type == 0) {
+                payload = handle_pre_key_olm_message(msg.sender, msg.sender_key, cipher.second);
+            } else {
+                nhlog::crypto()->error("Undecryptable olm message!");
+                failed_decryption = true;
+                continue;
+            }
+        }
 
-                const auto type = cipher.second.type;
-                nhlog::crypto()->info("type: {}", type == 0 ? "OLM_PRE_KEY" : "OLM_MESSAGE");
+        if (!payload.is_null()) {
+            mtx::events::collections::DeviceEvents device_event;
+
+            // Other properties are included in order to prevent an attacker from
+            // publishing someone else's curve25519 keys as their own and subsequently
+            // claiming to have sent messages which they didn't. sender must correspond
+            // to the user who sent the event, recipient to the local user, and
+            // recipient_keys to the local ed25519 key.
+            std::string receiver_ed25519 = payload["recipient_keys"]["ed25519"];
+            if (receiver_ed25519.empty() ||
+                receiver_ed25519 != olm::client()->identity_keys().ed25519) {
+                nhlog::crypto()->warn("Decrypted event doesn't include our ed25519: {}",
+                                      payload.dump());
+                return;
+            }
+            std::string receiver = payload["recipient"];
+            if (receiver.empty() || receiver != http::client()->user_id().to_string()) {
+                nhlog::crypto()->warn("Decrypted event doesn't include our user_id: {}",
+                                      payload.dump());
+                return;
+            }
+
+            // Clients must confirm that the sender_key and the ed25519 field value
+            // under the keys property match the keys returned by /keys/query for the
+            // given user, and must also verify the signature of the payload. Without
+            // this check, a client cannot be sure that the sender device owns the
+            // private part of the ed25519 key it claims to have in the Olm payload.
+            // This is crucial when the ed25519 key corresponds to a verified device.
+            std::string sender_ed25519 = payload["keys"]["ed25519"];
+            if (sender_ed25519.empty()) {
+                nhlog::crypto()->warn("Decrypted event doesn't include sender ed25519: {}",
+                                      payload.dump());
+                return;
+            }
 
-                auto payload = try_olm_decryption(msg.sender_key, cipher.second);
+            bool from_their_device = false;
+            for (auto [device_id, key] : otherUserDeviceKeys.device_keys) {
+                auto c_key = key.keys.find("curve25519:" + device_id);
+                auto e_key = key.keys.find("ed25519:" + device_id);
 
-                if (payload.is_null()) {
-                        // Check for PRE_KEY message
-                        if (cipher.second.type == 0) {
-                                payload = handle_pre_key_olm_message(
-                                  msg.sender, msg.sender_key, cipher.second);
-                        } else {
-                                nhlog::crypto()->error("Undecryptable olm message!");
-                                failed_decryption = true;
-                                continue;
-                        }
+                if (c_key == key.keys.end() || e_key == key.keys.end()) {
+                    nhlog::crypto()->warn("Skipping device {} as we have no keys for it.",
+                                          device_id);
+                } else if (c_key->second == msg.sender_key && e_key->second == sender_ed25519) {
+                    from_their_device = true;
+                    break;
                 }
+            }
+            if (!from_their_device) {
+                nhlog::crypto()->warn("Decrypted event isn't sent from a device "
+                                      "listed by that user! {}",
+                                      payload.dump());
+                return;
+            }
+
+            {
+                std::string msg_type = payload["type"];
+                json event_array     = json::array();
+                event_array.push_back(payload);
+
+                std::vector<mtx::events::collections::DeviceEvents> temp_events;
+                mtx::responses::utils::parse_device_events(event_array, temp_events);
+                if (temp_events.empty()) {
+                    nhlog::crypto()->warn("Decrypted unknown event: {}", payload.dump());
+                    return;
+                }
+                device_event = temp_events.at(0);
+            }
+
+            using namespace mtx::events;
+            if (auto e1 = std::get_if<DeviceEvent<msg::KeyVerificationAccept>>(&device_event)) {
+                ChatPage::instance()->receivedDeviceVerificationAccept(e1->content);
+            } else if (auto e2 =
+                         std::get_if<DeviceEvent<msg::KeyVerificationRequest>>(&device_event)) {
+                ChatPage::instance()->receivedDeviceVerificationRequest(e2->content, e2->sender);
+            } else if (auto e3 =
+                         std::get_if<DeviceEvent<msg::KeyVerificationCancel>>(&device_event)) {
+                ChatPage::instance()->receivedDeviceVerificationCancel(e3->content);
+            } else if (auto e4 = std::get_if<DeviceEvent<msg::KeyVerificationKey>>(&device_event)) {
+                ChatPage::instance()->receivedDeviceVerificationKey(e4->content);
+            } else if (auto e5 = std::get_if<DeviceEvent<msg::KeyVerificationMac>>(&device_event)) {
+                ChatPage::instance()->receivedDeviceVerificationMac(e5->content);
+            } else if (auto e6 =
+                         std::get_if<DeviceEvent<msg::KeyVerificationStart>>(&device_event)) {
+                ChatPage::instance()->receivedDeviceVerificationStart(e6->content, e6->sender);
+            } else if (auto e7 =
+                         std::get_if<DeviceEvent<msg::KeyVerificationReady>>(&device_event)) {
+                ChatPage::instance()->receivedDeviceVerificationReady(e7->content);
+            } else if (auto e8 =
+                         std::get_if<DeviceEvent<msg::KeyVerificationDone>>(&device_event)) {
+                ChatPage::instance()->receivedDeviceVerificationDone(e8->content);
+            } else if (auto roomKey = std::get_if<DeviceEvent<msg::RoomKey>>(&device_event)) {
+                create_inbound_megolm_session(*roomKey, msg.sender_key, sender_ed25519);
+            } else if (auto forwardedRoomKey =
+                         std::get_if<DeviceEvent<msg::ForwardedRoomKey>>(&device_event)) {
+                forwardedRoomKey->content.forwarding_curve25519_key_chain.push_back(msg.sender_key);
+                import_inbound_megolm_session(*forwardedRoomKey);
+            } else if (auto e = std::get_if<DeviceEvent<msg::SecretSend>>(&device_event)) {
+                auto local_user = http::client()->user_id();
+
+                if (msg.sender != local_user.to_string())
+                    return;
+
+                auto secret_name = request_id_to_secret_name.find(e->content.request_id);
+
+                if (secret_name != request_id_to_secret_name.end()) {
+                    nhlog::crypto()->info("Received secret: {}", secret_name->second);
+
+                    mtx::events::msg::SecretRequest secretRequest{};
+                    secretRequest.action = mtx::events::msg::RequestAction::Cancellation;
+                    secretRequest.requesting_device_id = http::client()->device_id();
+                    secretRequest.request_id           = e->content.request_id;
+
+                    auto verificationStatus = cache::verificationStatus(local_user.to_string());
+
+                    if (!verificationStatus)
+                        return;
 
-                if (!payload.is_null()) {
-                        mtx::events::collections::DeviceEvents device_event;
-
-                        // Other properties are included in order to prevent an attacker from
-                        // publishing someone else's curve25519 keys as their own and subsequently
-                        // claiming to have sent messages which they didn't. sender must correspond
-                        // to the user who sent the event, recipient to the local user, and
-                        // recipient_keys to the local ed25519 key.
-                        std::string receiver_ed25519 = payload["recipient_keys"]["ed25519"];
-                        if (receiver_ed25519.empty() ||
-                            receiver_ed25519 != olm::client()->identity_keys().ed25519) {
-                                nhlog::crypto()->warn(
-                                  "Decrypted event doesn't include our ed25519: {}",
-                                  payload.dump());
-                                return;
-                        }
-                        std::string receiver = payload["recipient"];
-                        if (receiver.empty() || receiver != http::client()->user_id().to_string()) {
-                                nhlog::crypto()->warn(
-                                  "Decrypted event doesn't include our user_id: {}",
-                                  payload.dump());
-                                return;
-                        }
-
-                        // Clients must confirm that the sender_key and the ed25519 field value
-                        // under the keys property match the keys returned by /keys/query for the
-                        // given user, and must also verify the signature of the payload. Without
-                        // this check, a client cannot be sure that the sender device owns the
-                        // private part of the ed25519 key it claims to have in the Olm payload.
-                        // This is crucial when the ed25519 key corresponds to a verified device.
-                        std::string sender_ed25519 = payload["keys"]["ed25519"];
-                        if (sender_ed25519.empty()) {
-                                nhlog::crypto()->warn(
-                                  "Decrypted event doesn't include sender ed25519: {}",
-                                  payload.dump());
-                                return;
+                    auto deviceKeys = cache::userKeys(local_user.to_string());
+                    std::string sender_device_id;
+                    if (deviceKeys) {
+                        for (auto &[dev, key] : deviceKeys->device_keys) {
+                            if (key.keys["curve25519:" + dev] == msg.sender_key) {
+                                sender_device_id = dev;
+                                break;
+                            }
                         }
+                    }
 
-                        bool from_their_device = false;
-                        for (auto [device_id, key] : otherUserDeviceKeys.device_keys) {
-                                auto c_key = key.keys.find("curve25519:" + device_id);
-                                auto e_key = key.keys.find("ed25519:" + device_id);
+                    std::map<mtx::identifiers::User,
+                             std::map<std::string, mtx::events::msg::SecretRequest>>
+                      body;
 
-                                if (c_key == key.keys.end() || e_key == key.keys.end()) {
-                                        nhlog::crypto()->warn(
-                                          "Skipping device {} as we have no keys for it.",
-                                          device_id);
-                                } else if (c_key->second == msg.sender_key &&
-                                           e_key->second == sender_ed25519) {
-                                        from_their_device = true;
-                                        break;
-                                }
-                        }
-                        if (!from_their_device) {
-                                nhlog::crypto()->warn("Decrypted event isn't sent from a device "
-                                                      "listed by that user! {}",
-                                                      payload.dump());
-                                return;
-                        }
+                    for (const auto &dev : verificationStatus->verified_devices) {
+                        if (dev != secretRequest.requesting_device_id && dev != sender_device_id)
+                            body[local_user][dev] = secretRequest;
+                    }
 
-                        {
-                                std::string msg_type = payload["type"];
-                                json event_array     = json::array();
-                                event_array.push_back(payload);
-
-                                std::vector<mtx::events::collections::DeviceEvents> temp_events;
-                                mtx::responses::utils::parse_device_events(event_array,
-                                                                           temp_events);
-                                if (temp_events.empty()) {
-                                        nhlog::crypto()->warn("Decrypted unknown event: {}",
-                                                              payload.dump());
-                                        return;
-                                }
-                                device_event = temp_events.at(0);
-                        }
+                    http::client()->send_to_device<mtx::events::msg::SecretRequest>(
+                      http::client()->generate_txn_id(),
+                      body,
+                      [name = secret_name->second](mtx::http::RequestErr err) {
+                          if (err) {
+                              nhlog::net()->error("Failed to send request cancellation "
+                                                  "for secrect "
+                                                  "'{}'",
+                                                  name);
+                          }
+                      });
 
-                        using namespace mtx::events;
-                        if (auto e1 =
-                              std::get_if<DeviceEvent<msg::KeyVerificationAccept>>(&device_event)) {
-                                ChatPage::instance()->receivedDeviceVerificationAccept(e1->content);
-                        } else if (auto e2 = std::get_if<DeviceEvent<msg::KeyVerificationRequest>>(
-                                     &device_event)) {
-                                ChatPage::instance()->receivedDeviceVerificationRequest(e2->content,
-                                                                                        e2->sender);
-                        } else if (auto e3 = std::get_if<DeviceEvent<msg::KeyVerificationCancel>>(
-                                     &device_event)) {
-                                ChatPage::instance()->receivedDeviceVerificationCancel(e3->content);
-                        } else if (auto e4 = std::get_if<DeviceEvent<msg::KeyVerificationKey>>(
-                                     &device_event)) {
-                                ChatPage::instance()->receivedDeviceVerificationKey(e4->content);
-                        } else if (auto e5 = std::get_if<DeviceEvent<msg::KeyVerificationMac>>(
-                                     &device_event)) {
-                                ChatPage::instance()->receivedDeviceVerificationMac(e5->content);
-                        } else if (auto e6 = std::get_if<DeviceEvent<msg::KeyVerificationStart>>(
-                                     &device_event)) {
-                                ChatPage::instance()->receivedDeviceVerificationStart(e6->content,
-                                                                                      e6->sender);
-                        } else if (auto e7 = std::get_if<DeviceEvent<msg::KeyVerificationReady>>(
-                                     &device_event)) {
-                                ChatPage::instance()->receivedDeviceVerificationReady(e7->content);
-                        } else if (auto e8 = std::get_if<DeviceEvent<msg::KeyVerificationDone>>(
-                                     &device_event)) {
-                                ChatPage::instance()->receivedDeviceVerificationDone(e8->content);
-                        } else if (auto roomKey =
-                                     std::get_if<DeviceEvent<msg::RoomKey>>(&device_event)) {
-                                create_inbound_megolm_session(
-                                  *roomKey, msg.sender_key, sender_ed25519);
-                        } else if (auto forwardedRoomKey =
-                                     std::get_if<DeviceEvent<msg::ForwardedRoomKey>>(
-                                       &device_event)) {
-                                forwardedRoomKey->content.forwarding_curve25519_key_chain.push_back(
-                                  msg.sender_key);
-                                import_inbound_megolm_session(*forwardedRoomKey);
-                        } else if (auto e =
-                                     std::get_if<DeviceEvent<msg::SecretSend>>(&device_event)) {
-                                auto local_user = http::client()->user_id();
-
-                                if (msg.sender != local_user.to_string())
-                                        return;
-
-                                auto secret_name =
-                                  request_id_to_secret_name.find(e->content.request_id);
-
-                                if (secret_name != request_id_to_secret_name.end()) {
-                                        nhlog::crypto()->info("Received secret: {}",
-                                                              secret_name->second);
-
-                                        mtx::events::msg::SecretRequest secretRequest{};
-                                        secretRequest.action =
-                                          mtx::events::msg::RequestAction::Cancellation;
-                                        secretRequest.requesting_device_id =
-                                          http::client()->device_id();
-                                        secretRequest.request_id = e->content.request_id;
-
-                                        auto verificationStatus =
-                                          cache::verificationStatus(local_user.to_string());
-
-                                        if (!verificationStatus)
-                                                return;
-
-                                        auto deviceKeys = cache::userKeys(local_user.to_string());
-                                        std::string sender_device_id;
-                                        if (deviceKeys) {
-                                                for (auto &[dev, key] : deviceKeys->device_keys) {
-                                                        if (key.keys["curve25519:" + dev] ==
-                                                            msg.sender_key) {
-                                                                sender_device_id = dev;
-                                                                break;
-                                                        }
-                                                }
-                                        }
-
-                                        std::map<
-                                          mtx::identifiers::User,
-                                          std::map<std::string, mtx::events::msg::SecretRequest>>
-                                          body;
-
-                                        for (const auto &dev :
-                                             verificationStatus->verified_devices) {
-                                                if (dev != secretRequest.requesting_device_id &&
-                                                    dev != sender_device_id)
-                                                        body[local_user][dev] = secretRequest;
-                                        }
-
-                                        http::client()
-                                          ->send_to_device<mtx::events::msg::SecretRequest>(
-                                            http::client()->generate_txn_id(),
-                                            body,
-                                            [name =
-                                               secret_name->second](mtx::http::RequestErr err) {
-                                                    if (err) {
-                                                            nhlog::net()->error(
-                                                              "Failed to send request cancellation "
-                                                              "for secrect "
-                                                              "'{}'",
-                                                              name);
-                                                    }
-                                            });
-
-                                        nhlog::crypto()->info("Storing secret {}",
-                                                              secret_name->second);
-                                        cache::client()->storeSecret(secret_name->second,
-                                                                     e->content.secret);
-
-                                        request_id_to_secret_name.erase(secret_name);
-                                }
-
-                        } else if (auto sec_req =
-                                     std::get_if<DeviceEvent<msg::SecretRequest>>(&device_event)) {
-                                handle_secret_request(sec_req, msg.sender);
-                        }
+                    nhlog::crypto()->info("Storing secret {}", secret_name->second);
+                    cache::client()->storeSecret(secret_name->second, e->content.secret);
 
-                        return;
-                } else {
-                        failed_decryption = true;
+                    request_id_to_secret_name.erase(secret_name);
                 }
-        }
 
-        if (failed_decryption) {
-                try {
-                        std::map<std::string, std::vector<std::string>> targets;
-                        for (auto [device_id, key] : otherUserDeviceKeys.device_keys) {
-                                if (key.keys.at("curve25519:" + device_id) == msg.sender_key)
-                                        targets[msg.sender].push_back(device_id);
-                        }
+            } else if (auto sec_req = std::get_if<DeviceEvent<msg::SecretRequest>>(&device_event)) {
+                handle_secret_request(sec_req, msg.sender);
+            }
 
-                        send_encrypted_to_device_messages(
-                          targets, mtx::events::DeviceEvent<mtx::events::msg::Dummy>{}, true);
-                        nhlog::crypto()->info("Recovering from broken olm channel with {}:{}",
-                                              msg.sender,
-                                              msg.sender_key);
-                } catch (std::exception &e) {
-                        nhlog::crypto()->error("Failed to recover from broken olm sessions: {}",
-                                               e.what());
-                }
+            return;
+        } else {
+            failed_decryption = true;
         }
+    }
+
+    if (failed_decryption) {
+        try {
+            std::map<std::string, std::vector<std::string>> targets;
+            for (auto [device_id, key] : otherUserDeviceKeys.device_keys) {
+                if (key.keys.at("curve25519:" + device_id) == msg.sender_key)
+                    targets[msg.sender].push_back(device_id);
+            }
+
+            send_encrypted_to_device_messages(
+              targets, mtx::events::DeviceEvent<mtx::events::msg::Dummy>{}, true);
+            nhlog::crypto()->info(
+              "Recovering from broken olm channel with {}:{}", msg.sender, msg.sender_key);
+        } catch (std::exception &e) {
+            nhlog::crypto()->error("Failed to recover from broken olm sessions: {}", e.what());
+        }
+    }
 }
 
 nlohmann::json
@@ -473,320 +425,291 @@ handle_pre_key_olm_message(const std::string &sender,
                            const std::string &sender_key,
                            const mtx::events::msg::OlmCipherContent &content)
 {
-        nhlog::crypto()->info("opening olm session with {}", sender);
+    nhlog::crypto()->info("opening olm session with {}", sender);
 
-        mtx::crypto::OlmSessionPtr inbound_session = nullptr;
-        try {
-                inbound_session =
-                  olm::client()->create_inbound_session_from(sender_key, content.body);
+    mtx::crypto::OlmSessionPtr inbound_session = nullptr;
+    try {
+        inbound_session = olm::client()->create_inbound_session_from(sender_key, content.body);
 
-                // We also remove the one time key used to establish that
-                // session so we'll have to update our copy of the account object.
-                cache::saveOlmAccount(olm::client()->save(cache::client()->pickleSecret()));
-        } catch (const mtx::crypto::olm_exception &e) {
-                nhlog::crypto()->critical(
-                  "failed to create inbound session with {}: {}", sender, e.what());
-                return {};
-        }
+        // We also remove the one time key used to establish that
+        // session so we'll have to update our copy of the account object.
+        cache::saveOlmAccount(olm::client()->save(cache::client()->pickleSecret()));
+    } catch (const mtx::crypto::olm_exception &e) {
+        nhlog::crypto()->critical("failed to create inbound session with {}: {}", sender, e.what());
+        return {};
+    }
 
-        if (!mtx::crypto::matches_inbound_session_from(
-              inbound_session.get(), sender_key, content.body)) {
-                nhlog::crypto()->warn("inbound olm session doesn't match sender's key ({})",
-                                      sender);
-                return {};
-        }
+    if (!mtx::crypto::matches_inbound_session_from(
+          inbound_session.get(), sender_key, content.body)) {
+        nhlog::crypto()->warn("inbound olm session doesn't match sender's key ({})", sender);
+        return {};
+    }
 
-        mtx::crypto::BinaryBuf output;
-        try {
-                output =
-                  olm::client()->decrypt_message(inbound_session.get(), content.type, content.body);
-        } catch (const mtx::crypto::olm_exception &e) {
-                nhlog::crypto()->critical(
-                  "failed to decrypt olm message {}: {}", content.body, e.what());
-                return {};
-        }
+    mtx::crypto::BinaryBuf output;
+    try {
+        output = olm::client()->decrypt_message(inbound_session.get(), content.type, content.body);
+    } catch (const mtx::crypto::olm_exception &e) {
+        nhlog::crypto()->critical("failed to decrypt olm message {}: {}", content.body, e.what());
+        return {};
+    }
 
-        auto plaintext = json::parse(std::string((char *)output.data(), output.size()));
-        nhlog::crypto()->debug("decrypted message: \n {}", plaintext.dump(2));
+    auto plaintext = json::parse(std::string((char *)output.data(), output.size()));
+    nhlog::crypto()->debug("decrypted message: \n {}", plaintext.dump(2));
 
-        try {
-                nhlog::crypto()->debug("New olm session: {}",
-                                       mtx::crypto::session_id(inbound_session.get()));
-                cache::saveOlmSession(
-                  sender_key, std::move(inbound_session), QDateTime::currentMSecsSinceEpoch());
-        } catch (const lmdb::error &e) {
-                nhlog::db()->warn(
-                  "failed to save inbound olm session from {}: {}", sender, e.what());
-        }
+    try {
+        nhlog::crypto()->debug("New olm session: {}",
+                               mtx::crypto::session_id(inbound_session.get()));
+        cache::saveOlmSession(
+          sender_key, std::move(inbound_session), QDateTime::currentMSecsSinceEpoch());
+    } catch (const lmdb::error &e) {
+        nhlog::db()->warn("failed to save inbound olm session from {}: {}", sender, e.what());
+    }
 
-        return plaintext;
+    return plaintext;
 }
 
 mtx::events::msg::Encrypted
 encrypt_group_message(const std::string &room_id, const std::string &device_id, nlohmann::json body)
 {
-        using namespace mtx::events;
-        using namespace mtx::identifiers;
-
-        auto own_user_id = http::client()->user_id().to_string();
-
-        auto members = cache::client()->getMembersWithKeys(
-          room_id, UserSettings::instance()->onlyShareKeysWithVerifiedUsers());
-
-        std::map<std::string, std::vector<std::string>> sendSessionTo;
-        mtx::crypto::OutboundGroupSessionPtr session = nullptr;
-        GroupSessionData group_session_data;
-
-        if (cache::outboundMegolmSessionExists(room_id)) {
-                auto res                = cache::getOutboundMegolmSession(room_id);
-                auto encryptionSettings = cache::client()->roomEncryptionSettings(room_id);
-                mtx::events::state::Encryption defaultSettings;
-
-                // rotate if we crossed the limits for this key
-                if (res.data.message_index <
-                      encryptionSettings.value_or(defaultSettings).rotation_period_msgs &&
-                    (QDateTime::currentMSecsSinceEpoch() - res.data.timestamp) <
-                      encryptionSettings.value_or(defaultSettings).rotation_period_ms) {
-                        auto member_it             = members.begin();
-                        auto session_member_it     = res.data.currently.keys.begin();
-                        auto session_member_it_end = res.data.currently.keys.end();
-
-                        while (member_it != members.end() ||
-                               session_member_it != session_member_it_end) {
-                                if (member_it == members.end()) {
-                                        // a member left, purge session!
-                                        nhlog::crypto()->debug(
-                                          "Rotating megolm session because of left member");
-                                        break;
-                                }
-
-                                if (session_member_it == session_member_it_end) {
-                                        // share with all remaining members
-                                        while (member_it != members.end()) {
-                                                sendSessionTo[member_it->first] = {};
-
-                                                if (member_it->second)
-                                                        for (const auto &dev :
-                                                             member_it->second->device_keys)
-                                                                if (member_it->first !=
-                                                                      own_user_id ||
-                                                                    dev.first != device_id)
-                                                                        sendSessionTo[member_it
-                                                                                        ->first]
-                                                                          .push_back(dev.first);
-
-                                                ++member_it;
-                                        }
-
-                                        session = std::move(res.session);
-                                        break;
-                                }
-
-                                if (member_it->first > session_member_it->first) {
-                                        // a member left, purge session
-                                        nhlog::crypto()->debug(
-                                          "Rotating megolm session because of left member");
-                                        break;
-                                } else if (member_it->first < session_member_it->first) {
-                                        // new member, send them the session at this index
-                                        sendSessionTo[member_it->first] = {};
-
-                                        if (member_it->second) {
-                                                for (const auto &dev :
-                                                     member_it->second->device_keys)
-                                                        if (member_it->first != own_user_id ||
-                                                            dev.first != device_id)
-                                                                sendSessionTo[member_it->first]
-                                                                  .push_back(dev.first);
-                                        }
-
-                                        ++member_it;
-                                } else {
-                                        // compare devices
-                                        bool device_removed = false;
-                                        for (const auto &dev :
-                                             session_member_it->second.deviceids) {
-                                                if (!member_it->second ||
-                                                    !member_it->second->device_keys.count(
-                                                      dev.first)) {
-                                                        device_removed = true;
-                                                        break;
-                                                }
-                                        }
-
-                                        if (device_removed) {
-                                                // device removed, rotate session!
-                                                nhlog::crypto()->debug(
-                                                  "Rotating megolm session because of removed "
-                                                  "device of {}",
-                                                  member_it->first);
-                                                break;
-                                        }
-
-                                        // check for new devices to share with
-                                        if (member_it->second)
-                                                for (const auto &dev :
-                                                     member_it->second->device_keys)
-                                                        if (!session_member_it->second.deviceids
-                                                               .count(dev.first) &&
-                                                            (member_it->first != own_user_id ||
-                                                             dev.first != device_id))
-                                                                sendSessionTo[member_it->first]
-                                                                  .push_back(dev.first);
-
-                                        ++member_it;
-                                        ++session_member_it;
-                                        if (member_it == members.end() &&
-                                            session_member_it == session_member_it_end) {
-                                                // all devices match or are newly added
-                                                session = std::move(res.session);
-                                        }
-                                }
-                        }
+    using namespace mtx::events;
+    using namespace mtx::identifiers;
+
+    auto own_user_id = http::client()->user_id().to_string();
+
+    auto members = cache::client()->getMembersWithKeys(
+      room_id, UserSettings::instance()->onlyShareKeysWithVerifiedUsers());
+
+    std::map<std::string, std::vector<std::string>> sendSessionTo;
+    mtx::crypto::OutboundGroupSessionPtr session = nullptr;
+    GroupSessionData group_session_data;
+
+    if (cache::outboundMegolmSessionExists(room_id)) {
+        auto res                = cache::getOutboundMegolmSession(room_id);
+        auto encryptionSettings = cache::client()->roomEncryptionSettings(room_id);
+        mtx::events::state::Encryption defaultSettings;
+
+        // rotate if we crossed the limits for this key
+        if (res.data.message_index <
+              encryptionSettings.value_or(defaultSettings).rotation_period_msgs &&
+            (QDateTime::currentMSecsSinceEpoch() - res.data.timestamp) <
+              encryptionSettings.value_or(defaultSettings).rotation_period_ms) {
+            auto member_it             = members.begin();
+            auto session_member_it     = res.data.currently.keys.begin();
+            auto session_member_it_end = res.data.currently.keys.end();
+
+            while (member_it != members.end() || session_member_it != session_member_it_end) {
+                if (member_it == members.end()) {
+                    // a member left, purge session!
+                    nhlog::crypto()->debug("Rotating megolm session because of left member");
+                    break;
                 }
 
-                group_session_data = std::move(res.data);
-        }
+                if (session_member_it == session_member_it_end) {
+                    // share with all remaining members
+                    while (member_it != members.end()) {
+                        sendSessionTo[member_it->first] = {};
 
-        if (!session) {
-                nhlog::ui()->debug("creating new outbound megolm session");
-
-                // Create a new outbound megolm session.
-                session                = olm::client()->init_outbound_group_session();
-                const auto session_id  = mtx::crypto::session_id(session.get());
-                const auto session_key = mtx::crypto::session_key(session.get());
-
-                // Saving the new megolm session.
-                GroupSessionData session_data{};
-                session_data.message_index              = 0;
-                session_data.timestamp                  = QDateTime::currentMSecsSinceEpoch();
-                session_data.sender_claimed_ed25519_key = olm::client()->identity_keys().ed25519;
-
-                sendSessionTo.clear();
-
-                for (const auto &[user, devices] : members) {
-                        sendSessionTo[user]               = {};
-                        session_data.currently.keys[user] = {};
-                        if (devices) {
-                                for (const auto &[device_id_, key] : devices->device_keys) {
-                                        (void)key;
-                                        if (device_id != device_id_ || user != own_user_id) {
-                                                sendSessionTo[user].push_back(device_id_);
-                                                session_data.currently.keys[user]
-                                                  .deviceids[device_id_] = 0;
-                                        }
-                                }
+                        if (member_it->second)
+                            for (const auto &dev : member_it->second->device_keys)
+                                if (member_it->first != own_user_id || dev.first != device_id)
+                                    sendSessionTo[member_it->first].push_back(dev.first);
+
+                        ++member_it;
+                    }
+
+                    session = std::move(res.session);
+                    break;
+                }
+
+                if (member_it->first > session_member_it->first) {
+                    // a member left, purge session
+                    nhlog::crypto()->debug("Rotating megolm session because of left member");
+                    break;
+                } else if (member_it->first < session_member_it->first) {
+                    // new member, send them the session at this index
+                    sendSessionTo[member_it->first] = {};
+
+                    if (member_it->second) {
+                        for (const auto &dev : member_it->second->device_keys)
+                            if (member_it->first != own_user_id || dev.first != device_id)
+                                sendSessionTo[member_it->first].push_back(dev.first);
+                    }
+
+                    ++member_it;
+                } else {
+                    // compare devices
+                    bool device_removed = false;
+                    for (const auto &dev : session_member_it->second.deviceids) {
+                        if (!member_it->second ||
+                            !member_it->second->device_keys.count(dev.first)) {
+                            device_removed = true;
+                            break;
                         }
+                    }
+
+                    if (device_removed) {
+                        // device removed, rotate session!
+                        nhlog::crypto()->debug("Rotating megolm session because of removed "
+                                               "device of {}",
+                                               member_it->first);
+                        break;
+                    }
+
+                    // check for new devices to share with
+                    if (member_it->second)
+                        for (const auto &dev : member_it->second->device_keys)
+                            if (!session_member_it->second.deviceids.count(dev.first) &&
+                                (member_it->first != own_user_id || dev.first != device_id))
+                                sendSessionTo[member_it->first].push_back(dev.first);
+
+                    ++member_it;
+                    ++session_member_it;
+                    if (member_it == members.end() && session_member_it == session_member_it_end) {
+                        // all devices match or are newly added
+                        session = std::move(res.session);
+                    }
                 }
+            }
+        }
 
-                {
-                        MegolmSessionIndex index;
-                        index.room_id    = room_id;
-                        index.session_id = session_id;
-                        index.sender_key = olm::client()->identity_keys().curve25519;
-                        auto megolm_session =
-                          olm::client()->init_inbound_group_session(session_key);
-                        backup_session_key(index, session_data, megolm_session);
-                        cache::saveInboundMegolmSession(
-                          index, std::move(megolm_session), session_data);
+        group_session_data = std::move(res.data);
+    }
+
+    if (!session) {
+        nhlog::ui()->debug("creating new outbound megolm session");
+
+        // Create a new outbound megolm session.
+        session                = olm::client()->init_outbound_group_session();
+        const auto session_id  = mtx::crypto::session_id(session.get());
+        const auto session_key = mtx::crypto::session_key(session.get());
+
+        // Saving the new megolm session.
+        GroupSessionData session_data{};
+        session_data.message_index              = 0;
+        session_data.timestamp                  = QDateTime::currentMSecsSinceEpoch();
+        session_data.sender_claimed_ed25519_key = olm::client()->identity_keys().ed25519;
+
+        sendSessionTo.clear();
+
+        for (const auto &[user, devices] : members) {
+            sendSessionTo[user]               = {};
+            session_data.currently.keys[user] = {};
+            if (devices) {
+                for (const auto &[device_id_, key] : devices->device_keys) {
+                    (void)key;
+                    if (device_id != device_id_ || user != own_user_id) {
+                        sendSessionTo[user].push_back(device_id_);
+                        session_data.currently.keys[user].deviceids[device_id_] = 0;
+                    }
                 }
+            }
+        }
 
-                cache::saveOutboundMegolmSession(room_id, session_data, session);
-                group_session_data = std::move(session_data);
+        {
+            MegolmSessionIndex index;
+            index.room_id       = room_id;
+            index.session_id    = session_id;
+            index.sender_key    = olm::client()->identity_keys().curve25519;
+            auto megolm_session = olm::client()->init_inbound_group_session(session_key);
+            backup_session_key(index, session_data, megolm_session);
+            cache::saveInboundMegolmSession(index, std::move(megolm_session), session_data);
         }
 
-        mtx::events::DeviceEvent<mtx::events::msg::RoomKey> megolm_payload{};
-        megolm_payload.content.algorithm   = MEGOLM_ALGO;
-        megolm_payload.content.room_id     = room_id;
-        megolm_payload.content.session_id  = mtx::crypto::session_id(session.get());
-        megolm_payload.content.session_key = mtx::crypto::session_key(session.get());
-        megolm_payload.type                = mtx::events::EventType::RoomKey;
-
-        if (!sendSessionTo.empty())
-                olm::send_encrypted_to_device_messages(sendSessionTo, megolm_payload);
-
-        // relations shouldn't be encrypted...
-        mtx::common::Relations relations = mtx::common::parse_relations(body["content"]);
-
-        auto payload = olm::client()->encrypt_group_message(session.get(), body.dump());
-
-        // Prepare the m.room.encrypted event.
-        msg::Encrypted data;
-        data.ciphertext = std::string((char *)payload.data(), payload.size());
-        data.sender_key = olm::client()->identity_keys().curve25519;
-        data.session_id = mtx::crypto::session_id(session.get());
-        data.device_id  = device_id;
-        data.algorithm  = MEGOLM_ALGO;
-        data.relations  = relations;
-
-        group_session_data.message_index = olm_outbound_group_session_message_index(session.get());
-        nhlog::crypto()->debug("next message_index {}", group_session_data.message_index);
-
-        // update current set of members for the session with the new members and that message_index
-        for (const auto &[user, devices] : sendSessionTo) {
-                if (!group_session_data.currently.keys.count(user))
-                        group_session_data.currently.keys[user] = {};
-
-                for (const auto &device_id_ : devices) {
-                        if (!group_session_data.currently.keys[user].deviceids.count(device_id_))
-                                group_session_data.currently.keys[user].deviceids[device_id_] =
-                                  group_session_data.message_index;
-                }
+        cache::saveOutboundMegolmSession(room_id, session_data, session);
+        group_session_data = std::move(session_data);
+    }
+
+    mtx::events::DeviceEvent<mtx::events::msg::RoomKey> megolm_payload{};
+    megolm_payload.content.algorithm   = MEGOLM_ALGO;
+    megolm_payload.content.room_id     = room_id;
+    megolm_payload.content.session_id  = mtx::crypto::session_id(session.get());
+    megolm_payload.content.session_key = mtx::crypto::session_key(session.get());
+    megolm_payload.type                = mtx::events::EventType::RoomKey;
+
+    if (!sendSessionTo.empty())
+        olm::send_encrypted_to_device_messages(sendSessionTo, megolm_payload);
+
+    // relations shouldn't be encrypted...
+    mtx::common::Relations relations = mtx::common::parse_relations(body["content"]);
+
+    auto payload = olm::client()->encrypt_group_message(session.get(), body.dump());
+
+    // Prepare the m.room.encrypted event.
+    msg::Encrypted data;
+    data.ciphertext = std::string((char *)payload.data(), payload.size());
+    data.sender_key = olm::client()->identity_keys().curve25519;
+    data.session_id = mtx::crypto::session_id(session.get());
+    data.device_id  = device_id;
+    data.algorithm  = MEGOLM_ALGO;
+    data.relations  = relations;
+
+    group_session_data.message_index = olm_outbound_group_session_message_index(session.get());
+    nhlog::crypto()->debug("next message_index {}", group_session_data.message_index);
+
+    // update current set of members for the session with the new members and that message_index
+    for (const auto &[user, devices] : sendSessionTo) {
+        if (!group_session_data.currently.keys.count(user))
+            group_session_data.currently.keys[user] = {};
+
+        for (const auto &device_id_ : devices) {
+            if (!group_session_data.currently.keys[user].deviceids.count(device_id_))
+                group_session_data.currently.keys[user].deviceids[device_id_] =
+                  group_session_data.message_index;
         }
+    }
 
-        // We need to re-pickle the session after we send a message to save the new message_index.
-        cache::updateOutboundMegolmSession(room_id, group_session_data, session);
+    // We need to re-pickle the session after we send a message to save the new message_index.
+    cache::updateOutboundMegolmSession(room_id, group_session_data, session);
 
-        return data;
+    return data;
 }
 
 nlohmann::json
 try_olm_decryption(const std::string &sender_key, const mtx::events::msg::OlmCipherContent &msg)
 {
-        auto session_ids = cache::getOlmSessions(sender_key);
+    auto session_ids = cache::getOlmSessions(sender_key);
 
-        nhlog::crypto()->info("attempt to decrypt message with {} known session_ids",
-                              session_ids.size());
+    nhlog::crypto()->info("attempt to decrypt message with {} known session_ids",
+                          session_ids.size());
 
-        for (const auto &id : session_ids) {
-                auto session = cache::getOlmSession(sender_key, id);
+    for (const auto &id : session_ids) {
+        auto session = cache::getOlmSession(sender_key, id);
 
-                if (!session) {
-                        nhlog::crypto()->warn("Unknown olm session: {}:{}", sender_key, id);
-                        continue;
-                }
+        if (!session) {
+            nhlog::crypto()->warn("Unknown olm session: {}:{}", sender_key, id);
+            continue;
+        }
 
-                mtx::crypto::BinaryBuf text;
+        mtx::crypto::BinaryBuf text;
 
-                try {
-                        text = olm::client()->decrypt_message(session->get(), msg.type, msg.body);
-                        nhlog::crypto()->debug("Updated olm session: {}",
-                                               mtx::crypto::session_id(session->get()));
-                        cache::saveOlmSession(
-                          id, std::move(session.value()), QDateTime::currentMSecsSinceEpoch());
-                } catch (const mtx::crypto::olm_exception &e) {
-                        nhlog::crypto()->debug("failed to decrypt olm message ({}, {}) with {}: {}",
-                                               msg.type,
-                                               sender_key,
-                                               id,
-                                               e.what());
-                        continue;
-                } catch (const lmdb::error &e) {
-                        nhlog::crypto()->critical("failed to save session: {}", e.what());
-                        return {};
-                }
+        try {
+            text = olm::client()->decrypt_message(session->get(), msg.type, msg.body);
+            nhlog::crypto()->debug("Updated olm session: {}",
+                                   mtx::crypto::session_id(session->get()));
+            cache::saveOlmSession(
+              id, std::move(session.value()), QDateTime::currentMSecsSinceEpoch());
+        } catch (const mtx::crypto::olm_exception &e) {
+            nhlog::crypto()->debug("failed to decrypt olm message ({}, {}) with {}: {}",
+                                   msg.type,
+                                   sender_key,
+                                   id,
+                                   e.what());
+            continue;
+        } catch (const lmdb::error &e) {
+            nhlog::crypto()->critical("failed to save session: {}", e.what());
+            return {};
+        }
 
-                try {
-                        return json::parse(std::string_view((char *)text.data(), text.size()));
-                } catch (const json::exception &e) {
-                        nhlog::crypto()->critical(
-                          "failed to parse the decrypted session msg: {} {}",
-                          e.what(),
-                          std::string_view((char *)text.data(), text.size()));
-                }
+        try {
+            return json::parse(std::string_view((char *)text.data(), text.size()));
+        } catch (const json::exception &e) {
+            nhlog::crypto()->critical("failed to parse the decrypted session msg: {} {}",
+                                      e.what(),
+                                      std::string_view((char *)text.data(), text.size()));
         }
+    }
 
-        return {};
+    return {};
 }
 
 void
@@ -794,75 +717,73 @@ create_inbound_megolm_session(const mtx::events::DeviceEvent<mtx::events::msg::R
                               const std::string &sender_key,
                               const std::string &sender_ed25519)
 {
-        MegolmSessionIndex index;
-        index.room_id    = roomKey.content.room_id;
-        index.session_id = roomKey.content.session_id;
-        index.sender_key = sender_key;
-
-        try {
-                GroupSessionData data{};
-                data.forwarding_curve25519_key_chain = {sender_key};
-                data.sender_claimed_ed25519_key      = sender_ed25519;
-
-                auto megolm_session =
-                  olm::client()->init_inbound_group_session(roomKey.content.session_key);
-                backup_session_key(index, data, megolm_session);
-                cache::saveInboundMegolmSession(index, std::move(megolm_session), data);
-        } catch (const lmdb::error &e) {
-                nhlog::crypto()->critical("failed to save inbound megolm session: {}", e.what());
-                return;
-        } catch (const mtx::crypto::olm_exception &e) {
-                nhlog::crypto()->critical("failed to create inbound megolm session: {}", e.what());
-                return;
-        }
-
-        nhlog::crypto()->info(
-          "established inbound megolm session ({}, {})", roomKey.content.room_id, roomKey.sender);
-
-        ChatPage::instance()->receivedSessionKey(index.room_id, index.session_id);
+    MegolmSessionIndex index;
+    index.room_id    = roomKey.content.room_id;
+    index.session_id = roomKey.content.session_id;
+    index.sender_key = sender_key;
+
+    try {
+        GroupSessionData data{};
+        data.forwarding_curve25519_key_chain = {sender_key};
+        data.sender_claimed_ed25519_key      = sender_ed25519;
+
+        auto megolm_session =
+          olm::client()->init_inbound_group_session(roomKey.content.session_key);
+        backup_session_key(index, data, megolm_session);
+        cache::saveInboundMegolmSession(index, std::move(megolm_session), data);
+    } catch (const lmdb::error &e) {
+        nhlog::crypto()->critical("failed to save inbound megolm session: {}", e.what());
+        return;
+    } catch (const mtx::crypto::olm_exception &e) {
+        nhlog::crypto()->critical("failed to create inbound megolm session: {}", e.what());
+        return;
+    }
+
+    nhlog::crypto()->info(
+      "established inbound megolm session ({}, {})", roomKey.content.room_id, roomKey.sender);
+
+    ChatPage::instance()->receivedSessionKey(index.room_id, index.session_id);
 }
 
 void
 import_inbound_megolm_session(
   const mtx::events::DeviceEvent<mtx::events::msg::ForwardedRoomKey> &roomKey)
 {
-        MegolmSessionIndex index;
-        index.room_id    = roomKey.content.room_id;
-        index.session_id = roomKey.content.session_id;
-        index.sender_key = roomKey.content.sender_key;
-
-        try {
-                auto megolm_session =
-                  olm::client()->import_inbound_group_session(roomKey.content.session_key);
-
-                GroupSessionData data{};
-                data.forwarding_curve25519_key_chain =
-                  roomKey.content.forwarding_curve25519_key_chain;
-                data.sender_claimed_ed25519_key = roomKey.content.sender_claimed_ed25519_key;
-                // may have come from online key backup, so we can't trust it...
-                data.trusted = false;
-                // if we got it forwarded from the sender, assume it is trusted. They may still have
-                // used key backup, but it is unlikely.
-                if (roomKey.content.forwarding_curve25519_key_chain.size() == 1 &&
-                    roomKey.content.forwarding_curve25519_key_chain.back() ==
-                      roomKey.content.sender_key) {
-                        data.trusted = true;
-                }
-
-                backup_session_key(index, data, megolm_session);
-                cache::saveInboundMegolmSession(index, std::move(megolm_session), data);
-        } catch (const lmdb::error &e) {
-                nhlog::crypto()->critical("failed to save inbound megolm session: {}", e.what());
-                return;
-        } catch (const mtx::crypto::olm_exception &e) {
-                nhlog::crypto()->critical("failed to import inbound megolm session: {}", e.what());
-                return;
+    MegolmSessionIndex index;
+    index.room_id    = roomKey.content.room_id;
+    index.session_id = roomKey.content.session_id;
+    index.sender_key = roomKey.content.sender_key;
+
+    try {
+        auto megolm_session =
+          olm::client()->import_inbound_group_session(roomKey.content.session_key);
+
+        GroupSessionData data{};
+        data.forwarding_curve25519_key_chain = roomKey.content.forwarding_curve25519_key_chain;
+        data.sender_claimed_ed25519_key      = roomKey.content.sender_claimed_ed25519_key;
+        // may have come from online key backup, so we can't trust it...
+        data.trusted = false;
+        // if we got it forwarded from the sender, assume it is trusted. They may still have
+        // used key backup, but it is unlikely.
+        if (roomKey.content.forwarding_curve25519_key_chain.size() == 1 &&
+            roomKey.content.forwarding_curve25519_key_chain.back() == roomKey.content.sender_key) {
+            data.trusted = true;
         }
 
-        nhlog::crypto()->info(
-          "established inbound megolm session ({}, {})", roomKey.content.room_id, roomKey.sender);
+        backup_session_key(index, data, megolm_session);
+        cache::saveInboundMegolmSession(index, std::move(megolm_session), data);
+    } catch (const lmdb::error &e) {
+        nhlog::crypto()->critical("failed to save inbound megolm session: {}", e.what());
+        return;
+    } catch (const mtx::crypto::olm_exception &e) {
+        nhlog::crypto()->critical("failed to import inbound megolm session: {}", e.what());
+        return;
+    }
+
+    nhlog::crypto()->info(
+      "established inbound megolm session ({}, {})", roomKey.content.room_id, roomKey.sender);
 
-        ChatPage::instance()->receivedSessionKey(index.room_id, index.session_id);
+    ChatPage::instance()->receivedSessionKey(index.room_id, index.session_id);
 }
 
 void
@@ -870,165 +791,156 @@ backup_session_key(const MegolmSessionIndex &idx,
                    const GroupSessionData &data,
                    mtx::crypto::InboundGroupSessionPtr &session)
 {
-        try {
-                if (!UserSettings::instance()->useOnlineKeyBackup()) {
-                        // Online key backup disabled
-                        return;
-                }
-
-                auto backupVersion = cache::client()->backupVersion();
-                if (!backupVersion) {
-                        // no trusted OKB
-                        return;
-                }
-
-                using namespace mtx::crypto;
-
-                auto decryptedSecret =
-                  cache::secret(mtx::secret_storage::secrets::megolm_backup_v1);
-                if (!decryptedSecret) {
-                        // no backup key available
-                        return;
-                }
-                auto sessionDecryptionKey = to_binary_buf(base642bin(*decryptedSecret));
-
-                auto public_key =
-                  mtx::crypto::CURVE25519_public_key_from_private(sessionDecryptionKey);
-
-                mtx::responses::backup::SessionData sessionData;
-                sessionData.algorithm                       = mtx::crypto::MEGOLM_ALGO;
-                sessionData.forwarding_curve25519_key_chain = data.forwarding_curve25519_key_chain;
-                sessionData.sender_claimed_keys["ed25519"]  = data.sender_claimed_ed25519_key;
-                sessionData.sender_key                      = idx.sender_key;
-                sessionData.session_key = mtx::crypto::export_session(session.get(), -1);
-
-                auto encrypt_session = mtx::crypto::encrypt_session(sessionData, public_key);
-
-                mtx::responses::backup::SessionBackup bk;
-                bk.first_message_index = olm_inbound_group_session_first_known_index(session.get());
-                bk.forwarded_count     = data.forwarding_curve25519_key_chain.size();
-                bk.is_verified         = false;
-                bk.session_data        = std::move(encrypt_session);
-
-                http::client()->put_room_keys(
-                  backupVersion->version,
-                  idx.room_id,
-                  idx.session_id,
-                  bk,
-                  [idx](mtx::http::RequestErr err) {
-                          if (err) {
-                                  nhlog::net()->warn(
-                                    "failed to backup session key ({}:{}): {} ({})",
-                                    idx.room_id,
-                                    idx.session_id,
-                                    err->matrix_error.error,
-                                    static_cast<int>(err->status_code));
-                          } else {
-                                  nhlog::crypto()->debug(
-                                    "backed up session key ({}:{})", idx.room_id, idx.session_id);
-                          }
-                  });
-        } catch (std::exception &e) {
-                nhlog::net()->warn("failed to backup session key: {}", e.what());
-        }
-}
-
-void
-mark_keys_as_published()
-{
-        olm::client()->mark_keys_as_published();
-        cache::saveOlmAccount(olm::client()->save(cache::client()->pickleSecret()));
-}
-
-void
-lookup_keybackup(const std::string room, const std::string session_id)
-{
+    try {
         if (!UserSettings::instance()->useOnlineKeyBackup()) {
-                // Online key backup disabled
-                return;
+            // Online key backup disabled
+            return;
         }
 
         auto backupVersion = cache::client()->backupVersion();
         if (!backupVersion) {
-                // no trusted OKB
-                return;
+            // no trusted OKB
+            return;
         }
 
         using namespace mtx::crypto;
 
         auto decryptedSecret = cache::secret(mtx::secret_storage::secrets::megolm_backup_v1);
         if (!decryptedSecret) {
-                // no backup key available
-                return;
+            // no backup key available
+            return;
         }
         auto sessionDecryptionKey = to_binary_buf(base642bin(*decryptedSecret));
 
-        http::client()->room_keys(
+        auto public_key = mtx::crypto::CURVE25519_public_key_from_private(sessionDecryptionKey);
+
+        mtx::responses::backup::SessionData sessionData;
+        sessionData.algorithm                       = mtx::crypto::MEGOLM_ALGO;
+        sessionData.forwarding_curve25519_key_chain = data.forwarding_curve25519_key_chain;
+        sessionData.sender_claimed_keys["ed25519"]  = data.sender_claimed_ed25519_key;
+        sessionData.sender_key                      = idx.sender_key;
+        sessionData.session_key = mtx::crypto::export_session(session.get(), -1);
+
+        auto encrypt_session = mtx::crypto::encrypt_session(sessionData, public_key);
+
+        mtx::responses::backup::SessionBackup bk;
+        bk.first_message_index = olm_inbound_group_session_first_known_index(session.get());
+        bk.forwarded_count     = data.forwarding_curve25519_key_chain.size();
+        bk.is_verified         = false;
+        bk.session_data        = std::move(encrypt_session);
+
+        http::client()->put_room_keys(
           backupVersion->version,
-          room,
-          session_id,
-          [room, session_id, sessionDecryptionKey](const mtx::responses::backup::SessionBackup &bk,
-                                                   mtx::http::RequestErr err) {
-                  if (err) {
-                          if (err->status_code != 404)
-                                  nhlog::crypto()->error(
-                                    "Failed to dowload key {}:{}: {} - {}",
-                                    room,
-                                    session_id,
-                                    mtx::errors::to_string(err->matrix_error.errcode),
-                                    err->matrix_error.error);
-                          return;
-                  }
-                  try {
-                          auto session = decrypt_session(bk.session_data, sessionDecryptionKey);
-
-                          if (session.algorithm != mtx::crypto::MEGOLM_ALGO)
-                                  // don't know this algorithm
-                                  return;
-
-                          MegolmSessionIndex index;
-                          index.room_id    = room;
-                          index.session_id = session_id;
-                          index.sender_key = session.sender_key;
-
-                          GroupSessionData data{};
-                          data.forwarding_curve25519_key_chain =
-                            session.forwarding_curve25519_key_chain;
-                          data.sender_claimed_ed25519_key = session.sender_claimed_keys["ed25519"];
-                          // online key backup can't be trusted, because anyone can upload to it.
-                          data.trusted = false;
-
-                          auto megolm_session =
-                            olm::client()->import_inbound_group_session(session.session_key);
-
-                          if (!cache::inboundMegolmSessionExists(index) ||
-                              olm_inbound_group_session_first_known_index(megolm_session.get()) <
-                                olm_inbound_group_session_first_known_index(
-                                  cache::getInboundMegolmSession(index).get())) {
-                                  cache::saveInboundMegolmSession(
-                                    index, std::move(megolm_session), data);
-
-                                  nhlog::crypto()->info("imported inbound megolm session "
-                                                        "from key backup ({}, {})",
-                                                        room,
-                                                        session_id);
-
-                                  // call on UI thread
-                                  QTimer::singleShot(0, ChatPage::instance(), [index] {
-                                          ChatPage::instance()->receivedSessionKey(
-                                            index.room_id, index.session_id);
-                                  });
-                          }
-                  } catch (const lmdb::error &e) {
-                          nhlog::crypto()->critical("failed to save inbound megolm session: {}",
-                                                    e.what());
-                          return;
-                  } catch (const mtx::crypto::olm_exception &e) {
-                          nhlog::crypto()->critical("failed to import inbound megolm session: {}",
-                                                    e.what());
-                          return;
-                  }
+          idx.room_id,
+          idx.session_id,
+          bk,
+          [idx](mtx::http::RequestErr err) {
+              if (err) {
+                  nhlog::net()->warn("failed to backup session key ({}:{}): {} ({})",
+                                     idx.room_id,
+                                     idx.session_id,
+                                     err->matrix_error.error,
+                                     static_cast<int>(err->status_code));
+              } else {
+                  nhlog::crypto()->debug(
+                    "backed up session key ({}:{})", idx.room_id, idx.session_id);
+              }
           });
+    } catch (std::exception &e) {
+        nhlog::net()->warn("failed to backup session key: {}", e.what());
+    }
+}
+
+void
+mark_keys_as_published()
+{
+    olm::client()->mark_keys_as_published();
+    cache::saveOlmAccount(olm::client()->save(cache::client()->pickleSecret()));
+}
+
+void
+lookup_keybackup(const std::string room, const std::string session_id)
+{
+    if (!UserSettings::instance()->useOnlineKeyBackup()) {
+        // Online key backup disabled
+        return;
+    }
+
+    auto backupVersion = cache::client()->backupVersion();
+    if (!backupVersion) {
+        // no trusted OKB
+        return;
+    }
+
+    using namespace mtx::crypto;
+
+    auto decryptedSecret = cache::secret(mtx::secret_storage::secrets::megolm_backup_v1);
+    if (!decryptedSecret) {
+        // no backup key available
+        return;
+    }
+    auto sessionDecryptionKey = to_binary_buf(base642bin(*decryptedSecret));
+
+    http::client()->room_keys(
+      backupVersion->version,
+      room,
+      session_id,
+      [room, session_id, sessionDecryptionKey](const mtx::responses::backup::SessionBackup &bk,
+                                               mtx::http::RequestErr err) {
+          if (err) {
+              if (err->status_code != 404)
+                  nhlog::crypto()->error("Failed to dowload key {}:{}: {} - {}",
+                                         room,
+                                         session_id,
+                                         mtx::errors::to_string(err->matrix_error.errcode),
+                                         err->matrix_error.error);
+              return;
+          }
+          try {
+              auto session = decrypt_session(bk.session_data, sessionDecryptionKey);
+
+              if (session.algorithm != mtx::crypto::MEGOLM_ALGO)
+                  // don't know this algorithm
+                  return;
+
+              MegolmSessionIndex index;
+              index.room_id    = room;
+              index.session_id = session_id;
+              index.sender_key = session.sender_key;
+
+              GroupSessionData data{};
+              data.forwarding_curve25519_key_chain = session.forwarding_curve25519_key_chain;
+              data.sender_claimed_ed25519_key      = session.sender_claimed_keys["ed25519"];
+              // online key backup can't be trusted, because anyone can upload to it.
+              data.trusted = false;
+
+              auto megolm_session =
+                olm::client()->import_inbound_group_session(session.session_key);
+
+              if (!cache::inboundMegolmSessionExists(index) ||
+                  olm_inbound_group_session_first_known_index(megolm_session.get()) <
+                    olm_inbound_group_session_first_known_index(
+                      cache::getInboundMegolmSession(index).get())) {
+                  cache::saveInboundMegolmSession(index, std::move(megolm_session), data);
+
+                  nhlog::crypto()->info("imported inbound megolm session "
+                                        "from key backup ({}, {})",
+                                        room,
+                                        session_id);
+
+                  // call on UI thread
+                  QTimer::singleShot(0, ChatPage::instance(), [index] {
+                      ChatPage::instance()->receivedSessionKey(index.room_id, index.session_id);
+                  });
+              }
+          } catch (const lmdb::error &e) {
+              nhlog::crypto()->critical("failed to save inbound megolm session: {}", e.what());
+              return;
+          } catch (const mtx::crypto::olm_exception &e) {
+              nhlog::crypto()->critical("failed to import inbound megolm session: {}", e.what());
+              return;
+          }
+      });
 }
 
 void
@@ -1036,158 +948,152 @@ send_key_request_for(mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> e,
                      const std::string &request_id,
                      bool cancel)
 {
-        using namespace mtx::events;
-
-        nhlog::crypto()->debug("sending key request: sender_key {}, session_id {}",
-                               e.content.sender_key,
-                               e.content.session_id);
-
-        mtx::events::msg::KeyRequest request;
-        request.action = cancel ? mtx::events::msg::RequestAction::Cancellation
-                                : mtx::events::msg::RequestAction::Request;
-
-        request.algorithm            = MEGOLM_ALGO;
-        request.room_id              = e.room_id;
-        request.sender_key           = e.content.sender_key;
-        request.session_id           = e.content.session_id;
-        request.request_id           = request_id;
-        request.requesting_device_id = http::client()->device_id();
-
-        nhlog::crypto()->debug("m.room_key_request: {}", json(request).dump(2));
-
-        std::map<mtx::identifiers::User, std::map<std::string, decltype(request)>> body;
-        body[mtx::identifiers::parse<mtx::identifiers::User>(e.sender)][e.content.device_id] =
-          request;
-        body[http::client()->user_id()]["*"] = request;
-
-        http::client()->send_to_device(
-          http::client()->generate_txn_id(), body, [e](mtx::http::RequestErr err) {
-                  if (err) {
-                          nhlog::net()->warn("failed to send "
-                                             "send_to_device "
-                                             "message: {}",
-                                             err->matrix_error.error);
-                  }
-
-                  nhlog::net()->info("m.room_key_request sent to {}:{} and your own devices",
-                                     e.sender,
-                                     e.content.device_id);
-          });
-
-        // http::client()->room_keys
+    using namespace mtx::events;
+
+    nhlog::crypto()->debug("sending key request: sender_key {}, session_id {}",
+                           e.content.sender_key,
+                           e.content.session_id);
+
+    mtx::events::msg::KeyRequest request;
+    request.action = cancel ? mtx::events::msg::RequestAction::Cancellation
+                            : mtx::events::msg::RequestAction::Request;
+
+    request.algorithm            = MEGOLM_ALGO;
+    request.room_id              = e.room_id;
+    request.sender_key           = e.content.sender_key;
+    request.session_id           = e.content.session_id;
+    request.request_id           = request_id;
+    request.requesting_device_id = http::client()->device_id();
+
+    nhlog::crypto()->debug("m.room_key_request: {}", json(request).dump(2));
+
+    std::map<mtx::identifiers::User, std::map<std::string, decltype(request)>> body;
+    body[mtx::identifiers::parse<mtx::identifiers::User>(e.sender)][e.content.device_id] = request;
+    body[http::client()->user_id()]["*"]                                                 = request;
+
+    http::client()->send_to_device(
+      http::client()->generate_txn_id(), body, [e](mtx::http::RequestErr err) {
+          if (err) {
+              nhlog::net()->warn("failed to send "
+                                 "send_to_device "
+                                 "message: {}",
+                                 err->matrix_error.error);
+          }
+
+          nhlog::net()->info(
+            "m.room_key_request sent to {}:{} and your own devices", e.sender, e.content.device_id);
+      });
+
+    // http::client()->room_keys
 }
 
 void
 handle_key_request_message(const mtx::events::DeviceEvent<mtx::events::msg::KeyRequest> &req)
 {
-        if (req.content.algorithm != MEGOLM_ALGO) {
-                nhlog::crypto()->debug("ignoring key request {} with invalid algorithm: {}",
-                                       req.content.request_id,
-                                       req.content.algorithm);
-                return;
-        }
-
-        // Check if we were the sender of the session being requested (unless it is actually us
-        // requesting the session).
-        if (req.sender != http::client()->user_id().to_string() &&
-            req.content.sender_key != olm::client()->identity_keys().curve25519) {
-                nhlog::crypto()->debug(
-                  "ignoring key request {} because we did not create the requested session: "
-                  "\nrequested({}) ours({})",
-                  req.content.request_id,
-                  req.content.sender_key,
-                  olm::client()->identity_keys().curve25519);
-                return;
-        }
-
-        // Check that the requested session_id and the one we have saved match.
-        MegolmSessionIndex index{};
-        index.room_id    = req.content.room_id;
-        index.session_id = req.content.session_id;
-        index.sender_key = req.content.sender_key;
-
-        // Check if we have the keys for the requested session.
-        auto sessionData = cache::getMegolmSessionData(index);
-        if (!sessionData) {
-                nhlog::crypto()->warn("requested session not found in room: {}",
-                                      req.content.room_id);
-                return;
-        }
-
-        const auto session = cache::getInboundMegolmSession(index);
-        if (!session) {
-                nhlog::crypto()->warn("No session with id {} in db", req.content.session_id);
-                return;
-        }
-
-        if (!cache::isRoomMember(req.sender, req.content.room_id)) {
-                nhlog::crypto()->warn(
-                  "user {} that requested the session key is not member of the room {}",
-                  req.sender,
-                  req.content.room_id);
-                return;
-        }
-
-        // check if device is verified
-        auto verificationStatus = cache::verificationStatus(req.sender);
-        bool verifiedDevice     = false;
-        if (verificationStatus &&
-            // Share keys, if the option to share with trusted users is enabled or with yourself
-            (ChatPage::instance()->userSettings()->shareKeysWithTrustedUsers() ||
-             req.sender == http::client()->user_id().to_string())) {
-                for (const auto &dev : verificationStatus->verified_devices) {
-                        if (dev == req.content.requesting_device_id) {
-                                verifiedDevice = true;
-                                nhlog::crypto()->debug("Verified device: {}", dev);
-                                break;
-                        }
-                }
-        }
-
-        bool shouldSeeKeys    = false;
-        uint64_t minimumIndex = -1;
-        if (sessionData->currently.keys.count(req.sender)) {
-                if (sessionData->currently.keys.at(req.sender)
-                      .deviceids.count(req.content.requesting_device_id)) {
-                        shouldSeeKeys = true;
-                        minimumIndex  = sessionData->currently.keys.at(req.sender)
-                                         .deviceids.at(req.content.requesting_device_id);
-                }
+    if (req.content.algorithm != MEGOLM_ALGO) {
+        nhlog::crypto()->debug("ignoring key request {} with invalid algorithm: {}",
+                               req.content.request_id,
+                               req.content.algorithm);
+        return;
+    }
+
+    // Check if we were the sender of the session being requested (unless it is actually us
+    // requesting the session).
+    if (req.sender != http::client()->user_id().to_string() &&
+        req.content.sender_key != olm::client()->identity_keys().curve25519) {
+        nhlog::crypto()->debug(
+          "ignoring key request {} because we did not create the requested session: "
+          "\nrequested({}) ours({})",
+          req.content.request_id,
+          req.content.sender_key,
+          olm::client()->identity_keys().curve25519);
+        return;
+    }
+
+    // Check that the requested session_id and the one we have saved match.
+    MegolmSessionIndex index{};
+    index.room_id    = req.content.room_id;
+    index.session_id = req.content.session_id;
+    index.sender_key = req.content.sender_key;
+
+    // Check if we have the keys for the requested session.
+    auto sessionData = cache::getMegolmSessionData(index);
+    if (!sessionData) {
+        nhlog::crypto()->warn("requested session not found in room: {}", req.content.room_id);
+        return;
+    }
+
+    const auto session = cache::getInboundMegolmSession(index);
+    if (!session) {
+        nhlog::crypto()->warn("No session with id {} in db", req.content.session_id);
+        return;
+    }
+
+    if (!cache::isRoomMember(req.sender, req.content.room_id)) {
+        nhlog::crypto()->warn("user {} that requested the session key is not member of the room {}",
+                              req.sender,
+                              req.content.room_id);
+        return;
+    }
+
+    // check if device is verified
+    auto verificationStatus = cache::verificationStatus(req.sender);
+    bool verifiedDevice     = false;
+    if (verificationStatus &&
+        // Share keys, if the option to share with trusted users is enabled or with yourself
+        (ChatPage::instance()->userSettings()->shareKeysWithTrustedUsers() ||
+         req.sender == http::client()->user_id().to_string())) {
+        for (const auto &dev : verificationStatus->verified_devices) {
+            if (dev == req.content.requesting_device_id) {
+                verifiedDevice = true;
+                nhlog::crypto()->debug("Verified device: {}", dev);
+                break;
+            }
         }
-
-        if (!verifiedDevice && !shouldSeeKeys) {
-                nhlog::crypto()->debug("ignoring key request for room {}", req.content.room_id);
-                return;
-        }
-
-        if (verifiedDevice) {
-                // share the minimum index we have
-                minimumIndex = -1;
-        }
-
-        try {
-                auto session_key = mtx::crypto::export_session(session.get(), minimumIndex);
-
-                //
-                // Prepare the m.room_key event.
-                //
-                mtx::events::msg::ForwardedRoomKey forward_key{};
-                forward_key.algorithm   = MEGOLM_ALGO;
-                forward_key.room_id     = index.room_id;
-                forward_key.session_id  = index.session_id;
-                forward_key.session_key = session_key;
-                forward_key.sender_key  = index.sender_key;
-
-                // TODO(Nico): Figure out if this is correct
-                forward_key.sender_claimed_ed25519_key = sessionData->sender_claimed_ed25519_key;
-                forward_key.forwarding_curve25519_key_chain =
-                  sessionData->forwarding_curve25519_key_chain;
-
-                send_megolm_key_to_device(
-                  req.sender, req.content.requesting_device_id, forward_key);
-        } catch (std::exception &e) {
-                nhlog::crypto()->error("Failed to forward session key: {}", e.what());
+    }
+
+    bool shouldSeeKeys    = false;
+    uint64_t minimumIndex = -1;
+    if (sessionData->currently.keys.count(req.sender)) {
+        if (sessionData->currently.keys.at(req.sender)
+              .deviceids.count(req.content.requesting_device_id)) {
+            shouldSeeKeys = true;
+            minimumIndex  = sessionData->currently.keys.at(req.sender)
+                             .deviceids.at(req.content.requesting_device_id);
         }
+    }
+
+    if (!verifiedDevice && !shouldSeeKeys) {
+        nhlog::crypto()->debug("ignoring key request for room {}", req.content.room_id);
+        return;
+    }
+
+    if (verifiedDevice) {
+        // share the minimum index we have
+        minimumIndex = -1;
+    }
+
+    try {
+        auto session_key = mtx::crypto::export_session(session.get(), minimumIndex);
+
+        //
+        // Prepare the m.room_key event.
+        //
+        mtx::events::msg::ForwardedRoomKey forward_key{};
+        forward_key.algorithm   = MEGOLM_ALGO;
+        forward_key.room_id     = index.room_id;
+        forward_key.session_id  = index.session_id;
+        forward_key.session_key = session_key;
+        forward_key.sender_key  = index.sender_key;
+
+        // TODO(Nico): Figure out if this is correct
+        forward_key.sender_claimed_ed25519_key      = sessionData->sender_claimed_ed25519_key;
+        forward_key.forwarding_curve25519_key_chain = sessionData->forwarding_curve25519_key_chain;
+
+        send_megolm_key_to_device(req.sender, req.content.requesting_device_id, forward_key);
+    } catch (std::exception &e) {
+        nhlog::crypto()->error("Failed to forward session key: {}", e.what());
+    }
 }
 
 void
@@ -1195,14 +1101,14 @@ send_megolm_key_to_device(const std::string &user_id,
                           const std::string &device_id,
                           const mtx::events::msg::ForwardedRoomKey &payload)
 {
-        mtx::events::DeviceEvent<mtx::events::msg::ForwardedRoomKey> room_key;
-        room_key.content = payload;
-        room_key.type    = mtx::events::EventType::ForwardedRoomKey;
-
-        std::map<std::string, std::vector<std::string>> targets;
-        targets[user_id] = {device_id};
-        send_encrypted_to_device_messages(targets, room_key);
-        nhlog::crypto()->debug("Forwarded key to {}:{}", user_id, device_id);
+    mtx::events::DeviceEvent<mtx::events::msg::ForwardedRoomKey> room_key;
+    room_key.content = payload;
+    room_key.type    = mtx::events::EventType::ForwardedRoomKey;
+
+    std::map<std::string, std::vector<std::string>> targets;
+    targets[user_id] = {device_id};
+    send_encrypted_to_device_messages(targets, room_key);
+    nhlog::crypto()->debug("Forwarded key to {}:{}", user_id, device_id);
 }
 
 DecryptionResult
@@ -1210,79 +1116,74 @@ decryptEvent(const MegolmSessionIndex &index,
              const mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> &event,
              bool dont_write_db)
 {
-        try {
-                if (!cache::client()->inboundMegolmSessionExists(index)) {
-                        return {DecryptionErrorCode::MissingSession, std::nullopt, std::nullopt};
-                }
-        } catch (const lmdb::error &e) {
-                return {DecryptionErrorCode::DbError, e.what(), std::nullopt};
-        }
-
-        // TODO: Lookup index,event_id,origin_server_ts tuple for replay attack errors
-
-        std::string msg_str;
-        try {
-                auto session = cache::client()->getInboundMegolmSession(index);
-                auto sessionData =
-                  cache::client()->getMegolmSessionData(index).value_or(GroupSessionData{});
-
-                auto res =
-                  olm::client()->decrypt_group_message(session.get(), event.content.ciphertext);
-                msg_str = std::string((char *)res.data.data(), res.data.size());
-
-                if (!event.event_id.empty() && event.event_id[0] == '$') {
-                        auto oldIdx = sessionData.indices.find(res.message_index);
-                        if (oldIdx != sessionData.indices.end()) {
-                                if (oldIdx->second != event.event_id)
-                                        return {DecryptionErrorCode::ReplayAttack,
-                                                std::nullopt,
-                                                std::nullopt};
-                        } else if (!dont_write_db) {
-                                sessionData.indices[res.message_index] = event.event_id;
-                                cache::client()->saveInboundMegolmSession(
-                                  index, std::move(session), sessionData);
-                        }
-                }
-        } catch (const lmdb::error &e) {
-                return {DecryptionErrorCode::DbError, e.what(), std::nullopt};
-        } catch (const mtx::crypto::olm_exception &e) {
-                if (e.error_code() == mtx::crypto::OlmErrorCode::UNKNOWN_MESSAGE_INDEX)
-                        return {DecryptionErrorCode::MissingSessionIndex, e.what(), std::nullopt};
-                return {DecryptionErrorCode::DecryptionFailed, e.what(), std::nullopt};
+    try {
+        if (!cache::client()->inboundMegolmSessionExists(index)) {
+            return {DecryptionErrorCode::MissingSession, std::nullopt, std::nullopt};
         }
-
-        try {
-                // Add missing fields for the event.
-                json body                = json::parse(msg_str);
-                body["event_id"]         = event.event_id;
-                body["sender"]           = event.sender;
-                body["origin_server_ts"] = event.origin_server_ts;
-                body["unsigned"]         = event.unsigned_data;
-
-                // relations are unencrypted in content...
-                mtx::common::add_relations(body["content"], event.content.relations);
-
-                mtx::events::collections::TimelineEvent te;
-                mtx::events::collections::from_json(body, te);
-
-                return {DecryptionErrorCode::NoError, std::nullopt, std::move(te.data)};
-        } catch (std::exception &e) {
-                return {DecryptionErrorCode::ParsingFailed, e.what(), std::nullopt};
+    } catch (const lmdb::error &e) {
+        return {DecryptionErrorCode::DbError, e.what(), std::nullopt};
+    }
+
+    // TODO: Lookup index,event_id,origin_server_ts tuple for replay attack errors
+
+    std::string msg_str;
+    try {
+        auto session = cache::client()->getInboundMegolmSession(index);
+        auto sessionData =
+          cache::client()->getMegolmSessionData(index).value_or(GroupSessionData{});
+
+        auto res = olm::client()->decrypt_group_message(session.get(), event.content.ciphertext);
+        msg_str  = std::string((char *)res.data.data(), res.data.size());
+
+        if (!event.event_id.empty() && event.event_id[0] == '$') {
+            auto oldIdx = sessionData.indices.find(res.message_index);
+            if (oldIdx != sessionData.indices.end()) {
+                if (oldIdx->second != event.event_id)
+                    return {DecryptionErrorCode::ReplayAttack, std::nullopt, std::nullopt};
+            } else if (!dont_write_db) {
+                sessionData.indices[res.message_index] = event.event_id;
+                cache::client()->saveInboundMegolmSession(index, std::move(session), sessionData);
+            }
         }
+    } catch (const lmdb::error &e) {
+        return {DecryptionErrorCode::DbError, e.what(), std::nullopt};
+    } catch (const mtx::crypto::olm_exception &e) {
+        if (e.error_code() == mtx::crypto::OlmErrorCode::UNKNOWN_MESSAGE_INDEX)
+            return {DecryptionErrorCode::MissingSessionIndex, e.what(), std::nullopt};
+        return {DecryptionErrorCode::DecryptionFailed, e.what(), std::nullopt};
+    }
+
+    try {
+        // Add missing fields for the event.
+        json body                = json::parse(msg_str);
+        body["event_id"]         = event.event_id;
+        body["sender"]           = event.sender;
+        body["origin_server_ts"] = event.origin_server_ts;
+        body["unsigned"]         = event.unsigned_data;
+
+        // relations are unencrypted in content...
+        mtx::common::add_relations(body["content"], event.content.relations);
+
+        mtx::events::collections::TimelineEvent te;
+        mtx::events::collections::from_json(body, te);
+
+        return {DecryptionErrorCode::NoError, std::nullopt, std::move(te.data)};
+    } catch (std::exception &e) {
+        return {DecryptionErrorCode::ParsingFailed, e.what(), std::nullopt};
+    }
 }
 
 crypto::Trust
 calculate_trust(const std::string &user_id, const MegolmSessionIndex &index)
 {
-        auto status              = cache::client()->verificationStatus(user_id);
-        auto megolmData          = cache::client()->getMegolmSessionData(index);
-        crypto::Trust trustlevel = crypto::Trust::Unverified;
+    auto status              = cache::client()->verificationStatus(user_id);
+    auto megolmData          = cache::client()->getMegolmSessionData(index);
+    crypto::Trust trustlevel = crypto::Trust::Unverified;
 
-        if (megolmData && megolmData->trusted &&
-            status.verified_device_keys.count(index.sender_key))
-                trustlevel = status.verified_device_keys.at(index.sender_key);
+    if (megolmData && megolmData->trusted && status.verified_device_keys.count(index.sender_key))
+        trustlevel = status.verified_device_keys.at(index.sender_key);
 
-        return trustlevel;
+    return trustlevel;
 }
 
 //! Send encrypted to device messages, targets is a map from userid to device ids or {} for all
@@ -1292,397 +1193,352 @@ send_encrypted_to_device_messages(const std::map<std::string, std::vector<std::s
                                   const mtx::events::collections::DeviceEvents &event,
                                   bool force_new_session)
 {
-        static QMap<QPair<std::string, std::string>, qint64> rateLimit;
+    static QMap<QPair<std::string, std::string>, qint64> rateLimit;
 
-        nlohmann::json ev_json = std::visit([](const auto &e) { return json(e); }, event);
+    nlohmann::json ev_json = std::visit([](const auto &e) { return json(e); }, event);
 
-        std::map<std::string, std::vector<std::string>> keysToQuery;
-        mtx::requests::ClaimKeys claims;
-        std::map<mtx::identifiers::User, std::map<std::string, mtx::events::msg::OlmEncrypted>>
-          messages;
-        std::map<std::string, std::map<std::string, DevicePublicKeys>> pks;
+    std::map<std::string, std::vector<std::string>> keysToQuery;
+    mtx::requests::ClaimKeys claims;
+    std::map<mtx::identifiers::User, std::map<std::string, mtx::events::msg::OlmEncrypted>>
+      messages;
+    std::map<std::string, std::map<std::string, DevicePublicKeys>> pks;
 
-        auto our_curve = olm::client()->identity_keys().curve25519;
+    auto our_curve = olm::client()->identity_keys().curve25519;
 
-        for (const auto &[user, devices] : targets) {
-                auto deviceKeys = cache::client()->userKeys(user);
+    for (const auto &[user, devices] : targets) {
+        auto deviceKeys = cache::client()->userKeys(user);
 
-                // no keys for user, query them
-                if (!deviceKeys) {
-                        keysToQuery[user] = devices;
-                        continue;
+        // no keys for user, query them
+        if (!deviceKeys) {
+            keysToQuery[user] = devices;
+            continue;
+        }
+
+        auto deviceTargets = devices;
+        if (devices.empty()) {
+            deviceTargets.clear();
+            for (const auto &[device, keys] : deviceKeys->device_keys) {
+                (void)keys;
+                deviceTargets.push_back(device);
+            }
+        }
+
+        for (const auto &device : deviceTargets) {
+            if (!deviceKeys->device_keys.count(device)) {
+                keysToQuery[user] = {};
+                break;
+            }
+
+            auto d = deviceKeys->device_keys.at(device);
+
+            if (!d.keys.count("curve25519:" + device) || !d.keys.count("ed25519:" + device)) {
+                nhlog::crypto()->warn("Skipping device {} since it has no keys!", device);
+                continue;
+            }
+
+            auto device_curve = d.keys.at("curve25519:" + device);
+            if (device_curve == our_curve) {
+                nhlog::crypto()->warn("Skipping our own device, since sending "
+                                      "ourselves olm messages makes no sense.");
+                continue;
+            }
+
+            auto session = cache::getLatestOlmSession(device_curve);
+            if (!session || force_new_session) {
+                auto currentTime = QDateTime::currentSecsSinceEpoch();
+                if (rateLimit.value(QPair(user, device)) + 60 * 60 * 10 < currentTime) {
+                    claims.one_time_keys[user][device] = mtx::crypto::SIGNED_CURVE25519;
+                    pks[user][device].ed25519          = d.keys.at("ed25519:" + device);
+                    pks[user][device].curve25519       = d.keys.at("curve25519:" + device);
+
+                    rateLimit.insert(QPair(user, device), currentTime);
+                } else {
+                    nhlog::crypto()->warn("Not creating new session with {}:{} "
+                                          "because of rate limit",
+                                          user,
+                                          device);
                 }
+                continue;
+            }
+
+            messages[mtx::identifiers::parse<mtx::identifiers::User>(user)][device] =
+              olm::client()
+                ->create_olm_encrypted_content(session->get(),
+                                               ev_json,
+                                               UserId(user),
+                                               d.keys.at("ed25519:" + device),
+                                               device_curve)
+                .get<mtx::events::msg::OlmEncrypted>();
+
+            try {
+                nhlog::crypto()->debug("Updated olm session: {}",
+                                       mtx::crypto::session_id(session->get()));
+                cache::saveOlmSession(d.keys.at("curve25519:" + device),
+                                      std::move(*session),
+                                      QDateTime::currentMSecsSinceEpoch());
+            } catch (const lmdb::error &e) {
+                nhlog::db()->critical("failed to save outbound olm session: {}", e.what());
+            } catch (const mtx::crypto::olm_exception &e) {
+                nhlog::crypto()->critical("failed to pickle outbound olm session: {}", e.what());
+            }
+        }
+    }
+
+    if (!messages.empty())
+        http::client()->send_to_device<mtx::events::msg::OlmEncrypted>(
+          http::client()->generate_txn_id(), messages, [](mtx::http::RequestErr err) {
+              if (err) {
+                  nhlog::net()->warn("failed to send "
+                                     "send_to_device "
+                                     "message: {}",
+                                     err->matrix_error.error);
+              }
+          });
 
-                auto deviceTargets = devices;
-                if (devices.empty()) {
-                        deviceTargets.clear();
-                        for (const auto &[device, keys] : deviceKeys->device_keys) {
-                                (void)keys;
-                                deviceTargets.push_back(device);
-                        }
+    auto BindPks = [ev_json](decltype(pks) pks_temp) {
+        return [pks = pks_temp, ev_json](const mtx::responses::ClaimKeys &res,
+                                         mtx::http::RequestErr) {
+            std::map<mtx::identifiers::User, std::map<std::string, mtx::events::msg::OlmEncrypted>>
+              messages;
+            for (const auto &[user_id, retrieved_devices] : res.one_time_keys) {
+                nhlog::net()->debug("claimed keys for {}", user_id);
+                if (retrieved_devices.size() == 0) {
+                    nhlog::net()->debug("no one-time keys found for user_id: {}", user_id);
+                    continue;
                 }
 
-                for (const auto &device : deviceTargets) {
-                        if (!deviceKeys->device_keys.count(device)) {
-                                keysToQuery[user] = {};
-                                break;
-                        }
+                for (const auto &rd : retrieved_devices) {
+                    const auto device_id = rd.first;
 
-                        auto d = deviceKeys->device_keys.at(device);
+                    nhlog::net()->debug("{} : \n {}", device_id, rd.second.dump(2));
 
-                        if (!d.keys.count("curve25519:" + device) ||
-                            !d.keys.count("ed25519:" + device)) {
-                                nhlog::crypto()->warn("Skipping device {} since it has no keys!",
-                                                      device);
-                                continue;
-                        }
+                    if (rd.second.empty() || !rd.second.begin()->contains("key")) {
+                        nhlog::net()->warn("Skipping device {} as it has no key.", device_id);
+                        continue;
+                    }
 
-                        auto device_curve = d.keys.at("curve25519:" + device);
-                        if (device_curve == our_curve) {
-                                nhlog::crypto()->warn("Skipping our own device, since sending "
-                                                      "ourselves olm messages makes no sense.");
-                                continue;
-                        }
+                    auto otk = rd.second.begin()->at("key");
 
-                        auto session = cache::getLatestOlmSession(device_curve);
-                        if (!session || force_new_session) {
-                                auto currentTime = QDateTime::currentSecsSinceEpoch();
-                                if (rateLimit.value(QPair(user, device)) + 60 * 60 * 10 <
-                                    currentTime) {
-                                        claims.one_time_keys[user][device] =
-                                          mtx::crypto::SIGNED_CURVE25519;
-                                        pks[user][device].ed25519 = d.keys.at("ed25519:" + device);
-                                        pks[user][device].curve25519 =
-                                          d.keys.at("curve25519:" + device);
-
-                                        rateLimit.insert(QPair(user, device), currentTime);
-                                } else {
-                                        nhlog::crypto()->warn("Not creating new session with {}:{} "
-                                                              "because of rate limit",
-                                                              user,
-                                                              device);
-                                }
-                                continue;
-                        }
+                    auto sign_key = pks.at(user_id).at(device_id).ed25519;
+                    auto id_key   = pks.at(user_id).at(device_id).curve25519;
+
+                    // Verify signature
+                    {
+                        auto signedKey = *rd.second.begin();
+                        std::string signature =
+                          signedKey["signatures"][user_id].value("ed25519:" + device_id, "");
 
-                        messages[mtx::identifiers::parse<mtx::identifiers::User>(user)][device] =
-                          olm::client()
-                            ->create_olm_encrypted_content(session->get(),
-                                                           ev_json,
-                                                           UserId(user),
-                                                           d.keys.at("ed25519:" + device),
-                                                           device_curve)
-                            .get<mtx::events::msg::OlmEncrypted>();
-
-                        try {
-                                nhlog::crypto()->debug("Updated olm session: {}",
-                                                       mtx::crypto::session_id(session->get()));
-                                cache::saveOlmSession(d.keys.at("curve25519:" + device),
-                                                      std::move(*session),
-                                                      QDateTime::currentMSecsSinceEpoch());
-                        } catch (const lmdb::error &e) {
-                                nhlog::db()->critical("failed to save outbound olm session: {}",
-                                                      e.what());
-                        } catch (const mtx::crypto::olm_exception &e) {
-                                nhlog::crypto()->critical(
-                                  "failed to pickle outbound olm session: {}", e.what());
+                        if (signature.empty() || !mtx::crypto::ed25519_verify_signature(
+                                                   sign_key, signedKey, signature)) {
+                            nhlog::net()->warn("Skipping device {} as its one time key "
+                                               "has an invalid signature.",
+                                               device_id);
+                            continue;
                         }
+                    }
+
+                    auto session = olm::client()->create_outbound_session(id_key, otk);
+
+                    messages[mtx::identifiers::parse<mtx::identifiers::User>(user_id)][device_id] =
+                      olm::client()
+                        ->create_olm_encrypted_content(
+                          session.get(), ev_json, UserId(user_id), sign_key, id_key)
+                        .get<mtx::events::msg::OlmEncrypted>();
+
+                    try {
+                        nhlog::crypto()->debug("Updated olm session: {}",
+                                               mtx::crypto::session_id(session.get()));
+                        cache::saveOlmSession(
+                          id_key, std::move(session), QDateTime::currentMSecsSinceEpoch());
+                    } catch (const lmdb::error &e) {
+                        nhlog::db()->critical("failed to save outbound olm session: {}", e.what());
+                    } catch (const mtx::crypto::olm_exception &e) {
+                        nhlog::crypto()->critical("failed to pickle outbound olm session: {}",
+                                                  e.what());
+                    }
                 }
-        }
+                nhlog::net()->info("send_to_device: {}", user_id);
+            }
 
-        if (!messages.empty())
+            if (!messages.empty())
                 http::client()->send_to_device<mtx::events::msg::OlmEncrypted>(
                   http::client()->generate_txn_id(), messages, [](mtx::http::RequestErr err) {
-                          if (err) {
-                                  nhlog::net()->warn("failed to send "
-                                                     "send_to_device "
-                                                     "message: {}",
-                                                     err->matrix_error.error);
-                          }
+                      if (err) {
+                          nhlog::net()->warn("failed to send "
+                                             "send_to_device "
+                                             "message: {}",
+                                             err->matrix_error.error);
+                      }
                   });
-
-        auto BindPks = [ev_json](decltype(pks) pks_temp) {
-                return [pks = pks_temp, ev_json](const mtx::responses::ClaimKeys &res,
-                                                 mtx::http::RequestErr) {
-                        std::map<mtx::identifiers::User,
-                                 std::map<std::string, mtx::events::msg::OlmEncrypted>>
-                          messages;
-                        for (const auto &[user_id, retrieved_devices] : res.one_time_keys) {
-                                nhlog::net()->debug("claimed keys for {}", user_id);
-                                if (retrieved_devices.size() == 0) {
-                                        nhlog::net()->debug(
-                                          "no one-time keys found for user_id: {}", user_id);
-                                        continue;
-                                }
-
-                                for (const auto &rd : retrieved_devices) {
-                                        const auto device_id = rd.first;
-
-                                        nhlog::net()->debug(
-                                          "{} : \n {}", device_id, rd.second.dump(2));
-
-                                        if (rd.second.empty() ||
-                                            !rd.second.begin()->contains("key")) {
-                                                nhlog::net()->warn(
-                                                  "Skipping device {} as it has no key.",
-                                                  device_id);
-                                                continue;
-                                        }
-
-                                        auto otk = rd.second.begin()->at("key");
-
-                                        auto sign_key = pks.at(user_id).at(device_id).ed25519;
-                                        auto id_key   = pks.at(user_id).at(device_id).curve25519;
-
-                                        // Verify signature
-                                        {
-                                                auto signedKey = *rd.second.begin();
-                                                std::string signature =
-                                                  signedKey["signatures"][user_id].value(
-                                                    "ed25519:" + device_id, "");
-
-                                                if (signature.empty() ||
-                                                    !mtx::crypto::ed25519_verify_signature(
-                                                      sign_key, signedKey, signature)) {
-                                                        nhlog::net()->warn(
-                                                          "Skipping device {} as its one time key "
-                                                          "has an invalid signature.",
-                                                          device_id);
-                                                        continue;
-                                                }
-                                        }
-
-                                        auto session =
-                                          olm::client()->create_outbound_session(id_key, otk);
-
-                                        messages[mtx::identifiers::parse<mtx::identifiers::User>(
-                                          user_id)][device_id] =
-                                          olm::client()
-                                            ->create_olm_encrypted_content(session.get(),
-                                                                           ev_json,
-                                                                           UserId(user_id),
-                                                                           sign_key,
-                                                                           id_key)
-                                            .get<mtx::events::msg::OlmEncrypted>();
-
-                                        try {
-                                                nhlog::crypto()->debug(
-                                                  "Updated olm session: {}",
-                                                  mtx::crypto::session_id(session.get()));
-                                                cache::saveOlmSession(
-                                                  id_key,
-                                                  std::move(session),
-                                                  QDateTime::currentMSecsSinceEpoch());
-                                        } catch (const lmdb::error &e) {
-                                                nhlog::db()->critical(
-                                                  "failed to save outbound olm session: {}",
-                                                  e.what());
-                                        } catch (const mtx::crypto::olm_exception &e) {
-                                                nhlog::crypto()->critical(
-                                                  "failed to pickle outbound olm session: {}",
-                                                  e.what());
-                                        }
-                                }
-                                nhlog::net()->info("send_to_device: {}", user_id);
-                        }
-
-                        if (!messages.empty())
-                                http::client()->send_to_device<mtx::events::msg::OlmEncrypted>(
-                                  http::client()->generate_txn_id(),
-                                  messages,
-                                  [](mtx::http::RequestErr err) {
-                                          if (err) {
-                                                  nhlog::net()->warn("failed to send "
-                                                                     "send_to_device "
-                                                                     "message: {}",
-                                                                     err->matrix_error.error);
-                                          }
-                                  });
-                };
         };
-
-        if (!claims.one_time_keys.empty())
-                http::client()->claim_keys(claims, BindPks(pks));
-
-        if (!keysToQuery.empty()) {
-                mtx::requests::QueryKeys req;
-                req.device_keys = keysToQuery;
-                http::client()->query_keys(
-                  req,
-                  [ev_json, BindPks, our_curve](const mtx::responses::QueryKeys &res,
-                                                mtx::http::RequestErr err) {
-                          if (err) {
-                                  nhlog::net()->warn("failed to query device keys: {} {}",
-                                                     err->matrix_error.error,
-                                                     static_cast<int>(err->status_code));
-                                  return;
-                          }
-
-                          nhlog::net()->info("queried keys");
-
-                          cache::client()->updateUserKeys(cache::nextBatchToken(), res);
-
-                          mtx::requests::ClaimKeys claim_keys;
-
-                          std::map<std::string, std::map<std::string, DevicePublicKeys>> deviceKeys;
-
-                          for (const auto &user : res.device_keys) {
-                                  for (const auto &dev : user.second) {
-                                          const auto user_id   = ::UserId(dev.second.user_id);
-                                          const auto device_id = DeviceId(dev.second.device_id);
-
-                                          if (user_id.get() ==
-                                                http::client()->user_id().to_string() &&
-                                              device_id.get() == http::client()->device_id())
-                                                  continue;
-
-                                          const auto device_keys = dev.second.keys;
-                                          const auto curveKey    = "curve25519:" + device_id.get();
-                                          const auto edKey       = "ed25519:" + device_id.get();
-
-                                          if ((device_keys.find(curveKey) == device_keys.end()) ||
-                                              (device_keys.find(edKey) == device_keys.end())) {
-                                                  nhlog::net()->debug(
-                                                    "ignoring malformed keys for device {}",
-                                                    device_id.get());
-                                                  continue;
-                                          }
-
-                                          DevicePublicKeys pks;
-                                          pks.ed25519    = device_keys.at(edKey);
-                                          pks.curve25519 = device_keys.at(curveKey);
-
-                                          if (pks.curve25519 == our_curve) {
-                                                  nhlog::crypto()->warn(
-                                                    "Skipping our own device, since sending "
-                                                    "ourselves olm messages makes no sense.");
-                                                  continue;
-                                          }
-
-                                          try {
-                                                  if (!mtx::crypto::verify_identity_signature(
-                                                        dev.second, device_id, user_id)) {
-                                                          nhlog::crypto()->warn(
-                                                            "failed to verify identity keys: {}",
-                                                            json(dev.second).dump(2));
-                                                          continue;
-                                                  }
-                                          } catch (const json::exception &e) {
-                                                  nhlog::crypto()->warn(
-                                                    "failed to parse device key json: {}",
-                                                    e.what());
-                                                  continue;
-                                          } catch (const mtx::crypto::olm_exception &e) {
-                                                  nhlog::crypto()->warn(
-                                                    "failed to verify device key json: {}",
-                                                    e.what());
-                                                  continue;
-                                          }
-
-                                          auto currentTime = QDateTime::currentSecsSinceEpoch();
-                                          if (rateLimit.value(QPair(user.first, device_id.get())) +
-                                                60 * 60 * 10 <
-                                              currentTime) {
-                                                  deviceKeys[user_id].emplace(device_id, pks);
-                                                  claim_keys.one_time_keys[user.first][device_id] =
-                                                    mtx::crypto::SIGNED_CURVE25519;
-
-                                                  rateLimit.insert(
-                                                    QPair(user.first, device_id.get()),
-                                                    currentTime);
-                                          } else {
-                                                  nhlog::crypto()->warn(
-                                                    "Not creating new session with {}:{} "
-                                                    "because of rate limit",
-                                                    user.first,
-                                                    device_id.get());
-                                                  continue;
-                                          }
-
-                                          nhlog::net()->info("{}", device_id.get());
-                                          nhlog::net()->info("  curve25519 {}", pks.curve25519);
-                                          nhlog::net()->info("  ed25519 {}", pks.ed25519);
-                                  }
+    };
+
+    if (!claims.one_time_keys.empty())
+        http::client()->claim_keys(claims, BindPks(pks));
+
+    if (!keysToQuery.empty()) {
+        mtx::requests::QueryKeys req;
+        req.device_keys = keysToQuery;
+        http::client()->query_keys(
+          req,
+          [ev_json, BindPks, our_curve](const mtx::responses::QueryKeys &res,
+                                        mtx::http::RequestErr err) {
+              if (err) {
+                  nhlog::net()->warn("failed to query device keys: {} {}",
+                                     err->matrix_error.error,
+                                     static_cast<int>(err->status_code));
+                  return;
+              }
+
+              nhlog::net()->info("queried keys");
+
+              cache::client()->updateUserKeys(cache::nextBatchToken(), res);
+
+              mtx::requests::ClaimKeys claim_keys;
+
+              std::map<std::string, std::map<std::string, DevicePublicKeys>> deviceKeys;
+
+              for (const auto &user : res.device_keys) {
+                  for (const auto &dev : user.second) {
+                      const auto user_id   = ::UserId(dev.second.user_id);
+                      const auto device_id = DeviceId(dev.second.device_id);
+
+                      if (user_id.get() == http::client()->user_id().to_string() &&
+                          device_id.get() == http::client()->device_id())
+                          continue;
+
+                      const auto device_keys = dev.second.keys;
+                      const auto curveKey    = "curve25519:" + device_id.get();
+                      const auto edKey       = "ed25519:" + device_id.get();
+
+                      if ((device_keys.find(curveKey) == device_keys.end()) ||
+                          (device_keys.find(edKey) == device_keys.end())) {
+                          nhlog::net()->debug("ignoring malformed keys for device {}",
+                                              device_id.get());
+                          continue;
+                      }
+
+                      DevicePublicKeys pks;
+                      pks.ed25519    = device_keys.at(edKey);
+                      pks.curve25519 = device_keys.at(curveKey);
+
+                      if (pks.curve25519 == our_curve) {
+                          nhlog::crypto()->warn("Skipping our own device, since sending "
+                                                "ourselves olm messages makes no sense.");
+                          continue;
+                      }
+
+                      try {
+                          if (!mtx::crypto::verify_identity_signature(
+                                dev.second, device_id, user_id)) {
+                              nhlog::crypto()->warn("failed to verify identity keys: {}",
+                                                    json(dev.second).dump(2));
+                              continue;
                           }
+                      } catch (const json::exception &e) {
+                          nhlog::crypto()->warn("failed to parse device key json: {}", e.what());
+                          continue;
+                      } catch (const mtx::crypto::olm_exception &e) {
+                          nhlog::crypto()->warn("failed to verify device key json: {}", e.what());
+                          continue;
+                      }
+
+                      auto currentTime = QDateTime::currentSecsSinceEpoch();
+                      if (rateLimit.value(QPair(user.first, device_id.get())) + 60 * 60 * 10 <
+                          currentTime) {
+                          deviceKeys[user_id].emplace(device_id, pks);
+                          claim_keys.one_time_keys[user.first][device_id] =
+                            mtx::crypto::SIGNED_CURVE25519;
+
+                          rateLimit.insert(QPair(user.first, device_id.get()), currentTime);
+                      } else {
+                          nhlog::crypto()->warn("Not creating new session with {}:{} "
+                                                "because of rate limit",
+                                                user.first,
+                                                device_id.get());
+                          continue;
+                      }
+
+                      nhlog::net()->info("{}", device_id.get());
+                      nhlog::net()->info("  curve25519 {}", pks.curve25519);
+                      nhlog::net()->info("  ed25519 {}", pks.ed25519);
+                  }
+              }
 
-                          if (!claim_keys.one_time_keys.empty())
-                                  http::client()->claim_keys(claim_keys, BindPks(deviceKeys));
-                  });
-        }
+              if (!claim_keys.one_time_keys.empty())
+                  http::client()->claim_keys(claim_keys, BindPks(deviceKeys));
+          });
+    }
 }
 
 void
 request_cross_signing_keys()
 {
-        mtx::events::msg::SecretRequest secretRequest{};
-        secretRequest.action               = mtx::events::msg::RequestAction::Request;
-        secretRequest.requesting_device_id = http::client()->device_id();
+    mtx::events::msg::SecretRequest secretRequest{};
+    secretRequest.action               = mtx::events::msg::RequestAction::Request;
+    secretRequest.requesting_device_id = http::client()->device_id();
 
-        auto local_user = http::client()->user_id();
+    auto local_user = http::client()->user_id();
 
-        auto verificationStatus = cache::verificationStatus(local_user.to_string());
+    auto verificationStatus = cache::verificationStatus(local_user.to_string());
 
-        if (!verificationStatus)
-                return;
+    if (!verificationStatus)
+        return;
 
-        auto request = [&](std::string secretName) {
-                secretRequest.name       = secretName;
-                secretRequest.request_id = "ss." + http::client()->generate_txn_id();
+    auto request = [&](std::string secretName) {
+        secretRequest.name       = secretName;
+        secretRequest.request_id = "ss." + http::client()->generate_txn_id();
 
-                request_id_to_secret_name[secretRequest.request_id] = secretRequest.name;
+        request_id_to_secret_name[secretRequest.request_id] = secretRequest.name;
 
-                std::map<mtx::identifiers::User,
-                         std::map<std::string, mtx::events::msg::SecretRequest>>
-                  body;
+        std::map<mtx::identifiers::User, std::map<std::string, mtx::events::msg::SecretRequest>>
+          body;
 
-                for (const auto &dev : verificationStatus->verified_devices) {
-                        if (dev != secretRequest.requesting_device_id)
-                                body[local_user][dev] = secretRequest;
-                }
+        for (const auto &dev : verificationStatus->verified_devices) {
+            if (dev != secretRequest.requesting_device_id)
+                body[local_user][dev] = secretRequest;
+        }
+
+        http::client()->send_to_device<mtx::events::msg::SecretRequest>(
+          http::client()->generate_txn_id(),
+          body,
+          [request_id = secretRequest.request_id, secretName](mtx::http::RequestErr err) {
+              if (err) {
+                  nhlog::net()->error("Failed to send request for secrect '{}'", secretName);
+                  // Cancel request on UI thread
+                  QTimer::singleShot(1, cache::client(), [request_id]() {
+                      request_id_to_secret_name.erase(request_id);
+                  });
+                  return;
+              }
+          });
 
+        for (const auto &dev : verificationStatus->verified_devices) {
+            if (dev != secretRequest.requesting_device_id)
+                body[local_user][dev].action = mtx::events::msg::RequestAction::Cancellation;
+        }
+
+        // timeout after 15 min
+        QTimer::singleShot(15 * 60 * 1000, [secretRequest, body]() {
+            if (request_id_to_secret_name.count(secretRequest.request_id)) {
+                request_id_to_secret_name.erase(secretRequest.request_id);
                 http::client()->send_to_device<mtx::events::msg::SecretRequest>(
                   http::client()->generate_txn_id(),
                   body,
-                  [request_id = secretRequest.request_id, secretName](mtx::http::RequestErr err) {
-                          if (err) {
-                                  nhlog::net()->error("Failed to send request for secrect '{}'",
-                                                      secretName);
-                                  // Cancel request on UI thread
-                                  QTimer::singleShot(1, cache::client(), [request_id]() {
-                                          request_id_to_secret_name.erase(request_id);
-                                  });
-                                  return;
-                          }
+                  [secretRequest](mtx::http::RequestErr err) {
+                      if (err) {
+                          nhlog::net()->error("Failed to cancel request for secrect '{}'",
+                                              secretRequest.name);
+                          return;
+                      }
                   });
+            }
+        });
+    };
 
-                for (const auto &dev : verificationStatus->verified_devices) {
-                        if (dev != secretRequest.requesting_device_id)
-                                body[local_user][dev].action =
-                                  mtx::events::msg::RequestAction::Cancellation;
-                }
-
-                // timeout after 15 min
-                QTimer::singleShot(15 * 60 * 1000, [secretRequest, body]() {
-                        if (request_id_to_secret_name.count(secretRequest.request_id)) {
-                                request_id_to_secret_name.erase(secretRequest.request_id);
-                                http::client()->send_to_device<mtx::events::msg::SecretRequest>(
-                                  http::client()->generate_txn_id(),
-                                  body,
-                                  [secretRequest](mtx::http::RequestErr err) {
-                                          if (err) {
-                                                  nhlog::net()->error(
-                                                    "Failed to cancel request for secrect '{}'",
-                                                    secretRequest.name);
-                                                  return;
-                                          }
-                                  });
-                        }
-                });
-        };
-
-        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(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);
 }
 
 namespace {
@@ -1690,67 +1546,63 @@ void
 unlock_secrets(const std::string &key,
                const std::map<std::string, mtx::secret_storage::AesHmacSha2EncryptedData> &secrets)
 {
-        http::client()->secret_storage_key(
-          key,
-          [secrets](mtx::secret_storage::AesHmacSha2KeyDescription keyDesc,
-                    mtx::http::RequestErr err) {
-                  if (err) {
-                          nhlog::net()->error("Failed to download secret storage key");
-                          return;
-                  }
-
-                  emit ChatPage::instance()->downloadedSecrets(keyDesc, secrets);
-          });
+    http::client()->secret_storage_key(
+      key,
+      [secrets](mtx::secret_storage::AesHmacSha2KeyDescription keyDesc, mtx::http::RequestErr err) {
+          if (err) {
+              nhlog::net()->error("Failed to download secret storage key");
+              return;
+          }
+
+          emit ChatPage::instance()->downloadedSecrets(keyDesc, secrets);
+      });
 }
 }
 
 void
 download_cross_signing_keys()
 {
-        using namespace mtx::secret_storage;
-        http::client()->secret_storage_secret(
-          secrets::megolm_backup_v1, [](Secret secret, mtx::http::RequestErr err) {
-                  std::optional<Secret> backup_key;
-                  if (!err)
-                          backup_key = secret;
-
-                  http::client()->secret_storage_secret(
-                    secrets::cross_signing_self_signing,
-                    [backup_key](Secret secret, mtx::http::RequestErr err) {
-                            std::optional<Secret> self_signing_key;
-                            if (!err)
-                                    self_signing_key = secret;
-
-                            http::client()->secret_storage_secret(
-                              secrets::cross_signing_user_signing,
-                              [backup_key, self_signing_key](Secret secret,
-                                                             mtx::http::RequestErr err) {
-                                      std::optional<Secret> user_signing_key;
-                                      if (!err)
-                                              user_signing_key = secret;
-
-                                      std::map<std::string,
-                                               std::map<std::string, AesHmacSha2EncryptedData>>
-                                        secrets;
-
-                                      if (backup_key && !backup_key->encrypted.empty())
-                                              secrets[backup_key->encrypted.begin()->first]
-                                                     [secrets::megolm_backup_v1] =
-                                                       backup_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] =
-                                                       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] =
-                                                       user_signing_key->encrypted.begin()->second;
-
-                                      for (const auto &[key, secrets] : secrets)
-                                              unlock_secrets(key, secrets);
-                              });
-                    });
-          });
+    using namespace mtx::secret_storage;
+    http::client()->secret_storage_secret(
+      secrets::megolm_backup_v1, [](Secret secret, mtx::http::RequestErr err) {
+          std::optional<Secret> backup_key;
+          if (!err)
+              backup_key = secret;
+
+          http::client()->secret_storage_secret(
+            secrets::cross_signing_self_signing,
+            [backup_key](Secret secret, mtx::http::RequestErr err) {
+                std::optional<Secret> self_signing_key;
+                if (!err)
+                    self_signing_key = secret;
+
+                http::client()->secret_storage_secret(
+                  secrets::cross_signing_user_signing,
+                  [backup_key, self_signing_key](Secret secret, mtx::http::RequestErr err) {
+                      std::optional<Secret> user_signing_key;
+                      if (!err)
+                          user_signing_key = secret;
+
+                      std::map<std::string, std::map<std::string, AesHmacSha2EncryptedData>>
+                        secrets;
+
+                      if (backup_key && !backup_key->encrypted.empty())
+                          secrets[backup_key->encrypted.begin()->first][secrets::megolm_backup_v1] =
+                            backup_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] =
+                                   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] =
+                                   user_signing_key->encrypted.begin()->second;
+
+                      for (const auto &[key, secrets] : secrets)
+                          unlock_secrets(key, secrets);
+                  });
+            });
+      });
 }
 
 } // namespace olm
diff --git a/src/Olm.h b/src/Olm.h
index eb60ae3a..44e2b8ed 100644
--- a/src/Olm.h
+++ b/src/Olm.h
@@ -18,32 +18,32 @@ Q_NAMESPACE
 
 enum DecryptionErrorCode
 {
-        NoError,
-        MissingSession, // Session was not found, retrieve from backup or request from other devices
-                        // and try again
-        MissingSessionIndex, // Session was found, but it does not reach back enough to this index,
-                             // retrieve from backup or request from other devices and try again
-        DbError,             // DB read failed
-        DecryptionFailed,    // libolm error
-        ParsingFailed,       // Failed to parse the actual event
-        ReplayAttack,        // Megolm index reused
+    NoError,
+    MissingSession, // Session was not found, retrieve from backup or request from other devices
+                    // and try again
+    MissingSessionIndex, // Session was found, but it does not reach back enough to this index,
+                         // retrieve from backup or request from other devices and try again
+    DbError,             // DB read failed
+    DecryptionFailed,    // libolm error
+    ParsingFailed,       // Failed to parse the actual event
+    ReplayAttack,        // Megolm index reused
 };
 Q_ENUM_NS(DecryptionErrorCode)
 
 struct DecryptionResult
 {
-        DecryptionErrorCode error;
-        std::optional<std::string> error_message;
-        std::optional<mtx::events::collections::TimelineEvents> event;
+    DecryptionErrorCode error;
+    std::optional<std::string> error_message;
+    std::optional<mtx::events::collections::TimelineEvents> event;
 };
 
 struct OlmMessage
 {
-        std::string sender_key;
-        std::string sender;
+    std::string sender_key;
+    std::string sender;
 
-        using RecipientKey = std::string;
-        std::map<RecipientKey, mtx::events::msg::OlmCipherContent> ciphertext;
+    using RecipientKey = std::string;
+    std::map<RecipientKey, mtx::events::msg::OlmCipherContent> ciphertext;
 };
 
 void
diff --git a/src/ReadReceiptsModel.cpp b/src/ReadReceiptsModel.cpp
index 25262c59..ff93f7d8 100644
--- a/src/ReadReceiptsModel.cpp
+++ b/src/ReadReceiptsModel.cpp
@@ -16,116 +16,115 @@ ReadReceiptsModel::ReadReceiptsModel(QString event_id, QString room_id, QObject
   , event_id_{event_id}
   , room_id_{room_id}
 {
-        try {
-                addUsers(cache::readReceipts(event_id_, room_id_));
-        } catch (const lmdb::error &) {
-                nhlog::db()->warn("failed to retrieve read receipts for {} {}",
-                                  event_id_.toStdString(),
-                                  room_id_.toStdString());
-
-                return;
-        }
+    try {
+        addUsers(cache::readReceipts(event_id_, room_id_));
+    } catch (const lmdb::error &) {
+        nhlog::db()->warn("failed to retrieve read receipts for {} {}",
+                          event_id_.toStdString(),
+                          room_id_.toStdString());
+
+        return;
+    }
 
-        connect(cache::client(), &Cache::newReadReceipts, this, &ReadReceiptsModel::update);
+    connect(cache::client(), &Cache::newReadReceipts, this, &ReadReceiptsModel::update);
 }
 
 void
 ReadReceiptsModel::update()
 {
-        try {
-                addUsers(cache::readReceipts(event_id_, room_id_));
-        } catch (const lmdb::error &) {
-                nhlog::db()->warn("failed to retrieve read receipts for {} {}",
-                                  event_id_.toStdString(),
-                                  room_id_.toStdString());
-
-                return;
-        }
+    try {
+        addUsers(cache::readReceipts(event_id_, room_id_));
+    } catch (const lmdb::error &) {
+        nhlog::db()->warn("failed to retrieve read receipts for {} {}",
+                          event_id_.toStdString(),
+                          room_id_.toStdString());
+
+        return;
+    }
 }
 
 QHash<int, QByteArray>
 ReadReceiptsModel::roleNames() const
 {
-        // Note: RawTimestamp is purposely not included here
-        return {
-          {Mxid, "mxid"},
-          {DisplayName, "displayName"},
-          {AvatarUrl, "avatarUrl"},
-          {Timestamp, "timestamp"},
-        };
+    // Note: RawTimestamp is purposely not included here
+    return {
+      {Mxid, "mxid"},
+      {DisplayName, "displayName"},
+      {AvatarUrl, "avatarUrl"},
+      {Timestamp, "timestamp"},
+    };
 }
 
 QVariant
 ReadReceiptsModel::data(const QModelIndex &index, int role) const
 {
-        if (!index.isValid() || index.row() >= (int)readReceipts_.size() || index.row() < 0)
-                return {};
-
-        switch (role) {
-        case Mxid:
-                return readReceipts_[index.row()].first;
-        case DisplayName:
-                return cache::displayName(room_id_, readReceipts_[index.row()].first);
-        case AvatarUrl:
-                return cache::avatarUrl(room_id_, readReceipts_[index.row()].first);
-        case Timestamp:
-                return dateFormat(readReceipts_[index.row()].second);
-        case RawTimestamp:
-                return readReceipts_[index.row()].second;
-        default:
-                return {};
-        }
+    if (!index.isValid() || index.row() >= (int)readReceipts_.size() || index.row() < 0)
+        return {};
+
+    switch (role) {
+    case Mxid:
+        return readReceipts_[index.row()].first;
+    case DisplayName:
+        return cache::displayName(room_id_, readReceipts_[index.row()].first);
+    case AvatarUrl:
+        return cache::avatarUrl(room_id_, readReceipts_[index.row()].first);
+    case Timestamp:
+        return dateFormat(readReceipts_[index.row()].second);
+    case RawTimestamp:
+        return readReceipts_[index.row()].second;
+    default:
+        return {};
+    }
 }
 
 void
 ReadReceiptsModel::addUsers(
   const std::multimap<uint64_t, std::string, std::greater<uint64_t>> &users)
 {
-        auto newReceipts = users.size() - readReceipts_.size();
-
-        if (newReceipts > 0) {
-                beginInsertRows(
-                  QModelIndex{}, readReceipts_.size(), readReceipts_.size() + newReceipts - 1);
+    auto newReceipts = users.size() - readReceipts_.size();
 
-                for (const auto &user : users) {
-                        QPair<QString, QDateTime> item = {
-                          QString::fromStdString(user.second),
-                          QDateTime::fromMSecsSinceEpoch(user.first)};
-                        if (!readReceipts_.contains(item))
-                                readReceipts_.push_back(item);
-                }
+    if (newReceipts > 0) {
+        beginInsertRows(
+          QModelIndex{}, readReceipts_.size(), readReceipts_.size() + newReceipts - 1);
 
-                endInsertRows();
+        for (const auto &user : users) {
+            QPair<QString, QDateTime> item = {QString::fromStdString(user.second),
+                                              QDateTime::fromMSecsSinceEpoch(user.first)};
+            if (!readReceipts_.contains(item))
+                readReceipts_.push_back(item);
         }
+
+        endInsertRows();
+    }
 }
 
 QString
 ReadReceiptsModel::dateFormat(const QDateTime &then) const
 {
-        auto now  = QDateTime::currentDateTime();
-        auto days = then.daysTo(now);
-
-        if (days == 0)
-                return QLocale::system().toString(then.time(), QLocale::ShortFormat);
-        else if (days < 2)
-                return tr("Yesterday, %1")
-                  .arg(QLocale::system().toString(then.time(), QLocale::ShortFormat));
-        else if (days < 7)
-                //: %1 is the name of the current day, %2 is the time the read receipt was read. The
-                //: result may look like this: Monday, 7:15
-                return QString("%1, %2")
-                  .arg(then.toString("dddd"))
-                  .arg(QLocale::system().toString(then.time(), QLocale::ShortFormat));
+    auto now  = QDateTime::currentDateTime();
+    auto days = then.daysTo(now);
 
+    if (days == 0)
         return QLocale::system().toString(then.time(), QLocale::ShortFormat);
+    else if (days < 2)
+        return tr("Yesterday, %1")
+          .arg(QLocale::system().toString(then.time(), QLocale::ShortFormat));
+    else if (days < 7)
+        //: %1 is the name of the current day, %2 is the time the read receipt was read. The
+        //: result may look like this: Monday, 7:15
+        return QString("%1, %2")
+          .arg(then.toString("dddd"))
+          .arg(QLocale::system().toString(then.time(), QLocale::ShortFormat));
+
+    return QLocale::system().toString(then.time(), QLocale::ShortFormat);
 }
 
 ReadReceiptsProxy::ReadReceiptsProxy(QString event_id, QString room_id, QObject *parent)
   : QSortFilterProxyModel{parent}
   , model_{event_id, room_id, this}
 {
-        setSourceModel(&model_);
-        setSortRole(ReadReceiptsModel::RawTimestamp);
-        sort(0, Qt::DescendingOrder);
-        setDynamicSortFilter(true);
+    setSourceModel(&model_);
+    setSortRole(ReadReceiptsModel::RawTimestamp);
+    sort(0, Qt::DescendingOrder);
+    setDynamicSortFilter(true);
 }
diff --git a/src/ReadReceiptsModel.h b/src/ReadReceiptsModel.h
index 3b45716c..7487fff8 100644
--- a/src/ReadReceiptsModel.h
+++ b/src/ReadReceiptsModel.h
@@ -13,61 +13,61 @@
 
 class ReadReceiptsModel : public QAbstractListModel
 {
-        Q_OBJECT
+    Q_OBJECT
 
 public:
-        enum Roles
-        {
-                Mxid,
-                DisplayName,
-                AvatarUrl,
-                Timestamp,
-                RawTimestamp,
-        };
-
-        explicit ReadReceiptsModel(QString event_id, QString room_id, QObject *parent = nullptr);
-
-        QString eventId() const { return event_id_; }
-        QString roomId() const { return room_id_; }
-
-        QHash<int, QByteArray> roleNames() const override;
-        int rowCount(const QModelIndex &parent) const override
-        {
-                Q_UNUSED(parent)
-                return readReceipts_.size();
-        }
-        QVariant data(const QModelIndex &index, int role) const override;
+    enum Roles
+    {
+        Mxid,
+        DisplayName,
+        AvatarUrl,
+        Timestamp,
+        RawTimestamp,
+    };
+
+    explicit ReadReceiptsModel(QString event_id, QString room_id, QObject *parent = nullptr);
+
+    QString eventId() const { return event_id_; }
+    QString roomId() const { return room_id_; }
+
+    QHash<int, QByteArray> roleNames() const override;
+    int rowCount(const QModelIndex &parent) const override
+    {
+        Q_UNUSED(parent)
+        return readReceipts_.size();
+    }
+    QVariant data(const QModelIndex &index, int role) const override;
 
 public slots:
-        void addUsers(const std::multimap<uint64_t, std::string, std::greater<uint64_t>> &users);
-        void update();
+    void addUsers(const std::multimap<uint64_t, std::string, std::greater<uint64_t>> &users);
+    void update();
 
 private:
-        QString dateFormat(const QDateTime &then) const;
+    QString dateFormat(const QDateTime &then) const;
 
-        QString event_id_;
-        QString room_id_;
-        QVector<QPair<QString, QDateTime>> readReceipts_;
+    QString event_id_;
+    QString room_id_;
+    QVector<QPair<QString, QDateTime>> readReceipts_;
 };
 
 class ReadReceiptsProxy : public QSortFilterProxyModel
 {
-        Q_OBJECT
+    Q_OBJECT
 
-        Q_PROPERTY(QString eventId READ eventId CONSTANT)
-        Q_PROPERTY(QString roomId READ roomId CONSTANT)
+    Q_PROPERTY(QString eventId READ eventId CONSTANT)
+    Q_PROPERTY(QString roomId READ roomId CONSTANT)
 
 public:
-        explicit ReadReceiptsProxy(QString event_id, QString room_id, QObject *parent = nullptr);
+    explicit ReadReceiptsProxy(QString event_id, QString room_id, QObject *parent = nullptr);
 
-        QString eventId() const { return event_id_; }
-        QString roomId() const { return room_id_; }
+    QString eventId() const { return event_id_; }
+    QString roomId() const { return room_id_; }
 
 private:
-        QString event_id_;
-        QString room_id_;
+    QString event_id_;
+    QString room_id_;
 
-        ReadReceiptsModel model_;
+    ReadReceiptsModel model_;
 };
 
 #endif // READRECEIPTSMODEL_H
diff --git a/src/RegisterPage.cpp b/src/RegisterPage.cpp
index fb6a1b97..0204a307 100644
--- a/src/RegisterPage.cpp
+++ b/src/RegisterPage.cpp
@@ -33,496 +33,483 @@ Q_DECLARE_METATYPE(mtx::user_interactive::Auth)
 RegisterPage::RegisterPage(QWidget *parent)
   : QWidget(parent)
 {
-        qRegisterMetaType<mtx::user_interactive::Unauthorized>();
-        qRegisterMetaType<mtx::user_interactive::Auth>();
-        top_layout_ = new QVBoxLayout();
-
-        back_layout_ = new QHBoxLayout();
-        back_layout_->setSpacing(0);
-        back_layout_->setContentsMargins(5, 5, -1, -1);
-
-        back_button_ = new FlatButton(this);
-        back_button_->setMinimumSize(QSize(30, 30));
-
-        QIcon icon;
-        icon.addFile(":/icons/icons/ui/angle-pointing-to-left.png");
-
-        back_button_->setIcon(icon);
-        back_button_->setIconSize(QSize(32, 32));
-
-        back_layout_->addWidget(back_button_, 0, Qt::AlignLeft | Qt::AlignVCenter);
-        back_layout_->addStretch(1);
-
-        QIcon logo;
-        logo.addFile(":/logos/register.png");
-
-        logo_ = new QLabel(this);
-        logo_->setPixmap(logo.pixmap(128));
-
-        logo_layout_ = new QHBoxLayout();
-        logo_layout_->setMargin(0);
-        logo_layout_->addWidget(logo_, 0, Qt::AlignHCenter);
-
-        form_wrapper_ = new QHBoxLayout();
-        form_widget_  = new QWidget();
-        form_widget_->setMinimumSize(QSize(350, 300));
-
-        form_layout_ = new QVBoxLayout();
-        form_layout_->setSpacing(20);
-        form_layout_->setContentsMargins(0, 0, 0, 40);
-        form_widget_->setLayout(form_layout_);
-
-        form_wrapper_->addStretch(1);
-        form_wrapper_->addWidget(form_widget_);
-        form_wrapper_->addStretch(1);
-
-        username_input_ = new TextField();
-        username_input_->setLabel(tr("Username"));
-        username_input_->setRegexp(QRegularExpression("[a-z0-9._=/-]+"));
-        username_input_->setToolTip(tr("The username must not be empty, and must contain only the "
-                                       "characters a-z, 0-9, ., _, =, -, and /."));
-
-        password_input_ = new TextField();
-        password_input_->setLabel(tr("Password"));
-        password_input_->setRegexp(QRegularExpression("^.{8,}$"));
-        password_input_->setEchoMode(QLineEdit::Password);
-        password_input_->setToolTip(tr("Please choose a secure password. The exact requirements "
-                                       "for password strength may depend on your server."));
-
-        password_confirmation_ = new TextField();
-        password_confirmation_->setLabel(tr("Password confirmation"));
-        password_confirmation_->setEchoMode(QLineEdit::Password);
-
-        server_input_ = new TextField();
-        server_input_->setLabel(tr("Homeserver"));
-        server_input_->setRegexp(QRegularExpression(".+"));
-        server_input_->setToolTip(
-          tr("A server that allows registration. Since matrix is decentralized, you need to first "
-             "find a server you can register on or host your own."));
-
-        error_username_label_ = new QLabel(this);
-        error_username_label_->setWordWrap(true);
-        error_username_label_->hide();
-
-        error_password_label_ = new QLabel(this);
-        error_password_label_->setWordWrap(true);
-        error_password_label_->hide();
-
-        error_password_confirmation_label_ = new QLabel(this);
-        error_password_confirmation_label_->setWordWrap(true);
-        error_password_confirmation_label_->hide();
-
-        error_server_label_ = new QLabel(this);
-        error_server_label_->setWordWrap(true);
-        error_server_label_->hide();
-
-        form_layout_->addWidget(username_input_, Qt::AlignHCenter);
-        form_layout_->addWidget(error_username_label_, Qt::AlignHCenter);
-        form_layout_->addWidget(password_input_, Qt::AlignHCenter);
-        form_layout_->addWidget(error_password_label_, Qt::AlignHCenter);
-        form_layout_->addWidget(password_confirmation_, Qt::AlignHCenter);
-        form_layout_->addWidget(error_password_confirmation_label_, Qt::AlignHCenter);
-        form_layout_->addWidget(server_input_, Qt::AlignHCenter);
-        form_layout_->addWidget(error_server_label_, Qt::AlignHCenter);
-
-        button_layout_ = new QHBoxLayout();
-        button_layout_->setSpacing(0);
-        button_layout_->setMargin(0);
-
-        error_label_ = new QLabel(this);
-        error_label_->setWordWrap(true);
-
-        register_button_ = new RaisedButton(tr("REGISTER"), this);
-        register_button_->setMinimumSize(350, 65);
-        register_button_->setFontSize(conf::btn::fontSize);
-        register_button_->setCornerRadius(conf::btn::cornerRadius);
-
-        button_layout_->addStretch(1);
-        button_layout_->addWidget(register_button_);
-        button_layout_->addStretch(1);
-
-        top_layout_->addLayout(back_layout_);
-        top_layout_->addLayout(logo_layout_);
-        top_layout_->addLayout(form_wrapper_);
-        top_layout_->addStretch(1);
-        top_layout_->addLayout(button_layout_);
-        top_layout_->addWidget(error_label_, 0, Qt::AlignHCenter);
-        top_layout_->addStretch(1);
-        setLayout(top_layout_);
-
-        connect(back_button_, SIGNAL(clicked()), this, SLOT(onBackButtonClicked()));
-        connect(register_button_, SIGNAL(clicked()), this, SLOT(onRegisterButtonClicked()));
-
-        connect(username_input_, SIGNAL(returnPressed()), register_button_, SLOT(click()));
-        connect(username_input_, &TextField::editingFinished, this, &RegisterPage::checkUsername);
-        connect(password_input_, SIGNAL(returnPressed()), register_button_, SLOT(click()));
-        connect(password_input_, &TextField::editingFinished, this, &RegisterPage::checkPassword);
-        connect(password_confirmation_, SIGNAL(returnPressed()), register_button_, SLOT(click()));
-        connect(password_confirmation_,
-                &TextField::editingFinished,
-                this,
-                &RegisterPage::checkPasswordConfirmation);
-        connect(server_input_, SIGNAL(returnPressed()), register_button_, SLOT(click()));
-        connect(server_input_, &TextField::editingFinished, this, &RegisterPage::checkServer);
-
-        connect(
-          this,
-          &RegisterPage::serverError,
-          this,
-          [this](const QString &msg) {
-                  server_input_->setValid(false);
-                  showError(error_server_label_, msg);
-          },
-          Qt::QueuedConnection);
-
-        connect(this, &RegisterPage::wellKnownLookup, this, &RegisterPage::doWellKnownLookup);
-        connect(this, &RegisterPage::versionsCheck, this, &RegisterPage::doVersionsCheck);
-        connect(this, &RegisterPage::registration, this, &RegisterPage::doRegistration);
-        connect(this, &RegisterPage::UIA, this, &RegisterPage::doUIA);
-        connect(
-          this, &RegisterPage::registrationWithAuth, this, &RegisterPage::doRegistrationWithAuth);
+    qRegisterMetaType<mtx::user_interactive::Unauthorized>();
+    qRegisterMetaType<mtx::user_interactive::Auth>();
+    top_layout_ = new QVBoxLayout();
+
+    back_layout_ = new QHBoxLayout();
+    back_layout_->setSpacing(0);
+    back_layout_->setContentsMargins(5, 5, -1, -1);
+
+    back_button_ = new FlatButton(this);
+    back_button_->setMinimumSize(QSize(30, 30));
+
+    QIcon icon;
+    icon.addFile(":/icons/icons/ui/angle-pointing-to-left.png");
+
+    back_button_->setIcon(icon);
+    back_button_->setIconSize(QSize(32, 32));
+
+    back_layout_->addWidget(back_button_, 0, Qt::AlignLeft | Qt::AlignVCenter);
+    back_layout_->addStretch(1);
+
+    QIcon logo;
+    logo.addFile(":/logos/register.png");
+
+    logo_ = new QLabel(this);
+    logo_->setPixmap(logo.pixmap(128));
+
+    logo_layout_ = new QHBoxLayout();
+    logo_layout_->setMargin(0);
+    logo_layout_->addWidget(logo_, 0, Qt::AlignHCenter);
+
+    form_wrapper_ = new QHBoxLayout();
+    form_widget_  = new QWidget();
+    form_widget_->setMinimumSize(QSize(350, 300));
+
+    form_layout_ = new QVBoxLayout();
+    form_layout_->setSpacing(20);
+    form_layout_->setContentsMargins(0, 0, 0, 40);
+    form_widget_->setLayout(form_layout_);
+
+    form_wrapper_->addStretch(1);
+    form_wrapper_->addWidget(form_widget_);
+    form_wrapper_->addStretch(1);
+
+    username_input_ = new TextField();
+    username_input_->setLabel(tr("Username"));
+    username_input_->setRegexp(QRegularExpression("[a-z0-9._=/-]+"));
+    username_input_->setToolTip(tr("The username must not be empty, and must contain only the "
+                                   "characters a-z, 0-9, ., _, =, -, and /."));
+
+    password_input_ = new TextField();
+    password_input_->setLabel(tr("Password"));
+    password_input_->setRegexp(QRegularExpression("^.{8,}$"));
+    password_input_->setEchoMode(QLineEdit::Password);
+    password_input_->setToolTip(tr("Please choose a secure password. The exact requirements "
+                                   "for password strength may depend on your server."));
+
+    password_confirmation_ = new TextField();
+    password_confirmation_->setLabel(tr("Password confirmation"));
+    password_confirmation_->setEchoMode(QLineEdit::Password);
+
+    server_input_ = new TextField();
+    server_input_->setLabel(tr("Homeserver"));
+    server_input_->setRegexp(QRegularExpression(".+"));
+    server_input_->setToolTip(
+      tr("A server that allows registration. Since matrix is decentralized, you need to first "
+         "find a server you can register on or host your own."));
+
+    error_username_label_ = new QLabel(this);
+    error_username_label_->setWordWrap(true);
+    error_username_label_->hide();
+
+    error_password_label_ = new QLabel(this);
+    error_password_label_->setWordWrap(true);
+    error_password_label_->hide();
+
+    error_password_confirmation_label_ = new QLabel(this);
+    error_password_confirmation_label_->setWordWrap(true);
+    error_password_confirmation_label_->hide();
+
+    error_server_label_ = new QLabel(this);
+    error_server_label_->setWordWrap(true);
+    error_server_label_->hide();
+
+    form_layout_->addWidget(username_input_, Qt::AlignHCenter);
+    form_layout_->addWidget(error_username_label_, Qt::AlignHCenter);
+    form_layout_->addWidget(password_input_, Qt::AlignHCenter);
+    form_layout_->addWidget(error_password_label_, Qt::AlignHCenter);
+    form_layout_->addWidget(password_confirmation_, Qt::AlignHCenter);
+    form_layout_->addWidget(error_password_confirmation_label_, Qt::AlignHCenter);
+    form_layout_->addWidget(server_input_, Qt::AlignHCenter);
+    form_layout_->addWidget(error_server_label_, Qt::AlignHCenter);
+
+    button_layout_ = new QHBoxLayout();
+    button_layout_->setSpacing(0);
+    button_layout_->setMargin(0);
+
+    error_label_ = new QLabel(this);
+    error_label_->setWordWrap(true);
+
+    register_button_ = new RaisedButton(tr("REGISTER"), this);
+    register_button_->setMinimumSize(350, 65);
+    register_button_->setFontSize(conf::btn::fontSize);
+    register_button_->setCornerRadius(conf::btn::cornerRadius);
+
+    button_layout_->addStretch(1);
+    button_layout_->addWidget(register_button_);
+    button_layout_->addStretch(1);
+
+    top_layout_->addLayout(back_layout_);
+    top_layout_->addLayout(logo_layout_);
+    top_layout_->addLayout(form_wrapper_);
+    top_layout_->addStretch(1);
+    top_layout_->addLayout(button_layout_);
+    top_layout_->addWidget(error_label_, 0, Qt::AlignHCenter);
+    top_layout_->addStretch(1);
+    setLayout(top_layout_);
+
+    connect(back_button_, SIGNAL(clicked()), this, SLOT(onBackButtonClicked()));
+    connect(register_button_, SIGNAL(clicked()), this, SLOT(onRegisterButtonClicked()));
+
+    connect(username_input_, SIGNAL(returnPressed()), register_button_, SLOT(click()));
+    connect(username_input_, &TextField::editingFinished, this, &RegisterPage::checkUsername);
+    connect(password_input_, SIGNAL(returnPressed()), register_button_, SLOT(click()));
+    connect(password_input_, &TextField::editingFinished, this, &RegisterPage::checkPassword);
+    connect(password_confirmation_, SIGNAL(returnPressed()), register_button_, SLOT(click()));
+    connect(password_confirmation_,
+            &TextField::editingFinished,
+            this,
+            &RegisterPage::checkPasswordConfirmation);
+    connect(server_input_, SIGNAL(returnPressed()), register_button_, SLOT(click()));
+    connect(server_input_, &TextField::editingFinished, this, &RegisterPage::checkServer);
+
+    connect(
+      this,
+      &RegisterPage::serverError,
+      this,
+      [this](const QString &msg) {
+          server_input_->setValid(false);
+          showError(error_server_label_, msg);
+      },
+      Qt::QueuedConnection);
+
+    connect(this, &RegisterPage::wellKnownLookup, this, &RegisterPage::doWellKnownLookup);
+    connect(this, &RegisterPage::versionsCheck, this, &RegisterPage::doVersionsCheck);
+    connect(this, &RegisterPage::registration, this, &RegisterPage::doRegistration);
+    connect(this, &RegisterPage::UIA, this, &RegisterPage::doUIA);
+    connect(this, &RegisterPage::registrationWithAuth, this, &RegisterPage::doRegistrationWithAuth);
 }
 
 void
 RegisterPage::onBackButtonClicked()
 {
-        emit backButtonClicked();
+    emit backButtonClicked();
 }
 
 void
 RegisterPage::showError(const QString &msg)
 {
-        emit errorOccurred();
-        auto rect  = QFontMetrics(font()).boundingRect(msg);
-        int width  = rect.width();
-        int height = rect.height();
-        error_label_->setFixedHeight(qCeil(width / 200.0) * height);
-        error_label_->setText(msg);
+    emit errorOccurred();
+    auto rect  = QFontMetrics(font()).boundingRect(msg);
+    int width  = rect.width();
+    int height = rect.height();
+    error_label_->setFixedHeight(qCeil(width / 200.0) * height);
+    error_label_->setText(msg);
 }
 
 void
 RegisterPage::showError(QLabel *label, const QString &msg)
 {
-        emit errorOccurred();
-        auto rect  = QFontMetrics(font()).boundingRect(msg);
-        int width  = rect.width();
-        int height = rect.height();
-        label->setFixedHeight((int)qCeil(width / 200.0) * height);
-        label->setText(msg);
-        label->show();
+    emit errorOccurred();
+    auto rect  = QFontMetrics(font()).boundingRect(msg);
+    int width  = rect.width();
+    int height = rect.height();
+    label->setFixedHeight((int)qCeil(width / 200.0) * height);
+    label->setText(msg);
+    label->show();
 }
 
 bool
 RegisterPage::checkOneField(QLabel *label, const TextField *t_field, const QString &msg)
 {
-        if (t_field->isValid()) {
-                label->hide();
-                return true;
-        } else {
-                showError(label, msg);
-                return false;
-        }
+    if (t_field->isValid()) {
+        label->hide();
+        return true;
+    } else {
+        showError(label, msg);
+        return false;
+    }
 }
 
 bool
 RegisterPage::checkUsername()
 {
-        return checkOneField(error_username_label_,
-                             username_input_,
-                             tr("The username must not be empty, and must contain only the "
-                                "characters a-z, 0-9, ., _, =, -, and /."));
+    return checkOneField(error_username_label_,
+                         username_input_,
+                         tr("The username must not be empty, and must contain only the "
+                            "characters a-z, 0-9, ., _, =, -, and /."));
 }
 
 bool
 RegisterPage::checkPassword()
 {
-        return checkOneField(
-          error_password_label_, password_input_, tr("Password is not long enough (min 8 chars)"));
+    return checkOneField(
+      error_password_label_, password_input_, tr("Password is not long enough (min 8 chars)"));
 }
 
 bool
 RegisterPage::checkPasswordConfirmation()
 {
-        if (password_input_->text() == password_confirmation_->text()) {
-                error_password_confirmation_label_->hide();
-                password_confirmation_->setValid(true);
-                return true;
-        } else {
-                showError(error_password_confirmation_label_, tr("Passwords don't match"));
-                password_confirmation_->setValid(false);
-                return false;
-        }
+    if (password_input_->text() == password_confirmation_->text()) {
+        error_password_confirmation_label_->hide();
+        password_confirmation_->setValid(true);
+        return true;
+    } else {
+        showError(error_password_confirmation_label_, tr("Passwords don't match"));
+        password_confirmation_->setValid(false);
+        return false;
+    }
 }
 
 bool
 RegisterPage::checkServer()
 {
-        // This doesn't check that the server is reachable,
-        // just that the input is not obviously wrong.
-        return checkOneField(error_server_label_, server_input_, tr("Invalid server name"));
+    // This doesn't check that the server is reachable,
+    // just that the input is not obviously wrong.
+    return checkOneField(error_server_label_, server_input_, tr("Invalid server name"));
 }
 
 void
 RegisterPage::onRegisterButtonClicked()
 {
-        if (checkUsername() && checkPassword() && checkPasswordConfirmation() && checkServer()) {
-                auto server = server_input_->text().toStdString();
-
-                http::client()->set_server(server);
-                http::client()->verify_certificates(
-                  !UserSettings::instance()->disableCertificateValidation());
-
-                // This starts a chain of `emit`s which ends up doing the
-                // registration. Signals are used rather than normal function
-                // calls so that the dialogs used in UIA work correctly.
-                //
-                // The sequence of events looks something like this:
-                //
-                // dowellKnownLookup
-                //   v
-                // doVersionsCheck
-                //   v
-                // doRegistration
-                //   v
-                // doUIA <-----------------+
-                //   v					   | More auth required
-                // doRegistrationWithAuth -+
-                //                         | Success
-                // 						   v
-                //                     registering
-
-                emit wellKnownLookup();
-
-                emit registering();
-        }
+    if (checkUsername() && checkPassword() && checkPasswordConfirmation() && checkServer()) {
+        auto server = server_input_->text().toStdString();
+
+        http::client()->set_server(server);
+        http::client()->verify_certificates(
+          !UserSettings::instance()->disableCertificateValidation());
+
+        // This starts a chain of `emit`s which ends up doing the
+        // registration. Signals are used rather than normal function
+        // calls so that the dialogs used in UIA work correctly.
+        //
+        // The sequence of events looks something like this:
+        //
+        // dowellKnownLookup
+        //   v
+        // doVersionsCheck
+        //   v
+        // doRegistration
+        //   v
+        // doUIA <-----------------+
+        //   v					   | More auth required
+        // doRegistrationWithAuth -+
+        //                         | Success
+        // 						   v
+        //                     registering
+
+        emit wellKnownLookup();
+
+        emit registering();
+    }
 }
 
 void
 RegisterPage::doWellKnownLookup()
 {
-        http::client()->well_known(
-          [this](const mtx::responses::WellKnown &res, mtx::http::RequestErr err) {
-                  if (err) {
-                          if (err->status_code == 404) {
-                                  nhlog::net()->info("Autodiscovery: No .well-known.");
-                                  // Check that the homeserver can be reached
-                                  emit versionsCheck();
-                                  return;
-                          }
-
-                          if (!err->parse_error.empty()) {
-                                  emit serverError(
-                                    tr("Autodiscovery failed. Received malformed response."));
-                                  nhlog::net()->error(
-                                    "Autodiscovery failed. Received malformed response.");
-                                  return;
-                          }
-
-                          emit serverError(tr("Autodiscovery failed. Unknown error when "
-                                              "requesting .well-known."));
-                          nhlog::net()->error("Autodiscovery failed. Unknown error when "
-                                              "requesting .well-known. {} {}",
-                                              err->status_code,
-                                              err->error_code);
-                          return;
-                  }
-
-                  nhlog::net()->info("Autodiscovery: Discovered '" + res.homeserver.base_url + "'");
-                  http::client()->set_server(res.homeserver.base_url);
+    http::client()->well_known(
+      [this](const mtx::responses::WellKnown &res, mtx::http::RequestErr err) {
+          if (err) {
+              if (err->status_code == 404) {
+                  nhlog::net()->info("Autodiscovery: No .well-known.");
                   // Check that the homeserver can be reached
                   emit versionsCheck();
-          });
+                  return;
+              }
+
+              if (!err->parse_error.empty()) {
+                  emit serverError(tr("Autodiscovery failed. Received malformed response."));
+                  nhlog::net()->error("Autodiscovery failed. Received malformed response.");
+                  return;
+              }
+
+              emit serverError(tr("Autodiscovery failed. Unknown error when "
+                                  "requesting .well-known."));
+              nhlog::net()->error("Autodiscovery failed. Unknown error when "
+                                  "requesting .well-known. {} {}",
+                                  err->status_code,
+                                  err->error_code);
+              return;
+          }
+
+          nhlog::net()->info("Autodiscovery: Discovered '" + res.homeserver.base_url + "'");
+          http::client()->set_server(res.homeserver.base_url);
+          // Check that the homeserver can be reached
+          emit versionsCheck();
+      });
 }
 
 void
 RegisterPage::doVersionsCheck()
 {
-        // Make a request to /_matrix/client/versions to check the address
-        // given is a Matrix homeserver.
-        http::client()->versions(
-          [this](const mtx::responses::Versions &, mtx::http::RequestErr err) {
-                  if (err) {
-                          if (err->status_code == 404) {
-                                  emit serverError(
-                                    tr("The required endpoints were not found. Possibly "
-                                       "not a Matrix server."));
-                                  return;
-                          }
-
-                          if (!err->parse_error.empty()) {
-                                  emit serverError(
-                                    tr("Received malformed response. Make sure the homeserver "
-                                       "domain is valid."));
-                                  return;
-                          }
-
-                          emit serverError(tr("An unknown error occured. Make sure the "
-                                              "homeserver domain is valid."));
-                          return;
-                  }
-
-                  // Attempt registration without an `auth` dict
-                  emit registration();
-          });
+    // Make a request to /_matrix/client/versions to check the address
+    // given is a Matrix homeserver.
+    http::client()->versions([this](const mtx::responses::Versions &, mtx::http::RequestErr err) {
+        if (err) {
+            if (err->status_code == 404) {
+                emit serverError(tr("The required endpoints were not found. Possibly "
+                                    "not a Matrix server."));
+                return;
+            }
+
+            if (!err->parse_error.empty()) {
+                emit serverError(tr("Received malformed response. Make sure the homeserver "
+                                    "domain is valid."));
+                return;
+            }
+
+            emit serverError(tr("An unknown error occured. Make sure the "
+                                "homeserver domain is valid."));
+            return;
+        }
+
+        // Attempt registration without an `auth` dict
+        emit registration();
+    });
 }
 
 void
 RegisterPage::doRegistration()
 {
-        // These inputs should still be alright, but check just in case
-        if (checkUsername() && checkPassword() && checkPasswordConfirmation()) {
-                auto username = username_input_->text().toStdString();
-                auto password = password_input_->text().toStdString();
-                http::client()->registration(username, password, registrationCb());
-        }
+    // These inputs should still be alright, but check just in case
+    if (checkUsername() && checkPassword() && checkPasswordConfirmation()) {
+        auto username = username_input_->text().toStdString();
+        auto password = password_input_->text().toStdString();
+        http::client()->registration(username, password, registrationCb());
+    }
 }
 
 void
 RegisterPage::doRegistrationWithAuth(const mtx::user_interactive::Auth &auth)
 {
-        // These inputs should still be alright, but check just in case
-        if (checkUsername() && checkPassword() && checkPasswordConfirmation()) {
-                auto username = username_input_->text().toStdString();
-                auto password = password_input_->text().toStdString();
-                http::client()->registration(username, password, auth, registrationCb());
-        }
+    // These inputs should still be alright, but check just in case
+    if (checkUsername() && checkPassword() && checkPasswordConfirmation()) {
+        auto username = username_input_->text().toStdString();
+        auto password = password_input_->text().toStdString();
+        http::client()->registration(username, password, auth, registrationCb());
+    }
 }
 
 mtx::http::Callback<mtx::responses::Register>
 RegisterPage::registrationCb()
 {
-        // Return a function to be used as the callback when an attempt at
-        // registration is made.
-        return [this](const mtx::responses::Register &res, mtx::http::RequestErr err) {
-                if (!err) {
-                        http::client()->set_user(res.user_id);
-                        http::client()->set_access_token(res.access_token);
-                        emit registerOk();
-                        return;
-                }
-
-                // The server requires registration flows.
-                if (err->status_code == 401) {
-                        if (err->matrix_error.unauthorized.flows.empty()) {
-                                nhlog::net()->warn("failed to retrieve registration flows: "
-                                                   "status_code({}), matrix_error({}) ",
-                                                   static_cast<int>(err->status_code),
-                                                   err->matrix_error.error);
-                                showError(QString::fromStdString(err->matrix_error.error));
-                                return;
-                        }
-
-                        // Attempt to complete a UIA stage
-                        emit UIA(err->matrix_error.unauthorized);
-                        return;
-                }
-
-                nhlog::net()->error("failed to register: status_code ({}), matrix_error({})",
-                                    static_cast<int>(err->status_code),
-                                    err->matrix_error.error);
+    // Return a function to be used as the callback when an attempt at
+    // registration is made.
+    return [this](const mtx::responses::Register &res, mtx::http::RequestErr err) {
+        if (!err) {
+            http::client()->set_user(res.user_id);
+            http::client()->set_access_token(res.access_token);
+            emit registerOk();
+            return;
+        }
 
+        // The server requires registration flows.
+        if (err->status_code == 401) {
+            if (err->matrix_error.unauthorized.flows.empty()) {
+                nhlog::net()->warn("failed to retrieve registration flows: "
+                                   "status_code({}), matrix_error({}) ",
+                                   static_cast<int>(err->status_code),
+                                   err->matrix_error.error);
                 showError(QString::fromStdString(err->matrix_error.error));
-        };
+                return;
+            }
+
+            // Attempt to complete a UIA stage
+            emit UIA(err->matrix_error.unauthorized);
+            return;
+        }
+
+        nhlog::net()->error("failed to register: status_code ({}), matrix_error({})",
+                            static_cast<int>(err->status_code),
+                            err->matrix_error.error);
+
+        showError(QString::fromStdString(err->matrix_error.error));
+    };
 }
 
 void
 RegisterPage::doUIA(const mtx::user_interactive::Unauthorized &unauthorized)
 {
-        auto completed_stages = unauthorized.completed;
-        auto flows            = unauthorized.flows;
-        auto session =
-          unauthorized.session.empty() ? http::client()->generate_txn_id() : unauthorized.session;
-
-        nhlog::ui()->info("Completed stages: {}", completed_stages.size());
-
-        if (!completed_stages.empty()) {
-                // Get rid of all flows which don't start with the sequence of
-                // stages that have already been completed.
-                flows.erase(
-                  std::remove_if(flows.begin(),
-                                 flows.end(),
-                                 [completed_stages](auto flow) {
-                                         if (completed_stages.size() > flow.stages.size())
-                                                 return true;
-                                         for (size_t f = 0; f < completed_stages.size(); f++)
-                                                 if (completed_stages[f] != flow.stages[f])
-                                                         return true;
-                                         return false;
-                                 }),
-                  flows.end());
-        }
+    auto completed_stages = unauthorized.completed;
+    auto flows            = unauthorized.flows;
+    auto session =
+      unauthorized.session.empty() ? http::client()->generate_txn_id() : unauthorized.session;
+
+    nhlog::ui()->info("Completed stages: {}", completed_stages.size());
+
+    if (!completed_stages.empty()) {
+        // Get rid of all flows which don't start with the sequence of
+        // stages that have already been completed.
+        flows.erase(std::remove_if(flows.begin(),
+                                   flows.end(),
+                                   [completed_stages](auto flow) {
+                                       if (completed_stages.size() > flow.stages.size())
+                                           return true;
+                                       for (size_t f = 0; f < completed_stages.size(); f++)
+                                           if (completed_stages[f] != flow.stages[f])
+                                               return true;
+                                       return false;
+                                   }),
+                    flows.end());
+    }
+
+    if (flows.empty()) {
+        nhlog::ui()->error("No available registration flows!");
+        showError(tr("No supported registration flows!"));
+        return;
+    }
+
+    auto current_stage = flows.front().stages.at(completed_stages.size());
+
+    if (current_stage == mtx::user_interactive::auth_types::recaptcha) {
+        auto captchaDialog = new dialogs::ReCaptcha(QString::fromStdString(session), this);
 
-        if (flows.empty()) {
-                nhlog::ui()->error("No available registration flows!");
-                showError(tr("No supported registration flows!"));
-                return;
-        }
+        connect(
+          captchaDialog, &dialogs::ReCaptcha::confirmation, this, [this, session, captchaDialog]() {
+              captchaDialog->close();
+              captchaDialog->deleteLater();
+              doRegistrationWithAuth(
+                mtx::user_interactive::Auth{session, mtx::user_interactive::auth::Fallback{}});
+          });
 
-        auto current_stage = flows.front().stages.at(completed_stages.size());
-
-        if (current_stage == mtx::user_interactive::auth_types::recaptcha) {
-                auto captchaDialog = new dialogs::ReCaptcha(QString::fromStdString(session), this);
-
-                connect(captchaDialog,
-                        &dialogs::ReCaptcha::confirmation,
-                        this,
-                        [this, session, captchaDialog]() {
-                                captchaDialog->close();
-                                captchaDialog->deleteLater();
-                                doRegistrationWithAuth(mtx::user_interactive::Auth{
-                                  session, mtx::user_interactive::auth::Fallback{}});
-                        });
-
-                connect(
-                  captchaDialog, &dialogs::ReCaptcha::cancel, this, &RegisterPage::errorOccurred);
-
-                QTimer::singleShot(1000, this, [captchaDialog]() { captchaDialog->show(); });
-
-        } else if (current_stage == mtx::user_interactive::auth_types::dummy) {
-                doRegistrationWithAuth(
-                  mtx::user_interactive::Auth{session, mtx::user_interactive::auth::Dummy{}});
-
-        } else if (current_stage == mtx::user_interactive::auth_types::registration_token) {
-                bool ok;
-                QString token =
-                  QInputDialog::getText(this,
-                                        tr("Registration token"),
-                                        tr("Please enter a valid registration token."),
-                                        QLineEdit::Normal,
-                                        QString(),
-                                        &ok);
-
-                if (ok) {
-                        emit registrationWithAuth(mtx::user_interactive::Auth{
-                          session,
-                          mtx::user_interactive::auth::RegistrationToken{token.toStdString()}});
-                } else {
-                        emit errorOccurred();
-                }
-        } else {
-                // use fallback
-                auto dialog = new dialogs::FallbackAuth(
-                  QString::fromStdString(current_stage), QString::fromStdString(session), this);
+        connect(captchaDialog, &dialogs::ReCaptcha::cancel, this, &RegisterPage::errorOccurred);
 
-                connect(
-                  dialog, &dialogs::FallbackAuth::confirmation, this, [this, session, dialog]() {
-                          dialog->close();
-                          dialog->deleteLater();
-                          emit registrationWithAuth(mtx::user_interactive::Auth{
-                            session, mtx::user_interactive::auth::Fallback{}});
-                  });
+        QTimer::singleShot(1000, this, [captchaDialog]() { captchaDialog->show(); });
 
-                connect(dialog, &dialogs::FallbackAuth::cancel, this, &RegisterPage::errorOccurred);
+    } else if (current_stage == mtx::user_interactive::auth_types::dummy) {
+        doRegistrationWithAuth(
+          mtx::user_interactive::Auth{session, mtx::user_interactive::auth::Dummy{}});
 
-                dialog->show();
+    } else if (current_stage == mtx::user_interactive::auth_types::registration_token) {
+        bool ok;
+        QString token = QInputDialog::getText(this,
+                                              tr("Registration token"),
+                                              tr("Please enter a valid registration token."),
+                                              QLineEdit::Normal,
+                                              QString(),
+                                              &ok);
+
+        if (ok) {
+            emit registrationWithAuth(mtx::user_interactive::Auth{
+              session, mtx::user_interactive::auth::RegistrationToken{token.toStdString()}});
+        } else {
+            emit errorOccurred();
         }
+    } else {
+        // use fallback
+        auto dialog = new dialogs::FallbackAuth(
+          QString::fromStdString(current_stage), QString::fromStdString(session), this);
+
+        connect(dialog, &dialogs::FallbackAuth::confirmation, this, [this, session, dialog]() {
+            dialog->close();
+            dialog->deleteLater();
+            emit registrationWithAuth(
+              mtx::user_interactive::Auth{session, mtx::user_interactive::auth::Fallback{}});
+        });
+
+        connect(dialog, &dialogs::FallbackAuth::cancel, this, &RegisterPage::errorOccurred);
+
+        dialog->show();
+    }
 }
 
 void
 RegisterPage::paintEvent(QPaintEvent *)
 {
-        QStyleOption opt;
-        opt.init(this);
-        QPainter p(this);
-        style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
+    QStyleOption opt;
+    opt.init(this);
+    QPainter p(this);
+    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
 }
diff --git a/src/RegisterPage.h b/src/RegisterPage.h
index 42ea00cb..b88808f9 100644
--- a/src/RegisterPage.h
+++ b/src/RegisterPage.h
@@ -21,76 +21,76 @@ class QHBoxLayout;
 
 class RegisterPage : public QWidget
 {
-        Q_OBJECT
+    Q_OBJECT
 
 public:
-        RegisterPage(QWidget *parent = nullptr);
+    RegisterPage(QWidget *parent = nullptr);
 
 protected:
-        void paintEvent(QPaintEvent *event) override;
+    void paintEvent(QPaintEvent *event) override;
 
 signals:
-        void backButtonClicked();
-        void errorOccurred();
+    void backButtonClicked();
+    void errorOccurred();
 
-        //! Used to trigger the corresponding slot outside of the main thread.
-        void serverError(const QString &err);
+    //! Used to trigger the corresponding slot outside of the main thread.
+    void serverError(const QString &err);
 
-        void wellKnownLookup();
-        void versionsCheck();
-        void registration();
-        void UIA(const mtx::user_interactive::Unauthorized &unauthorized);
-        void registrationWithAuth(const mtx::user_interactive::Auth &auth);
+    void wellKnownLookup();
+    void versionsCheck();
+    void registration();
+    void UIA(const mtx::user_interactive::Unauthorized &unauthorized);
+    void registrationWithAuth(const mtx::user_interactive::Auth &auth);
 
-        void registering();
-        void registerOk();
+    void registering();
+    void registerOk();
 
 private slots:
-        void onBackButtonClicked();
-        void onRegisterButtonClicked();
-
-        // function for showing different errors
-        void showError(const QString &msg);
-        void showError(QLabel *label, const QString &msg);
-
-        bool checkOneField(QLabel *label, const TextField *t_field, const QString &msg);
-        bool checkUsername();
-        bool checkPassword();
-        bool checkPasswordConfirmation();
-        bool checkServer();
-
-        void doWellKnownLookup();
-        void doVersionsCheck();
-        void doRegistration();
-        void doUIA(const mtx::user_interactive::Unauthorized &unauthorized);
-        void doRegistrationWithAuth(const mtx::user_interactive::Auth &auth);
-        mtx::http::Callback<mtx::responses::Register> registrationCb();
+    void onBackButtonClicked();
+    void onRegisterButtonClicked();
+
+    // function for showing different errors
+    void showError(const QString &msg);
+    void showError(QLabel *label, const QString &msg);
+
+    bool checkOneField(QLabel *label, const TextField *t_field, const QString &msg);
+    bool checkUsername();
+    bool checkPassword();
+    bool checkPasswordConfirmation();
+    bool checkServer();
+
+    void doWellKnownLookup();
+    void doVersionsCheck();
+    void doRegistration();
+    void doUIA(const mtx::user_interactive::Unauthorized &unauthorized);
+    void doRegistrationWithAuth(const mtx::user_interactive::Auth &auth);
+    mtx::http::Callback<mtx::responses::Register> registrationCb();
 
 private:
-        QVBoxLayout *top_layout_;
-
-        QHBoxLayout *back_layout_;
-        QHBoxLayout *logo_layout_;
-        QHBoxLayout *button_layout_;
-
-        QLabel *logo_;
-        QLabel *error_label_;
-        QLabel *error_username_label_;
-        QLabel *error_password_label_;
-        QLabel *error_password_confirmation_label_;
-        QLabel *error_server_label_;
-        QLabel *error_registration_token_label_;
-
-        FlatButton *back_button_;
-        RaisedButton *register_button_;
-
-        QWidget *form_widget_;
-        QHBoxLayout *form_wrapper_;
-        QVBoxLayout *form_layout_;
-
-        TextField *username_input_;
-        TextField *password_input_;
-        TextField *password_confirmation_;
-        TextField *server_input_;
-        TextField *registration_token_input_;
+    QVBoxLayout *top_layout_;
+
+    QHBoxLayout *back_layout_;
+    QHBoxLayout *logo_layout_;
+    QHBoxLayout *button_layout_;
+
+    QLabel *logo_;
+    QLabel *error_label_;
+    QLabel *error_username_label_;
+    QLabel *error_password_label_;
+    QLabel *error_password_confirmation_label_;
+    QLabel *error_server_label_;
+    QLabel *error_registration_token_label_;
+
+    FlatButton *back_button_;
+    RaisedButton *register_button_;
+
+    QWidget *form_widget_;
+    QHBoxLayout *form_wrapper_;
+    QVBoxLayout *form_layout_;
+
+    TextField *username_input_;
+    TextField *password_input_;
+    TextField *password_confirmation_;
+    TextField *server_input_;
+    TextField *registration_token_input_;
 };
diff --git a/src/RoomDirectoryModel.cpp b/src/RoomDirectoryModel.cpp
index cfa2b623..707571d6 100644
--- a/src/RoomDirectoryModel.cpp
+++ b/src/RoomDirectoryModel.cpp
@@ -12,207 +12,205 @@ RoomDirectoryModel::RoomDirectoryModel(QObject *parent, const std::string &serve
   : QAbstractListModel(parent)
   , server_(server)
 {
-        connect(ChatPage::instance(), &ChatPage::newRoom, this, [this](const QString &roomid) {
-                auto roomid_ = roomid.toStdString();
-
-                int i = 0;
-                for (const auto &room : publicRoomsData_) {
-                        if (room.room_id == roomid_) {
-                                emit dataChanged(index(i), index(i), {Roles::CanJoin});
-                                break;
-                        }
-                        i++;
-                }
-        });
-
-        connect(this,
-                &RoomDirectoryModel::fetchedRoomsBatch,
-                this,
-                &RoomDirectoryModel::displayRooms,
-                Qt::QueuedConnection);
+    connect(ChatPage::instance(), &ChatPage::newRoom, this, [this](const QString &roomid) {
+        auto roomid_ = roomid.toStdString();
+
+        int i = 0;
+        for (const auto &room : publicRoomsData_) {
+            if (room.room_id == roomid_) {
+                emit dataChanged(index(i), index(i), {Roles::CanJoin});
+                break;
+            }
+            i++;
+        }
+    });
+
+    connect(this,
+            &RoomDirectoryModel::fetchedRoomsBatch,
+            this,
+            &RoomDirectoryModel::displayRooms,
+            Qt::QueuedConnection);
 }
 
 QHash<int, QByteArray>
 RoomDirectoryModel::roleNames() const
 {
-        return {
-          {Roles::Name, "name"},
-          {Roles::Id, "roomid"},
-          {Roles::AvatarUrl, "avatarUrl"},
-          {Roles::Topic, "topic"},
-          {Roles::MemberCount, "numMembers"},
-          {Roles::Previewable, "canPreview"},
-          {Roles::CanJoin, "canJoin"},
-        };
+    return {
+      {Roles::Name, "name"},
+      {Roles::Id, "roomid"},
+      {Roles::AvatarUrl, "avatarUrl"},
+      {Roles::Topic, "topic"},
+      {Roles::MemberCount, "numMembers"},
+      {Roles::Previewable, "canPreview"},
+      {Roles::CanJoin, "canJoin"},
+    };
 }
 
 void
 RoomDirectoryModel::resetDisplayedData()
 {
-        beginResetModel();
+    beginResetModel();
 
-        prevBatch_    = "";
-        nextBatch_    = "";
-        canFetchMore_ = true;
+    prevBatch_    = "";
+    nextBatch_    = "";
+    canFetchMore_ = true;
 
-        publicRoomsData_.clear();
+    publicRoomsData_.clear();
 
-        endResetModel();
+    endResetModel();
 }
 
 void
 RoomDirectoryModel::setMatrixServer(const QString &s)
 {
-        server_ = s.toStdString();
+    server_ = s.toStdString();
 
-        nhlog::ui()->debug("Received matrix server: {}", server_);
+    nhlog::ui()->debug("Received matrix server: {}", server_);
 
-        resetDisplayedData();
+    resetDisplayedData();
 }
 
 void
 RoomDirectoryModel::setSearchTerm(const QString &f)
 {
-        userSearchString_ = f.toStdString();
+    userSearchString_ = f.toStdString();
 
-        nhlog::ui()->debug("Received user query: {}", userSearchString_);
+    nhlog::ui()->debug("Received user query: {}", userSearchString_);
 
-        resetDisplayedData();
+    resetDisplayedData();
 }
 
 bool
 RoomDirectoryModel::canJoinRoom(const QString &room) const
 {
-        return !room.isEmpty() && cache::getRoomInfo({room.toStdString()}).empty();
+    return !room.isEmpty() && cache::getRoomInfo({room.toStdString()}).empty();
 }
 
 std::vector<std::string>
 RoomDirectoryModel::getViasForRoom(const std::vector<std::string> &aliases)
 {
-        std::vector<std::string> vias;
-
-        vias.reserve(aliases.size());
-
-        std::transform(aliases.begin(),
-                       aliases.end(),
-                       std::back_inserter(vias),
-                       [](const auto &alias) { return alias.substr(alias.find(":") + 1); });
-
-        // When joining a room hosted on a homeserver other than the one the
-        // account has been registered on, the room's server has to be explicitly
-        // specified in the "server_name=..." URL parameter of the Matrix Join Room
-        // request. For more details consult the specs:
-        // https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-join-roomidoralias
-        if (!server_.empty()) {
-                vias.push_back(server_);
-        }
+    std::vector<std::string> vias;
+
+    vias.reserve(aliases.size());
+
+    std::transform(aliases.begin(), aliases.end(), std::back_inserter(vias), [](const auto &alias) {
+        return alias.substr(alias.find(":") + 1);
+    });
 
-        return vias;
+    // When joining a room hosted on a homeserver other than the one the
+    // account has been registered on, the room's server has to be explicitly
+    // specified in the "server_name=..." URL parameter of the Matrix Join Room
+    // request. For more details consult the specs:
+    // https://matrix.org/docs/spec/client_server/r0.6.1#post-matrix-client-r0-join-roomidoralias
+    if (!server_.empty()) {
+        vias.push_back(server_);
+    }
+
+    return vias;
 }
 
 void
 RoomDirectoryModel::joinRoom(const int &index)
 {
-        if (index >= 0 && static_cast<size_t>(index) < publicRoomsData_.size()) {
-                const auto &chunk = publicRoomsData_[index];
-                nhlog::ui()->debug("'Joining room {}", chunk.room_id);
-                ChatPage::instance()->joinRoomVia(chunk.room_id, getViasForRoom(chunk.aliases));
-        }
+    if (index >= 0 && static_cast<size_t>(index) < publicRoomsData_.size()) {
+        const auto &chunk = publicRoomsData_[index];
+        nhlog::ui()->debug("'Joining room {}", chunk.room_id);
+        ChatPage::instance()->joinRoomVia(chunk.room_id, getViasForRoom(chunk.aliases));
+    }
 }
 
 QVariant
 RoomDirectoryModel::data(const QModelIndex &index, int role) const
 {
-        if (hasIndex(index.row(), index.column(), index.parent())) {
-                const auto &room_chunk = publicRoomsData_[index.row()];
-                switch (role) {
-                case Roles::Name:
-                        return QString::fromStdString(room_chunk.name);
-                case Roles::Id:
-                        return QString::fromStdString(room_chunk.room_id);
-                case Roles::AvatarUrl:
-                        return QString::fromStdString(room_chunk.avatar_url);
-                case Roles::Topic:
-                        return QString::fromStdString(room_chunk.topic);
-                case Roles::MemberCount:
-                        return QVariant::fromValue(room_chunk.num_joined_members);
-                case Roles::Previewable:
-                        return QVariant::fromValue(room_chunk.world_readable);
-                case Roles::CanJoin:
-                        return canJoinRoom(QString::fromStdString(room_chunk.room_id));
-                }
+    if (hasIndex(index.row(), index.column(), index.parent())) {
+        const auto &room_chunk = publicRoomsData_[index.row()];
+        switch (role) {
+        case Roles::Name:
+            return QString::fromStdString(room_chunk.name);
+        case Roles::Id:
+            return QString::fromStdString(room_chunk.room_id);
+        case Roles::AvatarUrl:
+            return QString::fromStdString(room_chunk.avatar_url);
+        case Roles::Topic:
+            return QString::fromStdString(room_chunk.topic);
+        case Roles::MemberCount:
+            return QVariant::fromValue(room_chunk.num_joined_members);
+        case Roles::Previewable:
+            return QVariant::fromValue(room_chunk.world_readable);
+        case Roles::CanJoin:
+            return canJoinRoom(QString::fromStdString(room_chunk.room_id));
         }
-        return {};
+    }
+    return {};
 }
 
 void
 RoomDirectoryModel::fetchMore(const QModelIndex &)
 {
-        if (!canFetchMore_)
-                return;
-
-        nhlog::net()->debug("Fetching more rooms from mtxclient...");
-
-        mtx::requests::PublicRooms req;
-        req.limit                      = limit_;
-        req.since                      = prevBatch_;
-        req.filter.generic_search_term = userSearchString_;
-        // req.third_party_instance_id = third_party_instance_id;
-        auto requested_server = server_;
-
-        reachedEndOfPagination_ = false;
-        emit reachedEndOfPaginationChanged();
-
-        loadingMoreRooms_ = true;
-        emit loadingMoreRoomsChanged();
-
-        http::client()->post_public_rooms(
-          req,
-          [requested_server, this, req](const mtx::responses::PublicRooms &res,
-                                        mtx::http::RequestErr err) {
-                  loadingMoreRooms_ = false;
-                  emit loadingMoreRoomsChanged();
-
-                  if (err) {
-                          nhlog::net()->error(
-                            "Failed to retrieve rooms from mtxclient - {} - {} - {}",
-                            mtx::errors::to_string(err->matrix_error.errcode),
-                            err->matrix_error.error,
-                            err->parse_error);
-                  } else if (req.filter.generic_search_term == this->userSearchString_ &&
-                             req.since == this->prevBatch_ && requested_server == this->server_) {
-                          nhlog::net()->debug("signalling chunk to GUI thread");
-                          emit fetchedRoomsBatch(res.chunk, res.next_batch);
-                  }
-          },
-          requested_server);
+    if (!canFetchMore_)
+        return;
+
+    nhlog::net()->debug("Fetching more rooms from mtxclient...");
+
+    mtx::requests::PublicRooms req;
+    req.limit                      = limit_;
+    req.since                      = prevBatch_;
+    req.filter.generic_search_term = userSearchString_;
+    // req.third_party_instance_id = third_party_instance_id;
+    auto requested_server = server_;
+
+    reachedEndOfPagination_ = false;
+    emit reachedEndOfPaginationChanged();
+
+    loadingMoreRooms_ = true;
+    emit loadingMoreRoomsChanged();
+
+    http::client()->post_public_rooms(
+      req,
+      [requested_server, this, req](const mtx::responses::PublicRooms &res,
+                                    mtx::http::RequestErr err) {
+          loadingMoreRooms_ = false;
+          emit loadingMoreRoomsChanged();
+
+          if (err) {
+              nhlog::net()->error("Failed to retrieve rooms from mtxclient - {} - {} - {}",
+                                  mtx::errors::to_string(err->matrix_error.errcode),
+                                  err->matrix_error.error,
+                                  err->parse_error);
+          } else if (req.filter.generic_search_term == this->userSearchString_ &&
+                     req.since == this->prevBatch_ && requested_server == this->server_) {
+              nhlog::net()->debug("signalling chunk to GUI thread");
+              emit fetchedRoomsBatch(res.chunk, res.next_batch);
+          }
+      },
+      requested_server);
 }
 
 void
 RoomDirectoryModel::displayRooms(std::vector<mtx::responses::PublicRoomsChunk> fetched_rooms,
                                  const std::string &next_batch)
 {
-        nhlog::net()->debug("Prev batch: {} | Next batch: {}", prevBatch_, next_batch);
-
-        if (fetched_rooms.empty()) {
-                nhlog::net()->error("mtxclient helper thread yielded empty chunk!");
-                return;
-        }
-
-        beginInsertRows(QModelIndex(),
-                        static_cast<int>(publicRoomsData_.size()),
-                        static_cast<int>(publicRoomsData_.size() + fetched_rooms.size()) - 1);
-        this->publicRoomsData_.insert(
-          this->publicRoomsData_.end(), fetched_rooms.begin(), fetched_rooms.end());
-        endInsertRows();
-
-        if (next_batch.empty()) {
-                canFetchMore_           = false;
-                reachedEndOfPagination_ = true;
-                emit reachedEndOfPaginationChanged();
-        }
+    nhlog::net()->debug("Prev batch: {} | Next batch: {}", prevBatch_, next_batch);
+
+    if (fetched_rooms.empty()) {
+        nhlog::net()->error("mtxclient helper thread yielded empty chunk!");
+        return;
+    }
+
+    beginInsertRows(QModelIndex(),
+                    static_cast<int>(publicRoomsData_.size()),
+                    static_cast<int>(publicRoomsData_.size() + fetched_rooms.size()) - 1);
+    this->publicRoomsData_.insert(
+      this->publicRoomsData_.end(), fetched_rooms.begin(), fetched_rooms.end());
+    endInsertRows();
+
+    if (next_batch.empty()) {
+        canFetchMore_           = false;
+        reachedEndOfPagination_ = true;
+        emit reachedEndOfPaginationChanged();
+    }
 
-        prevBatch_ = next_batch;
+    prevBatch_ = next_batch;
 
-        nhlog::ui()->debug("Finished loading rooms");
+    nhlog::ui()->debug("Finished loading rooms");
 }
diff --git a/src/RoomDirectoryModel.h b/src/RoomDirectoryModel.h
index 80c04612..4699474b 100644
--- a/src/RoomDirectoryModel.h
+++ b/src/RoomDirectoryModel.h
@@ -25,74 +25,74 @@ struct PublicRooms;
 
 class RoomDirectoryModel : public QAbstractListModel
 {
-        Q_OBJECT
+    Q_OBJECT
 
-        Q_PROPERTY(bool loadingMoreRooms READ loadingMoreRooms NOTIFY loadingMoreRoomsChanged)
-        Q_PROPERTY(bool reachedEndOfPagination READ reachedEndOfPagination NOTIFY
-                     reachedEndOfPaginationChanged)
+    Q_PROPERTY(bool loadingMoreRooms READ loadingMoreRooms NOTIFY loadingMoreRoomsChanged)
+    Q_PROPERTY(
+      bool reachedEndOfPagination READ reachedEndOfPagination NOTIFY reachedEndOfPaginationChanged)
 
 public:
-        explicit RoomDirectoryModel(QObject *parent = nullptr, const std::string &server = "");
+    explicit RoomDirectoryModel(QObject *parent = nullptr, const std::string &server = "");
 
-        enum Roles
-        {
-                Name = Qt::UserRole,
-                Id,
-                AvatarUrl,
-                Topic,
-                MemberCount,
-                Previewable,
-                CanJoin,
-        };
-        QHash<int, QByteArray> roleNames() const override;
+    enum Roles
+    {
+        Name = Qt::UserRole,
+        Id,
+        AvatarUrl,
+        Topic,
+        MemberCount,
+        Previewable,
+        CanJoin,
+    };
+    QHash<int, QByteArray> roleNames() const override;
 
-        QVariant data(const QModelIndex &index, int role) const override;
+    QVariant data(const QModelIndex &index, int role) const override;
 
-        inline int rowCount(const QModelIndex &parent = QModelIndex()) const override
-        {
-                (void)parent;
-                return static_cast<int>(publicRoomsData_.size());
-        }
+    inline int rowCount(const QModelIndex &parent = QModelIndex()) const override
+    {
+        (void)parent;
+        return static_cast<int>(publicRoomsData_.size());
+    }
 
-        bool canFetchMore(const QModelIndex &) const override { return canFetchMore_; }
+    bool canFetchMore(const QModelIndex &) const override { return canFetchMore_; }
 
-        bool loadingMoreRooms() const { return loadingMoreRooms_; }
+    bool loadingMoreRooms() const { return loadingMoreRooms_; }
 
-        bool reachedEndOfPagination() const { return reachedEndOfPagination_; }
+    bool reachedEndOfPagination() const { return reachedEndOfPagination_; }
 
-        void fetchMore(const QModelIndex &) override;
+    void fetchMore(const QModelIndex &) override;
 
-        Q_INVOKABLE void joinRoom(const int &index = -1);
+    Q_INVOKABLE void joinRoom(const int &index = -1);
 
 signals:
-        void fetchedRoomsBatch(std::vector<mtx::responses::PublicRoomsChunk> rooms,
-                               const std::string &next_batch);
-        void loadingMoreRoomsChanged();
-        void reachedEndOfPaginationChanged();
+    void fetchedRoomsBatch(std::vector<mtx::responses::PublicRoomsChunk> rooms,
+                           const std::string &next_batch);
+    void loadingMoreRoomsChanged();
+    void reachedEndOfPaginationChanged();
 
 public slots:
-        void setMatrixServer(const QString &s = "");
-        void setSearchTerm(const QString &f);
+    void setMatrixServer(const QString &s = "");
+    void setSearchTerm(const QString &f);
 
 private slots:
 
-        void displayRooms(std::vector<mtx::responses::PublicRoomsChunk> rooms,
-                          const std::string &next_batch);
+    void displayRooms(std::vector<mtx::responses::PublicRoomsChunk> rooms,
+                      const std::string &next_batch);
 
 private:
-        bool canJoinRoom(const QString &room) const;
+    bool canJoinRoom(const QString &room) const;
 
-        static constexpr size_t limit_ = 50;
+    static constexpr size_t limit_ = 50;
 
-        std::string server_;
-        std::string userSearchString_;
-        std::string prevBatch_;
-        std::string nextBatch_;
-        bool canFetchMore_{true};
-        bool loadingMoreRooms_{false};
-        bool reachedEndOfPagination_{false};
-        std::vector<mtx::responses::PublicRoomsChunk> publicRoomsData_;
+    std::string server_;
+    std::string userSearchString_;
+    std::string prevBatch_;
+    std::string nextBatch_;
+    bool canFetchMore_{true};
+    bool loadingMoreRooms_{false};
+    bool reachedEndOfPagination_{false};
+    std::vector<mtx::responses::PublicRoomsChunk> publicRoomsData_;
 
-        std::vector<std::string> getViasForRoom(const std::vector<std::string> &room);
-        void resetDisplayedData();
+    std::vector<std::string> getViasForRoom(const std::vector<std::string> &room);
+    void resetDisplayedData();
 };
diff --git a/src/RoomsModel.cpp b/src/RoomsModel.cpp
index 656a0deb..8c05b7bb 100644
--- a/src/RoomsModel.cpp
+++ b/src/RoomsModel.cpp
@@ -14,71 +14,67 @@ RoomsModel::RoomsModel(bool showOnlyRoomWithAliases, QObject *parent)
   : QAbstractListModel(parent)
   , showOnlyRoomWithAliases_(showOnlyRoomWithAliases)
 {
-        std::vector<std::string> rooms_ = cache::joinedRooms();
-        roomInfos                       = cache::getRoomInfo(rooms_);
-        if (!showOnlyRoomWithAliases_) {
-                roomids.reserve(rooms_.size());
-                roomAliases.reserve(rooms_.size());
-        }
+    std::vector<std::string> rooms_ = cache::joinedRooms();
+    roomInfos                       = cache::getRoomInfo(rooms_);
+    if (!showOnlyRoomWithAliases_) {
+        roomids.reserve(rooms_.size());
+        roomAliases.reserve(rooms_.size());
+    }
 
-        for (const auto &r : rooms_) {
-                auto roomAliasesList = cache::client()->getRoomAliases(r);
+    for (const auto &r : rooms_) {
+        auto roomAliasesList = cache::client()->getRoomAliases(r);
 
-                if (showOnlyRoomWithAliases_) {
-                        if (roomAliasesList && !roomAliasesList->alias.empty()) {
-                                roomids.push_back(QString::fromStdString(r));
-                                roomAliases.push_back(
-                                  QString::fromStdString(roomAliasesList->alias));
-                        }
-                } else {
-                        roomids.push_back(QString::fromStdString(r));
-                        roomAliases.push_back(
-                          roomAliasesList ? QString::fromStdString(roomAliasesList->alias) : "");
-                }
+        if (showOnlyRoomWithAliases_) {
+            if (roomAliasesList && !roomAliasesList->alias.empty()) {
+                roomids.push_back(QString::fromStdString(r));
+                roomAliases.push_back(QString::fromStdString(roomAliasesList->alias));
+            }
+        } else {
+            roomids.push_back(QString::fromStdString(r));
+            roomAliases.push_back(roomAliasesList ? QString::fromStdString(roomAliasesList->alias)
+                                                  : "");
         }
+    }
 }
 
 QHash<int, QByteArray>
 RoomsModel::roleNames() const
 {
-        return {{CompletionModel::CompletionRole, "completionRole"},
-                {CompletionModel::SearchRole, "searchRole"},
-                {CompletionModel::SearchRole2, "searchRole2"},
-                {Roles::RoomAlias, "roomAlias"},
-                {Roles::AvatarUrl, "avatarUrl"},
-                {Roles::RoomID, "roomid"},
-                {Roles::RoomName, "roomName"}};
+    return {{CompletionModel::CompletionRole, "completionRole"},
+            {CompletionModel::SearchRole, "searchRole"},
+            {CompletionModel::SearchRole2, "searchRole2"},
+            {Roles::RoomAlias, "roomAlias"},
+            {Roles::AvatarUrl, "avatarUrl"},
+            {Roles::RoomID, "roomid"},
+            {Roles::RoomName, "roomName"}};
 }
 
 QVariant
 RoomsModel::data(const QModelIndex &index, int role) const
 {
-        if (hasIndex(index.row(), index.column(), index.parent())) {
-                switch (role) {
-                case CompletionModel::CompletionRole: {
-                        if (UserSettings::instance()->markdown()) {
-                                QString percentEncoding =
-                                  QUrl::toPercentEncoding(roomAliases[index.row()]);
-                                return QString("[%1](https://matrix.to/#/%2)")
-                                  .arg(roomAliases[index.row()], percentEncoding);
-                        } else {
-                                return roomAliases[index.row()];
-                        }
-                }
-                case CompletionModel::SearchRole:
-                case Qt::DisplayRole:
-                case Roles::RoomAlias:
-                        return roomAliases[index.row()].toHtmlEscaped();
-                case CompletionModel::SearchRole2:
-                case Roles::RoomName:
-                        return QString::fromStdString(roomInfos.at(roomids[index.row()]).name)
-                          .toHtmlEscaped();
-                case Roles::AvatarUrl:
-                        return QString::fromStdString(
-                          roomInfos.at(roomids[index.row()]).avatar_url);
-                case Roles::RoomID:
-                        return roomids[index.row()].toHtmlEscaped();
-                }
+    if (hasIndex(index.row(), index.column(), index.parent())) {
+        switch (role) {
+        case CompletionModel::CompletionRole: {
+            if (UserSettings::instance()->markdown()) {
+                QString percentEncoding = QUrl::toPercentEncoding(roomAliases[index.row()]);
+                return QString("[%1](https://matrix.to/#/%2)")
+                  .arg(roomAliases[index.row()], percentEncoding);
+            } else {
+                return roomAliases[index.row()];
+            }
+        }
+        case CompletionModel::SearchRole:
+        case Qt::DisplayRole:
+        case Roles::RoomAlias:
+            return roomAliases[index.row()].toHtmlEscaped();
+        case CompletionModel::SearchRole2:
+        case Roles::RoomName:
+            return QString::fromStdString(roomInfos.at(roomids[index.row()]).name).toHtmlEscaped();
+        case Roles::AvatarUrl:
+            return QString::fromStdString(roomInfos.at(roomids[index.row()]).avatar_url);
+        case Roles::RoomID:
+            return roomids[index.row()].toHtmlEscaped();
         }
-        return {};
+    }
+    return {};
 }
diff --git a/src/RoomsModel.h b/src/RoomsModel.h
index 255f207c..b6e29974 100644
--- a/src/RoomsModel.h
+++ b/src/RoomsModel.h
@@ -12,26 +12,26 @@
 class RoomsModel : public QAbstractListModel
 {
 public:
-        enum Roles
-        {
-                AvatarUrl = Qt::UserRole,
-                RoomAlias,
-                RoomID,
-                RoomName,
-        };
+    enum Roles
+    {
+        AvatarUrl = Qt::UserRole,
+        RoomAlias,
+        RoomID,
+        RoomName,
+    };
 
-        RoomsModel(bool showOnlyRoomWithAliases = false, QObject *parent = nullptr);
-        QHash<int, QByteArray> roleNames() const override;
-        int rowCount(const QModelIndex &parent = QModelIndex()) const override
-        {
-                (void)parent;
-                return (int)roomids.size();
-        }
-        QVariant data(const QModelIndex &index, int role) const override;
+    RoomsModel(bool showOnlyRoomWithAliases = false, QObject *parent = nullptr);
+    QHash<int, QByteArray> roleNames() const override;
+    int rowCount(const QModelIndex &parent = QModelIndex()) const override
+    {
+        (void)parent;
+        return (int)roomids.size();
+    }
+    QVariant data(const QModelIndex &index, int role) const override;
 
 private:
-        std::vector<QString> roomids;
-        std::vector<QString> roomAliases;
-        std::map<QString, RoomInfo> roomInfos;
-        bool showOnlyRoomWithAliases_;
+    std::vector<QString> roomids;
+    std::vector<QString> roomAliases;
+    std::map<QString, RoomInfo> roomInfos;
+    bool showOnlyRoomWithAliases_;
 };
diff --git a/src/SSOHandler.cpp b/src/SSOHandler.cpp
index 8fd0828c..a6f7ba11 100644
--- a/src/SSOHandler.cpp
+++ b/src/SSOHandler.cpp
@@ -12,46 +12,46 @@
 
 SSOHandler::SSOHandler(QObject *)
 {
-        QTimer::singleShot(120000, this, &SSOHandler::ssoFailed);
-
-        using namespace httplib;
-
-        svr.set_logger([](const Request &req, const Response &res) {
-                nhlog::net()->info("req: {}, res: {}", req.path, res.status);
-        });
-
-        svr.Get("/sso", [this](const Request &req, Response &res) {
-                if (req.has_param("loginToken")) {
-                        auto val = req.get_param_value("loginToken");
-                        res.set_content("SSO success", "text/plain");
-                        emit ssoSuccess(val);
-                } else {
-                        res.set_content("Missing loginToken for SSO login!", "text/plain");
-                        emit ssoFailed();
-                }
-        });
-
-        std::thread t([this]() {
-                this->port = svr.bind_to_any_port("localhost");
-                svr.listen_after_bind();
-        });
-        t.detach();
-
-        while (!svr.is_running()) {
-                std::this_thread::sleep_for(std::chrono::milliseconds(1));
+    QTimer::singleShot(120000, this, &SSOHandler::ssoFailed);
+
+    using namespace httplib;
+
+    svr.set_logger([](const Request &req, const Response &res) {
+        nhlog::net()->info("req: {}, res: {}", req.path, res.status);
+    });
+
+    svr.Get("/sso", [this](const Request &req, Response &res) {
+        if (req.has_param("loginToken")) {
+            auto val = req.get_param_value("loginToken");
+            res.set_content("SSO success", "text/plain");
+            emit ssoSuccess(val);
+        } else {
+            res.set_content("Missing loginToken for SSO login!", "text/plain");
+            emit ssoFailed();
         }
+    });
+
+    std::thread t([this]() {
+        this->port = svr.bind_to_any_port("localhost");
+        svr.listen_after_bind();
+    });
+    t.detach();
+
+    while (!svr.is_running()) {
+        std::this_thread::sleep_for(std::chrono::milliseconds(1));
+    }
 }
 
 SSOHandler::~SSOHandler()
 {
-        svr.stop();
-        while (svr.is_running()) {
-                std::this_thread::sleep_for(std::chrono::milliseconds(1));
-        }
+    svr.stop();
+    while (svr.is_running()) {
+        std::this_thread::sleep_for(std::chrono::milliseconds(1));
+    }
 }
 
 std::string
 SSOHandler::url() const
 {
-        return "http://localhost:" + std::to_string(port) + "/sso";
+    return "http://localhost:" + std::to_string(port) + "/sso";
 }
diff --git a/src/SSOHandler.h b/src/SSOHandler.h
index bd0d424d..ab652a06 100644
--- a/src/SSOHandler.h
+++ b/src/SSOHandler.h
@@ -9,20 +9,20 @@
 
 class SSOHandler : public QObject
 {
-        Q_OBJECT
+    Q_OBJECT
 
 public:
-        SSOHandler(QObject *parent = nullptr);
+    SSOHandler(QObject *parent = nullptr);
 
-        ~SSOHandler();
+    ~SSOHandler();
 
-        std::string url() const;
+    std::string url() const;
 
 signals:
-        void ssoSuccess(std::string token);
-        void ssoFailed();
+    void ssoSuccess(std::string token);
+    void ssoFailed();
 
 private:
-        httplib::Server svr;
-        int port = 0;
+    httplib::Server svr;
+    int port = 0;
 };
diff --git a/src/SingleImagePackModel.cpp b/src/SingleImagePackModel.cpp
index 6d0f0ad9..978a0480 100644
--- a/src/SingleImagePackModel.cpp
+++ b/src/SingleImagePackModel.cpp
@@ -24,344 +24,336 @@ SingleImagePackModel::SingleImagePackModel(ImagePackInfo pack_, QObject *parent)
   , old_statekey_(statekey_)
   , pack(std::move(pack_.pack))
 {
-        [[maybe_unused]] static auto imageInfoType = qRegisterMetaType<mtx::common::ImageInfo>();
+    [[maybe_unused]] static auto imageInfoType = qRegisterMetaType<mtx::common::ImageInfo>();
 
-        if (!pack.pack)
-                pack.pack = mtx::events::msc2545::ImagePack::PackDescription{};
+    if (!pack.pack)
+        pack.pack = mtx::events::msc2545::ImagePack::PackDescription{};
 
-        for (const auto &e : pack.images)
-                shortcodes.push_back(e.first);
+    for (const auto &e : pack.images)
+        shortcodes.push_back(e.first);
 
-        connect(this, &SingleImagePackModel::addImage, this, &SingleImagePackModel::addImageCb);
+    connect(this, &SingleImagePackModel::addImage, this, &SingleImagePackModel::addImageCb);
 }
 
 int
 SingleImagePackModel::rowCount(const QModelIndex &) const
 {
-        return (int)shortcodes.size();
+    return (int)shortcodes.size();
 }
 
 QHash<int, QByteArray>
 SingleImagePackModel::roleNames() const
 {
-        return {
-          {Roles::Url, "url"},
-          {Roles::ShortCode, "shortCode"},
-          {Roles::Body, "body"},
-          {Roles::IsEmote, "isEmote"},
-          {Roles::IsSticker, "isSticker"},
-        };
+    return {
+      {Roles::Url, "url"},
+      {Roles::ShortCode, "shortCode"},
+      {Roles::Body, "body"},
+      {Roles::IsEmote, "isEmote"},
+      {Roles::IsSticker, "isSticker"},
+    };
 }
 
 QVariant
 SingleImagePackModel::data(const QModelIndex &index, int role) const
 {
-        if (hasIndex(index.row(), index.column(), index.parent())) {
-                const auto &img = pack.images.at(shortcodes.at(index.row()));
-                switch (role) {
-                case Url:
-                        return QString::fromStdString(img.url);
-                case ShortCode:
-                        return QString::fromStdString(shortcodes.at(index.row()));
-                case Body:
-                        return QString::fromStdString(img.body);
-                case IsEmote:
-                        return img.overrides_usage() ? img.is_emoji() : pack.pack->is_emoji();
-                case IsSticker:
-                        return img.overrides_usage() ? img.is_sticker() : pack.pack->is_sticker();
-                default:
-                        return {};
-                }
+    if (hasIndex(index.row(), index.column(), index.parent())) {
+        const auto &img = pack.images.at(shortcodes.at(index.row()));
+        switch (role) {
+        case Url:
+            return QString::fromStdString(img.url);
+        case ShortCode:
+            return QString::fromStdString(shortcodes.at(index.row()));
+        case Body:
+            return QString::fromStdString(img.body);
+        case IsEmote:
+            return img.overrides_usage() ? img.is_emoji() : pack.pack->is_emoji();
+        case IsSticker:
+            return img.overrides_usage() ? img.is_sticker() : pack.pack->is_sticker();
+        default:
+            return {};
         }
-        return {};
+    }
+    return {};
 }
 
 bool
 SingleImagePackModel::setData(const QModelIndex &index, const QVariant &value, int role)
 {
-        using mtx::events::msc2545::PackUsage;
-
-        if (hasIndex(index.row(), index.column(), index.parent())) {
-                auto &img = pack.images.at(shortcodes.at(index.row()));
-                switch (role) {
-                case ShortCode: {
-                        auto newCode = value.toString().toStdString();
-
-                        // otherwise we delete this by accident
-                        if (pack.images.count(newCode))
-                                return false;
-
-                        auto tmp     = img;
-                        auto oldCode = shortcodes.at(index.row());
-                        pack.images.erase(oldCode);
-                        shortcodes[index.row()] = newCode;
-                        pack.images.insert({newCode, tmp});
-
-                        emit dataChanged(
-                          this->index(index.row()), this->index(index.row()), {Roles::ShortCode});
-                        return true;
-                }
-                case Body:
-                        img.body = value.toString().toStdString();
-                        emit dataChanged(
-                          this->index(index.row()), this->index(index.row()), {Roles::Body});
-                        return true;
-                case IsEmote: {
-                        bool isEmote = value.toBool();
-                        bool isSticker =
-                          img.overrides_usage() ? img.is_sticker() : pack.pack->is_sticker();
-
-                        img.usage.set(PackUsage::Emoji, isEmote);
-                        img.usage.set(PackUsage::Sticker, isSticker);
-
-                        if (img.usage == pack.pack->usage)
-                                img.usage.reset();
-
-                        emit dataChanged(
-                          this->index(index.row()), this->index(index.row()), {Roles::IsEmote});
-
-                        return true;
-                }
-                case IsSticker: {
-                        bool isEmote =
-                          img.overrides_usage() ? img.is_emoji() : pack.pack->is_emoji();
-                        bool isSticker = value.toBool();
-
-                        img.usage.set(PackUsage::Emoji, isEmote);
-                        img.usage.set(PackUsage::Sticker, isSticker);
-
-                        if (img.usage == pack.pack->usage)
-                                img.usage.reset();
-
-                        emit dataChanged(
-                          this->index(index.row()), this->index(index.row()), {Roles::IsSticker});
-
-                        return true;
-                }
-                }
+    using mtx::events::msc2545::PackUsage;
+
+    if (hasIndex(index.row(), index.column(), index.parent())) {
+        auto &img = pack.images.at(shortcodes.at(index.row()));
+        switch (role) {
+        case ShortCode: {
+            auto newCode = value.toString().toStdString();
+
+            // otherwise we delete this by accident
+            if (pack.images.count(newCode))
+                return false;
+
+            auto tmp     = img;
+            auto oldCode = shortcodes.at(index.row());
+            pack.images.erase(oldCode);
+            shortcodes[index.row()] = newCode;
+            pack.images.insert({newCode, tmp});
+
+            emit dataChanged(
+              this->index(index.row()), this->index(index.row()), {Roles::ShortCode});
+            return true;
         }
-        return false;
+        case Body:
+            img.body = value.toString().toStdString();
+            emit dataChanged(this->index(index.row()), this->index(index.row()), {Roles::Body});
+            return true;
+        case IsEmote: {
+            bool isEmote   = value.toBool();
+            bool isSticker = img.overrides_usage() ? img.is_sticker() : pack.pack->is_sticker();
+
+            img.usage.set(PackUsage::Emoji, isEmote);
+            img.usage.set(PackUsage::Sticker, isSticker);
+
+            if (img.usage == pack.pack->usage)
+                img.usage.reset();
+
+            emit dataChanged(this->index(index.row()), this->index(index.row()), {Roles::IsEmote});
+
+            return true;
+        }
+        case IsSticker: {
+            bool isEmote   = img.overrides_usage() ? img.is_emoji() : pack.pack->is_emoji();
+            bool isSticker = value.toBool();
+
+            img.usage.set(PackUsage::Emoji, isEmote);
+            img.usage.set(PackUsage::Sticker, isSticker);
+
+            if (img.usage == pack.pack->usage)
+                img.usage.reset();
+
+            emit dataChanged(
+              this->index(index.row()), this->index(index.row()), {Roles::IsSticker});
+
+            return true;
+        }
+        }
+    }
+    return false;
 }
 
 bool
 SingleImagePackModel::isGloballyEnabled() const
 {
-        if (auto roomPacks =
-              cache::client()->getAccountData(mtx::events::EventType::ImagePackRooms)) {
-                if (auto tmp = std::get_if<
-                      mtx::events::EphemeralEvent<mtx::events::msc2545::ImagePackRooms>>(
-                      &*roomPacks)) {
-                        if (tmp->content.rooms.count(roomid_) &&
-                            tmp->content.rooms.at(roomid_).count(statekey_))
-                                return true;
-                }
+    if (auto roomPacks = cache::client()->getAccountData(mtx::events::EventType::ImagePackRooms)) {
+        if (auto tmp =
+              std::get_if<mtx::events::EphemeralEvent<mtx::events::msc2545::ImagePackRooms>>(
+                &*roomPacks)) {
+            if (tmp->content.rooms.count(roomid_) &&
+                tmp->content.rooms.at(roomid_).count(statekey_))
+                return true;
         }
-        return false;
+    }
+    return false;
 }
 void
 SingleImagePackModel::setGloballyEnabled(bool enabled)
 {
-        mtx::events::msc2545::ImagePackRooms content{};
-        if (auto roomPacks =
-              cache::client()->getAccountData(mtx::events::EventType::ImagePackRooms)) {
-                if (auto tmp = std::get_if<
-                      mtx::events::EphemeralEvent<mtx::events::msc2545::ImagePackRooms>>(
-                      &*roomPacks)) {
-                        content = tmp->content;
-                }
+    mtx::events::msc2545::ImagePackRooms content{};
+    if (auto roomPacks = cache::client()->getAccountData(mtx::events::EventType::ImagePackRooms)) {
+        if (auto tmp =
+              std::get_if<mtx::events::EphemeralEvent<mtx::events::msc2545::ImagePackRooms>>(
+                &*roomPacks)) {
+            content = tmp->content;
         }
+    }
 
-        if (enabled)
-                content.rooms[roomid_][statekey_] = {};
-        else
-                content.rooms[roomid_].erase(statekey_);
+    if (enabled)
+        content.rooms[roomid_][statekey_] = {};
+    else
+        content.rooms[roomid_].erase(statekey_);
 
-        http::client()->put_account_data(content, [](mtx::http::RequestErr) {
-                // emit this->globallyEnabledChanged();
-        });
+    http::client()->put_account_data(content, [](mtx::http::RequestErr) {
+        // emit this->globallyEnabledChanged();
+    });
 }
 
 bool
 SingleImagePackModel::canEdit() const
 {
-        if (roomid_.empty())
-                return true;
-        else
-                return Permissions(QString::fromStdString(roomid_))
-                  .canChange(qml_mtx_events::ImagePackInRoom);
+    if (roomid_.empty())
+        return true;
+    else
+        return Permissions(QString::fromStdString(roomid_))
+          .canChange(qml_mtx_events::ImagePackInRoom);
 }
 
 void
 SingleImagePackModel::setPackname(QString val)
 {
-        auto val_ = val.toStdString();
-        if (val_ != this->pack.pack->display_name) {
-                this->pack.pack->display_name = val_;
-                emit packnameChanged();
-        }
+    auto val_ = val.toStdString();
+    if (val_ != this->pack.pack->display_name) {
+        this->pack.pack->display_name = val_;
+        emit packnameChanged();
+    }
 }
 
 void
 SingleImagePackModel::setAttribution(QString val)
 {
-        auto val_ = val.toStdString();
-        if (val_ != this->pack.pack->attribution) {
-                this->pack.pack->attribution = val_;
-                emit attributionChanged();
-        }
+    auto val_ = val.toStdString();
+    if (val_ != this->pack.pack->attribution) {
+        this->pack.pack->attribution = val_;
+        emit attributionChanged();
+    }
 }
 
 void
 SingleImagePackModel::setAvatarUrl(QString val)
 {
-        auto val_ = val.toStdString();
-        if (val_ != this->pack.pack->avatar_url) {
-                this->pack.pack->avatar_url = val_;
-                emit avatarUrlChanged();
-        }
+    auto val_ = val.toStdString();
+    if (val_ != this->pack.pack->avatar_url) {
+        this->pack.pack->avatar_url = val_;
+        emit avatarUrlChanged();
+    }
 }
 
 void
 SingleImagePackModel::setStatekey(QString val)
 {
-        auto val_ = val.toStdString();
-        if (val_ != statekey_) {
-                statekey_ = val_;
-                emit statekeyChanged();
-        }
+    auto val_ = val.toStdString();
+    if (val_ != statekey_) {
+        statekey_ = val_;
+        emit statekeyChanged();
+    }
 }
 
 void
 SingleImagePackModel::setIsStickerPack(bool val)
 {
-        using mtx::events::msc2545::PackUsage;
-        if (val != pack.pack->is_sticker()) {
-                pack.pack->usage.set(PackUsage::Sticker, val);
-                emit isStickerPackChanged();
-        }
+    using mtx::events::msc2545::PackUsage;
+    if (val != pack.pack->is_sticker()) {
+        pack.pack->usage.set(PackUsage::Sticker, val);
+        emit isStickerPackChanged();
+    }
 }
 
 void
 SingleImagePackModel::setIsEmotePack(bool val)
 {
-        using mtx::events::msc2545::PackUsage;
-        if (val != pack.pack->is_emoji()) {
-                pack.pack->usage.set(PackUsage::Emoji, val);
-                emit isEmotePackChanged();
-        }
+    using mtx::events::msc2545::PackUsage;
+    if (val != pack.pack->is_emoji()) {
+        pack.pack->usage.set(PackUsage::Emoji, val);
+        emit isEmotePackChanged();
+    }
 }
 
 void
 SingleImagePackModel::save()
 {
-        if (roomid_.empty()) {
-                http::client()->put_account_data(pack, [](mtx::http::RequestErr e) {
-                        if (e)
-                                ChatPage::instance()->showNotification(
-                                  tr("Failed to update image pack: %1")
-                                    .arg(QString::fromStdString(e->matrix_error.error)));
-                });
-        } else {
-                if (old_statekey_ != statekey_) {
-                        http::client()->send_state_event(
-                          roomid_,
-                          to_string(mtx::events::EventType::ImagePackInRoom),
-                          old_statekey_,
-                          nlohmann::json::object(),
-                          [](const mtx::responses::EventId &, mtx::http::RequestErr e) {
-                                  if (e)
-                                          ChatPage::instance()->showNotification(
-                                            tr("Failed to delete old image pack: %1")
-                                              .arg(QString::fromStdString(e->matrix_error.error)));
-                          });
-                }
-
-                http::client()->send_state_event(
-                  roomid_,
-                  statekey_,
-                  pack,
-                  [this](const mtx::responses::EventId &, mtx::http::RequestErr e) {
-                          if (e)
-                                  ChatPage::instance()->showNotification(
-                                    tr("Failed to update image pack: %1")
-                                      .arg(QString::fromStdString(e->matrix_error.error)));
-
-                          nhlog::net()->info("Uploaded image pack: %1", statekey_);
-                  });
+    if (roomid_.empty()) {
+        http::client()->put_account_data(pack, [](mtx::http::RequestErr e) {
+            if (e)
+                ChatPage::instance()->showNotification(
+                  tr("Failed to update image pack: %1")
+                    .arg(QString::fromStdString(e->matrix_error.error)));
+        });
+    } else {
+        if (old_statekey_ != statekey_) {
+            http::client()->send_state_event(
+              roomid_,
+              to_string(mtx::events::EventType::ImagePackInRoom),
+              old_statekey_,
+              nlohmann::json::object(),
+              [](const mtx::responses::EventId &, mtx::http::RequestErr e) {
+                  if (e)
+                      ChatPage::instance()->showNotification(
+                        tr("Failed to delete old image pack: %1")
+                          .arg(QString::fromStdString(e->matrix_error.error)));
+              });
         }
+
+        http::client()->send_state_event(
+          roomid_,
+          statekey_,
+          pack,
+          [this](const mtx::responses::EventId &, mtx::http::RequestErr e) {
+              if (e)
+                  ChatPage::instance()->showNotification(
+                    tr("Failed to update image pack: %1")
+                      .arg(QString::fromStdString(e->matrix_error.error)));
+
+              nhlog::net()->info("Uploaded image pack: %1", statekey_);
+          });
+    }
 }
 
 void
 SingleImagePackModel::addStickers(QList<QUrl> files)
 {
-        for (const auto &f : files) {
-                auto file = QFile(f.toLocalFile());
-                if (!file.open(QFile::ReadOnly)) {
-                        ChatPage::instance()->showNotification(
-                          tr("Failed to open image: %1").arg(f.toLocalFile()));
-                        return;
-                }
-
-                auto bytes = file.readAll();
-                auto img   = utils::readImage(bytes);
-
-                mtx::common::ImageInfo info{};
-
-                auto sz = img.size() / 2;
-                if (sz.width() > 512 || sz.height() > 512) {
-                        sz.scale(512, 512, Qt::AspectRatioMode::KeepAspectRatio);
-                } else if (img.height() < 128 && img.width() < 128) {
-                        sz = img.size();
-                }
-
-                info.h    = sz.height();
-                info.w    = sz.width();
-                info.size = bytes.size();
-                info.mimetype =
-                  QMimeDatabase().mimeTypeForFile(f.toLocalFile()).name().toStdString();
-
-                auto filename = f.fileName().toStdString();
-                http::client()->upload(
-                  bytes.toStdString(),
-                  QMimeDatabase().mimeTypeForFile(f.toLocalFile()).name().toStdString(),
-                  filename,
-                  [this, filename, info](const mtx::responses::ContentURI &uri,
-                                         mtx::http::RequestErr e) {
-                          if (e) {
-                                  ChatPage::instance()->showNotification(
-                                    tr("Failed to upload image: %1")
-                                      .arg(QString::fromStdString(e->matrix_error.error)));
-                                  return;
-                          }
-
-                          emit addImage(uri.content_uri, filename, info);
-                  });
+    for (const auto &f : files) {
+        auto file = QFile(f.toLocalFile());
+        if (!file.open(QFile::ReadOnly)) {
+            ChatPage::instance()->showNotification(
+              tr("Failed to open image: %1").arg(f.toLocalFile()));
+            return;
         }
+
+        auto bytes = file.readAll();
+        auto img   = utils::readImage(bytes);
+
+        mtx::common::ImageInfo info{};
+
+        auto sz = img.size() / 2;
+        if (sz.width() > 512 || sz.height() > 512) {
+            sz.scale(512, 512, Qt::AspectRatioMode::KeepAspectRatio);
+        } else if (img.height() < 128 && img.width() < 128) {
+            sz = img.size();
+        }
+
+        info.h        = sz.height();
+        info.w        = sz.width();
+        info.size     = bytes.size();
+        info.mimetype = QMimeDatabase().mimeTypeForFile(f.toLocalFile()).name().toStdString();
+
+        auto filename = f.fileName().toStdString();
+        http::client()->upload(
+          bytes.toStdString(),
+          QMimeDatabase().mimeTypeForFile(f.toLocalFile()).name().toStdString(),
+          filename,
+          [this, filename, info](const mtx::responses::ContentURI &uri, mtx::http::RequestErr e) {
+              if (e) {
+                  ChatPage::instance()->showNotification(
+                    tr("Failed to upload image: %1")
+                      .arg(QString::fromStdString(e->matrix_error.error)));
+                  return;
+              }
+
+              emit addImage(uri.content_uri, filename, info);
+          });
+    }
 }
 
 void
 SingleImagePackModel::remove(int idx)
 {
-        if (idx < (int)shortcodes.size() && idx >= 0) {
-                beginRemoveRows(QModelIndex(), idx, idx);
-                auto s = shortcodes.at(idx);
-                shortcodes.erase(shortcodes.begin() + idx);
-                pack.images.erase(s);
-                endRemoveRows();
-        }
+    if (idx < (int)shortcodes.size() && idx >= 0) {
+        beginRemoveRows(QModelIndex(), idx, idx);
+        auto s = shortcodes.at(idx);
+        shortcodes.erase(shortcodes.begin() + idx);
+        pack.images.erase(s);
+        endRemoveRows();
+    }
 }
 
 void
 SingleImagePackModel::addImageCb(std::string uri, std::string filename, mtx::common::ImageInfo info)
 {
-        mtx::events::msc2545::PackImage img{};
-        img.url  = uri;
-        img.info = info;
-        beginInsertRows(
-          QModelIndex(), static_cast<int>(shortcodes.size()), static_cast<int>(shortcodes.size()));
+    mtx::events::msc2545::PackImage img{};
+    img.url  = uri;
+    img.info = info;
+    beginInsertRows(
+      QModelIndex(), static_cast<int>(shortcodes.size()), static_cast<int>(shortcodes.size()));
 
-        pack.images[filename] = img;
-        shortcodes.push_back(filename);
+    pack.images[filename] = img;
+    shortcodes.push_back(filename);
 
-        endInsertRows();
+    endInsertRows();
 }
diff --git a/src/SingleImagePackModel.h b/src/SingleImagePackModel.h
index 60138d36..cd8b0547 100644
--- a/src/SingleImagePackModel.h
+++ b/src/SingleImagePackModel.h
@@ -14,81 +14,78 @@
 
 class SingleImagePackModel : public QAbstractListModel
 {
-        Q_OBJECT
-
-        Q_PROPERTY(QString roomid READ roomid CONSTANT)
-        Q_PROPERTY(QString statekey READ statekey WRITE setStatekey NOTIFY statekeyChanged)
-        Q_PROPERTY(
-          QString attribution READ attribution WRITE setAttribution NOTIFY attributionChanged)
-        Q_PROPERTY(QString packname READ packname WRITE setPackname NOTIFY packnameChanged)
-        Q_PROPERTY(QString avatarUrl READ avatarUrl WRITE setAvatarUrl NOTIFY avatarUrlChanged)
-        Q_PROPERTY(
-          bool isStickerPack READ isStickerPack WRITE setIsStickerPack NOTIFY isStickerPackChanged)
-        Q_PROPERTY(bool isEmotePack READ isEmotePack WRITE setIsEmotePack NOTIFY isEmotePackChanged)
-        Q_PROPERTY(bool isGloballyEnabled READ isGloballyEnabled WRITE setGloballyEnabled NOTIFY
-                     globallyEnabledChanged)
-        Q_PROPERTY(bool canEdit READ canEdit CONSTANT)
+    Q_OBJECT
+
+    Q_PROPERTY(QString roomid READ roomid CONSTANT)
+    Q_PROPERTY(QString statekey READ statekey WRITE setStatekey NOTIFY statekeyChanged)
+    Q_PROPERTY(QString attribution READ attribution WRITE setAttribution NOTIFY attributionChanged)
+    Q_PROPERTY(QString packname READ packname WRITE setPackname NOTIFY packnameChanged)
+    Q_PROPERTY(QString avatarUrl READ avatarUrl WRITE setAvatarUrl NOTIFY avatarUrlChanged)
+    Q_PROPERTY(
+      bool isStickerPack READ isStickerPack WRITE setIsStickerPack NOTIFY isStickerPackChanged)
+    Q_PROPERTY(bool isEmotePack READ isEmotePack WRITE setIsEmotePack NOTIFY isEmotePackChanged)
+    Q_PROPERTY(bool isGloballyEnabled READ isGloballyEnabled WRITE setGloballyEnabled NOTIFY
+                 globallyEnabledChanged)
+    Q_PROPERTY(bool canEdit READ canEdit CONSTANT)
 
 public:
-        enum Roles
-        {
-                Url = Qt::UserRole,
-                ShortCode,
-                Body,
-                IsEmote,
-                IsSticker,
-        };
-        Q_ENUM(Roles);
-
-        SingleImagePackModel(ImagePackInfo pack_, QObject *parent = nullptr);
-        QHash<int, QByteArray> roleNames() const override;
-        int rowCount(const QModelIndex &parent = QModelIndex()) const override;
-        QVariant data(const QModelIndex &index, int role) const override;
-        bool setData(const QModelIndex &index,
-                     const QVariant &value,
-                     int role = Qt::EditRole) override;
-
-        QString roomid() const { return QString::fromStdString(roomid_); }
-        QString statekey() const { return QString::fromStdString(statekey_); }
-        QString packname() const { return QString::fromStdString(pack.pack->display_name); }
-        QString attribution() const { return QString::fromStdString(pack.pack->attribution); }
-        QString avatarUrl() const { return QString::fromStdString(pack.pack->avatar_url); }
-        bool isStickerPack() const { return pack.pack->is_sticker(); }
-        bool isEmotePack() const { return pack.pack->is_emoji(); }
-
-        bool isGloballyEnabled() const;
-        bool canEdit() const;
-        void setGloballyEnabled(bool enabled);
-
-        void setPackname(QString val);
-        void setAttribution(QString val);
-        void setAvatarUrl(QString val);
-        void setStatekey(QString val);
-        void setIsStickerPack(bool val);
-        void setIsEmotePack(bool val);
-
-        Q_INVOKABLE void save();
-        Q_INVOKABLE void addStickers(QList<QUrl> files);
-        Q_INVOKABLE void remove(int index);
+    enum Roles
+    {
+        Url = Qt::UserRole,
+        ShortCode,
+        Body,
+        IsEmote,
+        IsSticker,
+    };
+    Q_ENUM(Roles);
+
+    SingleImagePackModel(ImagePackInfo pack_, QObject *parent = nullptr);
+    QHash<int, QByteArray> roleNames() const override;
+    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+    QVariant data(const QModelIndex &index, int role) const override;
+    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
+
+    QString roomid() const { return QString::fromStdString(roomid_); }
+    QString statekey() const { return QString::fromStdString(statekey_); }
+    QString packname() const { return QString::fromStdString(pack.pack->display_name); }
+    QString attribution() const { return QString::fromStdString(pack.pack->attribution); }
+    QString avatarUrl() const { return QString::fromStdString(pack.pack->avatar_url); }
+    bool isStickerPack() const { return pack.pack->is_sticker(); }
+    bool isEmotePack() const { return pack.pack->is_emoji(); }
+
+    bool isGloballyEnabled() const;
+    bool canEdit() const;
+    void setGloballyEnabled(bool enabled);
+
+    void setPackname(QString val);
+    void setAttribution(QString val);
+    void setAvatarUrl(QString val);
+    void setStatekey(QString val);
+    void setIsStickerPack(bool val);
+    void setIsEmotePack(bool val);
+
+    Q_INVOKABLE void save();
+    Q_INVOKABLE void addStickers(QList<QUrl> files);
+    Q_INVOKABLE void remove(int index);
 
 signals:
-        void globallyEnabledChanged();
-        void statekeyChanged();
-        void attributionChanged();
-        void packnameChanged();
-        void avatarUrlChanged();
-        void isEmotePackChanged();
-        void isStickerPackChanged();
+    void globallyEnabledChanged();
+    void statekeyChanged();
+    void attributionChanged();
+    void packnameChanged();
+    void avatarUrlChanged();
+    void isEmotePackChanged();
+    void isStickerPackChanged();
 
-        void addImage(std::string uri, std::string filename, mtx::common::ImageInfo info);
+    void addImage(std::string uri, std::string filename, mtx::common::ImageInfo info);
 
 private slots:
-        void addImageCb(std::string uri, std::string filename, mtx::common::ImageInfo info);
+    void addImageCb(std::string uri, std::string filename, mtx::common::ImageInfo info);
 
 private:
-        std::string roomid_;
-        std::string statekey_, old_statekey_;
+    std::string roomid_;
+    std::string statekey_, old_statekey_;
 
-        mtx::events::msc2545::ImagePack pack;
-        std::vector<std::string> shortcodes;
+    mtx::events::msc2545::ImagePack pack;
+    std::vector<std::string> shortcodes;
 };
diff --git a/src/TrayIcon.cpp b/src/TrayIcon.cpp
index db0130c8..98a1d242 100644
--- a/src/TrayIcon.cpp
+++ b/src/TrayIcon.cpp
@@ -19,7 +19,7 @@
 MsgCountComposedIcon::MsgCountComposedIcon(const QString &filename)
   : QIconEngine()
 {
-        icon_ = QIcon(filename);
+    icon_ = QIcon(filename);
 }
 
 void
@@ -28,95 +28,95 @@ MsgCountComposedIcon::paint(QPainter *painter,
                             QIcon::Mode mode,
                             QIcon::State state)
 {
-        painter->setRenderHint(QPainter::TextAntialiasing);
-        painter->setRenderHint(QPainter::SmoothPixmapTransform);
-        painter->setRenderHint(QPainter::Antialiasing);
-
-        icon_.paint(painter, rect, Qt::AlignCenter, mode, state);
-
-        if (msgCount <= 0)
-                return;
-
-        QColor backgroundColor("red");
-        QColor textColor("white");
-
-        QBrush brush;
-        brush.setStyle(Qt::SolidPattern);
-        brush.setColor(backgroundColor);
-
-        QFont f;
-        f.setPointSizeF(8);
-        f.setWeight(QFont::Thin);
-
-        painter->setBrush(brush);
-        painter->setPen(Qt::NoPen);
-        painter->setFont(f);
-
-        QRectF bubble(rect.width() - BubbleDiameter,
-                      rect.height() - BubbleDiameter,
-                      BubbleDiameter,
-                      BubbleDiameter);
-        painter->drawEllipse(bubble);
-        painter->setPen(QPen(textColor));
-        painter->setBrush(Qt::NoBrush);
-        painter->drawText(bubble, Qt::AlignCenter, QString::number(msgCount));
+    painter->setRenderHint(QPainter::TextAntialiasing);
+    painter->setRenderHint(QPainter::SmoothPixmapTransform);
+    painter->setRenderHint(QPainter::Antialiasing);
+
+    icon_.paint(painter, rect, Qt::AlignCenter, mode, state);
+
+    if (msgCount <= 0)
+        return;
+
+    QColor backgroundColor("red");
+    QColor textColor("white");
+
+    QBrush brush;
+    brush.setStyle(Qt::SolidPattern);
+    brush.setColor(backgroundColor);
+
+    QFont f;
+    f.setPointSizeF(8);
+    f.setWeight(QFont::Thin);
+
+    painter->setBrush(brush);
+    painter->setPen(Qt::NoPen);
+    painter->setFont(f);
+
+    QRectF bubble(rect.width() - BubbleDiameter,
+                  rect.height() - BubbleDiameter,
+                  BubbleDiameter,
+                  BubbleDiameter);
+    painter->drawEllipse(bubble);
+    painter->setPen(QPen(textColor));
+    painter->setBrush(Qt::NoBrush);
+    painter->drawText(bubble, Qt::AlignCenter, QString::number(msgCount));
 }
 
 QIconEngine *
 MsgCountComposedIcon::clone() const
 {
-        return new MsgCountComposedIcon(*this);
+    return new MsgCountComposedIcon(*this);
 }
 
 QList<QSize>
 MsgCountComposedIcon::availableSizes(QIcon::Mode mode, QIcon::State state) const
 {
-        Q_UNUSED(mode);
-        Q_UNUSED(state);
-        QList<QSize> sizes;
-        sizes.append(QSize(24, 24));
-        sizes.append(QSize(32, 32));
-        sizes.append(QSize(48, 48));
-        sizes.append(QSize(64, 64));
-        sizes.append(QSize(128, 128));
-        sizes.append(QSize(256, 256));
-        return sizes;
+    Q_UNUSED(mode);
+    Q_UNUSED(state);
+    QList<QSize> sizes;
+    sizes.append(QSize(24, 24));
+    sizes.append(QSize(32, 32));
+    sizes.append(QSize(48, 48));
+    sizes.append(QSize(64, 64));
+    sizes.append(QSize(128, 128));
+    sizes.append(QSize(256, 256));
+    return sizes;
 }
 
 QPixmap
 MsgCountComposedIcon::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)
 {
-        QImage img(size, QImage::Format_ARGB32);
-        img.fill(qRgba(0, 0, 0, 0));
-        QPixmap result = QPixmap::fromImage(img, Qt::NoFormatConversion);
-        {
-                QPainter painter(&result);
-                paint(&painter, QRect(QPoint(0, 0), size), mode, state);
-        }
-        return result;
+    QImage img(size, QImage::Format_ARGB32);
+    img.fill(qRgba(0, 0, 0, 0));
+    QPixmap result = QPixmap::fromImage(img, Qt::NoFormatConversion);
+    {
+        QPainter painter(&result);
+        paint(&painter, QRect(QPoint(0, 0), size), mode, state);
+    }
+    return result;
 }
 
 TrayIcon::TrayIcon(const QString &filename, QWidget *parent)
   : QSystemTrayIcon(parent)
 {
 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
-        setIcon(QIcon(filename));
+    setIcon(QIcon(filename));
 #else
-        icon_ = new MsgCountComposedIcon(filename);
-        setIcon(QIcon(icon_));
+    icon_ = new MsgCountComposedIcon(filename);
+    setIcon(QIcon(icon_));
 #endif
 
-        QMenu *menu = new QMenu(parent);
-        setContextMenu(menu);
+    QMenu *menu = new QMenu(parent);
+    setContextMenu(menu);
 
-        viewAction_ = new QAction(tr("Show"), this);
-        quitAction_ = new QAction(tr("Quit"), this);
+    viewAction_ = new QAction(tr("Show"), this);
+    quitAction_ = new QAction(tr("Quit"), this);
 
-        connect(viewAction_, SIGNAL(triggered()), parent, SLOT(show()));
-        connect(quitAction_, &QAction::triggered, this, QApplication::quit);
+    connect(viewAction_, SIGNAL(triggered()), parent, SLOT(show()));
+    connect(quitAction_, &QAction::triggered, this, QApplication::quit);
 
-        menu->addAction(viewAction_);
-        menu->addAction(quitAction_);
+    menu->addAction(viewAction_);
+    menu->addAction(quitAction_);
 }
 
 void
@@ -127,25 +127,25 @@ TrayIcon::setUnreadCount(int count)
 // currently, to avoid writing obj-c code, ignore deprecated warnings on the badge functions
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
-        auto labelText = count == 0 ? "" : QString::number(count);
+    auto labelText = count == 0 ? "" : QString::number(count);
 
-        if (labelText == QtMac::badgeLabelText())
-                return;
+    if (labelText == QtMac::badgeLabelText())
+        return;
 
-        QtMac::setBadgeLabelText(labelText);
+    QtMac::setBadgeLabelText(labelText);
 #pragma clang diagnostic pop
 #elif defined(Q_OS_WIN)
 // FIXME: Find a way to use Windows apis for the badge counter (if any).
 #else
-        if (count == icon_->msgCount)
-                return;
+    if (count == icon_->msgCount)
+        return;
 
-        // Custom drawing on Linux.
-        MsgCountComposedIcon *tmp = static_cast<MsgCountComposedIcon *>(icon_->clone());
-        tmp->msgCount             = count;
+    // Custom drawing on Linux.
+    MsgCountComposedIcon *tmp = static_cast<MsgCountComposedIcon *>(icon_->clone());
+    tmp->msgCount             = count;
 
-        setIcon(QIcon(tmp));
+    setIcon(QIcon(tmp));
 
-        icon_ = tmp;
+    icon_ = tmp;
 #endif
 }
diff --git a/src/TrayIcon.h b/src/TrayIcon.h
index 10dfafc5..1ce7fb0b 100644
--- a/src/TrayIcon.h
+++ b/src/TrayIcon.h
@@ -16,33 +16,33 @@ class QPainter;
 class MsgCountComposedIcon : public QIconEngine
 {
 public:
-        MsgCountComposedIcon(const QString &filename);
+    MsgCountComposedIcon(const QString &filename);
 
-        void paint(QPainter *p, const QRect &rect, QIcon::Mode mode, QIcon::State state) override;
-        QIconEngine *clone() const override;
-        QList<QSize> availableSizes(QIcon::Mode mode, QIcon::State state) const override;
-        QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
+    void paint(QPainter *p, const QRect &rect, QIcon::Mode mode, QIcon::State state) override;
+    QIconEngine *clone() const override;
+    QList<QSize> availableSizes(QIcon::Mode mode, QIcon::State state) const override;
+    QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override;
 
-        int msgCount = 0;
+    int msgCount = 0;
 
 private:
-        const int BubbleDiameter = 17;
+    const int BubbleDiameter = 17;
 
-        QIcon icon_;
+    QIcon icon_;
 };
 
 class TrayIcon : public QSystemTrayIcon
 {
-        Q_OBJECT
+    Q_OBJECT
 public:
-        TrayIcon(const QString &filename, QWidget *parent);
+    TrayIcon(const QString &filename, QWidget *parent);
 
 public slots:
-        void setUnreadCount(int count);
+    void setUnreadCount(int count);
 
 private:
-        QAction *viewAction_;
-        QAction *quitAction_;
+    QAction *viewAction_;
+    QAction *quitAction_;
 
-        MsgCountComposedIcon *icon_;
+    MsgCountComposedIcon *icon_;
 };
diff --git a/src/UserSettingsPage.cpp b/src/UserSettingsPage.cpp
index 7b01b0b8..cc1f8206 100644
--- a/src/UserSettingsPage.cpp
+++ b/src/UserSettingsPage.cpp
@@ -41,1499 +41,1484 @@ QSharedPointer<UserSettings> UserSettings::instance_;
 
 UserSettings::UserSettings()
 {
-        connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, []() {
-                instance_.clear();
-        });
+    connect(
+      QCoreApplication::instance(), &QCoreApplication::aboutToQuit, []() { instance_.clear(); });
 }
 
 QSharedPointer<UserSettings>
 UserSettings::instance()
 {
-        return instance_;
+    return instance_;
 }
 
 void
 UserSettings::initialize(std::optional<QString> profile)
 {
-        instance_.reset(new UserSettings());
-        instance_->load(profile);
+    instance_.reset(new UserSettings());
+    instance_->load(profile);
 }
 
 void
 UserSettings::load(std::optional<QString> profile)
 {
-        tray_        = settings.value("user/window/tray", false).toBool();
-        startInTray_ = settings.value("user/window/start_in_tray", false).toBool();
-
-        roomListWidth_      = settings.value("user/sidebar/room_list_width", -1).toInt();
-        communityListWidth_ = settings.value("user/sidebar/community_list_width", -1).toInt();
-
-        hasDesktopNotifications_ = settings.value("user/desktop_notifications", true).toBool();
-        hasAlertOnNotification_  = settings.value("user/alert_on_notification", false).toBool();
-        groupView_               = settings.value("user/group_view", true).toBool();
-        hiddenTags_              = settings.value("user/hidden_tags", QStringList{}).toStringList();
-        buttonsInTimeline_       = settings.value("user/timeline/buttons", true).toBool();
-        timelineMaxWidth_        = settings.value("user/timeline/max_width", 0).toInt();
-        messageHoverHighlight_ =
-          settings.value("user/timeline/message_hover_highlight", false).toBool();
-        enlargeEmojiOnlyMessages_ =
-          settings.value("user/timeline/enlarge_emoji_only_msg", false).toBool();
-        markdown_             = settings.value("user/markdown_enabled", true).toBool();
-        animateImagesOnHover_ = settings.value("user/animate_images_on_hover", false).toBool();
-        typingNotifications_  = settings.value("user/typing_notifications", true).toBool();
-        sortByImportance_     = settings.value("user/sort_by_unread", true).toBool();
-        readReceipts_         = settings.value("user/read_receipts", true).toBool();
-        theme_                = settings.value("user/theme", defaultTheme_).toString();
-        font_                 = settings.value("user/font_family", "default").toString();
-        avatarCircles_        = settings.value("user/avatar_circles", true).toBool();
-        useIdenticon_         = settings.value("user/use_identicon", true).toBool();
-        decryptSidebar_       = settings.value("user/decrypt_sidebar", true).toBool();
-        privacyScreen_        = settings.value("user/privacy_screen", false).toBool();
-        privacyScreenTimeout_ = settings.value("user/privacy_screen_timeout", 0).toInt();
-        mobileMode_           = settings.value("user/mobile_mode", false).toBool();
-        emojiFont_            = settings.value("user/emoji_font_family", "default").toString();
-        baseFontSize_         = settings.value("user/font_size", QFont().pointSizeF()).toDouble();
-        auto tempPresence     = settings.value("user/presence", "").toString().toStdString();
-        auto presenceValue    = QMetaEnum::fromType<Presence>().keyToValue(tempPresence.c_str());
-        if (presenceValue < 0)
-                presenceValue = 0;
-        presence_               = static_cast<Presence>(presenceValue);
-        ringtone_               = settings.value("user/ringtone", "Default").toString();
-        microphone_             = settings.value("user/microphone", QString()).toString();
-        camera_                 = settings.value("user/camera", QString()).toString();
-        cameraResolution_       = settings.value("user/camera_resolution", QString()).toString();
-        cameraFrameRate_        = settings.value("user/camera_frame_rate", QString()).toString();
-        screenShareFrameRate_   = settings.value("user/screen_share_frame_rate", 5).toInt();
-        screenSharePiP_         = settings.value("user/screen_share_pip", true).toBool();
-        screenShareRemoteVideo_ = settings.value("user/screen_share_remote_video", false).toBool();
-        screenShareHideCursor_  = settings.value("user/screen_share_hide_cursor", false).toBool();
-        useStunServer_          = settings.value("user/use_stun_server", false).toBool();
-
-        if (profile) // set to "" if it's the default to maintain compatibility
-                profile_ = (*profile == "default") ? "" : *profile;
-        else
-                profile_ = settings.value("user/currentProfile", "").toString();
-
-        QString prefix =
-          (profile_ != "" && profile_ != "default") ? "profile/" + profile_ + "/" : "";
-        accessToken_ = settings.value(prefix + "auth/access_token", "").toString();
-        homeserver_  = settings.value(prefix + "auth/home_server", "").toString();
-        userId_      = settings.value(prefix + "auth/user_id", "").toString();
-        deviceId_    = settings.value(prefix + "auth/device_id", "").toString();
-
-        shareKeysWithTrustedUsers_ =
-          settings.value(prefix + "user/automatically_share_keys_with_trusted_users", false)
-            .toBool();
-        onlyShareKeysWithVerifiedUsers_ =
-          settings.value(prefix + "user/only_share_keys_with_verified_users", false).toBool();
-        useOnlineKeyBackup_ = settings.value(prefix + "user/online_key_backup", false).toBool();
-
-        disableCertificateValidation_ =
-          settings.value("disable_certificate_validation", false).toBool();
-
-        applyTheme();
+    tray_        = settings.value("user/window/tray", false).toBool();
+    startInTray_ = settings.value("user/window/start_in_tray", false).toBool();
+
+    roomListWidth_      = settings.value("user/sidebar/room_list_width", -1).toInt();
+    communityListWidth_ = settings.value("user/sidebar/community_list_width", -1).toInt();
+
+    hasDesktopNotifications_ = settings.value("user/desktop_notifications", true).toBool();
+    hasAlertOnNotification_  = settings.value("user/alert_on_notification", false).toBool();
+    groupView_               = settings.value("user/group_view", true).toBool();
+    hiddenTags_              = settings.value("user/hidden_tags", QStringList{}).toStringList();
+    buttonsInTimeline_       = settings.value("user/timeline/buttons", true).toBool();
+    timelineMaxWidth_        = settings.value("user/timeline/max_width", 0).toInt();
+    messageHoverHighlight_ =
+      settings.value("user/timeline/message_hover_highlight", false).toBool();
+    enlargeEmojiOnlyMessages_ =
+      settings.value("user/timeline/enlarge_emoji_only_msg", false).toBool();
+    markdown_             = settings.value("user/markdown_enabled", true).toBool();
+    animateImagesOnHover_ = settings.value("user/animate_images_on_hover", false).toBool();
+    typingNotifications_  = settings.value("user/typing_notifications", true).toBool();
+    sortByImportance_     = settings.value("user/sort_by_unread", true).toBool();
+    readReceipts_         = settings.value("user/read_receipts", true).toBool();
+    theme_                = settings.value("user/theme", defaultTheme_).toString();
+    font_                 = settings.value("user/font_family", "default").toString();
+    avatarCircles_        = settings.value("user/avatar_circles", true).toBool();
+    useIdenticon_         = settings.value("user/use_identicon", true).toBool();
+    decryptSidebar_       = settings.value("user/decrypt_sidebar", true).toBool();
+    privacyScreen_        = settings.value("user/privacy_screen", false).toBool();
+    privacyScreenTimeout_ = settings.value("user/privacy_screen_timeout", 0).toInt();
+    mobileMode_           = settings.value("user/mobile_mode", false).toBool();
+    emojiFont_            = settings.value("user/emoji_font_family", "default").toString();
+    baseFontSize_         = settings.value("user/font_size", QFont().pointSizeF()).toDouble();
+    auto tempPresence     = settings.value("user/presence", "").toString().toStdString();
+    auto presenceValue    = QMetaEnum::fromType<Presence>().keyToValue(tempPresence.c_str());
+    if (presenceValue < 0)
+        presenceValue = 0;
+    presence_               = static_cast<Presence>(presenceValue);
+    ringtone_               = settings.value("user/ringtone", "Default").toString();
+    microphone_             = settings.value("user/microphone", QString()).toString();
+    camera_                 = settings.value("user/camera", QString()).toString();
+    cameraResolution_       = settings.value("user/camera_resolution", QString()).toString();
+    cameraFrameRate_        = settings.value("user/camera_frame_rate", QString()).toString();
+    screenShareFrameRate_   = settings.value("user/screen_share_frame_rate", 5).toInt();
+    screenSharePiP_         = settings.value("user/screen_share_pip", true).toBool();
+    screenShareRemoteVideo_ = settings.value("user/screen_share_remote_video", false).toBool();
+    screenShareHideCursor_  = settings.value("user/screen_share_hide_cursor", false).toBool();
+    useStunServer_          = settings.value("user/use_stun_server", false).toBool();
+
+    if (profile) // set to "" if it's the default to maintain compatibility
+        profile_ = (*profile == "default") ? "" : *profile;
+    else
+        profile_ = settings.value("user/currentProfile", "").toString();
+
+    QString prefix = (profile_ != "" && profile_ != "default") ? "profile/" + profile_ + "/" : "";
+    accessToken_   = settings.value(prefix + "auth/access_token", "").toString();
+    homeserver_    = settings.value(prefix + "auth/home_server", "").toString();
+    userId_        = settings.value(prefix + "auth/user_id", "").toString();
+    deviceId_      = settings.value(prefix + "auth/device_id", "").toString();
+
+    shareKeysWithTrustedUsers_ =
+      settings.value(prefix + "user/automatically_share_keys_with_trusted_users", false).toBool();
+    onlyShareKeysWithVerifiedUsers_ =
+      settings.value(prefix + "user/only_share_keys_with_verified_users", false).toBool();
+    useOnlineKeyBackup_ = settings.value(prefix + "user/online_key_backup", false).toBool();
+
+    disableCertificateValidation_ =
+      settings.value("disable_certificate_validation", false).toBool();
+
+    applyTheme();
 }
 void
 UserSettings::setMessageHoverHighlight(bool state)
 {
-        if (state == messageHoverHighlight_)
-                return;
-        messageHoverHighlight_ = state;
-        emit messageHoverHighlightChanged(state);
-        save();
+    if (state == messageHoverHighlight_)
+        return;
+    messageHoverHighlight_ = state;
+    emit messageHoverHighlightChanged(state);
+    save();
 }
 void
 UserSettings::setEnlargeEmojiOnlyMessages(bool state)
 {
-        if (state == enlargeEmojiOnlyMessages_)
-                return;
-        enlargeEmojiOnlyMessages_ = state;
-        emit enlargeEmojiOnlyMessagesChanged(state);
-        save();
+    if (state == enlargeEmojiOnlyMessages_)
+        return;
+    enlargeEmojiOnlyMessages_ = state;
+    emit enlargeEmojiOnlyMessagesChanged(state);
+    save();
 }
 void
 UserSettings::setTray(bool state)
 {
-        if (state == tray_)
-                return;
-        tray_ = state;
-        emit trayChanged(state);
-        save();
+    if (state == tray_)
+        return;
+    tray_ = state;
+    emit trayChanged(state);
+    save();
 }
 
 void
 UserSettings::setStartInTray(bool state)
 {
-        if (state == startInTray_)
-                return;
-        startInTray_ = state;
-        emit startInTrayChanged(state);
-        save();
+    if (state == startInTray_)
+        return;
+    startInTray_ = state;
+    emit startInTrayChanged(state);
+    save();
 }
 
 void
 UserSettings::setMobileMode(bool state)
 {
-        if (state == mobileMode_)
-                return;
-        mobileMode_ = state;
-        emit mobileModeChanged(state);
-        save();
+    if (state == mobileMode_)
+        return;
+    mobileMode_ = state;
+    emit mobileModeChanged(state);
+    save();
 }
 
 void
 UserSettings::setGroupView(bool state)
 {
-        if (groupView_ == state)
-                return;
+    if (groupView_ == state)
+        return;
 
-        groupView_ = state;
-        emit groupViewStateChanged(state);
-        save();
+    groupView_ = state;
+    emit groupViewStateChanged(state);
+    save();
 }
 
 void
 UserSettings::setHiddenTags(QStringList hiddenTags)
 {
-        hiddenTags_ = hiddenTags;
-        save();
+    hiddenTags_ = hiddenTags;
+    save();
 }
 
 void
 UserSettings::setMarkdown(bool state)
 {
-        if (state == markdown_)
-                return;
-        markdown_ = state;
-        emit markdownChanged(state);
-        save();
+    if (state == markdown_)
+        return;
+    markdown_ = state;
+    emit markdownChanged(state);
+    save();
 }
 
 void
 UserSettings::setAnimateImagesOnHover(bool state)
 {
-        if (state == animateImagesOnHover_)
-                return;
-        animateImagesOnHover_ = state;
-        emit animateImagesOnHoverChanged(state);
-        save();
+    if (state == animateImagesOnHover_)
+        return;
+    animateImagesOnHover_ = state;
+    emit animateImagesOnHoverChanged(state);
+    save();
 }
 
 void
 UserSettings::setReadReceipts(bool state)
 {
-        if (state == readReceipts_)
-                return;
-        readReceipts_ = state;
-        emit readReceiptsChanged(state);
-        save();
+    if (state == readReceipts_)
+        return;
+    readReceipts_ = state;
+    emit readReceiptsChanged(state);
+    save();
 }
 
 void
 UserSettings::setTypingNotifications(bool state)
 {
-        if (state == typingNotifications_)
-                return;
-        typingNotifications_ = state;
-        emit typingNotificationsChanged(state);
-        save();
+    if (state == typingNotifications_)
+        return;
+    typingNotifications_ = state;
+    emit typingNotificationsChanged(state);
+    save();
 }
 
 void
 UserSettings::setSortByImportance(bool state)
 {
-        if (state == sortByImportance_)
-                return;
-        sortByImportance_ = state;
-        emit roomSortingChanged(state);
-        save();
+    if (state == sortByImportance_)
+        return;
+    sortByImportance_ = state;
+    emit roomSortingChanged(state);
+    save();
 }
 
 void
 UserSettings::setButtonsInTimeline(bool state)
 {
-        if (state == buttonsInTimeline_)
-                return;
-        buttonsInTimeline_ = state;
-        emit buttonInTimelineChanged(state);
-        save();
+    if (state == buttonsInTimeline_)
+        return;
+    buttonsInTimeline_ = state;
+    emit buttonInTimelineChanged(state);
+    save();
 }
 
 void
 UserSettings::setTimelineMaxWidth(int state)
 {
-        if (state == timelineMaxWidth_)
-                return;
-        timelineMaxWidth_ = state;
-        emit timelineMaxWidthChanged(state);
-        save();
+    if (state == timelineMaxWidth_)
+        return;
+    timelineMaxWidth_ = state;
+    emit timelineMaxWidthChanged(state);
+    save();
 }
 void
 UserSettings::setCommunityListWidth(int state)
 {
-        if (state == communityListWidth_)
-                return;
-        communityListWidth_ = state;
-        emit communityListWidthChanged(state);
-        save();
+    if (state == communityListWidth_)
+        return;
+    communityListWidth_ = state;
+    emit communityListWidthChanged(state);
+    save();
 }
 void
 UserSettings::setRoomListWidth(int state)
 {
-        if (state == roomListWidth_)
-                return;
-        roomListWidth_ = state;
-        emit roomListWidthChanged(state);
-        save();
+    if (state == roomListWidth_)
+        return;
+    roomListWidth_ = state;
+    emit roomListWidthChanged(state);
+    save();
 }
 
 void
 UserSettings::setDesktopNotifications(bool state)
 {
-        if (state == hasDesktopNotifications_)
-                return;
-        hasDesktopNotifications_ = state;
-        emit desktopNotificationsChanged(state);
-        save();
+    if (state == hasDesktopNotifications_)
+        return;
+    hasDesktopNotifications_ = state;
+    emit desktopNotificationsChanged(state);
+    save();
 }
 
 void
 UserSettings::setAlertOnNotification(bool state)
 {
-        if (state == hasAlertOnNotification_)
-                return;
-        hasAlertOnNotification_ = state;
-        emit alertOnNotificationChanged(state);
-        save();
+    if (state == hasAlertOnNotification_)
+        return;
+    hasAlertOnNotification_ = state;
+    emit alertOnNotificationChanged(state);
+    save();
 }
 
 void
 UserSettings::setAvatarCircles(bool state)
 {
-        if (state == avatarCircles_)
-                return;
-        avatarCircles_ = state;
-        emit avatarCirclesChanged(state);
-        save();
+    if (state == avatarCircles_)
+        return;
+    avatarCircles_ = state;
+    emit avatarCirclesChanged(state);
+    save();
 }
 
 void
 UserSettings::setDecryptSidebar(bool state)
 {
-        if (state == decryptSidebar_)
-                return;
-        decryptSidebar_ = state;
-        emit decryptSidebarChanged(state);
-        save();
+    if (state == decryptSidebar_)
+        return;
+    decryptSidebar_ = state;
+    emit decryptSidebarChanged(state);
+    save();
 }
 
 void
 UserSettings::setPrivacyScreen(bool state)
 {
-        if (state == privacyScreen_) {
-                return;
-        }
-        privacyScreen_ = state;
-        emit privacyScreenChanged(state);
-        save();
+    if (state == privacyScreen_) {
+        return;
+    }
+    privacyScreen_ = state;
+    emit privacyScreenChanged(state);
+    save();
 }
 
 void
 UserSettings::setPrivacyScreenTimeout(int state)
 {
-        if (state == privacyScreenTimeout_) {
-                return;
-        }
-        privacyScreenTimeout_ = state;
-        emit privacyScreenTimeoutChanged(state);
-        save();
+    if (state == privacyScreenTimeout_) {
+        return;
+    }
+    privacyScreenTimeout_ = state;
+    emit privacyScreenTimeoutChanged(state);
+    save();
 }
 
 void
 UserSettings::setFontSize(double size)
 {
-        if (size == baseFontSize_)
-                return;
-        baseFontSize_ = size;
-        emit fontSizeChanged(size);
-        save();
+    if (size == baseFontSize_)
+        return;
+    baseFontSize_ = size;
+    emit fontSizeChanged(size);
+    save();
 }
 
 void
 UserSettings::setFontFamily(QString family)
 {
-        if (family == font_)
-                return;
-        font_ = family;
-        emit fontChanged(family);
-        save();
+    if (family == font_)
+        return;
+    font_ = family;
+    emit fontChanged(family);
+    save();
 }
 
 void
 UserSettings::setEmojiFontFamily(QString family)
 {
-        if (family == emojiFont_)
-                return;
+    if (family == emojiFont_)
+        return;
 
-        if (family == tr("Default")) {
-                emojiFont_ = "default";
-        } else {
-                emojiFont_ = family;
-        }
+    if (family == tr("Default")) {
+        emojiFont_ = "default";
+    } else {
+        emojiFont_ = family;
+    }
 
-        emit emojiFontChanged(family);
-        save();
+    emit emojiFontChanged(family);
+    save();
 }
 
 void
 UserSettings::setPresence(Presence state)
 {
-        if (state == presence_)
-                return;
-        presence_ = state;
-        emit presenceChanged(state);
-        save();
+    if (state == presence_)
+        return;
+    presence_ = state;
+    emit presenceChanged(state);
+    save();
 }
 
 void
 UserSettings::setTheme(QString theme)
 {
-        if (theme == theme_)
-                return;
-        theme_ = theme;
-        save();
-        applyTheme();
-        emit themeChanged(theme);
+    if (theme == theme_)
+        return;
+    theme_ = theme;
+    save();
+    applyTheme();
+    emit themeChanged(theme);
 }
 
 void
 UserSettings::setUseStunServer(bool useStunServer)
 {
-        if (useStunServer == useStunServer_)
-                return;
-        useStunServer_ = useStunServer;
-        emit useStunServerChanged(useStunServer);
-        save();
+    if (useStunServer == useStunServer_)
+        return;
+    useStunServer_ = useStunServer;
+    emit useStunServerChanged(useStunServer);
+    save();
 }
 
 void
 UserSettings::setOnlyShareKeysWithVerifiedUsers(bool shareKeys)
 {
-        if (shareKeys == onlyShareKeysWithVerifiedUsers_)
-                return;
+    if (shareKeys == onlyShareKeysWithVerifiedUsers_)
+        return;
 
-        onlyShareKeysWithVerifiedUsers_ = shareKeys;
-        emit onlyShareKeysWithVerifiedUsersChanged(shareKeys);
-        save();
+    onlyShareKeysWithVerifiedUsers_ = shareKeys;
+    emit onlyShareKeysWithVerifiedUsersChanged(shareKeys);
+    save();
 }
 
 void
 UserSettings::setShareKeysWithTrustedUsers(bool shareKeys)
 {
-        if (shareKeys == shareKeysWithTrustedUsers_)
-                return;
+    if (shareKeys == shareKeysWithTrustedUsers_)
+        return;
 
-        shareKeysWithTrustedUsers_ = shareKeys;
-        emit shareKeysWithTrustedUsersChanged(shareKeys);
-        save();
+    shareKeysWithTrustedUsers_ = shareKeys;
+    emit shareKeysWithTrustedUsersChanged(shareKeys);
+    save();
 }
 
 void
 UserSettings::setUseOnlineKeyBackup(bool useBackup)
 {
-        if (useBackup == useOnlineKeyBackup_)
-                return;
+    if (useBackup == useOnlineKeyBackup_)
+        return;
 
-        useOnlineKeyBackup_ = useBackup;
-        emit useOnlineKeyBackupChanged(useBackup);
-        save();
+    useOnlineKeyBackup_ = useBackup;
+    emit useOnlineKeyBackupChanged(useBackup);
+    save();
 }
 
 void
 UserSettings::setRingtone(QString ringtone)
 {
-        if (ringtone == ringtone_)
-                return;
-        ringtone_ = ringtone;
-        emit ringtoneChanged(ringtone);
-        save();
+    if (ringtone == ringtone_)
+        return;
+    ringtone_ = ringtone;
+    emit ringtoneChanged(ringtone);
+    save();
 }
 
 void
 UserSettings::setMicrophone(QString microphone)
 {
-        if (microphone == microphone_)
-                return;
-        microphone_ = microphone;
-        emit microphoneChanged(microphone);
-        save();
+    if (microphone == microphone_)
+        return;
+    microphone_ = microphone;
+    emit microphoneChanged(microphone);
+    save();
 }
 
 void
 UserSettings::setCamera(QString camera)
 {
-        if (camera == camera_)
-                return;
-        camera_ = camera;
-        emit cameraChanged(camera);
-        save();
+    if (camera == camera_)
+        return;
+    camera_ = camera;
+    emit cameraChanged(camera);
+    save();
 }
 
 void
 UserSettings::setCameraResolution(QString resolution)
 {
-        if (resolution == cameraResolution_)
-                return;
-        cameraResolution_ = resolution;
-        emit cameraResolutionChanged(resolution);
-        save();
+    if (resolution == cameraResolution_)
+        return;
+    cameraResolution_ = resolution;
+    emit cameraResolutionChanged(resolution);
+    save();
 }
 
 void
 UserSettings::setCameraFrameRate(QString frameRate)
 {
-        if (frameRate == cameraFrameRate_)
-                return;
-        cameraFrameRate_ = frameRate;
-        emit cameraFrameRateChanged(frameRate);
-        save();
+    if (frameRate == cameraFrameRate_)
+        return;
+    cameraFrameRate_ = frameRate;
+    emit cameraFrameRateChanged(frameRate);
+    save();
 }
 
 void
 UserSettings::setScreenShareFrameRate(int frameRate)
 {
-        if (frameRate == screenShareFrameRate_)
-                return;
-        screenShareFrameRate_ = frameRate;
-        emit screenShareFrameRateChanged(frameRate);
-        save();
+    if (frameRate == screenShareFrameRate_)
+        return;
+    screenShareFrameRate_ = frameRate;
+    emit screenShareFrameRateChanged(frameRate);
+    save();
 }
 
 void
 UserSettings::setScreenSharePiP(bool state)
 {
-        if (state == screenSharePiP_)
-                return;
-        screenSharePiP_ = state;
-        emit screenSharePiPChanged(state);
-        save();
+    if (state == screenSharePiP_)
+        return;
+    screenSharePiP_ = state;
+    emit screenSharePiPChanged(state);
+    save();
 }
 
 void
 UserSettings::setScreenShareRemoteVideo(bool state)
 {
-        if (state == screenShareRemoteVideo_)
-                return;
-        screenShareRemoteVideo_ = state;
-        emit screenShareRemoteVideoChanged(state);
-        save();
+    if (state == screenShareRemoteVideo_)
+        return;
+    screenShareRemoteVideo_ = state;
+    emit screenShareRemoteVideoChanged(state);
+    save();
 }
 
 void
 UserSettings::setScreenShareHideCursor(bool state)
 {
-        if (state == screenShareHideCursor_)
-                return;
-        screenShareHideCursor_ = state;
-        emit screenShareHideCursorChanged(state);
-        save();
+    if (state == screenShareHideCursor_)
+        return;
+    screenShareHideCursor_ = state;
+    emit screenShareHideCursorChanged(state);
+    save();
 }
 
 void
 UserSettings::setProfile(QString profile)
 {
-        if (profile == profile_)
-                return;
-        profile_ = profile;
-        emit profileChanged(profile_);
-        save();
+    if (profile == profile_)
+        return;
+    profile_ = profile;
+    emit profileChanged(profile_);
+    save();
 }
 
 void
 UserSettings::setUserId(QString userId)
 {
-        if (userId == userId_)
-                return;
-        userId_ = userId;
-        emit userIdChanged(userId_);
-        save();
+    if (userId == userId_)
+        return;
+    userId_ = userId;
+    emit userIdChanged(userId_);
+    save();
 }
 
 void
 UserSettings::setAccessToken(QString accessToken)
 {
-        if (accessToken == accessToken_)
-                return;
-        accessToken_ = accessToken;
-        emit accessTokenChanged(accessToken_);
-        save();
+    if (accessToken == accessToken_)
+        return;
+    accessToken_ = accessToken;
+    emit accessTokenChanged(accessToken_);
+    save();
 }
 
 void
 UserSettings::setDeviceId(QString deviceId)
 {
-        if (deviceId == deviceId_)
-                return;
-        deviceId_ = deviceId;
-        emit deviceIdChanged(deviceId_);
-        save();
+    if (deviceId == deviceId_)
+        return;
+    deviceId_ = deviceId;
+    emit deviceIdChanged(deviceId_);
+    save();
 }
 
 void
 UserSettings::setHomeserver(QString homeserver)
 {
-        if (homeserver == homeserver_)
-                return;
-        homeserver_ = homeserver;
-        emit homeserverChanged(homeserver_);
-        save();
+    if (homeserver == homeserver_)
+        return;
+    homeserver_ = homeserver;
+    emit homeserverChanged(homeserver_);
+    save();
 }
 
 void
 UserSettings::setDisableCertificateValidation(bool disabled)
 {
-        if (disabled == disableCertificateValidation_)
-                return;
-        disableCertificateValidation_ = disabled;
-        http::client()->verify_certificates(!disabled);
-        emit disableCertificateValidationChanged(disabled);
+    if (disabled == disableCertificateValidation_)
+        return;
+    disableCertificateValidation_ = disabled;
+    http::client()->verify_certificates(!disabled);
+    emit disableCertificateValidationChanged(disabled);
 }
 
 void
 UserSettings::setUseIdenticon(bool state)
 {
-        if (state == useIdenticon_)
-                return;
-        useIdenticon_ = state;
-        emit useIdenticonChanged(useIdenticon_);
-        save();
+    if (state == useIdenticon_)
+        return;
+    useIdenticon_ = state;
+    emit useIdenticonChanged(useIdenticon_);
+    save();
 }
 
 void
 UserSettings::applyTheme()
 {
-        QFile stylefile;
+    QFile stylefile;
 
-        if (this->theme() == "light") {
-                stylefile.setFileName(":/styles/styles/nheko.qss");
-        } else if (this->theme() == "dark") {
-                stylefile.setFileName(":/styles/styles/nheko-dark.qss");
-        } else {
-                stylefile.setFileName(":/styles/styles/system.qss");
-        }
-        QApplication::setPalette(Theme::paletteFromTheme(this->theme().toStdString()));
+    if (this->theme() == "light") {
+        stylefile.setFileName(":/styles/styles/nheko.qss");
+    } else if (this->theme() == "dark") {
+        stylefile.setFileName(":/styles/styles/nheko-dark.qss");
+    } else {
+        stylefile.setFileName(":/styles/styles/system.qss");
+    }
+    QApplication::setPalette(Theme::paletteFromTheme(this->theme().toStdString()));
 
-        stylefile.open(QFile::ReadOnly);
-        QString stylesheet = QString(stylefile.readAll());
+    stylefile.open(QFile::ReadOnly);
+    QString stylesheet = QString(stylefile.readAll());
 
-        qobject_cast<QApplication *>(QApplication::instance())->setStyleSheet(stylesheet);
+    qobject_cast<QApplication *>(QApplication::instance())->setStyleSheet(stylesheet);
 }
 
 void
 UserSettings::save()
 {
-        settings.beginGroup("user");
-
-        settings.beginGroup("window");
-        settings.setValue("tray", tray_);
-        settings.setValue("start_in_tray", startInTray_);
-        settings.endGroup(); // window
-
-        settings.beginGroup("sidebar");
-        settings.setValue("community_list_width", communityListWidth_);
-        settings.setValue("room_list_width", roomListWidth_);
-        settings.endGroup(); // window
-
-        settings.beginGroup("timeline");
-        settings.setValue("buttons", buttonsInTimeline_);
-        settings.setValue("message_hover_highlight", messageHoverHighlight_);
-        settings.setValue("enlarge_emoji_only_msg", enlargeEmojiOnlyMessages_);
-        settings.setValue("max_width", timelineMaxWidth_);
-        settings.endGroup(); // timeline
-
-        settings.setValue("avatar_circles", avatarCircles_);
-        settings.setValue("decrypt_sidebar", decryptSidebar_);
-        settings.setValue("privacy_screen", privacyScreen_);
-        settings.setValue("privacy_screen_timeout", privacyScreenTimeout_);
-        settings.setValue("mobile_mode", mobileMode_);
-        settings.setValue("font_size", baseFontSize_);
-        settings.setValue("typing_notifications", typingNotifications_);
-        settings.setValue("sort_by_unread", sortByImportance_);
-        settings.setValue("minor_events", sortByImportance_);
-        settings.setValue("read_receipts", readReceipts_);
-        settings.setValue("group_view", groupView_);
-        settings.setValue("hidden_tags", hiddenTags_);
-        settings.setValue("markdown_enabled", markdown_);
-        settings.setValue("animate_images_on_hover", animateImagesOnHover_);
-        settings.setValue("desktop_notifications", hasDesktopNotifications_);
-        settings.setValue("alert_on_notification", hasAlertOnNotification_);
-        settings.setValue("theme", theme());
-        settings.setValue("font_family", font_);
-        settings.setValue("emoji_font_family", emojiFont_);
-        settings.setValue("presence",
-                          QString::fromUtf8(QMetaEnum::fromType<Presence>().valueToKey(
-                            static_cast<int>(presence_))));
-        settings.setValue("ringtone", ringtone_);
-        settings.setValue("microphone", microphone_);
-        settings.setValue("camera", camera_);
-        settings.setValue("camera_resolution", cameraResolution_);
-        settings.setValue("camera_frame_rate", cameraFrameRate_);
-        settings.setValue("screen_share_frame_rate", screenShareFrameRate_);
-        settings.setValue("screen_share_pip", screenSharePiP_);
-        settings.setValue("screen_share_remote_video", screenShareRemoteVideo_);
-        settings.setValue("screen_share_hide_cursor", screenShareHideCursor_);
-        settings.setValue("use_stun_server", useStunServer_);
-        settings.setValue("currentProfile", profile_);
-        settings.setValue("use_identicon", useIdenticon_);
-
-        settings.endGroup(); // user
-
-        QString prefix =
-          (profile_ != "" && profile_ != "default") ? "profile/" + profile_ + "/" : "";
-        settings.setValue(prefix + "auth/access_token", accessToken_);
-        settings.setValue(prefix + "auth/home_server", homeserver_);
-        settings.setValue(prefix + "auth/user_id", userId_);
-        settings.setValue(prefix + "auth/device_id", deviceId_);
-
-        settings.setValue(prefix + "user/automatically_share_keys_with_trusted_users",
-                          shareKeysWithTrustedUsers_);
-        settings.setValue(prefix + "user/only_share_keys_with_verified_users",
-                          onlyShareKeysWithVerifiedUsers_);
-        settings.setValue(prefix + "user/online_key_backup", useOnlineKeyBackup_);
-
-        settings.setValue("disable_certificate_validation", disableCertificateValidation_);
-
-        settings.sync();
+    settings.beginGroup("user");
+
+    settings.beginGroup("window");
+    settings.setValue("tray", tray_);
+    settings.setValue("start_in_tray", startInTray_);
+    settings.endGroup(); // window
+
+    settings.beginGroup("sidebar");
+    settings.setValue("community_list_width", communityListWidth_);
+    settings.setValue("room_list_width", roomListWidth_);
+    settings.endGroup(); // window
+
+    settings.beginGroup("timeline");
+    settings.setValue("buttons", buttonsInTimeline_);
+    settings.setValue("message_hover_highlight", messageHoverHighlight_);
+    settings.setValue("enlarge_emoji_only_msg", enlargeEmojiOnlyMessages_);
+    settings.setValue("max_width", timelineMaxWidth_);
+    settings.endGroup(); // timeline
+
+    settings.setValue("avatar_circles", avatarCircles_);
+    settings.setValue("decrypt_sidebar", decryptSidebar_);
+    settings.setValue("privacy_screen", privacyScreen_);
+    settings.setValue("privacy_screen_timeout", privacyScreenTimeout_);
+    settings.setValue("mobile_mode", mobileMode_);
+    settings.setValue("font_size", baseFontSize_);
+    settings.setValue("typing_notifications", typingNotifications_);
+    settings.setValue("sort_by_unread", sortByImportance_);
+    settings.setValue("minor_events", sortByImportance_);
+    settings.setValue("read_receipts", readReceipts_);
+    settings.setValue("group_view", groupView_);
+    settings.setValue("hidden_tags", hiddenTags_);
+    settings.setValue("markdown_enabled", markdown_);
+    settings.setValue("animate_images_on_hover", animateImagesOnHover_);
+    settings.setValue("desktop_notifications", hasDesktopNotifications_);
+    settings.setValue("alert_on_notification", hasAlertOnNotification_);
+    settings.setValue("theme", theme());
+    settings.setValue("font_family", font_);
+    settings.setValue("emoji_font_family", emojiFont_);
+    settings.setValue(
+      "presence",
+      QString::fromUtf8(QMetaEnum::fromType<Presence>().valueToKey(static_cast<int>(presence_))));
+    settings.setValue("ringtone", ringtone_);
+    settings.setValue("microphone", microphone_);
+    settings.setValue("camera", camera_);
+    settings.setValue("camera_resolution", cameraResolution_);
+    settings.setValue("camera_frame_rate", cameraFrameRate_);
+    settings.setValue("screen_share_frame_rate", screenShareFrameRate_);
+    settings.setValue("screen_share_pip", screenSharePiP_);
+    settings.setValue("screen_share_remote_video", screenShareRemoteVideo_);
+    settings.setValue("screen_share_hide_cursor", screenShareHideCursor_);
+    settings.setValue("use_stun_server", useStunServer_);
+    settings.setValue("currentProfile", profile_);
+    settings.setValue("use_identicon", useIdenticon_);
+
+    settings.endGroup(); // user
+
+    QString prefix = (profile_ != "" && profile_ != "default") ? "profile/" + profile_ + "/" : "";
+    settings.setValue(prefix + "auth/access_token", accessToken_);
+    settings.setValue(prefix + "auth/home_server", homeserver_);
+    settings.setValue(prefix + "auth/user_id", userId_);
+    settings.setValue(prefix + "auth/device_id", deviceId_);
+
+    settings.setValue(prefix + "user/automatically_share_keys_with_trusted_users",
+                      shareKeysWithTrustedUsers_);
+    settings.setValue(prefix + "user/only_share_keys_with_verified_users",
+                      onlyShareKeysWithVerifiedUsers_);
+    settings.setValue(prefix + "user/online_key_backup", useOnlineKeyBackup_);
+
+    settings.setValue("disable_certificate_validation", disableCertificateValidation_);
+
+    settings.sync();
 }
 
 HorizontalLine::HorizontalLine(QWidget *parent)
   : QFrame{parent}
 {
-        setFrameShape(QFrame::HLine);
-        setFrameShadow(QFrame::Sunken);
+    setFrameShape(QFrame::HLine);
+    setFrameShadow(QFrame::Sunken);
 }
 
 UserSettingsPage::UserSettingsPage(QSharedPointer<UserSettings> settings, QWidget *parent)
   : QWidget{parent}
   , settings_{settings}
 {
-        topLayout_ = new QVBoxLayout{this};
-
-        QIcon icon;
-        icon.addFile(":/icons/icons/ui/angle-pointing-to-left.png");
-
-        auto backBtn_ = new FlatButton{this};
-        backBtn_->setMinimumSize(QSize(24, 24));
-        backBtn_->setIcon(icon);
-        backBtn_->setIconSize(QSize(24, 24));
-
-        QFont font;
-        font.setPointSizeF(font.pointSizeF() * 1.1);
-
-        auto versionInfo = new QLabel(QString("%1 | %2").arg(nheko::version).arg(nheko::build_os));
-        if (QCoreApplication::applicationName() != "nheko")
-                versionInfo->setText(versionInfo->text() + " | " +
-                                     tr("profile: %1").arg(QCoreApplication::applicationName()));
-        versionInfo->setTextInteractionFlags(Qt::TextBrowserInteraction);
-
-        topBarLayout_ = new QHBoxLayout;
-        topBarLayout_->setSpacing(0);
-        topBarLayout_->setMargin(0);
-        topBarLayout_->addWidget(backBtn_, 1, Qt::AlignLeft | Qt::AlignVCenter);
-        topBarLayout_->addStretch(1);
-
-        formLayout_ = new QFormLayout;
-
-        formLayout_->setLabelAlignment(Qt::AlignLeft);
-        formLayout_->setFormAlignment(Qt::AlignRight);
-        formLayout_->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
-        formLayout_->setRowWrapPolicy(QFormLayout::WrapLongRows);
-        formLayout_->setHorizontalSpacing(0);
-
-        auto general_ = new QLabel{tr("GENERAL"), this};
-        general_->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
-        general_->setFont(font);
-
-        trayToggle_                     = new Toggle{this};
-        startInTrayToggle_              = new Toggle{this};
-        avatarCircles_                  = new Toggle{this};
-        useIdenticon_                   = new Toggle{this};
-        decryptSidebar_                 = new Toggle(this);
-        privacyScreen_                  = new Toggle{this};
-        onlyShareKeysWithVerifiedUsers_ = new Toggle(this);
-        shareKeysWithTrustedUsers_      = new Toggle(this);
-        useOnlineKeyBackup_             = new Toggle(this);
-        groupViewToggle_                = new Toggle{this};
-        timelineButtonsToggle_          = new Toggle{this};
-        typingNotifications_            = new Toggle{this};
-        messageHoverHighlight_          = new Toggle{this};
-        enlargeEmojiOnlyMessages_       = new Toggle{this};
-        sortByImportance_               = new Toggle{this};
-        readReceipts_                   = new Toggle{this};
-        markdown_                       = new Toggle{this};
-        animateImagesOnHover_           = new Toggle{this};
-        desktopNotifications_           = new Toggle{this};
-        alertOnNotification_            = new Toggle{this};
-        useStunServer_                  = new Toggle{this};
-        mobileMode_                     = new Toggle{this};
-        scaleFactorCombo_               = new QComboBox{this};
-        fontSizeCombo_                  = new QComboBox{this};
-        fontSelectionCombo_             = new QFontComboBox{this};
-        emojiFontSelectionCombo_        = new QComboBox{this};
-        ringtoneCombo_                  = new QComboBox{this};
-        microphoneCombo_                = new QComboBox{this};
-        cameraCombo_                    = new QComboBox{this};
-        cameraResolutionCombo_          = new QComboBox{this};
-        cameraFrameRateCombo_           = new QComboBox{this};
-        timelineMaxWidthSpin_           = new QSpinBox{this};
-        privacyScreenTimeout_           = new QSpinBox{this};
-
-        trayToggle_->setChecked(settings_->tray());
-        startInTrayToggle_->setChecked(settings_->startInTray());
-        avatarCircles_->setChecked(settings_->avatarCircles());
-        useIdenticon_->setChecked(settings_->useIdenticon());
-        decryptSidebar_->setChecked(settings_->decryptSidebar());
-        privacyScreen_->setChecked(settings_->privacyScreen());
-        onlyShareKeysWithVerifiedUsers_->setChecked(settings_->onlyShareKeysWithVerifiedUsers());
-        shareKeysWithTrustedUsers_->setChecked(settings_->shareKeysWithTrustedUsers());
-        useOnlineKeyBackup_->setChecked(settings_->useOnlineKeyBackup());
-        groupViewToggle_->setChecked(settings_->groupView());
-        timelineButtonsToggle_->setChecked(settings_->buttonsInTimeline());
-        typingNotifications_->setChecked(settings_->typingNotifications());
-        messageHoverHighlight_->setChecked(settings_->messageHoverHighlight());
-        enlargeEmojiOnlyMessages_->setChecked(settings_->enlargeEmojiOnlyMessages());
-        sortByImportance_->setChecked(settings_->sortByImportance());
-        readReceipts_->setChecked(settings_->readReceipts());
-        markdown_->setChecked(settings_->markdown());
-        animateImagesOnHover_->setChecked(settings_->animateImagesOnHover());
-        desktopNotifications_->setChecked(settings_->hasDesktopNotifications());
-        alertOnNotification_->setChecked(settings_->hasAlertOnNotification());
-        useStunServer_->setChecked(settings_->useStunServer());
-        mobileMode_->setChecked(settings_->mobileMode());
-
-        if (!settings_->tray()) {
-                startInTrayToggle_->setState(false);
-                startInTrayToggle_->setDisabled(true);
-        }
-
-        if (!settings_->privacyScreen()) {
-                privacyScreenTimeout_->setDisabled(true);
-        }
-
-        avatarCircles_->setFixedSize(64, 48);
-
-        auto uiLabel_ = new QLabel{tr("INTERFACE"), this};
-        uiLabel_->setFixedHeight(uiLabel_->minimumHeight() + LayoutTopMargin);
-        uiLabel_->setAlignment(Qt::AlignBottom);
-        uiLabel_->setFont(font);
-
-        for (double option = 1; option <= 3; option += 0.25)
-                scaleFactorCombo_->addItem(QString::number(option));
-        for (double option = 6; option <= 24; option += 0.5)
-                fontSizeCombo_->addItem(QString("%1 ").arg(QString::number(option)));
-
-        QFontDatabase fontDb;
-
-        // TODO: Is there a way to limit to just emojis, rather than
-        // all emoji fonts?
-        auto emojiFamilies = fontDb.families(QFontDatabase::Symbol);
-        emojiFontSelectionCombo_->addItem(tr("Default"));
-        for (const auto &family : emojiFamilies) {
-                emojiFontSelectionCombo_->addItem(family);
-        }
-
-        QString currentFont = settings_->font();
-        if (currentFont != "default" || currentFont != "") {
-                fontSelectionCombo_->setCurrentIndex(fontSelectionCombo_->findText(currentFont));
+    topLayout_ = new QVBoxLayout{this};
+
+    QIcon icon;
+    icon.addFile(":/icons/icons/ui/angle-pointing-to-left.png");
+
+    auto backBtn_ = new FlatButton{this};
+    backBtn_->setMinimumSize(QSize(24, 24));
+    backBtn_->setIcon(icon);
+    backBtn_->setIconSize(QSize(24, 24));
+
+    QFont font;
+    font.setPointSizeF(font.pointSizeF() * 1.1);
+
+    auto versionInfo = new QLabel(QString("%1 | %2").arg(nheko::version).arg(nheko::build_os));
+    if (QCoreApplication::applicationName() != "nheko")
+        versionInfo->setText(versionInfo->text() + " | " +
+                             tr("profile: %1").arg(QCoreApplication::applicationName()));
+    versionInfo->setTextInteractionFlags(Qt::TextBrowserInteraction);
+
+    topBarLayout_ = new QHBoxLayout;
+    topBarLayout_->setSpacing(0);
+    topBarLayout_->setMargin(0);
+    topBarLayout_->addWidget(backBtn_, 1, Qt::AlignLeft | Qt::AlignVCenter);
+    topBarLayout_->addStretch(1);
+
+    formLayout_ = new QFormLayout;
+
+    formLayout_->setLabelAlignment(Qt::AlignLeft);
+    formLayout_->setFormAlignment(Qt::AlignRight);
+    formLayout_->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
+    formLayout_->setRowWrapPolicy(QFormLayout::WrapLongRows);
+    formLayout_->setHorizontalSpacing(0);
+
+    auto general_ = new QLabel{tr("GENERAL"), this};
+    general_->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
+    general_->setFont(font);
+
+    trayToggle_                     = new Toggle{this};
+    startInTrayToggle_              = new Toggle{this};
+    avatarCircles_                  = new Toggle{this};
+    useIdenticon_                   = new Toggle{this};
+    decryptSidebar_                 = new Toggle(this);
+    privacyScreen_                  = new Toggle{this};
+    onlyShareKeysWithVerifiedUsers_ = new Toggle(this);
+    shareKeysWithTrustedUsers_      = new Toggle(this);
+    useOnlineKeyBackup_             = new Toggle(this);
+    groupViewToggle_                = new Toggle{this};
+    timelineButtonsToggle_          = new Toggle{this};
+    typingNotifications_            = new Toggle{this};
+    messageHoverHighlight_          = new Toggle{this};
+    enlargeEmojiOnlyMessages_       = new Toggle{this};
+    sortByImportance_               = new Toggle{this};
+    readReceipts_                   = new Toggle{this};
+    markdown_                       = new Toggle{this};
+    animateImagesOnHover_           = new Toggle{this};
+    desktopNotifications_           = new Toggle{this};
+    alertOnNotification_            = new Toggle{this};
+    useStunServer_                  = new Toggle{this};
+    mobileMode_                     = new Toggle{this};
+    scaleFactorCombo_               = new QComboBox{this};
+    fontSizeCombo_                  = new QComboBox{this};
+    fontSelectionCombo_             = new QFontComboBox{this};
+    emojiFontSelectionCombo_        = new QComboBox{this};
+    ringtoneCombo_                  = new QComboBox{this};
+    microphoneCombo_                = new QComboBox{this};
+    cameraCombo_                    = new QComboBox{this};
+    cameraResolutionCombo_          = new QComboBox{this};
+    cameraFrameRateCombo_           = new QComboBox{this};
+    timelineMaxWidthSpin_           = new QSpinBox{this};
+    privacyScreenTimeout_           = new QSpinBox{this};
+
+    trayToggle_->setChecked(settings_->tray());
+    startInTrayToggle_->setChecked(settings_->startInTray());
+    avatarCircles_->setChecked(settings_->avatarCircles());
+    useIdenticon_->setChecked(settings_->useIdenticon());
+    decryptSidebar_->setChecked(settings_->decryptSidebar());
+    privacyScreen_->setChecked(settings_->privacyScreen());
+    onlyShareKeysWithVerifiedUsers_->setChecked(settings_->onlyShareKeysWithVerifiedUsers());
+    shareKeysWithTrustedUsers_->setChecked(settings_->shareKeysWithTrustedUsers());
+    useOnlineKeyBackup_->setChecked(settings_->useOnlineKeyBackup());
+    groupViewToggle_->setChecked(settings_->groupView());
+    timelineButtonsToggle_->setChecked(settings_->buttonsInTimeline());
+    typingNotifications_->setChecked(settings_->typingNotifications());
+    messageHoverHighlight_->setChecked(settings_->messageHoverHighlight());
+    enlargeEmojiOnlyMessages_->setChecked(settings_->enlargeEmojiOnlyMessages());
+    sortByImportance_->setChecked(settings_->sortByImportance());
+    readReceipts_->setChecked(settings_->readReceipts());
+    markdown_->setChecked(settings_->markdown());
+    animateImagesOnHover_->setChecked(settings_->animateImagesOnHover());
+    desktopNotifications_->setChecked(settings_->hasDesktopNotifications());
+    alertOnNotification_->setChecked(settings_->hasAlertOnNotification());
+    useStunServer_->setChecked(settings_->useStunServer());
+    mobileMode_->setChecked(settings_->mobileMode());
+
+    if (!settings_->tray()) {
+        startInTrayToggle_->setState(false);
+        startInTrayToggle_->setDisabled(true);
+    }
+
+    if (!settings_->privacyScreen()) {
+        privacyScreenTimeout_->setDisabled(true);
+    }
+
+    avatarCircles_->setFixedSize(64, 48);
+
+    auto uiLabel_ = new QLabel{tr("INTERFACE"), this};
+    uiLabel_->setFixedHeight(uiLabel_->minimumHeight() + LayoutTopMargin);
+    uiLabel_->setAlignment(Qt::AlignBottom);
+    uiLabel_->setFont(font);
+
+    for (double option = 1; option <= 3; option += 0.25)
+        scaleFactorCombo_->addItem(QString::number(option));
+    for (double option = 6; option <= 24; option += 0.5)
+        fontSizeCombo_->addItem(QString("%1 ").arg(QString::number(option)));
+
+    QFontDatabase fontDb;
+
+    // TODO: Is there a way to limit to just emojis, rather than
+    // all emoji fonts?
+    auto emojiFamilies = fontDb.families(QFontDatabase::Symbol);
+    emojiFontSelectionCombo_->addItem(tr("Default"));
+    for (const auto &family : emojiFamilies) {
+        emojiFontSelectionCombo_->addItem(family);
+    }
+
+    QString currentFont = settings_->font();
+    if (currentFont != "default" || currentFont != "") {
+        fontSelectionCombo_->setCurrentIndex(fontSelectionCombo_->findText(currentFont));
+    }
+
+    emojiFontSelectionCombo_->setCurrentIndex(
+      emojiFontSelectionCombo_->findText(settings_->emojiFont()));
+
+    themeCombo_ = new QComboBox{this};
+    themeCombo_->addItem("Light");
+    themeCombo_->addItem("Dark");
+    themeCombo_->addItem("System");
+
+    QString themeStr = settings_->theme();
+    themeStr.replace(0, 1, themeStr[0].toUpper());
+    int themeIndex = themeCombo_->findText(themeStr);
+    themeCombo_->setCurrentIndex(themeIndex);
+
+    timelineMaxWidthSpin_->setMinimum(0);
+    timelineMaxWidthSpin_->setMaximum(100'000'000);
+    timelineMaxWidthSpin_->setSingleStep(10);
+
+    privacyScreenTimeout_->setMinimum(0);
+    privacyScreenTimeout_->setMaximum(3600);
+    privacyScreenTimeout_->setSingleStep(10);
+
+    auto callsLabel = new QLabel{tr("CALLS"), this};
+    callsLabel->setFixedHeight(callsLabel->minimumHeight() + LayoutTopMargin);
+    callsLabel->setAlignment(Qt::AlignBottom);
+    callsLabel->setFont(font);
+
+    auto encryptionLabel_ = new QLabel{tr("ENCRYPTION"), this};
+    encryptionLabel_->setFixedHeight(encryptionLabel_->minimumHeight() + LayoutTopMargin);
+    encryptionLabel_->setAlignment(Qt::AlignBottom);
+    encryptionLabel_->setFont(font);
+
+    QFont monospaceFont;
+    monospaceFont.setFamily("Monospace");
+    monospaceFont.setStyleHint(QFont::Monospace);
+    monospaceFont.setPointSizeF(monospaceFont.pointSizeF() * 0.9);
+
+    deviceIdValue_ = new QLabel{this};
+    deviceIdValue_->setTextInteractionFlags(Qt::TextSelectableByMouse);
+    deviceIdValue_->setFont(monospaceFont);
+
+    deviceFingerprintValue_ = new QLabel{this};
+    deviceFingerprintValue_->setTextInteractionFlags(Qt::TextSelectableByMouse);
+    deviceFingerprintValue_->setFont(monospaceFont);
+
+    deviceFingerprintValue_->setText(utils::humanReadableFingerprint(QString(44, 'X')));
+
+    backupSecretCached      = new QLabel{this};
+    masterSecretCached      = new QLabel{this};
+    selfSigningSecretCached = new QLabel{this};
+    userSigningSecretCached = new QLabel{this};
+    backupSecretCached->setFont(monospaceFont);
+    masterSecretCached->setFont(monospaceFont);
+    selfSigningSecretCached->setFont(monospaceFont);
+    userSigningSecretCached->setFont(monospaceFont);
+
+    auto sessionKeysLabel = new QLabel{tr("Session Keys"), this};
+    sessionKeysLabel->setFont(font);
+    sessionKeysLabel->setMargin(OptionMargin);
+
+    auto sessionKeysImportBtn = new QPushButton{tr("IMPORT"), this};
+    auto sessionKeysExportBtn = new QPushButton{tr("EXPORT"), this};
+
+    auto sessionKeysLayout = new QHBoxLayout;
+    sessionKeysLayout->addWidget(new QLabel{"", this}, 1, Qt::AlignRight);
+    sessionKeysLayout->addWidget(sessionKeysExportBtn, 0, Qt::AlignRight);
+    sessionKeysLayout->addWidget(sessionKeysImportBtn, 0, Qt::AlignRight);
+
+    auto crossSigningKeysLabel = new QLabel{tr("Cross Signing Keys"), this};
+    crossSigningKeysLabel->setFont(font);
+    crossSigningKeysLabel->setMargin(OptionMargin);
+
+    auto crossSigningRequestBtn  = new QPushButton{tr("REQUEST"), this};
+    auto crossSigningDownloadBtn = new QPushButton{tr("DOWNLOAD"), this};
+
+    auto crossSigningKeysLayout = new QHBoxLayout;
+    crossSigningKeysLayout->addWidget(new QLabel{"", this}, 1, Qt::AlignRight);
+    crossSigningKeysLayout->addWidget(crossSigningRequestBtn, 0, Qt::AlignRight);
+    crossSigningKeysLayout->addWidget(crossSigningDownloadBtn, 0, Qt::AlignRight);
+
+    auto boxWrap = [this, &font](QString labelText, QWidget *field, QString tooltipText = "") {
+        auto label = new QLabel{labelText, this};
+        label->setFont(font);
+        label->setMargin(OptionMargin);
+
+        if (!tooltipText.isEmpty()) {
+            label->setToolTip(tooltipText);
         }
 
-        emojiFontSelectionCombo_->setCurrentIndex(
-          emojiFontSelectionCombo_->findText(settings_->emojiFont()));
-
-        themeCombo_ = new QComboBox{this};
-        themeCombo_->addItem("Light");
-        themeCombo_->addItem("Dark");
-        themeCombo_->addItem("System");
-
-        QString themeStr = settings_->theme();
-        themeStr.replace(0, 1, themeStr[0].toUpper());
-        int themeIndex = themeCombo_->findText(themeStr);
-        themeCombo_->setCurrentIndex(themeIndex);
-
-        timelineMaxWidthSpin_->setMinimum(0);
-        timelineMaxWidthSpin_->setMaximum(100'000'000);
-        timelineMaxWidthSpin_->setSingleStep(10);
-
-        privacyScreenTimeout_->setMinimum(0);
-        privacyScreenTimeout_->setMaximum(3600);
-        privacyScreenTimeout_->setSingleStep(10);
-
-        auto callsLabel = new QLabel{tr("CALLS"), this};
-        callsLabel->setFixedHeight(callsLabel->minimumHeight() + LayoutTopMargin);
-        callsLabel->setAlignment(Qt::AlignBottom);
-        callsLabel->setFont(font);
-
-        auto encryptionLabel_ = new QLabel{tr("ENCRYPTION"), this};
-        encryptionLabel_->setFixedHeight(encryptionLabel_->minimumHeight() + LayoutTopMargin);
-        encryptionLabel_->setAlignment(Qt::AlignBottom);
-        encryptionLabel_->setFont(font);
-
-        QFont monospaceFont;
-        monospaceFont.setFamily("Monospace");
-        monospaceFont.setStyleHint(QFont::Monospace);
-        monospaceFont.setPointSizeF(monospaceFont.pointSizeF() * 0.9);
-
-        deviceIdValue_ = new QLabel{this};
-        deviceIdValue_->setTextInteractionFlags(Qt::TextSelectableByMouse);
-        deviceIdValue_->setFont(monospaceFont);
-
-        deviceFingerprintValue_ = new QLabel{this};
-        deviceFingerprintValue_->setTextInteractionFlags(Qt::TextSelectableByMouse);
-        deviceFingerprintValue_->setFont(monospaceFont);
-
-        deviceFingerprintValue_->setText(utils::humanReadableFingerprint(QString(44, 'X')));
-
-        backupSecretCached      = new QLabel{this};
-        masterSecretCached      = new QLabel{this};
-        selfSigningSecretCached = new QLabel{this};
-        userSigningSecretCached = new QLabel{this};
-        backupSecretCached->setFont(monospaceFont);
-        masterSecretCached->setFont(monospaceFont);
-        selfSigningSecretCached->setFont(monospaceFont);
-        userSigningSecretCached->setFont(monospaceFont);
-
-        auto sessionKeysLabel = new QLabel{tr("Session Keys"), this};
-        sessionKeysLabel->setFont(font);
-        sessionKeysLabel->setMargin(OptionMargin);
-
-        auto sessionKeysImportBtn = new QPushButton{tr("IMPORT"), this};
-        auto sessionKeysExportBtn = new QPushButton{tr("EXPORT"), this};
-
-        auto sessionKeysLayout = new QHBoxLayout;
-        sessionKeysLayout->addWidget(new QLabel{"", this}, 1, Qt::AlignRight);
-        sessionKeysLayout->addWidget(sessionKeysExportBtn, 0, Qt::AlignRight);
-        sessionKeysLayout->addWidget(sessionKeysImportBtn, 0, Qt::AlignRight);
-
-        auto crossSigningKeysLabel = new QLabel{tr("Cross Signing Keys"), this};
-        crossSigningKeysLabel->setFont(font);
-        crossSigningKeysLabel->setMargin(OptionMargin);
-
-        auto crossSigningRequestBtn  = new QPushButton{tr("REQUEST"), this};
-        auto crossSigningDownloadBtn = new QPushButton{tr("DOWNLOAD"), this};
-
-        auto crossSigningKeysLayout = new QHBoxLayout;
-        crossSigningKeysLayout->addWidget(new QLabel{"", this}, 1, Qt::AlignRight);
-        crossSigningKeysLayout->addWidget(crossSigningRequestBtn, 0, Qt::AlignRight);
-        crossSigningKeysLayout->addWidget(crossSigningDownloadBtn, 0, Qt::AlignRight);
-
-        auto boxWrap = [this, &font](QString labelText, QWidget *field, QString tooltipText = "") {
-                auto label = new QLabel{labelText, this};
-                label->setFont(font);
-                label->setMargin(OptionMargin);
-
-                if (!tooltipText.isEmpty()) {
-                        label->setToolTip(tooltipText);
-                }
-
-                auto layout = new QHBoxLayout;
-                layout->addWidget(field, 0, Qt::AlignRight);
-
-                formLayout_->addRow(label, layout);
-        };
-
-        formLayout_->addRow(general_);
-        formLayout_->addRow(new HorizontalLine{this});
-        boxWrap(
-          tr("Minimize to tray"),
-          trayToggle_,
-          tr("Keep the application running in the background after closing the client window."));
-        boxWrap(tr("Start in tray"),
-                startInTrayToggle_,
-                tr("Start the application in the background without showing the client window."));
-        formLayout_->addRow(new HorizontalLine{this});
-        boxWrap(tr("Circular Avatars"),
-                avatarCircles_,
-                tr("Change the appearance of user avatars in chats.\nOFF - square, ON - Circle."));
-        boxWrap(tr("Use identicons"),
-                useIdenticon_,
-                tr("Display an identicon instead of a letter when a user has not set an avatar."));
-        boxWrap(tr("Group's sidebar"),
-                groupViewToggle_,
-                tr("Show a column containing groups and tags next to the room list."));
-        boxWrap(tr("Decrypt messages in sidebar"),
-                decryptSidebar_,
-                tr("Decrypt the messages shown in the sidebar.\nOnly affects messages in "
-                   "encrypted chats."));
-        boxWrap(tr("Privacy Screen"),
-                privacyScreen_,
-                tr("When the window loses focus, the timeline will\nbe blurred."));
-        boxWrap(
-          tr("Privacy screen timeout (in seconds [0 - 3600])"),
-          privacyScreenTimeout_,
-          tr("Set timeout (in seconds) for how long after window loses\nfocus before the screen"
-             " will be blurred.\nSet to 0 to blur immediately after focus loss. Max value of 1 "
-             "hour (3600 seconds)"));
-        boxWrap(tr("Show buttons in timeline"),
-                timelineButtonsToggle_,
-                tr("Show buttons to quickly reply, react or access additional options next to each "
-                   "message."));
-        boxWrap(tr("Limit width of timeline"),
-                timelineMaxWidthSpin_,
-                tr("Set the max width of messages in the timeline (in pixels). This can help "
-                   "readability on wide screen, when Nheko is maximised"));
-        boxWrap(tr("Typing notifications"),
-                typingNotifications_,
-                tr("Show who is typing in a room.\nThis will also enable or disable sending typing "
-                   "notifications to others."));
-        boxWrap(
-          tr("Sort rooms by unreads"),
-          sortByImportance_,
-          tr(
-            "Display rooms with new messages first.\nIf this is off, the list of rooms will only "
-            "be sorted by the timestamp of the last message in a room.\nIf this is on, rooms which "
-            "have active notifications (the small circle with a number in it) will be sorted on "
-            "top. Rooms, that you have muted, will still be sorted by timestamp, since you don't "
-            "seem to consider them as important as the other rooms."));
-        formLayout_->addRow(new HorizontalLine{this});
-        boxWrap(tr("Read receipts"),
-                readReceipts_,
-                tr("Show if your message was read.\nStatus is displayed next to timestamps."));
-        boxWrap(
-          tr("Send messages as Markdown"),
-          markdown_,
-          tr("Allow using markdown in messages.\nWhen disabled, all messages are sent as a plain "
-             "text."));
-        boxWrap(tr("Play animated images only on hover"),
-                animateImagesOnHover_,
-                tr("Plays media like GIFs or WEBPs only when explicitly hovering over them."));
-        boxWrap(tr("Desktop notifications"),
-                desktopNotifications_,
-                tr("Notify about received message when the client is not currently focused."));
-        boxWrap(tr("Alert on notification"),
-                alertOnNotification_,
-                tr("Show an alert when a message is received.\nThis usually causes the application "
-                   "icon in the task bar to animate in some fashion."));
-        boxWrap(tr("Highlight message on hover"),
-                messageHoverHighlight_,
-                tr("Change the background color of messages when you hover over them."));
-        boxWrap(tr("Large Emoji in timeline"),
-                enlargeEmojiOnlyMessages_,
-                tr("Make font size larger if messages with only a few emojis are displayed."));
-        formLayout_->addRow(uiLabel_);
-        formLayout_->addRow(new HorizontalLine{this});
-
-        boxWrap(tr("Touchscreen mode"),
-                mobileMode_,
-                tr("Will prevent text selection in the timeline to make touch scrolling easier."));
+        auto layout = new QHBoxLayout;
+        layout->addWidget(field, 0, Qt::AlignRight);
+
+        formLayout_->addRow(label, layout);
+    };
+
+    formLayout_->addRow(general_);
+    formLayout_->addRow(new HorizontalLine{this});
+    boxWrap(tr("Minimize to tray"),
+            trayToggle_,
+            tr("Keep the application running in the background after closing the client window."));
+    boxWrap(tr("Start in tray"),
+            startInTrayToggle_,
+            tr("Start the application in the background without showing the client window."));
+    formLayout_->addRow(new HorizontalLine{this});
+    boxWrap(tr("Circular Avatars"),
+            avatarCircles_,
+            tr("Change the appearance of user avatars in chats.\nOFF - square, ON - Circle."));
+    boxWrap(tr("Use identicons"),
+            useIdenticon_,
+            tr("Display an identicon instead of a letter when a user has not set an avatar."));
+    boxWrap(tr("Group's sidebar"),
+            groupViewToggle_,
+            tr("Show a column containing groups and tags next to the room list."));
+    boxWrap(tr("Decrypt messages in sidebar"),
+            decryptSidebar_,
+            tr("Decrypt the messages shown in the sidebar.\nOnly affects messages in "
+               "encrypted chats."));
+    boxWrap(tr("Privacy Screen"),
+            privacyScreen_,
+            tr("When the window loses focus, the timeline will\nbe blurred."));
+    boxWrap(tr("Privacy screen timeout (in seconds [0 - 3600])"),
+            privacyScreenTimeout_,
+            tr("Set timeout (in seconds) for how long after window loses\nfocus before the screen"
+               " will be blurred.\nSet to 0 to blur immediately after focus loss. Max value of 1 "
+               "hour (3600 seconds)"));
+    boxWrap(tr("Show buttons in timeline"),
+            timelineButtonsToggle_,
+            tr("Show buttons to quickly reply, react or access additional options next to each "
+               "message."));
+    boxWrap(tr("Limit width of timeline"),
+            timelineMaxWidthSpin_,
+            tr("Set the max width of messages in the timeline (in pixels). This can help "
+               "readability on wide screen, when Nheko is maximised"));
+    boxWrap(tr("Typing notifications"),
+            typingNotifications_,
+            tr("Show who is typing in a room.\nThis will also enable or disable sending typing "
+               "notifications to others."));
+    boxWrap(
+      tr("Sort rooms by unreads"),
+      sortByImportance_,
+      tr("Display rooms with new messages first.\nIf this is off, the list of rooms will only "
+         "be sorted by the timestamp of the last message in a room.\nIf this is on, rooms which "
+         "have active notifications (the small circle with a number in it) will be sorted on "
+         "top. Rooms, that you have muted, will still be sorted by timestamp, since you don't "
+         "seem to consider them as important as the other rooms."));
+    formLayout_->addRow(new HorizontalLine{this});
+    boxWrap(tr("Read receipts"),
+            readReceipts_,
+            tr("Show if your message was read.\nStatus is displayed next to timestamps."));
+    boxWrap(tr("Send messages as Markdown"),
+            markdown_,
+            tr("Allow using markdown in messages.\nWhen disabled, all messages are sent as a plain "
+               "text."));
+    boxWrap(tr("Play animated images only on hover"),
+            animateImagesOnHover_,
+            tr("Plays media like GIFs or WEBPs only when explicitly hovering over them."));
+    boxWrap(tr("Desktop notifications"),
+            desktopNotifications_,
+            tr("Notify about received message when the client is not currently focused."));
+    boxWrap(tr("Alert on notification"),
+            alertOnNotification_,
+            tr("Show an alert when a message is received.\nThis usually causes the application "
+               "icon in the task bar to animate in some fashion."));
+    boxWrap(tr("Highlight message on hover"),
+            messageHoverHighlight_,
+            tr("Change the background color of messages when you hover over them."));
+    boxWrap(tr("Large Emoji in timeline"),
+            enlargeEmojiOnlyMessages_,
+            tr("Make font size larger if messages with only a few emojis are displayed."));
+    formLayout_->addRow(uiLabel_);
+    formLayout_->addRow(new HorizontalLine{this});
+
+    boxWrap(tr("Touchscreen mode"),
+            mobileMode_,
+            tr("Will prevent text selection in the timeline to make touch scrolling easier."));
 #if !defined(Q_OS_MAC)
-        boxWrap(tr("Scale factor"),
-                scaleFactorCombo_,
-                tr("Change the scale factor of the whole user interface."));
+    boxWrap(tr("Scale factor"),
+            scaleFactorCombo_,
+            tr("Change the scale factor of the whole user interface."));
 #else
-        scaleFactorCombo_->hide();
+    scaleFactorCombo_->hide();
 #endif
-        boxWrap(tr("Font size"), fontSizeCombo_);
-        boxWrap(tr("Font Family"), fontSelectionCombo_);
+    boxWrap(tr("Font size"), fontSizeCombo_);
+    boxWrap(tr("Font Family"), fontSelectionCombo_);
 
 #if !defined(Q_OS_MAC)
-        boxWrap(tr("Emoji Font Family"), emojiFontSelectionCombo_);
+    boxWrap(tr("Emoji Font Family"), emojiFontSelectionCombo_);
 #else
-        emojiFontSelectionCombo_->hide();
+    emojiFontSelectionCombo_->hide();
 #endif
 
-        boxWrap(tr("Theme"), themeCombo_);
-
-        formLayout_->addRow(callsLabel);
-        formLayout_->addRow(new HorizontalLine{this});
-        boxWrap(tr("Ringtone"),
-                ringtoneCombo_,
-                tr("Set the notification sound to play when a call invite arrives"));
-        boxWrap(tr("Microphone"), microphoneCombo_);
-        boxWrap(tr("Camera"), cameraCombo_);
-        boxWrap(tr("Camera resolution"), cameraResolutionCombo_);
-        boxWrap(tr("Camera frame rate"), cameraFrameRateCombo_);
-
-        ringtoneCombo_->setSizeAdjustPolicy(QComboBox::AdjustToContents);
-        ringtoneCombo_->addItem("Mute");
-        ringtoneCombo_->addItem("Default");
-        ringtoneCombo_->addItem("Other...");
-        const QString &ringtone = settings_->ringtone();
-        if (!ringtone.isEmpty() && ringtone != "Mute" && ringtone != "Default")
-                ringtoneCombo_->addItem(ringtone);
-        microphoneCombo_->setSizeAdjustPolicy(QComboBox::AdjustToContents);
-        cameraCombo_->setSizeAdjustPolicy(QComboBox::AdjustToContents);
-        cameraResolutionCombo_->setSizeAdjustPolicy(QComboBox::AdjustToContents);
-        cameraFrameRateCombo_->setSizeAdjustPolicy(QComboBox::AdjustToContents);
-
-        boxWrap(tr("Allow fallback call assist server"),
-                useStunServer_,
-                tr("Will use turn.matrix.org as assist when your home server does not offer one."));
-
-        formLayout_->addRow(encryptionLabel_);
-        formLayout_->addRow(new HorizontalLine{this});
-        boxWrap(tr("Device ID"), deviceIdValue_);
-        boxWrap(tr("Device Fingerprint"), deviceFingerprintValue_);
-        boxWrap(tr("Send encrypted messages to verified users only"),
-                onlyShareKeysWithVerifiedUsers_,
-                tr("Requires a user to be verified to send encrypted messages to them. This "
-                   "improves safety but makes E2EE more tedious."));
-        boxWrap(tr("Share keys with verified users and devices"),
-                shareKeysWithTrustedUsers_,
-                tr("Automatically replies to key requests from other users, if they are verified, "
-                   "even if that device shouldn't have access to those keys otherwise."));
-        boxWrap(tr("Online Key Backup"),
-                useOnlineKeyBackup_,
-                tr("Download message encryption keys from and upload to the encrypted online key "
-                   "backup."));
-        formLayout_->addRow(new HorizontalLine{this});
-        formLayout_->addRow(sessionKeysLabel, sessionKeysLayout);
-        formLayout_->addRow(crossSigningKeysLabel, crossSigningKeysLayout);
-
-        boxWrap(tr("Master signing key"),
-                masterSecretCached,
-                tr("Your most important key. You don't need to have it cached, since not caching "
-                   "it makes it less likely it can be stolen and it is only needed to rotate your "
-                   "other signing keys."));
-        boxWrap(tr("User signing key"),
-                userSigningSecretCached,
-                tr("The key to verify other users. If it is cached, verifying a user will verify "
-                   "all their devices."));
-        boxWrap(
-          tr("Self signing key"),
-          selfSigningSecretCached,
-          tr("The key to verify your own devices. If it is cached, verifying one of your devices "
-             "will mark it verified for all your other devices and for users, that have verified "
-             "you."));
-        boxWrap(tr("Backup key"),
-                backupSecretCached,
-                tr("The key to decrypt online key backups. If it is cached, you can enable online "
-                   "key backup to store encryption keys securely encrypted on the server."));
-        updateSecretStatus();
-
-        auto scrollArea_ = new QScrollArea{this};
-        scrollArea_->setFrameShape(QFrame::NoFrame);
-        scrollArea_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
-        scrollArea_->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
-        scrollArea_->setWidgetResizable(true);
-        scrollArea_->setAlignment(Qt::AlignTop | Qt::AlignVCenter);
-
-        QScroller::grabGesture(scrollArea_, QScroller::TouchGesture);
-
-        auto spacingAroundForm = new QHBoxLayout;
-        spacingAroundForm->addStretch(1);
-        spacingAroundForm->addLayout(formLayout_, 0);
-        spacingAroundForm->addStretch(1);
-
-        auto scrollAreaContents_ = new QWidget{this};
-        scrollAreaContents_->setObjectName("UserSettingScrollWidget");
-        scrollAreaContents_->setLayout(spacingAroundForm);
-
-        scrollArea_->setWidget(scrollAreaContents_);
-        topLayout_->addLayout(topBarLayout_);
-        topLayout_->addWidget(scrollArea_, Qt::AlignTop);
-        topLayout_->addStretch(1);
-        topLayout_->addWidget(versionInfo);
-
-        connect(themeCombo_,
-                static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
-                [this](const QString &text) {
-                        settings_->setTheme(text.toLower());
-                        emit themeChanged();
-                });
-        connect(scaleFactorCombo_,
-                static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
-                [](const QString &factor) { utils::setScaleFactor(factor.toFloat()); });
-        connect(fontSizeCombo_,
-                static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
-                [this](const QString &size) { settings_->setFontSize(size.trimmed().toDouble()); });
-        connect(fontSelectionCombo_,
-                static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
-                [this](const QString &family) { settings_->setFontFamily(family.trimmed()); });
-        connect(emojiFontSelectionCombo_,
-                static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
-                [this](const QString &family) { settings_->setEmojiFontFamily(family.trimmed()); });
-
-        connect(ringtoneCombo_,
-                static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
-                [this](const QString &ringtone) {
-                        if (ringtone == "Other...") {
-                                QString homeFolder =
-                                  QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
-                                auto filepath = QFileDialog::getOpenFileName(
-                                  this, tr("Select a file"), homeFolder, tr("All Files (*)"));
-                                if (!filepath.isEmpty()) {
-                                        const auto &oldSetting = settings_->ringtone();
-                                        if (oldSetting != "Mute" && oldSetting != "Default")
-                                                ringtoneCombo_->removeItem(
-                                                  ringtoneCombo_->findText(oldSetting));
-                                        settings_->setRingtone(filepath);
-                                        ringtoneCombo_->addItem(filepath);
-                                        ringtoneCombo_->setCurrentText(filepath);
-                                } else {
-                                        ringtoneCombo_->setCurrentText(settings_->ringtone());
-                                }
-                        } else if (ringtone == "Mute" || ringtone == "Default") {
-                                const auto &oldSetting = settings_->ringtone();
-                                if (oldSetting != "Mute" && oldSetting != "Default")
-                                        ringtoneCombo_->removeItem(
-                                          ringtoneCombo_->findText(oldSetting));
-                                settings_->setRingtone(ringtone);
-                        }
-                });
-
-        connect(microphoneCombo_,
-                static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
-                [this](const QString &microphone) { settings_->setMicrophone(microphone); });
-
-        connect(cameraCombo_,
-                static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
-                [this](const QString &camera) {
-                        settings_->setCamera(camera);
-                        std::vector<std::string> resolutions =
-                          CallDevices::instance().resolutions(camera.toStdString());
-                        cameraResolutionCombo_->clear();
-                        for (const auto &resolution : resolutions)
-                                cameraResolutionCombo_->addItem(QString::fromStdString(resolution));
-                });
-
-        connect(cameraResolutionCombo_,
-                static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
-                [this](const QString &resolution) {
-                        settings_->setCameraResolution(resolution);
-                        std::vector<std::string> frameRates = CallDevices::instance().frameRates(
-                          settings_->camera().toStdString(), resolution.toStdString());
-                        cameraFrameRateCombo_->clear();
-                        for (const auto &frameRate : frameRates)
-                                cameraFrameRateCombo_->addItem(QString::fromStdString(frameRate));
-                });
-
-        connect(cameraFrameRateCombo_,
-                static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
-                [this](const QString &frameRate) { settings_->setCameraFrameRate(frameRate); });
-
-        connect(trayToggle_, &Toggle::toggled, this, [this](bool enabled) {
-                settings_->setTray(enabled);
-                if (enabled) {
-                        startInTrayToggle_->setChecked(false);
-                        startInTrayToggle_->setEnabled(true);
-                        startInTrayToggle_->setState(false);
-                        settings_->setStartInTray(false);
-                } else {
-                        startInTrayToggle_->setChecked(false);
-                        startInTrayToggle_->setState(false);
-                        startInTrayToggle_->setDisabled(true);
-                        settings_->setStartInTray(false);
+    boxWrap(tr("Theme"), themeCombo_);
+
+    formLayout_->addRow(callsLabel);
+    formLayout_->addRow(new HorizontalLine{this});
+    boxWrap(tr("Ringtone"),
+            ringtoneCombo_,
+            tr("Set the notification sound to play when a call invite arrives"));
+    boxWrap(tr("Microphone"), microphoneCombo_);
+    boxWrap(tr("Camera"), cameraCombo_);
+    boxWrap(tr("Camera resolution"), cameraResolutionCombo_);
+    boxWrap(tr("Camera frame rate"), cameraFrameRateCombo_);
+
+    ringtoneCombo_->setSizeAdjustPolicy(QComboBox::AdjustToContents);
+    ringtoneCombo_->addItem("Mute");
+    ringtoneCombo_->addItem("Default");
+    ringtoneCombo_->addItem("Other...");
+    const QString &ringtone = settings_->ringtone();
+    if (!ringtone.isEmpty() && ringtone != "Mute" && ringtone != "Default")
+        ringtoneCombo_->addItem(ringtone);
+    microphoneCombo_->setSizeAdjustPolicy(QComboBox::AdjustToContents);
+    cameraCombo_->setSizeAdjustPolicy(QComboBox::AdjustToContents);
+    cameraResolutionCombo_->setSizeAdjustPolicy(QComboBox::AdjustToContents);
+    cameraFrameRateCombo_->setSizeAdjustPolicy(QComboBox::AdjustToContents);
+
+    boxWrap(tr("Allow fallback call assist server"),
+            useStunServer_,
+            tr("Will use turn.matrix.org as assist when your home server does not offer one."));
+
+    formLayout_->addRow(encryptionLabel_);
+    formLayout_->addRow(new HorizontalLine{this});
+    boxWrap(tr("Device ID"), deviceIdValue_);
+    boxWrap(tr("Device Fingerprint"), deviceFingerprintValue_);
+    boxWrap(tr("Send encrypted messages to verified users only"),
+            onlyShareKeysWithVerifiedUsers_,
+            tr("Requires a user to be verified to send encrypted messages to them. This "
+               "improves safety but makes E2EE more tedious."));
+    boxWrap(tr("Share keys with verified users and devices"),
+            shareKeysWithTrustedUsers_,
+            tr("Automatically replies to key requests from other users, if they are verified, "
+               "even if that device shouldn't have access to those keys otherwise."));
+    boxWrap(tr("Online Key Backup"),
+            useOnlineKeyBackup_,
+            tr("Download message encryption keys from and upload to the encrypted online key "
+               "backup."));
+    formLayout_->addRow(new HorizontalLine{this});
+    formLayout_->addRow(sessionKeysLabel, sessionKeysLayout);
+    formLayout_->addRow(crossSigningKeysLabel, crossSigningKeysLayout);
+
+    boxWrap(tr("Master signing key"),
+            masterSecretCached,
+            tr("Your most important key. You don't need to have it cached, since not caching "
+               "it makes it less likely it can be stolen and it is only needed to rotate your "
+               "other signing keys."));
+    boxWrap(tr("User signing key"),
+            userSigningSecretCached,
+            tr("The key to verify other users. If it is cached, verifying a user will verify "
+               "all their devices."));
+    boxWrap(tr("Self signing key"),
+            selfSigningSecretCached,
+            tr("The key to verify your own devices. If it is cached, verifying one of your devices "
+               "will mark it verified for all your other devices and for users, that have verified "
+               "you."));
+    boxWrap(tr("Backup key"),
+            backupSecretCached,
+            tr("The key to decrypt online key backups. If it is cached, you can enable online "
+               "key backup to store encryption keys securely encrypted on the server."));
+    updateSecretStatus();
+
+    auto scrollArea_ = new QScrollArea{this};
+    scrollArea_->setFrameShape(QFrame::NoFrame);
+    scrollArea_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+    scrollArea_->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
+    scrollArea_->setWidgetResizable(true);
+    scrollArea_->setAlignment(Qt::AlignTop | Qt::AlignVCenter);
+
+    QScroller::grabGesture(scrollArea_, QScroller::TouchGesture);
+
+    auto spacingAroundForm = new QHBoxLayout;
+    spacingAroundForm->addStretch(1);
+    spacingAroundForm->addLayout(formLayout_, 0);
+    spacingAroundForm->addStretch(1);
+
+    auto scrollAreaContents_ = new QWidget{this};
+    scrollAreaContents_->setObjectName("UserSettingScrollWidget");
+    scrollAreaContents_->setLayout(spacingAroundForm);
+
+    scrollArea_->setWidget(scrollAreaContents_);
+    topLayout_->addLayout(topBarLayout_);
+    topLayout_->addWidget(scrollArea_, Qt::AlignTop);
+    topLayout_->addStretch(1);
+    topLayout_->addWidget(versionInfo);
+
+    connect(themeCombo_,
+            static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
+            [this](const QString &text) {
+                settings_->setTheme(text.toLower());
+                emit themeChanged();
+            });
+    connect(scaleFactorCombo_,
+            static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
+            [](const QString &factor) { utils::setScaleFactor(factor.toFloat()); });
+    connect(fontSizeCombo_,
+            static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
+            [this](const QString &size) { settings_->setFontSize(size.trimmed().toDouble()); });
+    connect(fontSelectionCombo_,
+            static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
+            [this](const QString &family) { settings_->setFontFamily(family.trimmed()); });
+    connect(emojiFontSelectionCombo_,
+            static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
+            [this](const QString &family) { settings_->setEmojiFontFamily(family.trimmed()); });
+
+    connect(ringtoneCombo_,
+            static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
+            [this](const QString &ringtone) {
+                if (ringtone == "Other...") {
+                    QString homeFolder =
+                      QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
+                    auto filepath = QFileDialog::getOpenFileName(
+                      this, tr("Select a file"), homeFolder, tr("All Files (*)"));
+                    if (!filepath.isEmpty()) {
+                        const auto &oldSetting = settings_->ringtone();
+                        if (oldSetting != "Mute" && oldSetting != "Default")
+                            ringtoneCombo_->removeItem(ringtoneCombo_->findText(oldSetting));
+                        settings_->setRingtone(filepath);
+                        ringtoneCombo_->addItem(filepath);
+                        ringtoneCombo_->setCurrentText(filepath);
+                    } else {
+                        ringtoneCombo_->setCurrentText(settings_->ringtone());
+                    }
+                } else if (ringtone == "Mute" || ringtone == "Default") {
+                    const auto &oldSetting = settings_->ringtone();
+                    if (oldSetting != "Mute" && oldSetting != "Default")
+                        ringtoneCombo_->removeItem(ringtoneCombo_->findText(oldSetting));
+                    settings_->setRingtone(ringtone);
                 }
-                emit trayOptionChanged(enabled);
-        });
-
-        connect(startInTrayToggle_, &Toggle::toggled, this, [this](bool enabled) {
-                settings_->setStartInTray(enabled);
-        });
-
-        connect(mobileMode_, &Toggle::toggled, this, [this](bool enabled) {
-                settings_->setMobileMode(enabled);
-        });
+            });
+
+    connect(microphoneCombo_,
+            static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
+            [this](const QString &microphone) { settings_->setMicrophone(microphone); });
+
+    connect(cameraCombo_,
+            static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
+            [this](const QString &camera) {
+                settings_->setCamera(camera);
+                std::vector<std::string> resolutions =
+                  CallDevices::instance().resolutions(camera.toStdString());
+                cameraResolutionCombo_->clear();
+                for (const auto &resolution : resolutions)
+                    cameraResolutionCombo_->addItem(QString::fromStdString(resolution));
+            });
+
+    connect(cameraResolutionCombo_,
+            static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
+            [this](const QString &resolution) {
+                settings_->setCameraResolution(resolution);
+                std::vector<std::string> frameRates = CallDevices::instance().frameRates(
+                  settings_->camera().toStdString(), resolution.toStdString());
+                cameraFrameRateCombo_->clear();
+                for (const auto &frameRate : frameRates)
+                    cameraFrameRateCombo_->addItem(QString::fromStdString(frameRate));
+            });
+
+    connect(cameraFrameRateCombo_,
+            static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
+            [this](const QString &frameRate) { settings_->setCameraFrameRate(frameRate); });
+
+    connect(trayToggle_, &Toggle::toggled, this, [this](bool enabled) {
+        settings_->setTray(enabled);
+        if (enabled) {
+            startInTrayToggle_->setChecked(false);
+            startInTrayToggle_->setEnabled(true);
+            startInTrayToggle_->setState(false);
+            settings_->setStartInTray(false);
+        } else {
+            startInTrayToggle_->setChecked(false);
+            startInTrayToggle_->setState(false);
+            startInTrayToggle_->setDisabled(true);
+            settings_->setStartInTray(false);
+        }
+        emit trayOptionChanged(enabled);
+    });
 
-        connect(groupViewToggle_, &Toggle::toggled, this, [this](bool enabled) {
-                settings_->setGroupView(enabled);
-        });
+    connect(startInTrayToggle_, &Toggle::toggled, this, [this](bool enabled) {
+        settings_->setStartInTray(enabled);
+    });
 
-        connect(decryptSidebar_, &Toggle::toggled, this, [this](bool enabled) {
-                settings_->setDecryptSidebar(enabled);
-        });
+    connect(mobileMode_, &Toggle::toggled, this, [this](bool enabled) {
+        settings_->setMobileMode(enabled);
+    });
 
-        connect(privacyScreen_, &Toggle::toggled, this, [this](bool enabled) {
-                settings_->setPrivacyScreen(enabled);
-                if (enabled) {
-                        privacyScreenTimeout_->setEnabled(true);
-                } else {
-                        privacyScreenTimeout_->setDisabled(true);
-                }
-        });
+    connect(groupViewToggle_, &Toggle::toggled, this, [this](bool enabled) {
+        settings_->setGroupView(enabled);
+    });
 
-        connect(onlyShareKeysWithVerifiedUsers_, &Toggle::toggled, this, [this](bool enabled) {
-                settings_->setOnlyShareKeysWithVerifiedUsers(enabled);
-        });
+    connect(decryptSidebar_, &Toggle::toggled, this, [this](bool enabled) {
+        settings_->setDecryptSidebar(enabled);
+    });
 
-        connect(shareKeysWithTrustedUsers_, &Toggle::toggled, this, [this](bool enabled) {
-                settings_->setShareKeysWithTrustedUsers(enabled);
-        });
+    connect(privacyScreen_, &Toggle::toggled, this, [this](bool enabled) {
+        settings_->setPrivacyScreen(enabled);
+        if (enabled) {
+            privacyScreenTimeout_->setEnabled(true);
+        } else {
+            privacyScreenTimeout_->setDisabled(true);
+        }
+    });
+
+    connect(onlyShareKeysWithVerifiedUsers_, &Toggle::toggled, this, [this](bool enabled) {
+        settings_->setOnlyShareKeysWithVerifiedUsers(enabled);
+    });
+
+    connect(shareKeysWithTrustedUsers_, &Toggle::toggled, this, [this](bool enabled) {
+        settings_->setShareKeysWithTrustedUsers(enabled);
+    });
+
+    connect(useOnlineKeyBackup_, &Toggle::toggled, this, [this](bool enabled) {
+        if (enabled) {
+            if (QMessageBox::question(
+                  this,
+                  tr("Enable online key backup"),
+                  tr("The Nheko authors recommend not enabling online key backup until "
+                     "symmetric online key backup is available. Enable anyway?")) !=
+                QMessageBox::StandardButton::Yes) {
+                useOnlineKeyBackup_->setState(false);
+                return;
+            }
+        }
+        settings_->setUseOnlineKeyBackup(enabled);
+    });
 
-        connect(useOnlineKeyBackup_, &Toggle::toggled, this, [this](bool enabled) {
-                if (enabled) {
-                        if (QMessageBox::question(
-                              this,
-                              tr("Enable online key backup"),
-                              tr("The Nheko authors recommend not enabling online key backup until "
-                                 "symmetric online key backup is available. Enable anyway?")) !=
-                            QMessageBox::StandardButton::Yes) {
-                                useOnlineKeyBackup_->setState(false);
-                                return;
-                        }
-                }
-                settings_->setUseOnlineKeyBackup(enabled);
-        });
+    connect(avatarCircles_, &Toggle::toggled, this, [this](bool enabled) {
+        settings_->setAvatarCircles(enabled);
+    });
 
-        connect(avatarCircles_, &Toggle::toggled, this, [this](bool enabled) {
-                settings_->setAvatarCircles(enabled);
+    if (JdenticonProvider::isAvailable())
+        connect(useIdenticon_, &Toggle::toggled, this, [this](bool enabled) {
+            settings_->setUseIdenticon(enabled);
         });
+    else
+        useIdenticon_->setDisabled(true);
 
-        if (JdenticonProvider::isAvailable())
-                connect(useIdenticon_, &Toggle::toggled, this, [this](bool enabled) {
-                        settings_->setUseIdenticon(enabled);
-                });
-        else
-                useIdenticon_->setDisabled(true);
+    connect(
+      markdown_, &Toggle::toggled, this, [this](bool enabled) { settings_->setMarkdown(enabled); });
 
-        connect(markdown_, &Toggle::toggled, this, [this](bool enabled) {
-                settings_->setMarkdown(enabled);
-        });
+    connect(animateImagesOnHover_, &Toggle::toggled, this, [this](bool enabled) {
+        settings_->setAnimateImagesOnHover(enabled);
+    });
 
-        connect(animateImagesOnHover_, &Toggle::toggled, this, [this](bool enabled) {
-                settings_->setAnimateImagesOnHover(enabled);
-        });
+    connect(typingNotifications_, &Toggle::toggled, this, [this](bool enabled) {
+        settings_->setTypingNotifications(enabled);
+    });
 
-        connect(typingNotifications_, &Toggle::toggled, this, [this](bool enabled) {
-                settings_->setTypingNotifications(enabled);
-        });
+    connect(sortByImportance_, &Toggle::toggled, this, [this](bool enabled) {
+        settings_->setSortByImportance(enabled);
+    });
 
-        connect(sortByImportance_, &Toggle::toggled, this, [this](bool enabled) {
-                settings_->setSortByImportance(enabled);
-        });
+    connect(timelineButtonsToggle_, &Toggle::toggled, this, [this](bool enabled) {
+        settings_->setButtonsInTimeline(enabled);
+    });
 
-        connect(timelineButtonsToggle_, &Toggle::toggled, this, [this](bool enabled) {
-                settings_->setButtonsInTimeline(enabled);
-        });
+    connect(readReceipts_, &Toggle::toggled, this, [this](bool enabled) {
+        settings_->setReadReceipts(enabled);
+    });
 
-        connect(readReceipts_, &Toggle::toggled, this, [this](bool enabled) {
-                settings_->setReadReceipts(enabled);
-        });
+    connect(desktopNotifications_, &Toggle::toggled, this, [this](bool enabled) {
+        settings_->setDesktopNotifications(enabled);
+    });
 
-        connect(desktopNotifications_, &Toggle::toggled, this, [this](bool enabled) {
-                settings_->setDesktopNotifications(enabled);
-        });
-
-        connect(alertOnNotification_, &Toggle::toggled, this, [this](bool enabled) {
-                settings_->setAlertOnNotification(enabled);
-        });
+    connect(alertOnNotification_, &Toggle::toggled, this, [this](bool enabled) {
+        settings_->setAlertOnNotification(enabled);
+    });
 
-        connect(messageHoverHighlight_, &Toggle::toggled, this, [this](bool enabled) {
-                settings_->setMessageHoverHighlight(enabled);
-        });
+    connect(messageHoverHighlight_, &Toggle::toggled, this, [this](bool enabled) {
+        settings_->setMessageHoverHighlight(enabled);
+    });
 
-        connect(enlargeEmojiOnlyMessages_, &Toggle::toggled, this, [this](bool enabled) {
-                settings_->setEnlargeEmojiOnlyMessages(enabled);
-        });
+    connect(enlargeEmojiOnlyMessages_, &Toggle::toggled, this, [this](bool enabled) {
+        settings_->setEnlargeEmojiOnlyMessages(enabled);
+    });
 
-        connect(useStunServer_, &Toggle::toggled, this, [this](bool enabled) {
-                settings_->setUseStunServer(enabled);
-        });
+    connect(useStunServer_, &Toggle::toggled, this, [this](bool enabled) {
+        settings_->setUseStunServer(enabled);
+    });
 
-        connect(timelineMaxWidthSpin_,
-                qOverload<int>(&QSpinBox::valueChanged),
-                this,
-                [this](int newValue) { settings_->setTimelineMaxWidth(newValue); });
+    connect(timelineMaxWidthSpin_,
+            qOverload<int>(&QSpinBox::valueChanged),
+            this,
+            [this](int newValue) { settings_->setTimelineMaxWidth(newValue); });
 
-        connect(privacyScreenTimeout_,
-                qOverload<int>(&QSpinBox::valueChanged),
-                this,
-                [this](int newValue) { settings_->setPrivacyScreenTimeout(newValue); });
+    connect(privacyScreenTimeout_,
+            qOverload<int>(&QSpinBox::valueChanged),
+            this,
+            [this](int newValue) { settings_->setPrivacyScreenTimeout(newValue); });
 
-        connect(
-          sessionKeysImportBtn, &QPushButton::clicked, this, &UserSettingsPage::importSessionKeys);
+    connect(
+      sessionKeysImportBtn, &QPushButton::clicked, this, &UserSettingsPage::importSessionKeys);
 
-        connect(
-          sessionKeysExportBtn, &QPushButton::clicked, this, &UserSettingsPage::exportSessionKeys);
+    connect(
+      sessionKeysExportBtn, &QPushButton::clicked, this, &UserSettingsPage::exportSessionKeys);
 
-        connect(crossSigningRequestBtn, &QPushButton::clicked, this, []() {
-                olm::request_cross_signing_keys();
-        });
+    connect(crossSigningRequestBtn, &QPushButton::clicked, this, []() {
+        olm::request_cross_signing_keys();
+    });
 
-        connect(crossSigningDownloadBtn, &QPushButton::clicked, this, []() {
-                olm::download_cross_signing_keys();
-        });
+    connect(crossSigningDownloadBtn, &QPushButton::clicked, this, []() {
+        olm::download_cross_signing_keys();
+    });
 
-        connect(backBtn_, &QPushButton::clicked, this, [this]() {
-                settings_->save();
-                emit moveBack();
-        });
+    connect(backBtn_, &QPushButton::clicked, this, [this]() {
+        settings_->save();
+        emit moveBack();
+    });
 }
 
 void
 UserSettingsPage::showEvent(QShowEvent *)
 {
-        // FIXME macOS doesn't show the full option unless a space is added.
-        utils::restoreCombobox(fontSizeCombo_, QString::number(settings_->fontSize()) + " ");
-        utils::restoreCombobox(scaleFactorCombo_, QString::number(utils::scaleFactor()));
-        utils::restoreCombobox(themeCombo_, settings_->theme());
-        utils::restoreCombobox(ringtoneCombo_, settings_->ringtone());
-
-        trayToggle_->setState(settings_->tray());
-        startInTrayToggle_->setState(settings_->startInTray());
-        groupViewToggle_->setState(settings_->groupView());
-        decryptSidebar_->setState(settings_->decryptSidebar());
-        privacyScreen_->setState(settings_->privacyScreen());
-        onlyShareKeysWithVerifiedUsers_->setState(settings_->onlyShareKeysWithVerifiedUsers());
-        shareKeysWithTrustedUsers_->setState(settings_->shareKeysWithTrustedUsers());
-        useOnlineKeyBackup_->setState(settings_->useOnlineKeyBackup());
-        avatarCircles_->setState(settings_->avatarCircles());
-        typingNotifications_->setState(settings_->typingNotifications());
-        sortByImportance_->setState(settings_->sortByImportance());
-        timelineButtonsToggle_->setState(settings_->buttonsInTimeline());
-        mobileMode_->setState(settings_->mobileMode());
-        readReceipts_->setState(settings_->readReceipts());
-        markdown_->setState(settings_->markdown());
-        desktopNotifications_->setState(settings_->hasDesktopNotifications());
-        alertOnNotification_->setState(settings_->hasAlertOnNotification());
-        messageHoverHighlight_->setState(settings_->messageHoverHighlight());
-        enlargeEmojiOnlyMessages_->setState(settings_->enlargeEmojiOnlyMessages());
-        deviceIdValue_->setText(QString::fromStdString(http::client()->device_id()));
-        timelineMaxWidthSpin_->setValue(settings_->timelineMaxWidth());
-        privacyScreenTimeout_->setValue(settings_->privacyScreenTimeout());
-
-        auto mics = CallDevices::instance().names(false, settings_->microphone().toStdString());
-        microphoneCombo_->clear();
-        for (const auto &m : mics)
-                microphoneCombo_->addItem(QString::fromStdString(m));
-
-        auto cameraResolution = settings_->cameraResolution();
-        auto cameraFrameRate  = settings_->cameraFrameRate();
-
-        auto cameras = CallDevices::instance().names(true, settings_->camera().toStdString());
-        cameraCombo_->clear();
-        for (const auto &c : cameras)
-                cameraCombo_->addItem(QString::fromStdString(c));
-
-        utils::restoreCombobox(cameraResolutionCombo_, cameraResolution);
-        utils::restoreCombobox(cameraFrameRateCombo_, cameraFrameRate);
-
-        useStunServer_->setState(settings_->useStunServer());
-
-        deviceFingerprintValue_->setText(
-          utils::humanReadableFingerprint(olm::client()->identity_keys().ed25519));
+    // FIXME macOS doesn't show the full option unless a space is added.
+    utils::restoreCombobox(fontSizeCombo_, QString::number(settings_->fontSize()) + " ");
+    utils::restoreCombobox(scaleFactorCombo_, QString::number(utils::scaleFactor()));
+    utils::restoreCombobox(themeCombo_, settings_->theme());
+    utils::restoreCombobox(ringtoneCombo_, settings_->ringtone());
+
+    trayToggle_->setState(settings_->tray());
+    startInTrayToggle_->setState(settings_->startInTray());
+    groupViewToggle_->setState(settings_->groupView());
+    decryptSidebar_->setState(settings_->decryptSidebar());
+    privacyScreen_->setState(settings_->privacyScreen());
+    onlyShareKeysWithVerifiedUsers_->setState(settings_->onlyShareKeysWithVerifiedUsers());
+    shareKeysWithTrustedUsers_->setState(settings_->shareKeysWithTrustedUsers());
+    useOnlineKeyBackup_->setState(settings_->useOnlineKeyBackup());
+    avatarCircles_->setState(settings_->avatarCircles());
+    typingNotifications_->setState(settings_->typingNotifications());
+    sortByImportance_->setState(settings_->sortByImportance());
+    timelineButtonsToggle_->setState(settings_->buttonsInTimeline());
+    mobileMode_->setState(settings_->mobileMode());
+    readReceipts_->setState(settings_->readReceipts());
+    markdown_->setState(settings_->markdown());
+    desktopNotifications_->setState(settings_->hasDesktopNotifications());
+    alertOnNotification_->setState(settings_->hasAlertOnNotification());
+    messageHoverHighlight_->setState(settings_->messageHoverHighlight());
+    enlargeEmojiOnlyMessages_->setState(settings_->enlargeEmojiOnlyMessages());
+    deviceIdValue_->setText(QString::fromStdString(http::client()->device_id()));
+    timelineMaxWidthSpin_->setValue(settings_->timelineMaxWidth());
+    privacyScreenTimeout_->setValue(settings_->privacyScreenTimeout());
+
+    auto mics = CallDevices::instance().names(false, settings_->microphone().toStdString());
+    microphoneCombo_->clear();
+    for (const auto &m : mics)
+        microphoneCombo_->addItem(QString::fromStdString(m));
+
+    auto cameraResolution = settings_->cameraResolution();
+    auto cameraFrameRate  = settings_->cameraFrameRate();
+
+    auto cameras = CallDevices::instance().names(true, settings_->camera().toStdString());
+    cameraCombo_->clear();
+    for (const auto &c : cameras)
+        cameraCombo_->addItem(QString::fromStdString(c));
+
+    utils::restoreCombobox(cameraResolutionCombo_, cameraResolution);
+    utils::restoreCombobox(cameraFrameRateCombo_, cameraFrameRate);
+
+    useStunServer_->setState(settings_->useStunServer());
+
+    deviceFingerprintValue_->setText(
+      utils::humanReadableFingerprint(olm::client()->identity_keys().ed25519));
 }
 
 void
 UserSettingsPage::paintEvent(QPaintEvent *)
 {
-        QStyleOption opt;
-        opt.init(this);
-        QPainter p(this);
-        style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
+    QStyleOption opt;
+    opt.init(this);
+    QPainter p(this);
+    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
 }
 
 void
 UserSettingsPage::importSessionKeys()
 {
-        const QString homeFolder = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
-        const QString fileName =
-          QFileDialog::getOpenFileName(this, tr("Open Sessions File"), homeFolder, "");
-
-        QFile file(fileName);
-        if (!file.open(QIODevice::ReadOnly)) {
-                QMessageBox::warning(this, tr("Error"), file.errorString());
-                return;
-        }
-
-        auto bin     = file.peek(file.size());
-        auto payload = std::string(bin.data(), bin.size());
-
-        bool ok;
-        auto password = QInputDialog::getText(this,
-                                              tr("File Password"),
-                                              tr("Enter the passphrase to decrypt the file:"),
-                                              QLineEdit::Password,
-                                              "",
-                                              &ok);
-        if (!ok)
-                return;
-
-        if (password.isEmpty()) {
-                QMessageBox::warning(this, tr("Error"), tr("The password cannot be empty"));
-                return;
-        }
-
-        try {
-                auto sessions =
-                  mtx::crypto::decrypt_exported_sessions(payload, password.toStdString());
-                cache::importSessionKeys(std::move(sessions));
-        } catch (const std::exception &e) {
-                QMessageBox::warning(this, tr("Error"), e.what());
-        }
+    const QString homeFolder = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
+    const QString fileName =
+      QFileDialog::getOpenFileName(this, tr("Open Sessions File"), homeFolder, "");
+
+    QFile file(fileName);
+    if (!file.open(QIODevice::ReadOnly)) {
+        QMessageBox::warning(this, tr("Error"), file.errorString());
+        return;
+    }
+
+    auto bin     = file.peek(file.size());
+    auto payload = std::string(bin.data(), bin.size());
+
+    bool ok;
+    auto password = QInputDialog::getText(this,
+                                          tr("File Password"),
+                                          tr("Enter the passphrase to decrypt the file:"),
+                                          QLineEdit::Password,
+                                          "",
+                                          &ok);
+    if (!ok)
+        return;
+
+    if (password.isEmpty()) {
+        QMessageBox::warning(this, tr("Error"), tr("The password cannot be empty"));
+        return;
+    }
+
+    try {
+        auto sessions = mtx::crypto::decrypt_exported_sessions(payload, password.toStdString());
+        cache::importSessionKeys(std::move(sessions));
+    } catch (const std::exception &e) {
+        QMessageBox::warning(this, tr("Error"), e.what());
+    }
 }
 
 void
 UserSettingsPage::exportSessionKeys()
 {
-        // Open password dialog.
-        bool ok;
-        auto password = QInputDialog::getText(this,
-                                              tr("File Password"),
-                                              tr("Enter passphrase to encrypt your session keys:"),
-                                              QLineEdit::Password,
-                                              "",
-                                              &ok);
-        if (!ok)
-                return;
-
-        if (password.isEmpty()) {
-                QMessageBox::warning(this, tr("Error"), tr("The password cannot be empty"));
-                return;
-        }
-
-        // Open file dialog to save the file.
-        const QString homeFolder = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
-        const QString fileName =
-          QFileDialog::getSaveFileName(this, tr("File to save the exported session keys"), "", "");
-
-        QFile file(fileName);
-        if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
-                QMessageBox::warning(this, tr("Error"), file.errorString());
-                return;
-        }
-
-        // Export sessions & save to file.
-        try {
-                auto encrypted_blob = mtx::crypto::encrypt_exported_sessions(
-                  cache::exportSessionKeys(), password.toStdString());
-
-                QString b64 = QString::fromStdString(mtx::crypto::bin2base64(encrypted_blob));
-
-                QString prefix("-----BEGIN MEGOLM SESSION DATA-----");
-                QString suffix("-----END MEGOLM SESSION DATA-----");
-                QString newline("\n");
-                QTextStream out(&file);
-                out << prefix << newline << b64 << newline << suffix << newline;
-                file.close();
-        } catch (const std::exception &e) {
-                QMessageBox::warning(this, tr("Error"), e.what());
-        }
+    // Open password dialog.
+    bool ok;
+    auto password = QInputDialog::getText(this,
+                                          tr("File Password"),
+                                          tr("Enter passphrase to encrypt your session keys:"),
+                                          QLineEdit::Password,
+                                          "",
+                                          &ok);
+    if (!ok)
+        return;
+
+    if (password.isEmpty()) {
+        QMessageBox::warning(this, tr("Error"), tr("The password cannot be empty"));
+        return;
+    }
+
+    // Open file dialog to save the file.
+    const QString homeFolder = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
+    const QString fileName =
+      QFileDialog::getSaveFileName(this, tr("File to save the exported session keys"), "", "");
+
+    QFile file(fileName);
+    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+        QMessageBox::warning(this, tr("Error"), file.errorString());
+        return;
+    }
+
+    // Export sessions & save to file.
+    try {
+        auto encrypted_blob = mtx::crypto::encrypt_exported_sessions(cache::exportSessionKeys(),
+                                                                     password.toStdString());
+
+        QString b64 = QString::fromStdString(mtx::crypto::bin2base64(encrypted_blob));
+
+        QString prefix("-----BEGIN MEGOLM SESSION DATA-----");
+        QString suffix("-----END MEGOLM SESSION DATA-----");
+        QString newline("\n");
+        QTextStream out(&file);
+        out << prefix << newline << b64 << newline << suffix << newline;
+        file.close();
+    } catch (const std::exception &e) {
+        QMessageBox::warning(this, tr("Error"), e.what());
+    }
 }
 
 void
 UserSettingsPage::updateSecretStatus()
 {
-        QString ok      = "QLabel { color : #00cc66; }";
-        QString notSoOk = "QLabel { color : #ff9933; }";
-
-        auto updateLabel = [&ok, &notSoOk](QLabel *label, const std::string &secretName) {
-                if (cache::secret(secretName)) {
-                        label->setStyleSheet(ok);
-                        label->setText(tr("CACHED"));
-                } else {
-                        if (secretName == mtx::secret_storage::secrets::cross_signing_master)
-                                label->setStyleSheet(ok);
-                        else
-                                label->setStyleSheet(notSoOk);
-                        label->setText(tr("NOT CACHED"));
-                }
-        };
-
-        updateLabel(masterSecretCached, mtx::secret_storage::secrets::cross_signing_master);
-        updateLabel(userSigningSecretCached,
-                    mtx::secret_storage::secrets::cross_signing_user_signing);
-        updateLabel(selfSigningSecretCached,
-                    mtx::secret_storage::secrets::cross_signing_self_signing);
-        updateLabel(backupSecretCached, mtx::secret_storage::secrets::megolm_backup_v1);
+    QString ok      = "QLabel { color : #00cc66; }";
+    QString notSoOk = "QLabel { color : #ff9933; }";
+
+    auto updateLabel = [&ok, &notSoOk](QLabel *label, const std::string &secretName) {
+        if (cache::secret(secretName)) {
+            label->setStyleSheet(ok);
+            label->setText(tr("CACHED"));
+        } else {
+            if (secretName == mtx::secret_storage::secrets::cross_signing_master)
+                label->setStyleSheet(ok);
+            else
+                label->setStyleSheet(notSoOk);
+            label->setText(tr("NOT CACHED"));
+        }
+    };
+
+    updateLabel(masterSecretCached, mtx::secret_storage::secrets::cross_signing_master);
+    updateLabel(userSigningSecretCached, mtx::secret_storage::secrets::cross_signing_user_signing);
+    updateLabel(selfSigningSecretCached, mtx::secret_storage::secrets::cross_signing_self_signing);
+    updateLabel(backupSecretCached, mtx::secret_storage::secrets::megolm_backup_v1);
 }
diff --git a/src/UserSettingsPage.h b/src/UserSettingsPage.h
index bcd9439b..31e28db2 100644
--- a/src/UserSettingsPage.h
+++ b/src/UserSettingsPage.h
@@ -30,402 +30,395 @@ constexpr int LayoutBottomMargin = LayoutTopMargin;
 
 class UserSettings : public QObject
 {
-        Q_OBJECT
-
-        Q_PROPERTY(QString theme READ theme WRITE setTheme NOTIFY themeChanged)
-        Q_PROPERTY(bool messageHoverHighlight READ messageHoverHighlight WRITE
-                     setMessageHoverHighlight NOTIFY messageHoverHighlightChanged)
-        Q_PROPERTY(bool enlargeEmojiOnlyMessages READ enlargeEmojiOnlyMessages WRITE
-                     setEnlargeEmojiOnlyMessages NOTIFY enlargeEmojiOnlyMessagesChanged)
-        Q_PROPERTY(bool tray READ tray WRITE setTray NOTIFY trayChanged)
-        Q_PROPERTY(bool startInTray READ startInTray WRITE setStartInTray NOTIFY startInTrayChanged)
-        Q_PROPERTY(bool groupView READ groupView WRITE setGroupView NOTIFY groupViewStateChanged)
-        Q_PROPERTY(bool markdown READ markdown WRITE setMarkdown NOTIFY markdownChanged)
-        Q_PROPERTY(bool animateImagesOnHover READ animateImagesOnHover WRITE setAnimateImagesOnHover
-                     NOTIFY animateImagesOnHoverChanged)
-        Q_PROPERTY(bool typingNotifications READ typingNotifications WRITE setTypingNotifications
-                     NOTIFY typingNotificationsChanged)
-        Q_PROPERTY(bool sortByImportance READ sortByImportance WRITE setSortByImportance NOTIFY
-                     roomSortingChanged)
-        Q_PROPERTY(bool buttonsInTimeline READ buttonsInTimeline WRITE setButtonsInTimeline NOTIFY
-                     buttonInTimelineChanged)
-        Q_PROPERTY(
-          bool readReceipts READ readReceipts WRITE setReadReceipts NOTIFY readReceiptsChanged)
-        Q_PROPERTY(bool desktopNotifications READ hasDesktopNotifications WRITE
-                     setDesktopNotifications NOTIFY desktopNotificationsChanged)
-        Q_PROPERTY(bool alertOnNotification READ hasAlertOnNotification WRITE setAlertOnNotification
-                     NOTIFY alertOnNotificationChanged)
-        Q_PROPERTY(
-          bool avatarCircles READ avatarCircles WRITE setAvatarCircles NOTIFY avatarCirclesChanged)
-        Q_PROPERTY(bool decryptSidebar READ decryptSidebar WRITE setDecryptSidebar NOTIFY
-                     decryptSidebarChanged)
-        Q_PROPERTY(
-          bool privacyScreen READ privacyScreen WRITE setPrivacyScreen NOTIFY privacyScreenChanged)
-        Q_PROPERTY(int privacyScreenTimeout READ privacyScreenTimeout WRITE setPrivacyScreenTimeout
-                     NOTIFY privacyScreenTimeoutChanged)
-        Q_PROPERTY(int timelineMaxWidth READ timelineMaxWidth WRITE setTimelineMaxWidth NOTIFY
-                     timelineMaxWidthChanged)
-        Q_PROPERTY(
-          int roomListWidth READ roomListWidth WRITE setRoomListWidth NOTIFY roomListWidthChanged)
-        Q_PROPERTY(int communityListWidth READ communityListWidth WRITE setCommunityListWidth NOTIFY
-                     communityListWidthChanged)
-        Q_PROPERTY(bool mobileMode READ mobileMode WRITE setMobileMode NOTIFY mobileModeChanged)
-        Q_PROPERTY(double fontSize READ fontSize WRITE setFontSize NOTIFY fontSizeChanged)
-        Q_PROPERTY(QString font READ font WRITE setFontFamily NOTIFY fontChanged)
-        Q_PROPERTY(
-          QString emojiFont READ emojiFont WRITE setEmojiFontFamily NOTIFY emojiFontChanged)
-        Q_PROPERTY(Presence presence READ presence WRITE setPresence NOTIFY presenceChanged)
-        Q_PROPERTY(QString ringtone READ ringtone WRITE setRingtone NOTIFY ringtoneChanged)
-        Q_PROPERTY(QString microphone READ microphone WRITE setMicrophone NOTIFY microphoneChanged)
-        Q_PROPERTY(QString camera READ camera WRITE setCamera NOTIFY cameraChanged)
-        Q_PROPERTY(QString cameraResolution READ cameraResolution WRITE setCameraResolution NOTIFY
-                     cameraResolutionChanged)
-        Q_PROPERTY(QString cameraFrameRate READ cameraFrameRate WRITE setCameraFrameRate NOTIFY
-                     cameraFrameRateChanged)
-        Q_PROPERTY(int screenShareFrameRate READ screenShareFrameRate WRITE setScreenShareFrameRate
-                     NOTIFY screenShareFrameRateChanged)
-        Q_PROPERTY(bool screenSharePiP READ screenSharePiP WRITE setScreenSharePiP NOTIFY
-                     screenSharePiPChanged)
-        Q_PROPERTY(bool screenShareRemoteVideo READ screenShareRemoteVideo WRITE
-                     setScreenShareRemoteVideo NOTIFY screenShareRemoteVideoChanged)
-        Q_PROPERTY(bool screenShareHideCursor READ screenShareHideCursor WRITE
-                     setScreenShareHideCursor NOTIFY screenShareHideCursorChanged)
-        Q_PROPERTY(
-          bool useStunServer READ useStunServer WRITE setUseStunServer NOTIFY useStunServerChanged)
-        Q_PROPERTY(bool onlyShareKeysWithVerifiedUsers READ onlyShareKeysWithVerifiedUsers WRITE
-                     setOnlyShareKeysWithVerifiedUsers NOTIFY onlyShareKeysWithVerifiedUsersChanged)
-        Q_PROPERTY(bool shareKeysWithTrustedUsers READ shareKeysWithTrustedUsers WRITE
-                     setShareKeysWithTrustedUsers NOTIFY shareKeysWithTrustedUsersChanged)
-        Q_PROPERTY(bool useOnlineKeyBackup READ useOnlineKeyBackup WRITE setUseOnlineKeyBackup
-                     NOTIFY useOnlineKeyBackupChanged)
-        Q_PROPERTY(QString profile READ profile WRITE setProfile NOTIFY profileChanged)
-        Q_PROPERTY(QString userId READ userId WRITE setUserId NOTIFY userIdChanged)
-        Q_PROPERTY(
-          QString accessToken READ accessToken WRITE setAccessToken NOTIFY accessTokenChanged)
-        Q_PROPERTY(QString deviceId READ deviceId WRITE setDeviceId NOTIFY deviceIdChanged)
-        Q_PROPERTY(QString homeserver READ homeserver WRITE setHomeserver NOTIFY homeserverChanged)
-        Q_PROPERTY(bool disableCertificateValidation READ disableCertificateValidation WRITE
-                     setDisableCertificateValidation NOTIFY disableCertificateValidationChanged)
-        Q_PROPERTY(
-          bool useIdenticon READ useIdenticon WRITE setUseIdenticon NOTIFY useIdenticonChanged)
-
-        UserSettings();
+    Q_OBJECT
+
+    Q_PROPERTY(QString theme READ theme WRITE setTheme NOTIFY themeChanged)
+    Q_PROPERTY(bool messageHoverHighlight READ messageHoverHighlight WRITE setMessageHoverHighlight
+                 NOTIFY messageHoverHighlightChanged)
+    Q_PROPERTY(bool enlargeEmojiOnlyMessages READ enlargeEmojiOnlyMessages WRITE
+                 setEnlargeEmojiOnlyMessages NOTIFY enlargeEmojiOnlyMessagesChanged)
+    Q_PROPERTY(bool tray READ tray WRITE setTray NOTIFY trayChanged)
+    Q_PROPERTY(bool startInTray READ startInTray WRITE setStartInTray NOTIFY startInTrayChanged)
+    Q_PROPERTY(bool groupView READ groupView WRITE setGroupView NOTIFY groupViewStateChanged)
+    Q_PROPERTY(bool markdown READ markdown WRITE setMarkdown NOTIFY markdownChanged)
+    Q_PROPERTY(bool animateImagesOnHover READ animateImagesOnHover WRITE setAnimateImagesOnHover
+                 NOTIFY animateImagesOnHoverChanged)
+    Q_PROPERTY(bool typingNotifications READ typingNotifications WRITE setTypingNotifications NOTIFY
+                 typingNotificationsChanged)
+    Q_PROPERTY(bool sortByImportance READ sortByImportance WRITE setSortByImportance NOTIFY
+                 roomSortingChanged)
+    Q_PROPERTY(bool buttonsInTimeline READ buttonsInTimeline WRITE setButtonsInTimeline NOTIFY
+                 buttonInTimelineChanged)
+    Q_PROPERTY(bool readReceipts READ readReceipts WRITE setReadReceipts NOTIFY readReceiptsChanged)
+    Q_PROPERTY(bool desktopNotifications READ hasDesktopNotifications WRITE setDesktopNotifications
+                 NOTIFY desktopNotificationsChanged)
+    Q_PROPERTY(bool alertOnNotification READ hasAlertOnNotification WRITE setAlertOnNotification
+                 NOTIFY alertOnNotificationChanged)
+    Q_PROPERTY(
+      bool avatarCircles READ avatarCircles WRITE setAvatarCircles NOTIFY avatarCirclesChanged)
+    Q_PROPERTY(
+      bool decryptSidebar READ decryptSidebar WRITE setDecryptSidebar NOTIFY decryptSidebarChanged)
+    Q_PROPERTY(
+      bool privacyScreen READ privacyScreen WRITE setPrivacyScreen NOTIFY privacyScreenChanged)
+    Q_PROPERTY(int privacyScreenTimeout READ privacyScreenTimeout WRITE setPrivacyScreenTimeout
+                 NOTIFY privacyScreenTimeoutChanged)
+    Q_PROPERTY(int timelineMaxWidth READ timelineMaxWidth WRITE setTimelineMaxWidth NOTIFY
+                 timelineMaxWidthChanged)
+    Q_PROPERTY(
+      int roomListWidth READ roomListWidth WRITE setRoomListWidth NOTIFY roomListWidthChanged)
+    Q_PROPERTY(int communityListWidth READ communityListWidth WRITE setCommunityListWidth NOTIFY
+                 communityListWidthChanged)
+    Q_PROPERTY(bool mobileMode READ mobileMode WRITE setMobileMode NOTIFY mobileModeChanged)
+    Q_PROPERTY(double fontSize READ fontSize WRITE setFontSize NOTIFY fontSizeChanged)
+    Q_PROPERTY(QString font READ font WRITE setFontFamily NOTIFY fontChanged)
+    Q_PROPERTY(QString emojiFont READ emojiFont WRITE setEmojiFontFamily NOTIFY emojiFontChanged)
+    Q_PROPERTY(Presence presence READ presence WRITE setPresence NOTIFY presenceChanged)
+    Q_PROPERTY(QString ringtone READ ringtone WRITE setRingtone NOTIFY ringtoneChanged)
+    Q_PROPERTY(QString microphone READ microphone WRITE setMicrophone NOTIFY microphoneChanged)
+    Q_PROPERTY(QString camera READ camera WRITE setCamera NOTIFY cameraChanged)
+    Q_PROPERTY(QString cameraResolution READ cameraResolution WRITE setCameraResolution NOTIFY
+                 cameraResolutionChanged)
+    Q_PROPERTY(QString cameraFrameRate READ cameraFrameRate WRITE setCameraFrameRate NOTIFY
+                 cameraFrameRateChanged)
+    Q_PROPERTY(int screenShareFrameRate READ screenShareFrameRate WRITE setScreenShareFrameRate
+                 NOTIFY screenShareFrameRateChanged)
+    Q_PROPERTY(
+      bool screenSharePiP READ screenSharePiP WRITE setScreenSharePiP NOTIFY screenSharePiPChanged)
+    Q_PROPERTY(bool screenShareRemoteVideo READ screenShareRemoteVideo WRITE
+                 setScreenShareRemoteVideo NOTIFY screenShareRemoteVideoChanged)
+    Q_PROPERTY(bool screenShareHideCursor READ screenShareHideCursor WRITE setScreenShareHideCursor
+                 NOTIFY screenShareHideCursorChanged)
+    Q_PROPERTY(
+      bool useStunServer READ useStunServer WRITE setUseStunServer NOTIFY useStunServerChanged)
+    Q_PROPERTY(bool onlyShareKeysWithVerifiedUsers READ onlyShareKeysWithVerifiedUsers WRITE
+                 setOnlyShareKeysWithVerifiedUsers NOTIFY onlyShareKeysWithVerifiedUsersChanged)
+    Q_PROPERTY(bool shareKeysWithTrustedUsers READ shareKeysWithTrustedUsers WRITE
+                 setShareKeysWithTrustedUsers NOTIFY shareKeysWithTrustedUsersChanged)
+    Q_PROPERTY(bool useOnlineKeyBackup READ useOnlineKeyBackup WRITE setUseOnlineKeyBackup NOTIFY
+                 useOnlineKeyBackupChanged)
+    Q_PROPERTY(QString profile READ profile WRITE setProfile NOTIFY profileChanged)
+    Q_PROPERTY(QString userId READ userId WRITE setUserId NOTIFY userIdChanged)
+    Q_PROPERTY(QString accessToken READ accessToken WRITE setAccessToken NOTIFY accessTokenChanged)
+    Q_PROPERTY(QString deviceId READ deviceId WRITE setDeviceId NOTIFY deviceIdChanged)
+    Q_PROPERTY(QString homeserver READ homeserver WRITE setHomeserver NOTIFY homeserverChanged)
+    Q_PROPERTY(bool disableCertificateValidation READ disableCertificateValidation WRITE
+                 setDisableCertificateValidation NOTIFY disableCertificateValidationChanged)
+    Q_PROPERTY(bool useIdenticon READ useIdenticon WRITE setUseIdenticon NOTIFY useIdenticonChanged)
+
+    UserSettings();
 
 public:
-        static QSharedPointer<UserSettings> instance();
-        static void initialize(std::optional<QString> profile);
-
-        QSettings *qsettings() { return &settings; }
-
-        enum class Presence
-        {
-                AutomaticPresence,
-                Online,
-                Unavailable,
-                Offline,
-        };
-        Q_ENUM(Presence)
-
-        void save();
-        void load(std::optional<QString> profile);
-        void applyTheme();
-        void setTheme(QString theme);
-        void setMessageHoverHighlight(bool state);
-        void setEnlargeEmojiOnlyMessages(bool state);
-        void setTray(bool state);
-        void setStartInTray(bool state);
-        void setMobileMode(bool mode);
-        void setFontSize(double size);
-        void setFontFamily(QString family);
-        void setEmojiFontFamily(QString family);
-        void setGroupView(bool state);
-        void setMarkdown(bool state);
-        void setAnimateImagesOnHover(bool state);
-        void setReadReceipts(bool state);
-        void setTypingNotifications(bool state);
-        void setSortByImportance(bool state);
-        void setButtonsInTimeline(bool state);
-        void setTimelineMaxWidth(int state);
-        void setCommunityListWidth(int state);
-        void setRoomListWidth(int state);
-        void setDesktopNotifications(bool state);
-        void setAlertOnNotification(bool state);
-        void setAvatarCircles(bool state);
-        void setDecryptSidebar(bool state);
-        void setPrivacyScreen(bool state);
-        void setPrivacyScreenTimeout(int state);
-        void setPresence(Presence state);
-        void setRingtone(QString ringtone);
-        void setMicrophone(QString microphone);
-        void setCamera(QString camera);
-        void setCameraResolution(QString resolution);
-        void setCameraFrameRate(QString frameRate);
-        void setScreenShareFrameRate(int frameRate);
-        void setScreenSharePiP(bool state);
-        void setScreenShareRemoteVideo(bool state);
-        void setScreenShareHideCursor(bool state);
-        void setUseStunServer(bool state);
-        void setOnlyShareKeysWithVerifiedUsers(bool state);
-        void setShareKeysWithTrustedUsers(bool state);
-        void setUseOnlineKeyBackup(bool state);
-        void setProfile(QString profile);
-        void setUserId(QString userId);
-        void setAccessToken(QString accessToken);
-        void setDeviceId(QString deviceId);
-        void setHomeserver(QString homeserver);
-        void setDisableCertificateValidation(bool disabled);
-        void setHiddenTags(QStringList hiddenTags);
-        void setUseIdenticon(bool state);
-
-        QString theme() const { return !theme_.isEmpty() ? theme_ : defaultTheme_; }
-        bool messageHoverHighlight() const { return messageHoverHighlight_; }
-        bool enlargeEmojiOnlyMessages() const { return enlargeEmojiOnlyMessages_; }
-        bool tray() const { return tray_; }
-        bool startInTray() const { return startInTray_; }
-        bool groupView() const { return groupView_; }
-        bool avatarCircles() const { return avatarCircles_; }
-        bool decryptSidebar() const { return decryptSidebar_; }
-        bool privacyScreen() const { return privacyScreen_; }
-        int privacyScreenTimeout() const { return privacyScreenTimeout_; }
-        bool markdown() const { return markdown_; }
-        bool animateImagesOnHover() const { return animateImagesOnHover_; }
-        bool typingNotifications() const { return typingNotifications_; }
-        bool sortByImportance() const { return sortByImportance_; }
-        bool buttonsInTimeline() const { return buttonsInTimeline_; }
-        bool mobileMode() const { return mobileMode_; }
-        bool readReceipts() const { return readReceipts_; }
-        bool hasDesktopNotifications() const { return hasDesktopNotifications_; }
-        bool hasAlertOnNotification() const { return hasAlertOnNotification_; }
-        bool hasNotifications() const
-        {
-                return hasDesktopNotifications() || hasAlertOnNotification();
+    static QSharedPointer<UserSettings> instance();
+    static void initialize(std::optional<QString> profile);
+
+    QSettings *qsettings() { return &settings; }
+
+    enum class Presence
+    {
+        AutomaticPresence,
+        Online,
+        Unavailable,
+        Offline,
+    };
+    Q_ENUM(Presence)
+
+    void save();
+    void load(std::optional<QString> profile);
+    void applyTheme();
+    void setTheme(QString theme);
+    void setMessageHoverHighlight(bool state);
+    void setEnlargeEmojiOnlyMessages(bool state);
+    void setTray(bool state);
+    void setStartInTray(bool state);
+    void setMobileMode(bool mode);
+    void setFontSize(double size);
+    void setFontFamily(QString family);
+    void setEmojiFontFamily(QString family);
+    void setGroupView(bool state);
+    void setMarkdown(bool state);
+    void setAnimateImagesOnHover(bool state);
+    void setReadReceipts(bool state);
+    void setTypingNotifications(bool state);
+    void setSortByImportance(bool state);
+    void setButtonsInTimeline(bool state);
+    void setTimelineMaxWidth(int state);
+    void setCommunityListWidth(int state);
+    void setRoomListWidth(int state);
+    void setDesktopNotifications(bool state);
+    void setAlertOnNotification(bool state);
+    void setAvatarCircles(bool state);
+    void setDecryptSidebar(bool state);
+    void setPrivacyScreen(bool state);
+    void setPrivacyScreenTimeout(int state);
+    void setPresence(Presence state);
+    void setRingtone(QString ringtone);
+    void setMicrophone(QString microphone);
+    void setCamera(QString camera);
+    void setCameraResolution(QString resolution);
+    void setCameraFrameRate(QString frameRate);
+    void setScreenShareFrameRate(int frameRate);
+    void setScreenSharePiP(bool state);
+    void setScreenShareRemoteVideo(bool state);
+    void setScreenShareHideCursor(bool state);
+    void setUseStunServer(bool state);
+    void setOnlyShareKeysWithVerifiedUsers(bool state);
+    void setShareKeysWithTrustedUsers(bool state);
+    void setUseOnlineKeyBackup(bool state);
+    void setProfile(QString profile);
+    void setUserId(QString userId);
+    void setAccessToken(QString accessToken);
+    void setDeviceId(QString deviceId);
+    void setHomeserver(QString homeserver);
+    void setDisableCertificateValidation(bool disabled);
+    void setHiddenTags(QStringList hiddenTags);
+    void setUseIdenticon(bool state);
+
+    QString theme() const { return !theme_.isEmpty() ? theme_ : defaultTheme_; }
+    bool messageHoverHighlight() const { return messageHoverHighlight_; }
+    bool enlargeEmojiOnlyMessages() const { return enlargeEmojiOnlyMessages_; }
+    bool tray() const { return tray_; }
+    bool startInTray() const { return startInTray_; }
+    bool groupView() const { return groupView_; }
+    bool avatarCircles() const { return avatarCircles_; }
+    bool decryptSidebar() const { return decryptSidebar_; }
+    bool privacyScreen() const { return privacyScreen_; }
+    int privacyScreenTimeout() const { return privacyScreenTimeout_; }
+    bool markdown() const { return markdown_; }
+    bool animateImagesOnHover() const { return animateImagesOnHover_; }
+    bool typingNotifications() const { return typingNotifications_; }
+    bool sortByImportance() const { return sortByImportance_; }
+    bool buttonsInTimeline() const { return buttonsInTimeline_; }
+    bool mobileMode() const { return mobileMode_; }
+    bool readReceipts() const { return readReceipts_; }
+    bool hasDesktopNotifications() const { return hasDesktopNotifications_; }
+    bool hasAlertOnNotification() const { return hasAlertOnNotification_; }
+    bool hasNotifications() const { return hasDesktopNotifications() || hasAlertOnNotification(); }
+    int timelineMaxWidth() const { return timelineMaxWidth_; }
+    int communityListWidth() const { return communityListWidth_; }
+    int roomListWidth() const { return roomListWidth_; }
+    double fontSize() const { return baseFontSize_; }
+    QString font() const { return font_; }
+    QString emojiFont() const
+    {
+        if (emojiFont_ == "Default") {
+            return tr("Default");
         }
-        int timelineMaxWidth() const { return timelineMaxWidth_; }
-        int communityListWidth() const { return communityListWidth_; }
-        int roomListWidth() const { return roomListWidth_; }
-        double fontSize() const { return baseFontSize_; }
-        QString font() const { return font_; }
-        QString emojiFont() const
-        {
-                if (emojiFont_ == "Default") {
-                        return tr("Default");
-                }
-
-                return emojiFont_;
-        }
-        Presence presence() const { return presence_; }
-        QString ringtone() const { return ringtone_; }
-        QString microphone() const { return microphone_; }
-        QString camera() const { return camera_; }
-        QString cameraResolution() const { return cameraResolution_; }
-        QString cameraFrameRate() const { return cameraFrameRate_; }
-        int screenShareFrameRate() const { return screenShareFrameRate_; }
-        bool screenSharePiP() const { return screenSharePiP_; }
-        bool screenShareRemoteVideo() const { return screenShareRemoteVideo_; }
-        bool screenShareHideCursor() const { return screenShareHideCursor_; }
-        bool useStunServer() const { return useStunServer_; }
-        bool shareKeysWithTrustedUsers() const { return shareKeysWithTrustedUsers_; }
-        bool onlyShareKeysWithVerifiedUsers() const { return onlyShareKeysWithVerifiedUsers_; }
-        bool useOnlineKeyBackup() const { return useOnlineKeyBackup_; }
-        QString profile() const { return profile_; }
-        QString userId() const { return userId_; }
-        QString accessToken() const { return accessToken_; }
-        QString deviceId() const { return deviceId_; }
-        QString homeserver() const { return homeserver_; }
-        bool disableCertificateValidation() const { return disableCertificateValidation_; }
-        QStringList hiddenTags() const { return hiddenTags_; }
-        bool useIdenticon() const { return useIdenticon_ && JdenticonProvider::isAvailable(); }
+
+        return emojiFont_;
+    }
+    Presence presence() const { return presence_; }
+    QString ringtone() const { return ringtone_; }
+    QString microphone() const { return microphone_; }
+    QString camera() const { return camera_; }
+    QString cameraResolution() const { return cameraResolution_; }
+    QString cameraFrameRate() const { return cameraFrameRate_; }
+    int screenShareFrameRate() const { return screenShareFrameRate_; }
+    bool screenSharePiP() const { return screenSharePiP_; }
+    bool screenShareRemoteVideo() const { return screenShareRemoteVideo_; }
+    bool screenShareHideCursor() const { return screenShareHideCursor_; }
+    bool useStunServer() const { return useStunServer_; }
+    bool shareKeysWithTrustedUsers() const { return shareKeysWithTrustedUsers_; }
+    bool onlyShareKeysWithVerifiedUsers() const { return onlyShareKeysWithVerifiedUsers_; }
+    bool useOnlineKeyBackup() const { return useOnlineKeyBackup_; }
+    QString profile() const { return profile_; }
+    QString userId() const { return userId_; }
+    QString accessToken() const { return accessToken_; }
+    QString deviceId() const { return deviceId_; }
+    QString homeserver() const { return homeserver_; }
+    bool disableCertificateValidation() const { return disableCertificateValidation_; }
+    QStringList hiddenTags() const { return hiddenTags_; }
+    bool useIdenticon() const { return useIdenticon_ && JdenticonProvider::isAvailable(); }
 
 signals:
-        void groupViewStateChanged(bool state);
-        void roomSortingChanged(bool state);
-        void themeChanged(QString state);
-        void messageHoverHighlightChanged(bool state);
-        void enlargeEmojiOnlyMessagesChanged(bool state);
-        void trayChanged(bool state);
-        void startInTrayChanged(bool state);
-        void markdownChanged(bool state);
-        void animateImagesOnHoverChanged(bool state);
-        void typingNotificationsChanged(bool state);
-        void buttonInTimelineChanged(bool state);
-        void readReceiptsChanged(bool state);
-        void desktopNotificationsChanged(bool state);
-        void alertOnNotificationChanged(bool state);
-        void avatarCirclesChanged(bool state);
-        void decryptSidebarChanged(bool state);
-        void privacyScreenChanged(bool state);
-        void privacyScreenTimeoutChanged(int state);
-        void timelineMaxWidthChanged(int state);
-        void roomListWidthChanged(int state);
-        void communityListWidthChanged(int state);
-        void mobileModeChanged(bool mode);
-        void fontSizeChanged(double state);
-        void fontChanged(QString state);
-        void emojiFontChanged(QString state);
-        void presenceChanged(Presence state);
-        void ringtoneChanged(QString ringtone);
-        void microphoneChanged(QString microphone);
-        void cameraChanged(QString camera);
-        void cameraResolutionChanged(QString resolution);
-        void cameraFrameRateChanged(QString frameRate);
-        void screenShareFrameRateChanged(int frameRate);
-        void screenSharePiPChanged(bool state);
-        void screenShareRemoteVideoChanged(bool state);
-        void screenShareHideCursorChanged(bool state);
-        void useStunServerChanged(bool state);
-        void onlyShareKeysWithVerifiedUsersChanged(bool state);
-        void shareKeysWithTrustedUsersChanged(bool state);
-        void useOnlineKeyBackupChanged(bool state);
-        void profileChanged(QString profile);
-        void userIdChanged(QString userId);
-        void accessTokenChanged(QString accessToken);
-        void deviceIdChanged(QString deviceId);
-        void homeserverChanged(QString homeserver);
-        void disableCertificateValidationChanged(bool disabled);
-        void useIdenticonChanged(bool state);
+    void groupViewStateChanged(bool state);
+    void roomSortingChanged(bool state);
+    void themeChanged(QString state);
+    void messageHoverHighlightChanged(bool state);
+    void enlargeEmojiOnlyMessagesChanged(bool state);
+    void trayChanged(bool state);
+    void startInTrayChanged(bool state);
+    void markdownChanged(bool state);
+    void animateImagesOnHoverChanged(bool state);
+    void typingNotificationsChanged(bool state);
+    void buttonInTimelineChanged(bool state);
+    void readReceiptsChanged(bool state);
+    void desktopNotificationsChanged(bool state);
+    void alertOnNotificationChanged(bool state);
+    void avatarCirclesChanged(bool state);
+    void decryptSidebarChanged(bool state);
+    void privacyScreenChanged(bool state);
+    void privacyScreenTimeoutChanged(int state);
+    void timelineMaxWidthChanged(int state);
+    void roomListWidthChanged(int state);
+    void communityListWidthChanged(int state);
+    void mobileModeChanged(bool mode);
+    void fontSizeChanged(double state);
+    void fontChanged(QString state);
+    void emojiFontChanged(QString state);
+    void presenceChanged(Presence state);
+    void ringtoneChanged(QString ringtone);
+    void microphoneChanged(QString microphone);
+    void cameraChanged(QString camera);
+    void cameraResolutionChanged(QString resolution);
+    void cameraFrameRateChanged(QString frameRate);
+    void screenShareFrameRateChanged(int frameRate);
+    void screenSharePiPChanged(bool state);
+    void screenShareRemoteVideoChanged(bool state);
+    void screenShareHideCursorChanged(bool state);
+    void useStunServerChanged(bool state);
+    void onlyShareKeysWithVerifiedUsersChanged(bool state);
+    void shareKeysWithTrustedUsersChanged(bool state);
+    void useOnlineKeyBackupChanged(bool state);
+    void profileChanged(QString profile);
+    void userIdChanged(QString userId);
+    void accessTokenChanged(QString accessToken);
+    void deviceIdChanged(QString deviceId);
+    void homeserverChanged(QString homeserver);
+    void disableCertificateValidationChanged(bool disabled);
+    void useIdenticonChanged(bool state);
 
 private:
-        // Default to system theme if QT_QPA_PLATFORMTHEME var is set.
-        QString defaultTheme_ =
-          QProcessEnvironment::systemEnvironment().value("QT_QPA_PLATFORMTHEME", "").isEmpty()
-            ? "light"
-            : "system";
-        QString theme_;
-        bool messageHoverHighlight_;
-        bool enlargeEmojiOnlyMessages_;
-        bool tray_;
-        bool startInTray_;
-        bool groupView_;
-        bool markdown_;
-        bool animateImagesOnHover_;
-        bool typingNotifications_;
-        bool sortByImportance_;
-        bool buttonsInTimeline_;
-        bool readReceipts_;
-        bool hasDesktopNotifications_;
-        bool hasAlertOnNotification_;
-        bool avatarCircles_;
-        bool decryptSidebar_;
-        bool privacyScreen_;
-        int privacyScreenTimeout_;
-        bool shareKeysWithTrustedUsers_;
-        bool onlyShareKeysWithVerifiedUsers_;
-        bool useOnlineKeyBackup_;
-        bool mobileMode_;
-        int timelineMaxWidth_;
-        int roomListWidth_;
-        int communityListWidth_;
-        double baseFontSize_;
-        QString font_;
-        QString emojiFont_;
-        Presence presence_;
-        QString ringtone_;
-        QString microphone_;
-        QString camera_;
-        QString cameraResolution_;
-        QString cameraFrameRate_;
-        int screenShareFrameRate_;
-        bool screenSharePiP_;
-        bool screenShareRemoteVideo_;
-        bool screenShareHideCursor_;
-        bool useStunServer_;
-        bool disableCertificateValidation_ = false;
-        QString profile_;
-        QString userId_;
-        QString accessToken_;
-        QString deviceId_;
-        QString homeserver_;
-        QStringList hiddenTags_;
-        bool useIdenticon_;
-
-        QSettings settings;
-
-        static QSharedPointer<UserSettings> instance_;
+    // Default to system theme if QT_QPA_PLATFORMTHEME var is set.
+    QString defaultTheme_ =
+      QProcessEnvironment::systemEnvironment().value("QT_QPA_PLATFORMTHEME", "").isEmpty()
+        ? "light"
+        : "system";
+    QString theme_;
+    bool messageHoverHighlight_;
+    bool enlargeEmojiOnlyMessages_;
+    bool tray_;
+    bool startInTray_;
+    bool groupView_;
+    bool markdown_;
+    bool animateImagesOnHover_;
+    bool typingNotifications_;
+    bool sortByImportance_;
+    bool buttonsInTimeline_;
+    bool readReceipts_;
+    bool hasDesktopNotifications_;
+    bool hasAlertOnNotification_;
+    bool avatarCircles_;
+    bool decryptSidebar_;
+    bool privacyScreen_;
+    int privacyScreenTimeout_;
+    bool shareKeysWithTrustedUsers_;
+    bool onlyShareKeysWithVerifiedUsers_;
+    bool useOnlineKeyBackup_;
+    bool mobileMode_;
+    int timelineMaxWidth_;
+    int roomListWidth_;
+    int communityListWidth_;
+    double baseFontSize_;
+    QString font_;
+    QString emojiFont_;
+    Presence presence_;
+    QString ringtone_;
+    QString microphone_;
+    QString camera_;
+    QString cameraResolution_;
+    QString cameraFrameRate_;
+    int screenShareFrameRate_;
+    bool screenSharePiP_;
+    bool screenShareRemoteVideo_;
+    bool screenShareHideCursor_;
+    bool useStunServer_;
+    bool disableCertificateValidation_ = false;
+    QString profile_;
+    QString userId_;
+    QString accessToken_;
+    QString deviceId_;
+    QString homeserver_;
+    QStringList hiddenTags_;
+    bool useIdenticon_;
+
+    QSettings settings;
+
+    static QSharedPointer<UserSettings> instance_;
 };
 
 class HorizontalLine : public QFrame
 {
-        Q_OBJECT
+    Q_OBJECT
 
 public:
-        HorizontalLine(QWidget *parent = nullptr);
+    HorizontalLine(QWidget *parent = nullptr);
 };
 
 class UserSettingsPage : public QWidget
 {
-        Q_OBJECT
+    Q_OBJECT
 
 public:
-        UserSettingsPage(QSharedPointer<UserSettings> settings, QWidget *parent = nullptr);
+    UserSettingsPage(QSharedPointer<UserSettings> settings, QWidget *parent = nullptr);
 
 protected:
-        void showEvent(QShowEvent *event) override;
-        void paintEvent(QPaintEvent *event) override;
+    void showEvent(QShowEvent *event) override;
+    void paintEvent(QPaintEvent *event) override;
 
 signals:
-        void moveBack();
-        void trayOptionChanged(bool value);
-        void themeChanged();
-        void decryptSidebarChanged();
+    void moveBack();
+    void trayOptionChanged(bool value);
+    void themeChanged();
+    void decryptSidebarChanged();
 
 public slots:
-        void updateSecretStatus();
+    void updateSecretStatus();
 
 private slots:
-        void importSessionKeys();
-        void exportSessionKeys();
+    void importSessionKeys();
+    void exportSessionKeys();
 
 private:
-        // Layouts
-        QVBoxLayout *topLayout_;
-        QHBoxLayout *topBarLayout_;
-        QFormLayout *formLayout_;
-
-        // Shared settings object.
-        QSharedPointer<UserSettings> settings_;
-
-        Toggle *trayToggle_;
-        Toggle *startInTrayToggle_;
-        Toggle *groupViewToggle_;
-        Toggle *timelineButtonsToggle_;
-        Toggle *typingNotifications_;
-        Toggle *messageHoverHighlight_;
-        Toggle *enlargeEmojiOnlyMessages_;
-        Toggle *sortByImportance_;
-        Toggle *readReceipts_;
-        Toggle *markdown_;
-        Toggle *animateImagesOnHover_;
-        Toggle *desktopNotifications_;
-        Toggle *alertOnNotification_;
-        Toggle *avatarCircles_;
-        Toggle *useIdenticon_;
-        Toggle *useStunServer_;
-        Toggle *decryptSidebar_;
-        Toggle *privacyScreen_;
-        QSpinBox *privacyScreenTimeout_;
-        Toggle *shareKeysWithTrustedUsers_;
-        Toggle *onlyShareKeysWithVerifiedUsers_;
-        Toggle *useOnlineKeyBackup_;
-        Toggle *mobileMode_;
-        QLabel *deviceFingerprintValue_;
-        QLabel *deviceIdValue_;
-        QLabel *backupSecretCached;
-        QLabel *masterSecretCached;
-        QLabel *selfSigningSecretCached;
-        QLabel *userSigningSecretCached;
-
-        QComboBox *themeCombo_;
-        QComboBox *scaleFactorCombo_;
-        QComboBox *fontSizeCombo_;
-        QFontComboBox *fontSelectionCombo_;
-        QComboBox *emojiFontSelectionCombo_;
-        QComboBox *ringtoneCombo_;
-        QComboBox *microphoneCombo_;
-        QComboBox *cameraCombo_;
-        QComboBox *cameraResolutionCombo_;
-        QComboBox *cameraFrameRateCombo_;
-
-        QSpinBox *timelineMaxWidthSpin_;
-
-        int sideMargin_ = 0;
+    // Layouts
+    QVBoxLayout *topLayout_;
+    QHBoxLayout *topBarLayout_;
+    QFormLayout *formLayout_;
+
+    // Shared settings object.
+    QSharedPointer<UserSettings> settings_;
+
+    Toggle *trayToggle_;
+    Toggle *startInTrayToggle_;
+    Toggle *groupViewToggle_;
+    Toggle *timelineButtonsToggle_;
+    Toggle *typingNotifications_;
+    Toggle *messageHoverHighlight_;
+    Toggle *enlargeEmojiOnlyMessages_;
+    Toggle *sortByImportance_;
+    Toggle *readReceipts_;
+    Toggle *markdown_;
+    Toggle *animateImagesOnHover_;
+    Toggle *desktopNotifications_;
+    Toggle *alertOnNotification_;
+    Toggle *avatarCircles_;
+    Toggle *useIdenticon_;
+    Toggle *useStunServer_;
+    Toggle *decryptSidebar_;
+    Toggle *privacyScreen_;
+    QSpinBox *privacyScreenTimeout_;
+    Toggle *shareKeysWithTrustedUsers_;
+    Toggle *onlyShareKeysWithVerifiedUsers_;
+    Toggle *useOnlineKeyBackup_;
+    Toggle *mobileMode_;
+    QLabel *deviceFingerprintValue_;
+    QLabel *deviceIdValue_;
+    QLabel *backupSecretCached;
+    QLabel *masterSecretCached;
+    QLabel *selfSigningSecretCached;
+    QLabel *userSigningSecretCached;
+
+    QComboBox *themeCombo_;
+    QComboBox *scaleFactorCombo_;
+    QComboBox *fontSizeCombo_;
+    QFontComboBox *fontSelectionCombo_;
+    QComboBox *emojiFontSelectionCombo_;
+    QComboBox *ringtoneCombo_;
+    QComboBox *microphoneCombo_;
+    QComboBox *cameraCombo_;
+    QComboBox *cameraResolutionCombo_;
+    QComboBox *cameraFrameRateCombo_;
+
+    QSpinBox *timelineMaxWidthSpin_;
+
+    int sideMargin_ = 0;
 };
diff --git a/src/UsersModel.cpp b/src/UsersModel.cpp
index 13b05f0e..f82353cc 100644
--- a/src/UsersModel.cpp
+++ b/src/UsersModel.cpp
@@ -14,51 +14,51 @@ UsersModel::UsersModel(const std::string &roomId, QObject *parent)
   : QAbstractListModel(parent)
   , room_id(roomId)
 {
-        roomMembers_ = cache::roomMembers(roomId);
-        for (const auto &m : roomMembers_) {
-                displayNames.push_back(QString::fromStdString(cache::displayName(room_id, m)));
-                userids.push_back(QString::fromStdString(m));
-        }
+    roomMembers_ = cache::roomMembers(roomId);
+    for (const auto &m : roomMembers_) {
+        displayNames.push_back(QString::fromStdString(cache::displayName(room_id, m)));
+        userids.push_back(QString::fromStdString(m));
+    }
 }
 
 QHash<int, QByteArray>
 UsersModel::roleNames() const
 {
-        return {
-          {CompletionModel::CompletionRole, "completionRole"},
-          {CompletionModel::SearchRole, "searchRole"},
-          {CompletionModel::SearchRole2, "searchRole2"},
-          {Roles::DisplayName, "displayName"},
-          {Roles::AvatarUrl, "avatarUrl"},
-          {Roles::UserID, "userid"},
-        };
+    return {
+      {CompletionModel::CompletionRole, "completionRole"},
+      {CompletionModel::SearchRole, "searchRole"},
+      {CompletionModel::SearchRole2, "searchRole2"},
+      {Roles::DisplayName, "displayName"},
+      {Roles::AvatarUrl, "avatarUrl"},
+      {Roles::UserID, "userid"},
+    };
 }
 
 QVariant
 UsersModel::data(const QModelIndex &index, int role) const
 {
-        if (hasIndex(index.row(), index.column(), index.parent())) {
-                switch (role) {
-                case CompletionModel::CompletionRole:
-                        if (UserSettings::instance()->markdown())
-                                return QString("[%1](https://matrix.to/#/%2)")
-                                  .arg(displayNames[index.row()].toHtmlEscaped())
-                                  .arg(QString(QUrl::toPercentEncoding(userids[index.row()])));
-                        else
-                                return displayNames[index.row()];
-                case CompletionModel::SearchRole:
-                        return displayNames[index.row()];
-                case Qt::DisplayRole:
-                case Roles::DisplayName:
-                        return displayNames[index.row()].toHtmlEscaped();
-                case CompletionModel::SearchRole2:
-                        return userids[index.row()];
-                case Roles::AvatarUrl:
-                        return cache::avatarUrl(QString::fromStdString(room_id),
-                                                QString::fromStdString(roomMembers_[index.row()]));
-                case Roles::UserID:
-                        return userids[index.row()].toHtmlEscaped();
-                }
+    if (hasIndex(index.row(), index.column(), index.parent())) {
+        switch (role) {
+        case CompletionModel::CompletionRole:
+            if (UserSettings::instance()->markdown())
+                return QString("[%1](https://matrix.to/#/%2)")
+                  .arg(displayNames[index.row()].toHtmlEscaped())
+                  .arg(QString(QUrl::toPercentEncoding(userids[index.row()])));
+            else
+                return displayNames[index.row()];
+        case CompletionModel::SearchRole:
+            return displayNames[index.row()];
+        case Qt::DisplayRole:
+        case Roles::DisplayName:
+            return displayNames[index.row()].toHtmlEscaped();
+        case CompletionModel::SearchRole2:
+            return userids[index.row()];
+        case Roles::AvatarUrl:
+            return cache::avatarUrl(QString::fromStdString(room_id),
+                                    QString::fromStdString(roomMembers_[index.row()]));
+        case Roles::UserID:
+            return userids[index.row()].toHtmlEscaped();
         }
-        return {};
+    }
+    return {};
 }
diff --git a/src/UsersModel.h b/src/UsersModel.h
index 5bc94b0f..e719a8bd 100644
--- a/src/UsersModel.h
+++ b/src/UsersModel.h
@@ -9,25 +9,25 @@
 class UsersModel : public QAbstractListModel
 {
 public:
-        enum Roles
-        {
-                AvatarUrl = Qt::UserRole,
-                DisplayName,
-                UserID,
-        };
+    enum Roles
+    {
+        AvatarUrl = Qt::UserRole,
+        DisplayName,
+        UserID,
+    };
 
-        UsersModel(const std::string &roomId, QObject *parent = nullptr);
-        QHash<int, QByteArray> roleNames() const override;
-        int rowCount(const QModelIndex &parent = QModelIndex()) const override
-        {
-                (void)parent;
-                return (int)roomMembers_.size();
-        }
-        QVariant data(const QModelIndex &index, int role) const override;
+    UsersModel(const std::string &roomId, QObject *parent = nullptr);
+    QHash<int, QByteArray> roleNames() const override;
+    int rowCount(const QModelIndex &parent = QModelIndex()) const override
+    {
+        (void)parent;
+        return (int)roomMembers_.size();
+    }
+    QVariant data(const QModelIndex &index, int role) const override;
 
 private:
-        std::string room_id;
-        std::vector<std::string> roomMembers_;
-        std::vector<QString> displayNames;
-        std::vector<QString> userids;
+    std::string room_id;
+    std::vector<std::string> roomMembers_;
+    std::vector<QString> displayNames;
+    std::vector<QString> userids;
 };
diff --git a/src/Utils.cpp b/src/Utils.cpp
index 3f524c6c..b0fb01b1 100644
--- a/src/Utils.cpp
+++ b/src/Utils.cpp
@@ -38,155 +38,154 @@ template<class T, class Event>
 static DescInfo
 createDescriptionInfo(const Event &event, const QString &localUser, const QString &displayName)
 {
-        const auto msg    = std::get<T>(event);
-        const auto sender = QString::fromStdString(msg.sender);
+    const auto msg    = std::get<T>(event);
+    const auto sender = QString::fromStdString(msg.sender);
 
-        const auto username = displayName;
-        const auto ts       = QDateTime::fromMSecsSinceEpoch(msg.origin_server_ts);
-        auto body           = utils::event_body(event).trimmed();
-        if (mtx::accessors::relations(event).reply_to())
-                body = QString::fromStdString(utils::stripReplyFromBody(body.toStdString()));
+    const auto username = displayName;
+    const auto ts       = QDateTime::fromMSecsSinceEpoch(msg.origin_server_ts);
+    auto body           = utils::event_body(event).trimmed();
+    if (mtx::accessors::relations(event).reply_to())
+        body = QString::fromStdString(utils::stripReplyFromBody(body.toStdString()));
 
-        return DescInfo{QString::fromStdString(msg.event_id),
-                        sender,
-                        utils::messageDescription<T>(username, body, sender == localUser),
-                        utils::descriptiveTime(ts),
-                        msg.origin_server_ts,
-                        ts};
+    return DescInfo{QString::fromStdString(msg.event_id),
+                    sender,
+                    utils::messageDescription<T>(username, body, sender == localUser),
+                    utils::descriptiveTime(ts),
+                    msg.origin_server_ts,
+                    ts};
 }
 
 std::string
 utils::stripReplyFromBody(const std::string &bodyi)
 {
-        QString body = QString::fromStdString(bodyi);
-        QRegularExpression plainQuote("^>.*?$\n?", QRegularExpression::MultilineOption);
-        while (body.startsWith(">"))
-                body.remove(plainQuote);
-        if (body.startsWith("\n"))
-                body.remove(0, 1);
+    QString body = QString::fromStdString(bodyi);
+    QRegularExpression plainQuote("^>.*?$\n?", QRegularExpression::MultilineOption);
+    while (body.startsWith(">"))
+        body.remove(plainQuote);
+    if (body.startsWith("\n"))
+        body.remove(0, 1);
 
-        body.replace("@room", QString::fromUtf8("@\u2060room"));
-        return body.toStdString();
+    body.replace("@room", QString::fromUtf8("@\u2060room"));
+    return body.toStdString();
 }
 
 std::string
 utils::stripReplyFromFormattedBody(const std::string &formatted_bodyi)
 {
-        QString formatted_body = QString::fromStdString(formatted_bodyi);
-        formatted_body.remove(QRegularExpression("<mx-reply>.*</mx-reply>",
-                                                 QRegularExpression::DotMatchesEverythingOption));
-        formatted_body.replace("@room", QString::fromUtf8("@\u2060room"));
-        return formatted_body.toStdString();
+    QString formatted_body = QString::fromStdString(formatted_bodyi);
+    formatted_body.remove(QRegularExpression("<mx-reply>.*</mx-reply>",
+                                             QRegularExpression::DotMatchesEverythingOption));
+    formatted_body.replace("@room", QString::fromUtf8("@\u2060room"));
+    return formatted_body.toStdString();
 }
 
 RelatedInfo
 utils::stripReplyFallbacks(const TimelineEvent &event, std::string id, QString room_id_)
 {
-        RelatedInfo related   = {};
-        related.quoted_user   = QString::fromStdString(mtx::accessors::sender(event));
-        related.related_event = std::move(id);
-        related.type          = mtx::accessors::msg_type(event);
+    RelatedInfo related   = {};
+    related.quoted_user   = QString::fromStdString(mtx::accessors::sender(event));
+    related.related_event = std::move(id);
+    related.type          = mtx::accessors::msg_type(event);
 
-        // get body, strip reply fallback, then transform the event to text, if it is a media event
-        // etc
-        related.quoted_body = QString::fromStdString(mtx::accessors::body(event));
-        related.quoted_body =
-          QString::fromStdString(stripReplyFromBody(related.quoted_body.toStdString()));
-        related.quoted_body = utils::getQuoteBody(related);
+    // get body, strip reply fallback, then transform the event to text, if it is a media event
+    // etc
+    related.quoted_body = QString::fromStdString(mtx::accessors::body(event));
+    related.quoted_body =
+      QString::fromStdString(stripReplyFromBody(related.quoted_body.toStdString()));
+    related.quoted_body = utils::getQuoteBody(related);
 
-        // get quoted body and strip reply fallback
-        related.quoted_formatted_body = mtx::accessors::formattedBodyWithFallback(event);
-        related.quoted_formatted_body = QString::fromStdString(
-          stripReplyFromFormattedBody(related.quoted_formatted_body.toStdString()));
-        related.room = room_id_;
+    // get quoted body and strip reply fallback
+    related.quoted_formatted_body = mtx::accessors::formattedBodyWithFallback(event);
+    related.quoted_formatted_body = QString::fromStdString(
+      stripReplyFromFormattedBody(related.quoted_formatted_body.toStdString()));
+    related.room = room_id_;
 
-        return related;
+    return related;
 }
 
 QString
 utils::localUser()
 {
-        return QString::fromStdString(http::client()->user_id().to_string());
+    return QString::fromStdString(http::client()->user_id().to_string());
 }
 
 bool
 utils::codepointIsEmoji(uint code)
 {
-        // TODO: Be more precise here.
-        return (code >= 0x2600 && code <= 0x27bf) || (code >= 0x2b00 && code <= 0x2bff) ||
-               (code >= 0x1f000 && code <= 0x1faff) || code == 0x200d || code == 0xfe0f;
+    // TODO: Be more precise here.
+    return (code >= 0x2600 && code <= 0x27bf) || (code >= 0x2b00 && code <= 0x2bff) ||
+           (code >= 0x1f000 && code <= 0x1faff) || code == 0x200d || code == 0xfe0f;
 }
 
 QString
 utils::replaceEmoji(const QString &body)
 {
-        QString fmtBody;
-        fmtBody.reserve(body.size());
-
-        QVector<uint> utf32_string = body.toUcs4();
-
-        bool insideFontBlock = false;
-        for (auto &code : utf32_string) {
-                if (utils::codepointIsEmoji(code)) {
-                        if (!insideFontBlock) {
-                                fmtBody += QStringLiteral("<font face=\"") %
-                                           UserSettings::instance()->emojiFont() %
-                                           QStringLiteral("\">");
-                                insideFontBlock = true;
-                        }
-
-                } else {
-                        if (insideFontBlock) {
-                                fmtBody += QStringLiteral("</font>");
-                                insideFontBlock = false;
-                        }
-                }
-                if (QChar::requiresSurrogates(code)) {
-                        QChar emoji[] = {static_cast<ushort>(QChar::highSurrogate(code)),
-                                         static_cast<ushort>(QChar::lowSurrogate(code))};
-                        fmtBody.append(emoji, 2);
-                } else {
-                        fmtBody.append(QChar(static_cast<ushort>(code)));
-                }
-        }
-        if (insideFontBlock) {
+    QString fmtBody;
+    fmtBody.reserve(body.size());
+
+    QVector<uint> utf32_string = body.toUcs4();
+
+    bool insideFontBlock = false;
+    for (auto &code : utf32_string) {
+        if (utils::codepointIsEmoji(code)) {
+            if (!insideFontBlock) {
+                fmtBody += QStringLiteral("<font face=\"") % UserSettings::instance()->emojiFont() %
+                           QStringLiteral("\">");
+                insideFontBlock = true;
+            }
+
+        } else {
+            if (insideFontBlock) {
                 fmtBody += QStringLiteral("</font>");
+                insideFontBlock = false;
+            }
         }
+        if (QChar::requiresSurrogates(code)) {
+            QChar emoji[] = {static_cast<ushort>(QChar::highSurrogate(code)),
+                             static_cast<ushort>(QChar::lowSurrogate(code))};
+            fmtBody.append(emoji, 2);
+        } else {
+            fmtBody.append(QChar(static_cast<ushort>(code)));
+        }
+    }
+    if (insideFontBlock) {
+        fmtBody += QStringLiteral("</font>");
+    }
 
-        return fmtBody;
+    return fmtBody;
 }
 
 void
 utils::setScaleFactor(float factor)
 {
-        if (factor < 1 || factor > 3)
-                return;
+    if (factor < 1 || factor > 3)
+        return;
 
-        QSettings settings;
-        settings.setValue("settings/scale_factor", factor);
+    QSettings settings;
+    settings.setValue("settings/scale_factor", factor);
 }
 
 float
 utils::scaleFactor()
 {
-        QSettings settings;
-        return settings.value("settings/scale_factor", -1).toFloat();
+    QSettings settings;
+    return settings.value("settings/scale_factor", -1).toFloat();
 }
 
 QString
 utils::descriptiveTime(const QDateTime &then)
 {
-        const auto now  = QDateTime::currentDateTime();
-        const auto days = then.daysTo(now);
+    const auto now  = QDateTime::currentDateTime();
+    const auto days = then.daysTo(now);
 
-        if (days == 0)
-                return QLocale::system().toString(then.time(), QLocale::ShortFormat);
-        else if (days < 2)
-                return QString(QCoreApplication::translate("descriptiveTime", "Yesterday"));
-        else if (days < 7)
-                return then.toString("dddd");
+    if (days == 0)
+        return QLocale::system().toString(then.time(), QLocale::ShortFormat);
+    else if (days < 2)
+        return QString(QCoreApplication::translate("descriptiveTime", "Yesterday"));
+    else if (days < 7)
+        return then.toString("dddd");
 
-        return QLocale::system().toString(then.date(), QLocale::ShortFormat);
+    return QLocale::system().toString(then.date(), QLocale::ShortFormat);
 }
 
 DescInfo
@@ -194,630 +193,622 @@ utils::getMessageDescription(const TimelineEvent &event,
                              const QString &localUser,
                              const QString &displayName)
 {
-        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 Text       = mtx::events::RoomEvent<mtx::events::msg::Text>;
-        using Video      = mtx::events::RoomEvent<mtx::events::msg::Video>;
-        using CallInvite = mtx::events::RoomEvent<mtx::events::msg::CallInvite>;
-        using CallAnswer = mtx::events::RoomEvent<mtx::events::msg::CallAnswer>;
-        using CallHangUp = mtx::events::RoomEvent<mtx::events::msg::CallHangUp>;
-        using Encrypted  = mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>;
-
-        if (std::holds_alternative<Audio>(event)) {
-                return createDescriptionInfo<Audio>(event, localUser, displayName);
-        } else if (std::holds_alternative<Emote>(event)) {
-                return createDescriptionInfo<Emote>(event, localUser, displayName);
-        } else if (std::holds_alternative<File>(event)) {
-                return createDescriptionInfo<File>(event, localUser, displayName);
-        } else if (std::holds_alternative<Image>(event)) {
-                return createDescriptionInfo<Image>(event, localUser, displayName);
-        } else if (std::holds_alternative<Notice>(event)) {
-                return createDescriptionInfo<Notice>(event, localUser, displayName);
-        } else if (std::holds_alternative<Text>(event)) {
-                return createDescriptionInfo<Text>(event, localUser, displayName);
-        } else if (std::holds_alternative<Video>(event)) {
-                return createDescriptionInfo<Video>(event, localUser, displayName);
-        } else if (std::holds_alternative<CallInvite>(event)) {
-                return createDescriptionInfo<CallInvite>(event, localUser, displayName);
-        } else if (std::holds_alternative<CallAnswer>(event)) {
-                return createDescriptionInfo<CallAnswer>(event, localUser, displayName);
-        } else if (std::holds_alternative<CallHangUp>(event)) {
-                return createDescriptionInfo<CallHangUp>(event, localUser, displayName);
-        } else if (std::holds_alternative<mtx::events::Sticker>(event)) {
-                return createDescriptionInfo<mtx::events::Sticker>(event, localUser, displayName);
-        } else if (auto msg = std::get_if<Encrypted>(&event); msg != nullptr) {
-                const auto sender = QString::fromStdString(msg->sender);
-
-                const auto username = displayName;
-                const auto ts       = QDateTime::fromMSecsSinceEpoch(msg->origin_server_ts);
-
-                DescInfo info;
-                info.userid = sender;
-                info.body   = QString(" %1").arg(
-                  messageDescription<Encrypted>(username, "", sender == localUser));
-                info.timestamp       = msg->origin_server_ts;
-                info.descriptiveTime = utils::descriptiveTime(ts);
-                info.event_id        = QString::fromStdString(msg->event_id);
-                info.datetime        = ts;
-
-                return info;
-        }
+    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 Text       = mtx::events::RoomEvent<mtx::events::msg::Text>;
+    using Video      = mtx::events::RoomEvent<mtx::events::msg::Video>;
+    using CallInvite = mtx::events::RoomEvent<mtx::events::msg::CallInvite>;
+    using CallAnswer = mtx::events::RoomEvent<mtx::events::msg::CallAnswer>;
+    using CallHangUp = mtx::events::RoomEvent<mtx::events::msg::CallHangUp>;
+    using Encrypted  = mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>;
+
+    if (std::holds_alternative<Audio>(event)) {
+        return createDescriptionInfo<Audio>(event, localUser, displayName);
+    } else if (std::holds_alternative<Emote>(event)) {
+        return createDescriptionInfo<Emote>(event, localUser, displayName);
+    } else if (std::holds_alternative<File>(event)) {
+        return createDescriptionInfo<File>(event, localUser, displayName);
+    } else if (std::holds_alternative<Image>(event)) {
+        return createDescriptionInfo<Image>(event, localUser, displayName);
+    } else if (std::holds_alternative<Notice>(event)) {
+        return createDescriptionInfo<Notice>(event, localUser, displayName);
+    } else if (std::holds_alternative<Text>(event)) {
+        return createDescriptionInfo<Text>(event, localUser, displayName);
+    } else if (std::holds_alternative<Video>(event)) {
+        return createDescriptionInfo<Video>(event, localUser, displayName);
+    } else if (std::holds_alternative<CallInvite>(event)) {
+        return createDescriptionInfo<CallInvite>(event, localUser, displayName);
+    } else if (std::holds_alternative<CallAnswer>(event)) {
+        return createDescriptionInfo<CallAnswer>(event, localUser, displayName);
+    } else if (std::holds_alternative<CallHangUp>(event)) {
+        return createDescriptionInfo<CallHangUp>(event, localUser, displayName);
+    } else if (std::holds_alternative<mtx::events::Sticker>(event)) {
+        return createDescriptionInfo<mtx::events::Sticker>(event, localUser, displayName);
+    } else if (auto msg = std::get_if<Encrypted>(&event); msg != nullptr) {
+        const auto sender = QString::fromStdString(msg->sender);
+
+        const auto username = displayName;
+        const auto ts       = QDateTime::fromMSecsSinceEpoch(msg->origin_server_ts);
+
+        DescInfo info;
+        info.userid = sender;
+        info.body =
+          QString(" %1").arg(messageDescription<Encrypted>(username, "", sender == localUser));
+        info.timestamp       = msg->origin_server_ts;
+        info.descriptiveTime = utils::descriptiveTime(ts);
+        info.event_id        = QString::fromStdString(msg->event_id);
+        info.datetime        = ts;
+
+        return info;
+    }
 
-        return DescInfo{};
+    return DescInfo{};
 }
 
 QString
 utils::firstChar(const QString &input)
 {
-        if (input.isEmpty())
-                return input;
+    if (input.isEmpty())
+        return input;
 
-        for (auto const &c : input.toUcs4()) {
-                if (QString::fromUcs4(&c, 1) != QString("#"))
-                        return QString::fromUcs4(&c, 1).toUpper();
-        }
+    for (auto const &c : input.toUcs4()) {
+        if (QString::fromUcs4(&c, 1) != QString("#"))
+            return QString::fromUcs4(&c, 1).toUpper();
+    }
 
-        return QString::fromUcs4(&input.toUcs4().at(0), 1).toUpper();
+    return QString::fromUcs4(&input.toUcs4().at(0), 1).toUpper();
 }
 
 QString
 utils::humanReadableFileSize(uint64_t bytes)
 {
-        constexpr static const char *units[] = {"B", "KiB", "MiB", "GiB", "TiB"};
-        constexpr static const int length    = sizeof(units) / sizeof(units[0]);
+    constexpr static const char *units[] = {"B", "KiB", "MiB", "GiB", "TiB"};
+    constexpr static const int length    = sizeof(units) / sizeof(units[0]);
 
-        int u       = 0;
-        double size = static_cast<double>(bytes);
-        while (size >= 1024.0 && u < length) {
-                ++u;
-                size /= 1024.0;
-        }
+    int u       = 0;
+    double size = static_cast<double>(bytes);
+    while (size >= 1024.0 && u < length) {
+        ++u;
+        size /= 1024.0;
+    }
 
-        return QString::number(size, 'g', 4) + ' ' + units[u];
+    return QString::number(size, 'g', 4) + ' ' + units[u];
 }
 
 int
 utils::levenshtein_distance(const std::string &s1, const std::string &s2)
 {
-        const auto nlen = s1.size();
-        const auto hlen = s2.size();
+    const auto nlen = s1.size();
+    const auto hlen = s2.size();
 
-        if (hlen == 0)
-                return -1;
-        if (nlen == 1)
-                return (int)s2.find(s1);
+    if (hlen == 0)
+        return -1;
+    if (nlen == 1)
+        return (int)s2.find(s1);
 
-        std::vector<int> row1(hlen + 1, 0);
+    std::vector<int> row1(hlen + 1, 0);
 
-        for (size_t i = 0; i < nlen; ++i) {
-                std::vector<int> row2(1, (int)i + 1);
-
-                for (size_t j = 0; j < hlen; ++j) {
-                        const int cost = s1[i] != s2[j];
-                        row2.push_back(
-                          std::min(row1[j + 1] + 1, std::min(row2[j] + 1, row1[j] + cost)));
-                }
+    for (size_t i = 0; i < nlen; ++i) {
+        std::vector<int> row2(1, (int)i + 1);
 
-                row1.swap(row2);
+        for (size_t j = 0; j < hlen; ++j) {
+            const int cost = s1[i] != s2[j];
+            row2.push_back(std::min(row1[j + 1] + 1, std::min(row2[j] + 1, row1[j] + cost)));
         }
 
-        return *std::min_element(row1.begin(), row1.end());
+        row1.swap(row2);
+    }
+
+    return *std::min_element(row1.begin(), row1.end());
 }
 
 QString
 utils::event_body(const mtx::events::collections::TimelineEvents &e)
 {
-        using namespace mtx::events;
-        if (auto ev = std::get_if<RoomEvent<msg::Audio>>(&e); ev != nullptr)
-                return QString::fromStdString(ev->content.body);
-        if (auto ev = std::get_if<RoomEvent<msg::Emote>>(&e); ev != nullptr)
-                return QString::fromStdString(ev->content.body);
-        if (auto ev = std::get_if<RoomEvent<msg::File>>(&e); ev != nullptr)
-                return QString::fromStdString(ev->content.body);
-        if (auto ev = std::get_if<RoomEvent<msg::Image>>(&e); ev != nullptr)
-                return QString::fromStdString(ev->content.body);
-        if (auto ev = std::get_if<RoomEvent<msg::Notice>>(&e); ev != nullptr)
-                return QString::fromStdString(ev->content.body);
-        if (auto ev = std::get_if<RoomEvent<msg::Text>>(&e); ev != nullptr)
-                return QString::fromStdString(ev->content.body);
-        if (auto ev = std::get_if<RoomEvent<msg::Video>>(&e); ev != nullptr)
-                return QString::fromStdString(ev->content.body);
-
-        return "";
+    using namespace mtx::events;
+    if (auto ev = std::get_if<RoomEvent<msg::Audio>>(&e); ev != nullptr)
+        return QString::fromStdString(ev->content.body);
+    if (auto ev = std::get_if<RoomEvent<msg::Emote>>(&e); ev != nullptr)
+        return QString::fromStdString(ev->content.body);
+    if (auto ev = std::get_if<RoomEvent<msg::File>>(&e); ev != nullptr)
+        return QString::fromStdString(ev->content.body);
+    if (auto ev = std::get_if<RoomEvent<msg::Image>>(&e); ev != nullptr)
+        return QString::fromStdString(ev->content.body);
+    if (auto ev = std::get_if<RoomEvent<msg::Notice>>(&e); ev != nullptr)
+        return QString::fromStdString(ev->content.body);
+    if (auto ev = std::get_if<RoomEvent<msg::Text>>(&e); ev != nullptr)
+        return QString::fromStdString(ev->content.body);
+    if (auto ev = std::get_if<RoomEvent<msg::Video>>(&e); ev != nullptr)
+        return QString::fromStdString(ev->content.body);
+
+    return "";
 }
 
 QPixmap
 utils::scaleImageToPixmap(const QImage &img, int size)
 {
-        if (img.isNull())
-                return QPixmap();
+    if (img.isNull())
+        return QPixmap();
 
-        // Deprecated in 5.13: const double sz =
-        //  std::ceil(QApplication::desktop()->screen()->devicePixelRatioF() * (double)size);
-        const double sz =
-          std::ceil(QGuiApplication::primaryScreen()->devicePixelRatio() * (double)size);
-        return QPixmap::fromImage(
-          img.scaled(sz, sz, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
+    // Deprecated in 5.13: const double sz =
+    //  std::ceil(QApplication::desktop()->screen()->devicePixelRatioF() * (double)size);
+    const double sz =
+      std::ceil(QGuiApplication::primaryScreen()->devicePixelRatio() * (double)size);
+    return QPixmap::fromImage(img.scaled(sz, sz, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
 }
 
 QPixmap
 utils::scaleDown(uint64_t maxWidth, uint64_t maxHeight, const QPixmap &source)
 {
-        if (source.isNull())
-                return QPixmap();
+    if (source.isNull())
+        return QPixmap();
 
-        const double widthRatio     = (double)maxWidth / (double)source.width();
-        const double heightRatio    = (double)maxHeight / (double)source.height();
-        const double minAspectRatio = std::min(widthRatio, heightRatio);
+    const double widthRatio     = (double)maxWidth / (double)source.width();
+    const double heightRatio    = (double)maxHeight / (double)source.height();
+    const double minAspectRatio = std::min(widthRatio, heightRatio);
 
-        // Size of the output image.
-        int w, h = 0;
+    // Size of the output image.
+    int w, h = 0;
 
-        if (minAspectRatio > 1) {
-                w = source.width();
-                h = source.height();
-        } else {
-                w = source.width() * minAspectRatio;
-                h = source.height() * minAspectRatio;
-        }
+    if (minAspectRatio > 1) {
+        w = source.width();
+        h = source.height();
+    } else {
+        w = source.width() * minAspectRatio;
+        h = source.height() * minAspectRatio;
+    }
 
-        return source.scaled(w, h, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+    return source.scaled(w, h, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
 }
 
 QString
 utils::mxcToHttp(const QUrl &url, const QString &server, int port)
 {
-        auto mxcParts = mtx::client::utils::parse_mxc_url(url.toString().toStdString());
+    auto mxcParts = mtx::client::utils::parse_mxc_url(url.toString().toStdString());
 
-        return QString("https://%1:%2/_matrix/media/r0/download/%3/%4")
-          .arg(server)
-          .arg(port)
-          .arg(QString::fromStdString(mxcParts.server))
-          .arg(QString::fromStdString(mxcParts.media_id));
+    return QString("https://%1:%2/_matrix/media/r0/download/%3/%4")
+      .arg(server)
+      .arg(port)
+      .arg(QString::fromStdString(mxcParts.server))
+      .arg(QString::fromStdString(mxcParts.media_id));
 }
 
 QString
 utils::humanReadableFingerprint(const std::string &ed25519)
 {
-        return humanReadableFingerprint(QString::fromStdString(ed25519));
+    return humanReadableFingerprint(QString::fromStdString(ed25519));
 }
 QString
 utils::humanReadableFingerprint(const QString &ed25519)
 {
-        QString fingerprint;
-        for (int i = 0; i < ed25519.length(); i = i + 4) {
-                fingerprint.append(ed25519.midRef(i, 4));
-                if (i > 0 && i % 16 == 12)
-                        fingerprint.append('\n');
-                else if (i < ed25519.length())
-                        fingerprint.append(' ');
-        }
-        return fingerprint;
+    QString fingerprint;
+    for (int i = 0; i < ed25519.length(); i = i + 4) {
+        fingerprint.append(ed25519.midRef(i, 4));
+        if (i > 0 && i % 16 == 12)
+            fingerprint.append('\n');
+        else if (i < ed25519.length())
+            fingerprint.append(' ');
+    }
+    return fingerprint;
 }
 
 QString
 utils::linkifyMessage(const QString &body)
 {
-        // Convert to valid XML.
-        auto doc = body;
-        doc.replace(conf::strings::url_regex, conf::strings::url_html);
-        doc.replace(QRegularExpression("\\b(?<![\"'])(?>(matrix:[\\S]{5,}))(?![\"'])\\b"),
-                    conf::strings::url_html);
+    // Convert to valid XML.
+    auto doc = body;
+    doc.replace(conf::strings::url_regex, conf::strings::url_html);
+    doc.replace(QRegularExpression("\\b(?<![\"'])(?>(matrix:[\\S]{5,}))(?![\"'])\\b"),
+                conf::strings::url_html);
 
-        return doc;
+    return doc;
 }
 
 QString
 utils::escapeBlacklistedHtml(const QString &rawStr)
 {
-        static const std::array allowedTags = {
-          "font",       "/font",       "del",    "/del",    "h1",    "/h1",    "h2",     "/h2",
-          "h3",         "/h3",         "h4",     "/h4",     "h5",    "/h5",    "h6",     "/h6",
-          "blockquote", "/blockquote", "p",      "/p",      "a",     "/a",     "ul",     "/ul",
-          "ol",         "/ol",         "sup",    "/sup",    "sub",   "/sub",   "li",     "/li",
-          "b",          "/b",          "i",      "/i",      "u",     "/u",     "strong", "/strong",
-          "em",         "/em",         "strike", "/strike", "code",  "/code",  "hr",     "/hr",
-          "br",         "br/",         "div",    "/div",    "table", "/table", "thead",  "/thead",
-          "tbody",      "/tbody",      "tr",     "/tr",     "th",    "/th",    "td",     "/td",
-          "caption",    "/caption",    "pre",    "/pre",    "span",  "/span",  "img",    "/img"};
-        QByteArray data = rawStr.toUtf8();
-        QByteArray buffer;
-        const int length = data.size();
-        buffer.reserve(length);
-        bool escapingTag = false;
-        for (int pos = 0; pos != length; ++pos) {
-                switch (data.at(pos)) {
-                case '<': {
-                        bool oneTagMatched = false;
-                        const int endPos =
-                          static_cast<int>(std::min(static_cast<size_t>(data.indexOf('>', pos)),
-                                                    static_cast<size_t>(data.indexOf(' ', pos))));
-
-                        auto mid = data.mid(pos + 1, endPos - pos - 1);
-                        for (const auto &tag : allowedTags) {
-                                // TODO: Check src and href attribute
-                                if (mid.toLower() == tag) {
-                                        oneTagMatched = true;
-                                }
-                        }
-                        if (oneTagMatched)
-                                buffer.append('<');
-                        else {
-                                escapingTag = true;
-                                buffer.append("&lt;");
-                        }
-                        break;
-                }
-                case '>':
-                        if (escapingTag) {
-                                buffer.append("&gt;");
-                                escapingTag = false;
-                        } else
-                                buffer.append('>');
-                        break;
-                default:
-                        buffer.append(data.at(pos));
-                        break;
+    static const std::array allowedTags = {
+      "font",       "/font",       "del",    "/del",    "h1",    "/h1",    "h2",     "/h2",
+      "h3",         "/h3",         "h4",     "/h4",     "h5",    "/h5",    "h6",     "/h6",
+      "blockquote", "/blockquote", "p",      "/p",      "a",     "/a",     "ul",     "/ul",
+      "ol",         "/ol",         "sup",    "/sup",    "sub",   "/sub",   "li",     "/li",
+      "b",          "/b",          "i",      "/i",      "u",     "/u",     "strong", "/strong",
+      "em",         "/em",         "strike", "/strike", "code",  "/code",  "hr",     "/hr",
+      "br",         "br/",         "div",    "/div",    "table", "/table", "thead",  "/thead",
+      "tbody",      "/tbody",      "tr",     "/tr",     "th",    "/th",    "td",     "/td",
+      "caption",    "/caption",    "pre",    "/pre",    "span",  "/span",  "img",    "/img"};
+    QByteArray data = rawStr.toUtf8();
+    QByteArray buffer;
+    const int length = data.size();
+    buffer.reserve(length);
+    bool escapingTag = false;
+    for (int pos = 0; pos != length; ++pos) {
+        switch (data.at(pos)) {
+        case '<': {
+            bool oneTagMatched = false;
+            const int endPos =
+              static_cast<int>(std::min(static_cast<size_t>(data.indexOf('>', pos)),
+                                        static_cast<size_t>(data.indexOf(' ', pos))));
+
+            auto mid = data.mid(pos + 1, endPos - pos - 1);
+            for (const auto &tag : allowedTags) {
+                // TODO: Check src and href attribute
+                if (mid.toLower() == tag) {
+                    oneTagMatched = true;
                 }
+            }
+            if (oneTagMatched)
+                buffer.append('<');
+            else {
+                escapingTag = true;
+                buffer.append("&lt;");
+            }
+            break;
         }
-        return QString::fromUtf8(buffer);
+        case '>':
+            if (escapingTag) {
+                buffer.append("&gt;");
+                escapingTag = false;
+            } else
+                buffer.append('>');
+            break;
+        default:
+            buffer.append(data.at(pos));
+            break;
+        }
+    }
+    return QString::fromUtf8(buffer);
 }
 
 QString
 utils::markdownToHtml(const QString &text, bool rainbowify)
 {
-        const auto str = text.toUtf8();
-        cmark_node *const node =
-          cmark_parse_document(str.constData(), str.size(), CMARK_OPT_UNSAFE);
-
-        if (rainbowify) {
-                // create iterator over node
-                cmark_iter *iter = cmark_iter_new(node);
-
-                cmark_event_type ev_type;
-
-                // First loop to get total text length
-                int textLen = 0;
-                while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
-                        cmark_node *cur = cmark_iter_get_node(iter);
-                        // only text nodes (no code or semilar)
-                        if (cmark_node_get_type(cur) != CMARK_NODE_TEXT)
-                                continue;
-                        // count up by length of current node's text
-                        QTextBoundaryFinder tbf(QTextBoundaryFinder::BoundaryType::Grapheme,
-                                                QString(cmark_node_get_literal(cur)));
-                        while (tbf.toNextBoundary() != -1)
-                                textLen++;
-                }
+    const auto str         = text.toUtf8();
+    cmark_node *const node = cmark_parse_document(str.constData(), str.size(), CMARK_OPT_UNSAFE);
+
+    if (rainbowify) {
+        // create iterator over node
+        cmark_iter *iter = cmark_iter_new(node);
+
+        cmark_event_type ev_type;
+
+        // First loop to get total text length
+        int textLen = 0;
+        while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
+            cmark_node *cur = cmark_iter_get_node(iter);
+            // only text nodes (no code or semilar)
+            if (cmark_node_get_type(cur) != CMARK_NODE_TEXT)
+                continue;
+            // count up by length of current node's text
+            QTextBoundaryFinder tbf(QTextBoundaryFinder::BoundaryType::Grapheme,
+                                    QString(cmark_node_get_literal(cur)));
+            while (tbf.toNextBoundary() != -1)
+                textLen++;
+        }
 
-                // create new iter to start over
-                cmark_iter_free(iter);
-                iter = cmark_iter_new(node);
-
-                // Second loop to rainbowify
-                int charIdx = 0;
-                while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
-                        cmark_node *cur = cmark_iter_get_node(iter);
-                        // only text nodes (no code or semilar)
-                        if (cmark_node_get_type(cur) != CMARK_NODE_TEXT)
-                                continue;
-
-                        // get text in current node
-                        QString nodeText(cmark_node_get_literal(cur));
-                        // create buffer to append rainbow text to
-                        QString buf;
-                        int boundaryStart = 0;
-                        int boundaryEnd   = 0;
-                        // use QTextBoundaryFinder to iterate ofer graphemes
-                        QTextBoundaryFinder tbf(QTextBoundaryFinder::BoundaryType::Grapheme,
-                                                nodeText);
-                        while ((boundaryEnd = tbf.toNextBoundary()) != -1) {
-                                charIdx++;
-                                // Split text to get current char
-                                auto curChar =
-                                  nodeText.midRef(boundaryStart, boundaryEnd - boundaryStart);
-                                boundaryStart = boundaryEnd;
-                                // Don't rainbowify whitespaces
-                                if (curChar.trimmed().isEmpty() ||
-                                    codepointIsEmoji(curChar.toUcs4().first())) {
-                                        buf.append(curChar);
-                                        continue;
-                                }
-
-                                // get correct color for char index
-                                // Use colors as described here:
-                                // https://shark.comfsm.fm/~dleeling/cis/hsl_rainbow.html
-                                auto color =
-                                  QColor::fromHslF((charIdx - 1.0) / textLen * (5. / 6.), 0.9, 0.5);
-                                // format color for HTML
-                                auto colorString = color.name(QColor::NameFormat::HexRgb);
-                                // create HTML element for current char
-                                auto curCharColored = QString("<font color=\"%0\">%1</font>")
-                                                        .arg(colorString)
-                                                        .arg(curChar);
-                                // append colored HTML element to buffer
-                                buf.append(curCharColored);
-                        }
-
-                        // create HTML_INLINE node to prevent HTML from being escaped
-                        auto htmlNode = cmark_node_new(CMARK_NODE_HTML_INLINE);
-                        // set content of HTML node to buffer contents
-                        cmark_node_set_literal(htmlNode, buf.toUtf8().data());
-                        // replace current node with HTML node
-                        cmark_node_replace(cur, htmlNode);
-                        // free memory of old node
-                        cmark_node_free(cur);
+        // create new iter to start over
+        cmark_iter_free(iter);
+        iter = cmark_iter_new(node);
+
+        // Second loop to rainbowify
+        int charIdx = 0;
+        while ((ev_type = cmark_iter_next(iter)) != CMARK_EVENT_DONE) {
+            cmark_node *cur = cmark_iter_get_node(iter);
+            // only text nodes (no code or semilar)
+            if (cmark_node_get_type(cur) != CMARK_NODE_TEXT)
+                continue;
+
+            // get text in current node
+            QString nodeText(cmark_node_get_literal(cur));
+            // create buffer to append rainbow text to
+            QString buf;
+            int boundaryStart = 0;
+            int boundaryEnd   = 0;
+            // use QTextBoundaryFinder to iterate ofer graphemes
+            QTextBoundaryFinder tbf(QTextBoundaryFinder::BoundaryType::Grapheme, nodeText);
+            while ((boundaryEnd = tbf.toNextBoundary()) != -1) {
+                charIdx++;
+                // Split text to get current char
+                auto curChar  = nodeText.midRef(boundaryStart, boundaryEnd - boundaryStart);
+                boundaryStart = boundaryEnd;
+                // Don't rainbowify whitespaces
+                if (curChar.trimmed().isEmpty() || codepointIsEmoji(curChar.toUcs4().first())) {
+                    buf.append(curChar);
+                    continue;
                 }
 
-                cmark_iter_free(iter);
+                // get correct color for char index
+                // Use colors as described here:
+                // https://shark.comfsm.fm/~dleeling/cis/hsl_rainbow.html
+                auto color = QColor::fromHslF((charIdx - 1.0) / textLen * (5. / 6.), 0.9, 0.5);
+                // format color for HTML
+                auto colorString = color.name(QColor::NameFormat::HexRgb);
+                // create HTML element for current char
+                auto curCharColored =
+                  QString("<font color=\"%0\">%1</font>").arg(colorString).arg(curChar);
+                // append colored HTML element to buffer
+                buf.append(curCharColored);
+            }
+
+            // create HTML_INLINE node to prevent HTML from being escaped
+            auto htmlNode = cmark_node_new(CMARK_NODE_HTML_INLINE);
+            // set content of HTML node to buffer contents
+            cmark_node_set_literal(htmlNode, buf.toUtf8().data());
+            // replace current node with HTML node
+            cmark_node_replace(cur, htmlNode);
+            // free memory of old node
+            cmark_node_free(cur);
         }
 
-        const char *tmp_buf = cmark_render_html(node, CMARK_OPT_UNSAFE);
-        // Copy the null terminated output buffer.
-        std::string html(tmp_buf);
+        cmark_iter_free(iter);
+    }
 
-        // The buffer is no longer needed.
-        free((char *)tmp_buf);
+    const char *tmp_buf = cmark_render_html(node, CMARK_OPT_UNSAFE);
+    // Copy the null terminated output buffer.
+    std::string html(tmp_buf);
 
-        auto result = linkifyMessage(escapeBlacklistedHtml(QString::fromStdString(html))).trimmed();
+    // The buffer is no longer needed.
+    free((char *)tmp_buf);
 
-        if (result.count("<p>") == 1 && result.startsWith("<p>") && result.endsWith("</p>")) {
-                result = result.mid(3, result.size() - 3 - 4);
-        }
+    auto result = linkifyMessage(escapeBlacklistedHtml(QString::fromStdString(html))).trimmed();
 
-        return result;
-}
+    if (result.count("<p>") == 1 && result.startsWith("<p>") && result.endsWith("</p>")) {
+        result = result.mid(3, result.size() - 3 - 4);
+    }
 
-QString
-utils::getFormattedQuoteBody(const RelatedInfo &related, const QString &html)
-{
-        auto getFormattedBody = [related]() -> QString {
-                using MsgType = mtx::events::MessageType;
-
-                switch (related.type) {
-                case MsgType::File: {
-                        return "sent a file.";
-                }
-                case MsgType::Image: {
-                        return "sent an image.";
-                }
-                case MsgType::Audio: {
-                        return "sent an audio file.";
-                }
-                case MsgType::Video: {
-                        return "sent a video";
-                }
-                default: {
-                        return related.quoted_formatted_body;
-                }
-                }
-        };
-        return QString("<mx-reply><blockquote><a "
-                       "href=\"https://matrix.to/#/%1/%2\">In reply "
-                       "to</a> <a href=\"https://matrix.to/#/%3\">%4</a><br"
-                       "/>%5</blockquote></mx-reply>")
-                 .arg(related.room,
-                      QString::fromStdString(related.related_event),
-                      related.quoted_user,
-                      related.quoted_user,
-                      getFormattedBody()) +
-               html;
+    return result;
 }
 
 QString
-utils::getQuoteBody(const RelatedInfo &related)
+utils::getFormattedQuoteBody(const RelatedInfo &related, const QString &html)
 {
+    auto getFormattedBody = [related]() -> QString {
         using MsgType = mtx::events::MessageType;
 
         switch (related.type) {
         case MsgType::File: {
-                return "sent a file.";
+            return "sent a file.";
         }
         case MsgType::Image: {
-                return "sent an image.";
+            return "sent an image.";
         }
         case MsgType::Audio: {
-                return "sent an audio file.";
+            return "sent an audio file.";
         }
         case MsgType::Video: {
-                return "sent a video";
+            return "sent a video";
         }
         default: {
-                return related.quoted_body;
+            return related.quoted_formatted_body;
         }
         }
+    };
+    return QString("<mx-reply><blockquote><a "
+                   "href=\"https://matrix.to/#/%1/%2\">In reply "
+                   "to</a> <a href=\"https://matrix.to/#/%3\">%4</a><br"
+                   "/>%5</blockquote></mx-reply>")
+             .arg(related.room,
+                  QString::fromStdString(related.related_event),
+                  related.quoted_user,
+                  related.quoted_user,
+                  getFormattedBody()) +
+           html;
+}
+
+QString
+utils::getQuoteBody(const RelatedInfo &related)
+{
+    using MsgType = mtx::events::MessageType;
+
+    switch (related.type) {
+    case MsgType::File: {
+        return "sent a file.";
+    }
+    case MsgType::Image: {
+        return "sent an image.";
+    }
+    case MsgType::Audio: {
+        return "sent an audio file.";
+    }
+    case MsgType::Video: {
+        return "sent a video";
+    }
+    default: {
+        return related.quoted_body;
+    }
+    }
 }
 
 QString
 utils::linkColor()
 {
-        const auto theme = UserSettings::instance()->theme();
+    const auto theme = UserSettings::instance()->theme();
 
-        if (theme == "light") {
-                return "#0077b5";
-        } else if (theme == "dark") {
-                return "#38A3D8";
-        } else {
-                return QPalette().color(QPalette::Link).name();
-        }
+    if (theme == "light") {
+        return "#0077b5";
+    } else if (theme == "dark") {
+        return "#38A3D8";
+    } else {
+        return QPalette().color(QPalette::Link).name();
+    }
 }
 
 uint32_t
 utils::hashQString(const QString &input)
 {
-        uint32_t hash = 0;
+    uint32_t hash = 0;
 
-        for (int i = 0; i < input.length(); i++) {
-                hash = input.at(i).digitValue() + ((hash << 5) - hash);
-        }
+    for (int i = 0; i < input.length(); i++) {
+        hash = input.at(i).digitValue() + ((hash << 5) - hash);
+    }
 
-        return hash;
+    return hash;
 }
 
 QColor
 utils::generateContrastingHexColor(const QString &input, const QColor &backgroundCol)
 {
-        const qreal backgroundLum = luminance(backgroundCol);
-
-        // Create a color for the input
-        auto hash = hashQString(input);
-        // create a hue value based on the hash of the input.
-        auto userHue = static_cast<int>(hash % 360);
-        // start with moderate saturation and lightness values.
-        auto sat       = 220;
-        auto lightness = 125;
-
-        // converting to a QColor makes the luminance calc easier.
-        QColor inputColor = QColor::fromHsl(userHue, sat, lightness);
-
-        // calculate the initial luminance and contrast of the
-        // generated color.  It's possible that no additional
-        // work will be necessary.
-        auto lum      = luminance(inputColor);
-        auto contrast = computeContrast(lum, backgroundLum);
-
-        // If the contrast doesn't meet our criteria,
-        // try again and again until they do by modifying first
-        // the lightness and then the saturation of the color.
-        int iterationCount = 9;
-        while (contrast < 5) {
-                // if our lightness is at it's bounds, try changing
-                // saturation instead.
-                if (lightness == 242 || lightness == 13) {
-                        qreal newSat = qBound(26.0, sat * 1.25, 242.0);
-
-                        inputColor.setHsl(userHue, qFloor(newSat), lightness);
-                        auto tmpLum         = luminance(inputColor);
-                        auto higherContrast = computeContrast(tmpLum, backgroundLum);
-                        if (higherContrast > contrast) {
-                                contrast = higherContrast;
-                                sat      = newSat;
-                        } else {
-                                newSat = qBound(26.0, sat / 1.25, 242.0);
-                                inputColor.setHsl(userHue, qFloor(newSat), lightness);
-                                tmpLum             = luminance(inputColor);
-                                auto lowerContrast = computeContrast(tmpLum, backgroundLum);
-                                if (lowerContrast > contrast) {
-                                        contrast = lowerContrast;
-                                        sat      = newSat;
-                                }
-                        }
-                } else {
-                        qreal newLightness = qBound(13.0, lightness * 1.25, 242.0);
-
-                        inputColor.setHsl(userHue, sat, qFloor(newLightness));
-
-                        auto tmpLum         = luminance(inputColor);
-                        auto higherContrast = computeContrast(tmpLum, backgroundLum);
-
-                        // Check to make sure we have actually improved contrast
-                        if (higherContrast > contrast) {
-                                contrast  = higherContrast;
-                                lightness = newLightness;
-                                // otherwise, try going the other way instead.
-                        } else {
-                                newLightness = qBound(13.0, lightness / 1.25, 242.0);
-                                inputColor.setHsl(userHue, sat, qFloor(newLightness));
-                                tmpLum             = luminance(inputColor);
-                                auto lowerContrast = computeContrast(tmpLum, backgroundLum);
-                                if (lowerContrast > contrast) {
-                                        contrast  = lowerContrast;
-                                        lightness = newLightness;
-                                }
-                        }
+    const qreal backgroundLum = luminance(backgroundCol);
+
+    // Create a color for the input
+    auto hash = hashQString(input);
+    // create a hue value based on the hash of the input.
+    auto userHue = static_cast<int>(hash % 360);
+    // start with moderate saturation and lightness values.
+    auto sat       = 220;
+    auto lightness = 125;
+
+    // converting to a QColor makes the luminance calc easier.
+    QColor inputColor = QColor::fromHsl(userHue, sat, lightness);
+
+    // calculate the initial luminance and contrast of the
+    // generated color.  It's possible that no additional
+    // work will be necessary.
+    auto lum      = luminance(inputColor);
+    auto contrast = computeContrast(lum, backgroundLum);
+
+    // If the contrast doesn't meet our criteria,
+    // try again and again until they do by modifying first
+    // the lightness and then the saturation of the color.
+    int iterationCount = 9;
+    while (contrast < 5) {
+        // if our lightness is at it's bounds, try changing
+        // saturation instead.
+        if (lightness == 242 || lightness == 13) {
+            qreal newSat = qBound(26.0, sat * 1.25, 242.0);
+
+            inputColor.setHsl(userHue, qFloor(newSat), lightness);
+            auto tmpLum         = luminance(inputColor);
+            auto higherContrast = computeContrast(tmpLum, backgroundLum);
+            if (higherContrast > contrast) {
+                contrast = higherContrast;
+                sat      = newSat;
+            } else {
+                newSat = qBound(26.0, sat / 1.25, 242.0);
+                inputColor.setHsl(userHue, qFloor(newSat), lightness);
+                tmpLum             = luminance(inputColor);
+                auto lowerContrast = computeContrast(tmpLum, backgroundLum);
+                if (lowerContrast > contrast) {
+                    contrast = lowerContrast;
+                    sat      = newSat;
                 }
-
-                // don't loop forever, just give up at some point!
-                // Someone smart may find a better solution
-                if (--iterationCount < 0)
-                        break;
+            }
+        } else {
+            qreal newLightness = qBound(13.0, lightness * 1.25, 242.0);
+
+            inputColor.setHsl(userHue, sat, qFloor(newLightness));
+
+            auto tmpLum         = luminance(inputColor);
+            auto higherContrast = computeContrast(tmpLum, backgroundLum);
+
+            // Check to make sure we have actually improved contrast
+            if (higherContrast > contrast) {
+                contrast  = higherContrast;
+                lightness = newLightness;
+                // otherwise, try going the other way instead.
+            } else {
+                newLightness = qBound(13.0, lightness / 1.25, 242.0);
+                inputColor.setHsl(userHue, sat, qFloor(newLightness));
+                tmpLum             = luminance(inputColor);
+                auto lowerContrast = computeContrast(tmpLum, backgroundLum);
+                if (lowerContrast > contrast) {
+                    contrast  = lowerContrast;
+                    lightness = newLightness;
+                }
+            }
         }
 
-        // get the hex value of the generated color.
-        auto colorHex = inputColor.name();
+        // don't loop forever, just give up at some point!
+        // Someone smart may find a better solution
+        if (--iterationCount < 0)
+            break;
+    }
 
-        return colorHex;
+    // get the hex value of the generated color.
+    auto colorHex = inputColor.name();
+
+    return colorHex;
 }
 
 qreal
 utils::computeContrast(const qreal &one, const qreal &two)
 {
-        auto ratio = (one + 0.05) / (two + 0.05);
+    auto ratio = (one + 0.05) / (two + 0.05);
 
-        if (two > one) {
-                ratio = 1 / ratio;
-        }
+    if (two > one) {
+        ratio = 1 / ratio;
+    }
 
-        return ratio;
+    return ratio;
 }
 
 qreal
 utils::luminance(const QColor &col)
 {
-        int colRgb[3] = {col.red(), col.green(), col.blue()};
-        qreal lumRgb[3];
+    int colRgb[3] = {col.red(), col.green(), col.blue()};
+    qreal lumRgb[3];
 
-        for (int i = 0; i < 3; i++) {
-                qreal v   = colRgb[i] / 255.0;
-                lumRgb[i] = v <= 0.03928 ? v / 12.92 : qPow((v + 0.055) / 1.055, 2.4);
-        }
+    for (int i = 0; i < 3; i++) {
+        qreal v   = colRgb[i] / 255.0;
+        lumRgb[i] = v <= 0.03928 ? v / 12.92 : qPow((v + 0.055) / 1.055, 2.4);
+    }
 
-        auto lum = lumRgb[0] * 0.2126 + lumRgb[1] * 0.7152 + lumRgb[2] * 0.0722;
+    auto lum = lumRgb[0] * 0.2126 + lumRgb[1] * 0.7152 + lumRgb[2] * 0.0722;
 
-        return lum;
+    return lum;
 }
 
 void
 utils::centerWidget(QWidget *widget, QWidget *parent)
 {
-        auto findCenter = [childRect = widget->rect()](QRect hostRect) -> QPoint {
-                return QPoint(hostRect.center().x() - (childRect.width() * 0.5),
-                              hostRect.center().y() - (childRect.height() * 0.5));
-        };
+    auto findCenter = [childRect = widget->rect()](QRect hostRect) -> QPoint {
+        return QPoint(hostRect.center().x() - (childRect.width() * 0.5),
+                      hostRect.center().y() - (childRect.height() * 0.5));
+    };
 
-        if (parent) {
-                widget->move(parent->window()->frameGeometry().topLeft() +
-                             parent->window()->rect().center() - widget->rect().center());
-                return;
-        }
+    if (parent) {
+        widget->move(parent->window()->frameGeometry().topLeft() +
+                     parent->window()->rect().center() - widget->rect().center());
+        return;
+    }
 
-        // Deprecated in 5.13: widget->move(findCenter(QApplication::desktop()->screenGeometry()));
-        widget->move(findCenter(QGuiApplication::primaryScreen()->geometry()));
+    // Deprecated in 5.13: widget->move(findCenter(QApplication::desktop()->screenGeometry()));
+    widget->move(findCenter(QGuiApplication::primaryScreen()->geometry()));
 }
 
 void
 utils::restoreCombobox(QComboBox *combo, const QString &value)
 {
-        for (auto i = 0; i < combo->count(); ++i) {
-                if (value == combo->itemText(i)) {
-                        combo->setCurrentIndex(i);
-                        break;
-                }
+    for (auto i = 0; i < combo->count(); ++i) {
+        if (value == combo->itemText(i)) {
+            combo->setCurrentIndex(i);
+            break;
         }
+    }
 }
 
 QImage
 utils::readImageFromFile(const QString &filename)
 {
-        QImageReader reader(filename);
-        reader.setAutoTransform(true);
-        return reader.read();
+    QImageReader reader(filename);
+    reader.setAutoTransform(true);
+    return reader.read();
 }
 QImage
 utils::readImage(const QByteArray &data)
 {
-        QBuffer buf;
-        buf.setData(data);
-        QImageReader reader(&buf);
-        reader.setAutoTransform(true);
-        return reader.read();
+    QBuffer buf;
+    buf.setData(data);
+    QImageReader reader(&buf);
+    reader.setAutoTransform(true);
+    return reader.read();
 }
 
 bool
 utils::isReply(const mtx::events::collections::TimelineEvents &e)
 {
-        return mtx::accessors::relations(e).reply_to().has_value();
+    return mtx::accessors::relations(e).reply_to().has_value();
 }
diff --git a/src/Utils.h b/src/Utils.h
index 8f37a574..da82ec7c 100644
--- a/src/Utils.h
+++ b/src/Utils.h
@@ -29,12 +29,12 @@ class QComboBox;
 // outgoing messages
 struct RelatedInfo
 {
-        using MsgType = mtx::events::MessageType;
-        MsgType type;
-        QString room;
-        QString quoted_body, quoted_formatted_body;
-        std::string related_event;
-        QString quoted_user;
+    using MsgType = mtx::events::MessageType;
+    MsgType type;
+    QString room;
+    QString quoted_body, quoted_formatted_body;
+    std::string related_event;
+    QString quoted_user;
 };
 
 namespace utils {
@@ -97,112 +97,96 @@ messageDescription(const QString &username = "",
                    const QString &body     = "",
                    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 Video      = mtx::events::RoomEvent<mtx::events::msg::Video>;
-        using CallInvite = mtx::events::RoomEvent<mtx::events::msg::CallInvite>;
-        using CallAnswer = mtx::events::RoomEvent<mtx::events::msg::CallAnswer>;
-        using CallHangUp = mtx::events::RoomEvent<mtx::events::msg::CallHangUp>;
-        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) {
-                if (isLocal)
-                        return QCoreApplication::translate("message-description sent:", "You: %1")
-                          .arg(body);
-                else
-                        return QCoreApplication::translate("message-description sent:", "%1: %2")
-                          .arg(username)
-                          .arg(body);
-        } else if (std::is_same<T, Emote>::value) {
-                return QString("* %1 %2").arg(username).arg(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 {
-                return QCoreApplication::translate("utils", "Unknown Message Type");
-        }
+    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 Video      = mtx::events::RoomEvent<mtx::events::msg::Video>;
+    using CallInvite = mtx::events::RoomEvent<mtx::events::msg::CallInvite>;
+    using CallAnswer = mtx::events::RoomEvent<mtx::events::msg::CallAnswer>;
+    using CallHangUp = mtx::events::RoomEvent<mtx::events::msg::CallHangUp>;
+    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) {
+        if (isLocal)
+            return QCoreApplication::translate("message-description sent:", "You: %1").arg(body);
+        else
+            return QCoreApplication::translate("message-description sent:", "%1: %2")
+              .arg(username)
+              .arg(body);
+    } else if (std::is_same<T, Emote>::value) {
+        return QString("* %1 %2").arg(username).arg(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 {
+        return QCoreApplication::translate("utils", "Unknown Message Type");
+    }
 }
 
 //! Scale down an image to fit to the given width & height limitations.
@@ -214,19 +198,19 @@ template<typename ContainerT, typename PredicateT>
 void
 erase_if(ContainerT &items, const PredicateT &predicate)
 {
-        for (auto it = items.begin(); it != items.end();) {
-                if (predicate(*it))
-                        it = items.erase(it);
-                else
-                        ++it;
-        }
+    for (auto it = items.begin(); it != items.end();) {
+        if (predicate(*it))
+            it = items.erase(it);
+        else
+            ++it;
+    }
 }
 
 template<class T>
 QString
 message_body(const mtx::events::collections::TimelineEvents &event)
 {
-        return QString::fromStdString(std::get<T>(event).content.body);
+    return QString::fromStdString(std::get<T>(event).content.body);
 }
 
 //! Calculate the Levenshtein distance between two strings with character skipping.
@@ -253,13 +237,13 @@ template<typename RoomMessageT>
 QString
 getMessageBody(const RoomMessageT &event)
 {
-        if (event.content.format.empty())
-                return QString::fromStdString(event.content.body).toHtmlEscaped();
+    if (event.content.format.empty())
+        return QString::fromStdString(event.content.body).toHtmlEscaped();
 
-        if (event.content.format != mtx::common::FORMAT_MSG_TYPE)
-                return QString::fromStdString(event.content.body).toHtmlEscaped();
+    if (event.content.format != mtx::common::FORMAT_MSG_TYPE)
+        return QString::fromStdString(event.content.body).toHtmlEscaped();
 
-        return QString::fromStdString(event.content.formatted_body);
+    return QString::fromStdString(event.content.formatted_body);
 }
 
 //! Replace raw URLs in text with HTML link tags.
diff --git a/src/WebRTCSession.cpp b/src/WebRTCSession.cpp
index 72330435..801a365c 100644
--- a/src/WebRTCSession.cpp
+++ b/src/WebRTCSession.cpp
@@ -43,47 +43,47 @@ using webrtc::State;
 WebRTCSession::WebRTCSession()
   : devices_(CallDevices::instance())
 {
-        qRegisterMetaType<webrtc::CallType>();
-        qmlRegisterUncreatableMetaObject(
-          webrtc::staticMetaObject, "im.nheko", 1, 0, "CallType", "Can't instantiate enum");
+    qRegisterMetaType<webrtc::CallType>();
+    qmlRegisterUncreatableMetaObject(
+      webrtc::staticMetaObject, "im.nheko", 1, 0, "CallType", "Can't instantiate enum");
 
-        qRegisterMetaType<webrtc::State>();
-        qmlRegisterUncreatableMetaObject(
-          webrtc::staticMetaObject, "im.nheko", 1, 0, "WebRTCState", "Can't instantiate enum");
+    qRegisterMetaType<webrtc::State>();
+    qmlRegisterUncreatableMetaObject(
+      webrtc::staticMetaObject, "im.nheko", 1, 0, "WebRTCState", "Can't instantiate enum");
 
-        connect(this, &WebRTCSession::stateChanged, this, &WebRTCSession::setState);
-        init();
+    connect(this, &WebRTCSession::stateChanged, this, &WebRTCSession::setState);
+    init();
 }
 
 bool
 WebRTCSession::init(std::string *errorMessage)
 {
 #ifdef GSTREAMER_AVAILABLE
-        if (initialised_)
-                return true;
+    if (initialised_)
+        return true;
 
-        GError *error = nullptr;
-        if (!gst_init_check(nullptr, nullptr, &error)) {
-                std::string strError("WebRTC: failed to initialise GStreamer: ");
-                if (error) {
-                        strError += error->message;
-                        g_error_free(error);
-                }
-                nhlog::ui()->error(strError);
-                if (errorMessage)
-                        *errorMessage = strError;
-                return false;
+    GError *error = nullptr;
+    if (!gst_init_check(nullptr, nullptr, &error)) {
+        std::string strError("WebRTC: failed to initialise GStreamer: ");
+        if (error) {
+            strError += error->message;
+            g_error_free(error);
         }
-
-        initialised_   = true;
-        gchar *version = gst_version_string();
-        nhlog::ui()->info("WebRTC: initialised {}", version);
-        g_free(version);
-        devices_.init();
-        return true;
-#else
-        (void)errorMessage;
+        nhlog::ui()->error(strError);
+        if (errorMessage)
+            *errorMessage = strError;
         return false;
+    }
+
+    initialised_   = true;
+    gchar *version = gst_version_string();
+    nhlog::ui()->info("WebRTC: initialised {}", version);
+    g_free(version);
+    devices_.init();
+    return true;
+#else
+    (void)errorMessage;
+    return false;
 #endif
 }
 
@@ -100,81 +100,77 @@ GstPad *remotePiPSinkPad_ = nullptr;
 gboolean
 newBusMessage(GstBus *bus G_GNUC_UNUSED, GstMessage *msg, gpointer user_data)
 {
-        WebRTCSession *session = static_cast<WebRTCSession *>(user_data);
-        switch (GST_MESSAGE_TYPE(msg)) {
-        case GST_MESSAGE_EOS:
-                nhlog::ui()->error("WebRTC: end of stream");
-                session->end();
-                break;
-        case GST_MESSAGE_ERROR:
-                GError *error;
-                gchar *debug;
-                gst_message_parse_error(msg, &error, &debug);
-                nhlog::ui()->error(
-                  "WebRTC: error from element {}: {}", GST_OBJECT_NAME(msg->src), error->message);
-                g_clear_error(&error);
-                g_free(debug);
-                session->end();
-                break;
-        default:
-                break;
-        }
-        return TRUE;
+    WebRTCSession *session = static_cast<WebRTCSession *>(user_data);
+    switch (GST_MESSAGE_TYPE(msg)) {
+    case GST_MESSAGE_EOS:
+        nhlog::ui()->error("WebRTC: end of stream");
+        session->end();
+        break;
+    case GST_MESSAGE_ERROR:
+        GError *error;
+        gchar *debug;
+        gst_message_parse_error(msg, &error, &debug);
+        nhlog::ui()->error(
+          "WebRTC: error from element {}: {}", GST_OBJECT_NAME(msg->src), error->message);
+        g_clear_error(&error);
+        g_free(debug);
+        session->end();
+        break;
+    default:
+        break;
+    }
+    return TRUE;
 }
 
 GstWebRTCSessionDescription *
 parseSDP(const std::string &sdp, GstWebRTCSDPType type)
 {
-        GstSDPMessage *msg;
-        gst_sdp_message_new(&msg);
-        if (gst_sdp_message_parse_buffer((guint8 *)sdp.c_str(), sdp.size(), msg) == GST_SDP_OK) {
-                return gst_webrtc_session_description_new(type, msg);
-        } else {
-                nhlog::ui()->error("WebRTC: failed to parse remote session description");
-                gst_sdp_message_free(msg);
-                return nullptr;
-        }
+    GstSDPMessage *msg;
+    gst_sdp_message_new(&msg);
+    if (gst_sdp_message_parse_buffer((guint8 *)sdp.c_str(), sdp.size(), msg) == GST_SDP_OK) {
+        return gst_webrtc_session_description_new(type, msg);
+    } else {
+        nhlog::ui()->error("WebRTC: failed to parse remote session description");
+        gst_sdp_message_free(msg);
+        return nullptr;
+    }
 }
 
 void
 setLocalDescription(GstPromise *promise, gpointer webrtc)
 {
-        const GstStructure *reply = gst_promise_get_reply(promise);
-        gboolean isAnswer = gst_structure_id_has_field(reply, g_quark_from_string("answer"));
-        GstWebRTCSessionDescription *gstsdp = nullptr;
-        gst_structure_get(reply,
-                          isAnswer ? "answer" : "offer",
-                          GST_TYPE_WEBRTC_SESSION_DESCRIPTION,
-                          &gstsdp,
-                          nullptr);
-        gst_promise_unref(promise);
-        g_signal_emit_by_name(webrtc, "set-local-description", gstsdp, nullptr);
-
-        gchar *sdp = gst_sdp_message_as_text(gstsdp->sdp);
-        localsdp_  = std::string(sdp);
-        g_free(sdp);
-        gst_webrtc_session_description_free(gstsdp);
-
-        nhlog::ui()->debug(
-          "WebRTC: local description set ({}):\n{}", isAnswer ? "answer" : "offer", localsdp_);
+    const GstStructure *reply = gst_promise_get_reply(promise);
+    gboolean isAnswer         = gst_structure_id_has_field(reply, g_quark_from_string("answer"));
+    GstWebRTCSessionDescription *gstsdp = nullptr;
+    gst_structure_get(
+      reply, isAnswer ? "answer" : "offer", GST_TYPE_WEBRTC_SESSION_DESCRIPTION, &gstsdp, nullptr);
+    gst_promise_unref(promise);
+    g_signal_emit_by_name(webrtc, "set-local-description", gstsdp, nullptr);
+
+    gchar *sdp = gst_sdp_message_as_text(gstsdp->sdp);
+    localsdp_  = std::string(sdp);
+    g_free(sdp);
+    gst_webrtc_session_description_free(gstsdp);
+
+    nhlog::ui()->debug(
+      "WebRTC: local description set ({}):\n{}", isAnswer ? "answer" : "offer", localsdp_);
 }
 
 void
 createOffer(GstElement *webrtc)
 {
-        // create-offer first, then set-local-description
-        GstPromise *promise =
-          gst_promise_new_with_change_func(setLocalDescription, webrtc, nullptr);
-        g_signal_emit_by_name(webrtc, "create-offer", nullptr, promise);
+    // create-offer first, then set-local-description
+    GstPromise *promise = gst_promise_new_with_change_func(setLocalDescription, webrtc, nullptr);
+    g_signal_emit_by_name(webrtc, "create-offer", nullptr, promise);
 }
 
 void
 createAnswer(GstPromise *promise, gpointer webrtc)
 {
-        // create-answer first, then set-local-description
-        gst_promise_unref(promise);
-        promise = gst_promise_new_with_change_func(setLocalDescription, webrtc, nullptr);
-        g_signal_emit_by_name(webrtc, "create-answer", nullptr, promise);
+    // create-answer first, then set-local-description
+    gst_promise_unref(promise);
+    promise = gst_promise_new_with_change_func(setLocalDescription, webrtc, nullptr);
+    g_signal_emit_by_name(webrtc, "create-answer", nullptr, promise);
 }
 
 void
@@ -182,18 +178,18 @@ iceGatheringStateChanged(GstElement *webrtc,
                          GParamSpec *pspec G_GNUC_UNUSED,
                          gpointer user_data G_GNUC_UNUSED)
 {
-        GstWebRTCICEGatheringState newState;
-        g_object_get(webrtc, "ice-gathering-state", &newState, nullptr);
-        if (newState == GST_WEBRTC_ICE_GATHERING_STATE_COMPLETE) {
-                nhlog::ui()->debug("WebRTC: GstWebRTCICEGatheringState -> Complete");
-                if (WebRTCSession::instance().isOffering()) {
-                        emit WebRTCSession::instance().offerCreated(localsdp_, localcandidates_);
-                        emit WebRTCSession::instance().stateChanged(State::OFFERSENT);
-                } else {
-                        emit WebRTCSession::instance().answerCreated(localsdp_, localcandidates_);
-                        emit WebRTCSession::instance().stateChanged(State::ANSWERSENT);
-                }
+    GstWebRTCICEGatheringState newState;
+    g_object_get(webrtc, "ice-gathering-state", &newState, nullptr);
+    if (newState == GST_WEBRTC_ICE_GATHERING_STATE_COMPLETE) {
+        nhlog::ui()->debug("WebRTC: GstWebRTCICEGatheringState -> Complete");
+        if (WebRTCSession::instance().isOffering()) {
+            emit WebRTCSession::instance().offerCreated(localsdp_, localcandidates_);
+            emit WebRTCSession::instance().stateChanged(State::OFFERSENT);
+        } else {
+            emit WebRTCSession::instance().answerCreated(localsdp_, localcandidates_);
+            emit WebRTCSession::instance().stateChanged(State::ANSWERSENT);
         }
+    }
 }
 
 void
@@ -202,8 +198,8 @@ addLocalICECandidate(GstElement *webrtc G_GNUC_UNUSED,
                      gchar *candidate,
                      gpointer G_GNUC_UNUSED)
 {
-        nhlog::ui()->debug("WebRTC: local candidate: (m-line:{}):{}", mlineIndex, candidate);
-        localcandidates_.push_back({std::string() /*max-bundle*/, (uint16_t)mlineIndex, candidate});
+    nhlog::ui()->debug("WebRTC: local candidate: (m-line:{}):{}", mlineIndex, candidate);
+    localcandidates_.push_back({std::string() /*max-bundle*/, (uint16_t)mlineIndex, candidate});
 }
 
 void
@@ -211,337 +207,327 @@ iceConnectionStateChanged(GstElement *webrtc,
                           GParamSpec *pspec G_GNUC_UNUSED,
                           gpointer user_data G_GNUC_UNUSED)
 {
-        GstWebRTCICEConnectionState newState;
-        g_object_get(webrtc, "ice-connection-state", &newState, nullptr);
-        switch (newState) {
-        case GST_WEBRTC_ICE_CONNECTION_STATE_CHECKING:
-                nhlog::ui()->debug("WebRTC: GstWebRTCICEConnectionState -> Checking");
-                emit WebRTCSession::instance().stateChanged(State::CONNECTING);
-                break;
-        case GST_WEBRTC_ICE_CONNECTION_STATE_FAILED:
-                nhlog::ui()->error("WebRTC: GstWebRTCICEConnectionState -> Failed");
-                emit WebRTCSession::instance().stateChanged(State::ICEFAILED);
-                break;
-        default:
-                break;
-        }
+    GstWebRTCICEConnectionState newState;
+    g_object_get(webrtc, "ice-connection-state", &newState, nullptr);
+    switch (newState) {
+    case GST_WEBRTC_ICE_CONNECTION_STATE_CHECKING:
+        nhlog::ui()->debug("WebRTC: GstWebRTCICEConnectionState -> Checking");
+        emit WebRTCSession::instance().stateChanged(State::CONNECTING);
+        break;
+    case GST_WEBRTC_ICE_CONNECTION_STATE_FAILED:
+        nhlog::ui()->error("WebRTC: GstWebRTCICEConnectionState -> Failed");
+        emit WebRTCSession::instance().stateChanged(State::ICEFAILED);
+        break;
+    default:
+        break;
+    }
 }
 
 // https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/issues/1164
 struct KeyFrameRequestData
 {
-        GstElement *pipe      = nullptr;
-        GstElement *decodebin = nullptr;
-        gint packetsLost      = 0;
-        guint timerid         = 0;
-        std::string statsField;
+    GstElement *pipe      = nullptr;
+    GstElement *decodebin = nullptr;
+    gint packetsLost      = 0;
+    guint timerid         = 0;
+    std::string statsField;
 } keyFrameRequestData_;
 
 void
 sendKeyFrameRequest()
 {
-        GstPad *sinkpad = gst_element_get_static_pad(keyFrameRequestData_.decodebin, "sink");
-        if (!gst_pad_push_event(sinkpad,
-                                gst_event_new_custom(GST_EVENT_CUSTOM_UPSTREAM,
-                                                     gst_structure_new_empty("GstForceKeyUnit"))))
-                nhlog::ui()->error("WebRTC: key frame request failed");
-        else
-                nhlog::ui()->debug("WebRTC: sent key frame request");
-
-        gst_object_unref(sinkpad);
+    GstPad *sinkpad = gst_element_get_static_pad(keyFrameRequestData_.decodebin, "sink");
+    if (!gst_pad_push_event(sinkpad,
+                            gst_event_new_custom(GST_EVENT_CUSTOM_UPSTREAM,
+                                                 gst_structure_new_empty("GstForceKeyUnit"))))
+        nhlog::ui()->error("WebRTC: key frame request failed");
+    else
+        nhlog::ui()->debug("WebRTC: sent key frame request");
+
+    gst_object_unref(sinkpad);
 }
 
 void
 testPacketLoss_(GstPromise *promise, gpointer G_GNUC_UNUSED)
 {
-        const GstStructure *reply = gst_promise_get_reply(promise);
-        gint packetsLost          = 0;
-        GstStructure *rtpStats;
-        if (!gst_structure_get(reply,
-                               keyFrameRequestData_.statsField.c_str(),
-                               GST_TYPE_STRUCTURE,
-                               &rtpStats,
-                               nullptr)) {
-                nhlog::ui()->error("WebRTC: get-stats: no field: {}",
-                                   keyFrameRequestData_.statsField);
-                gst_promise_unref(promise);
-                return;
-        }
-        gst_structure_get_int(rtpStats, "packets-lost", &packetsLost);
-        gst_structure_free(rtpStats);
+    const GstStructure *reply = gst_promise_get_reply(promise);
+    gint packetsLost          = 0;
+    GstStructure *rtpStats;
+    if (!gst_structure_get(
+          reply, keyFrameRequestData_.statsField.c_str(), GST_TYPE_STRUCTURE, &rtpStats, nullptr)) {
+        nhlog::ui()->error("WebRTC: get-stats: no field: {}", keyFrameRequestData_.statsField);
         gst_promise_unref(promise);
-        if (packetsLost > keyFrameRequestData_.packetsLost) {
-                nhlog::ui()->debug("WebRTC: inbound video lost packet count: {}", packetsLost);
-                keyFrameRequestData_.packetsLost = packetsLost;
-                sendKeyFrameRequest();
-        }
+        return;
+    }
+    gst_structure_get_int(rtpStats, "packets-lost", &packetsLost);
+    gst_structure_free(rtpStats);
+    gst_promise_unref(promise);
+    if (packetsLost > keyFrameRequestData_.packetsLost) {
+        nhlog::ui()->debug("WebRTC: inbound video lost packet count: {}", packetsLost);
+        keyFrameRequestData_.packetsLost = packetsLost;
+        sendKeyFrameRequest();
+    }
 }
 
 gboolean
 testPacketLoss(gpointer G_GNUC_UNUSED)
 {
-        if (keyFrameRequestData_.pipe) {
-                GstElement *webrtc =
-                  gst_bin_get_by_name(GST_BIN(keyFrameRequestData_.pipe), "webrtcbin");
-                GstPromise *promise =
-                  gst_promise_new_with_change_func(testPacketLoss_, nullptr, nullptr);
-                g_signal_emit_by_name(webrtc, "get-stats", nullptr, promise);
-                gst_object_unref(webrtc);
-                return TRUE;
-        }
-        return FALSE;
+    if (keyFrameRequestData_.pipe) {
+        GstElement *webrtc  = gst_bin_get_by_name(GST_BIN(keyFrameRequestData_.pipe), "webrtcbin");
+        GstPromise *promise = gst_promise_new_with_change_func(testPacketLoss_, nullptr, nullptr);
+        g_signal_emit_by_name(webrtc, "get-stats", nullptr, promise);
+        gst_object_unref(webrtc);
+        return TRUE;
+    }
+    return FALSE;
 }
 
 void
 setWaitForKeyFrame(GstBin *decodebin G_GNUC_UNUSED, GstElement *element, gpointer G_GNUC_UNUSED)
 {
-        if (!std::strcmp(
-              gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(gst_element_get_factory(element))),
-              "rtpvp8depay"))
-                g_object_set(element, "wait-for-keyframe", TRUE, nullptr);
+    if (!std::strcmp(
+          gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(gst_element_get_factory(element))),
+          "rtpvp8depay"))
+        g_object_set(element, "wait-for-keyframe", TRUE, nullptr);
 }
 
 GstElement *
 newAudioSinkChain(GstElement *pipe)
 {
-        GstElement *queue    = gst_element_factory_make("queue", nullptr);
-        GstElement *convert  = gst_element_factory_make("audioconvert", nullptr);
-        GstElement *resample = gst_element_factory_make("audioresample", nullptr);
-        GstElement *sink     = gst_element_factory_make("autoaudiosink", nullptr);
-        gst_bin_add_many(GST_BIN(pipe), queue, convert, resample, sink, nullptr);
-        gst_element_link_many(queue, convert, resample, sink, nullptr);
-        gst_element_sync_state_with_parent(queue);
-        gst_element_sync_state_with_parent(convert);
-        gst_element_sync_state_with_parent(resample);
-        gst_element_sync_state_with_parent(sink);
-        return queue;
+    GstElement *queue    = gst_element_factory_make("queue", nullptr);
+    GstElement *convert  = gst_element_factory_make("audioconvert", nullptr);
+    GstElement *resample = gst_element_factory_make("audioresample", nullptr);
+    GstElement *sink     = gst_element_factory_make("autoaudiosink", nullptr);
+    gst_bin_add_many(GST_BIN(pipe), queue, convert, resample, sink, nullptr);
+    gst_element_link_many(queue, convert, resample, sink, nullptr);
+    gst_element_sync_state_with_parent(queue);
+    gst_element_sync_state_with_parent(convert);
+    gst_element_sync_state_with_parent(resample);
+    gst_element_sync_state_with_parent(sink);
+    return queue;
 }
 
 GstElement *
 newVideoSinkChain(GstElement *pipe)
 {
-        // use compositor for now; acceleration needs investigation
-        GstElement *queue          = gst_element_factory_make("queue", nullptr);
-        GstElement *compositor     = gst_element_factory_make("compositor", "compositor");
-        GstElement *glupload       = gst_element_factory_make("glupload", nullptr);
-        GstElement *glcolorconvert = gst_element_factory_make("glcolorconvert", nullptr);
-        GstElement *qmlglsink      = gst_element_factory_make("qmlglsink", nullptr);
-        GstElement *glsinkbin      = gst_element_factory_make("glsinkbin", nullptr);
-        g_object_set(compositor, "background", 1, nullptr);
-        g_object_set(qmlglsink, "widget", WebRTCSession::instance().getVideoItem(), nullptr);
-        g_object_set(glsinkbin, "sink", qmlglsink, nullptr);
-        gst_bin_add_many(
-          GST_BIN(pipe), queue, compositor, glupload, glcolorconvert, glsinkbin, nullptr);
-        gst_element_link_many(queue, compositor, glupload, glcolorconvert, glsinkbin, nullptr);
-        gst_element_sync_state_with_parent(queue);
-        gst_element_sync_state_with_parent(compositor);
-        gst_element_sync_state_with_parent(glupload);
-        gst_element_sync_state_with_parent(glcolorconvert);
-        gst_element_sync_state_with_parent(glsinkbin);
-        return queue;
+    // use compositor for now; acceleration needs investigation
+    GstElement *queue          = gst_element_factory_make("queue", nullptr);
+    GstElement *compositor     = gst_element_factory_make("compositor", "compositor");
+    GstElement *glupload       = gst_element_factory_make("glupload", nullptr);
+    GstElement *glcolorconvert = gst_element_factory_make("glcolorconvert", nullptr);
+    GstElement *qmlglsink      = gst_element_factory_make("qmlglsink", nullptr);
+    GstElement *glsinkbin      = gst_element_factory_make("glsinkbin", nullptr);
+    g_object_set(compositor, "background", 1, nullptr);
+    g_object_set(qmlglsink, "widget", WebRTCSession::instance().getVideoItem(), nullptr);
+    g_object_set(glsinkbin, "sink", qmlglsink, nullptr);
+    gst_bin_add_many(
+      GST_BIN(pipe), queue, compositor, glupload, glcolorconvert, glsinkbin, nullptr);
+    gst_element_link_many(queue, compositor, glupload, glcolorconvert, glsinkbin, nullptr);
+    gst_element_sync_state_with_parent(queue);
+    gst_element_sync_state_with_parent(compositor);
+    gst_element_sync_state_with_parent(glupload);
+    gst_element_sync_state_with_parent(glcolorconvert);
+    gst_element_sync_state_with_parent(glsinkbin);
+    return queue;
 }
 
 std::pair<int, int>
 getResolution(GstPad *pad)
 {
-        std::pair<int, int> ret;
-        GstCaps *caps         = gst_pad_get_current_caps(pad);
-        const GstStructure *s = gst_caps_get_structure(caps, 0);
-        gst_structure_get_int(s, "width", &ret.first);
-        gst_structure_get_int(s, "height", &ret.second);
-        gst_caps_unref(caps);
-        return ret;
+    std::pair<int, int> ret;
+    GstCaps *caps         = gst_pad_get_current_caps(pad);
+    const GstStructure *s = gst_caps_get_structure(caps, 0);
+    gst_structure_get_int(s, "width", &ret.first);
+    gst_structure_get_int(s, "height", &ret.second);
+    gst_caps_unref(caps);
+    return ret;
 }
 
 std::pair<int, int>
 getResolution(GstElement *pipe, const gchar *elementName, const gchar *padName)
 {
-        GstElement *element = gst_bin_get_by_name(GST_BIN(pipe), elementName);
-        GstPad *pad         = gst_element_get_static_pad(element, padName);
-        auto ret            = getResolution(pad);
-        gst_object_unref(pad);
-        gst_object_unref(element);
-        return ret;
+    GstElement *element = gst_bin_get_by_name(GST_BIN(pipe), elementName);
+    GstPad *pad         = gst_element_get_static_pad(element, padName);
+    auto ret            = getResolution(pad);
+    gst_object_unref(pad);
+    gst_object_unref(element);
+    return ret;
 }
 
 std::pair<int, int>
 getPiPDimensions(const std::pair<int, int> &resolution, int fullWidth, double scaleFactor)
 {
-        int pipWidth  = fullWidth * scaleFactor;
-        int pipHeight = static_cast<double>(resolution.second) / resolution.first * pipWidth;
-        return {pipWidth, pipHeight};
+    int pipWidth  = fullWidth * scaleFactor;
+    int pipHeight = static_cast<double>(resolution.second) / resolution.first * pipWidth;
+    return {pipWidth, pipHeight};
 }
 
 void
 addLocalPiP(GstElement *pipe, const std::pair<int, int> &videoCallSize)
 {
-        // embed localUser's camera into received video (CallType::VIDEO)
-        // OR embed screen share into received video (CallType::SCREEN)
-        GstElement *tee = gst_bin_get_by_name(GST_BIN(pipe), "videosrctee");
-        if (!tee)
-                return;
-
-        GstElement *queue = gst_element_factory_make("queue", nullptr);
-        gst_bin_add(GST_BIN(pipe), queue);
-        gst_element_link(tee, queue);
-        gst_element_sync_state_with_parent(queue);
-        gst_object_unref(tee);
-
-        GstElement *compositor = gst_bin_get_by_name(GST_BIN(pipe), "compositor");
-        localPiPSinkPad_       = gst_element_get_request_pad(compositor, "sink_%u");
-        g_object_set(localPiPSinkPad_, "zorder", 2, nullptr);
-
-        bool isVideo         = WebRTCSession::instance().callType() == CallType::VIDEO;
-        const gchar *element = isVideo ? "camerafilter" : "screenshare";
-        const gchar *pad     = isVideo ? "sink" : "src";
-        auto resolution      = getResolution(pipe, element, pad);
-        auto pipSize         = getPiPDimensions(resolution, videoCallSize.first, 0.25);
-        nhlog::ui()->debug(
-          "WebRTC: local picture-in-picture: {}x{}", pipSize.first, pipSize.second);
-        g_object_set(localPiPSinkPad_, "width", pipSize.first, "height", pipSize.second, nullptr);
-        gint offset = videoCallSize.first / 80;
-        g_object_set(localPiPSinkPad_, "xpos", offset, "ypos", offset, nullptr);
-
-        GstPad *srcpad = gst_element_get_static_pad(queue, "src");
-        if (GST_PAD_LINK_FAILED(gst_pad_link(srcpad, localPiPSinkPad_)))
-                nhlog::ui()->error("WebRTC: failed to link local PiP elements");
-        gst_object_unref(srcpad);
-        gst_object_unref(compositor);
+    // embed localUser's camera into received video (CallType::VIDEO)
+    // OR embed screen share into received video (CallType::SCREEN)
+    GstElement *tee = gst_bin_get_by_name(GST_BIN(pipe), "videosrctee");
+    if (!tee)
+        return;
+
+    GstElement *queue = gst_element_factory_make("queue", nullptr);
+    gst_bin_add(GST_BIN(pipe), queue);
+    gst_element_link(tee, queue);
+    gst_element_sync_state_with_parent(queue);
+    gst_object_unref(tee);
+
+    GstElement *compositor = gst_bin_get_by_name(GST_BIN(pipe), "compositor");
+    localPiPSinkPad_       = gst_element_get_request_pad(compositor, "sink_%u");
+    g_object_set(localPiPSinkPad_, "zorder", 2, nullptr);
+
+    bool isVideo         = WebRTCSession::instance().callType() == CallType::VIDEO;
+    const gchar *element = isVideo ? "camerafilter" : "screenshare";
+    const gchar *pad     = isVideo ? "sink" : "src";
+    auto resolution      = getResolution(pipe, element, pad);
+    auto pipSize         = getPiPDimensions(resolution, videoCallSize.first, 0.25);
+    nhlog::ui()->debug("WebRTC: local picture-in-picture: {}x{}", pipSize.first, pipSize.second);
+    g_object_set(localPiPSinkPad_, "width", pipSize.first, "height", pipSize.second, nullptr);
+    gint offset = videoCallSize.first / 80;
+    g_object_set(localPiPSinkPad_, "xpos", offset, "ypos", offset, nullptr);
+
+    GstPad *srcpad = gst_element_get_static_pad(queue, "src");
+    if (GST_PAD_LINK_FAILED(gst_pad_link(srcpad, localPiPSinkPad_)))
+        nhlog::ui()->error("WebRTC: failed to link local PiP elements");
+    gst_object_unref(srcpad);
+    gst_object_unref(compositor);
 }
 
 void
 addRemotePiP(GstElement *pipe)
 {
-        // embed localUser's camera into screen image being shared
-        if (remotePiPSinkPad_) {
-                auto camRes   = getResolution(pipe, "camerafilter", "sink");
-                auto shareRes = getResolution(pipe, "screenshare", "src");
-                auto pipSize  = getPiPDimensions(camRes, shareRes.first, 0.2);
-                nhlog::ui()->debug(
-                  "WebRTC: screen share picture-in-picture: {}x{}", pipSize.first, pipSize.second);
-
-                gint offset = shareRes.first / 100;
-                g_object_set(remotePiPSinkPad_, "zorder", 2, nullptr);
-                g_object_set(
-                  remotePiPSinkPad_, "width", pipSize.first, "height", pipSize.second, nullptr);
-                g_object_set(remotePiPSinkPad_,
-                             "xpos",
-                             shareRes.first - pipSize.first - offset,
-                             "ypos",
-                             shareRes.second - pipSize.second - offset,
-                             nullptr);
-        }
+    // embed localUser's camera into screen image being shared
+    if (remotePiPSinkPad_) {
+        auto camRes   = getResolution(pipe, "camerafilter", "sink");
+        auto shareRes = getResolution(pipe, "screenshare", "src");
+        auto pipSize  = getPiPDimensions(camRes, shareRes.first, 0.2);
+        nhlog::ui()->debug(
+          "WebRTC: screen share picture-in-picture: {}x{}", pipSize.first, pipSize.second);
+
+        gint offset = shareRes.first / 100;
+        g_object_set(remotePiPSinkPad_, "zorder", 2, nullptr);
+        g_object_set(remotePiPSinkPad_, "width", pipSize.first, "height", pipSize.second, nullptr);
+        g_object_set(remotePiPSinkPad_,
+                     "xpos",
+                     shareRes.first - pipSize.first - offset,
+                     "ypos",
+                     shareRes.second - pipSize.second - offset,
+                     nullptr);
+    }
 }
 
 void
 addLocalVideo(GstElement *pipe)
 {
-        GstElement *queue = newVideoSinkChain(pipe);
-        GstElement *tee   = gst_bin_get_by_name(GST_BIN(pipe), "videosrctee");
-        GstPad *srcpad    = gst_element_get_request_pad(tee, "src_%u");
-        GstPad *sinkpad   = gst_element_get_static_pad(queue, "sink");
-        if (GST_PAD_LINK_FAILED(gst_pad_link(srcpad, sinkpad)))
-                nhlog::ui()->error("WebRTC: failed to link videosrctee -> video sink chain");
-        gst_object_unref(srcpad);
+    GstElement *queue = newVideoSinkChain(pipe);
+    GstElement *tee   = gst_bin_get_by_name(GST_BIN(pipe), "videosrctee");
+    GstPad *srcpad    = gst_element_get_request_pad(tee, "src_%u");
+    GstPad *sinkpad   = gst_element_get_static_pad(queue, "sink");
+    if (GST_PAD_LINK_FAILED(gst_pad_link(srcpad, sinkpad)))
+        nhlog::ui()->error("WebRTC: failed to link videosrctee -> video sink chain");
+    gst_object_unref(srcpad);
 }
 
 void
 linkNewPad(GstElement *decodebin, GstPad *newpad, GstElement *pipe)
 {
-        GstPad *sinkpad               = gst_element_get_static_pad(decodebin, "sink");
-        GstCaps *sinkcaps             = gst_pad_get_current_caps(sinkpad);
-        const GstStructure *structure = gst_caps_get_structure(sinkcaps, 0);
-
-        gchar *mediaType = nullptr;
-        guint ssrc       = 0;
-        gst_structure_get(
-          structure, "media", G_TYPE_STRING, &mediaType, "ssrc", G_TYPE_UINT, &ssrc, nullptr);
-        gst_caps_unref(sinkcaps);
-        gst_object_unref(sinkpad);
-
-        WebRTCSession *session = &WebRTCSession::instance();
-        GstElement *queue      = nullptr;
-        if (!std::strcmp(mediaType, "audio")) {
-                nhlog::ui()->debug("WebRTC: received incoming audio stream");
-                haveAudioStream_ = true;
-                queue            = newAudioSinkChain(pipe);
-        } else if (!std::strcmp(mediaType, "video")) {
-                nhlog::ui()->debug("WebRTC: received incoming video stream");
-                if (!session->getVideoItem()) {
-                        g_free(mediaType);
-                        nhlog::ui()->error("WebRTC: video call item not set");
-                        return;
-                }
-                haveVideoStream_ = true;
-                keyFrameRequestData_.statsField =
-                  std::string("rtp-inbound-stream-stats_") + std::to_string(ssrc);
-                queue              = newVideoSinkChain(pipe);
-                auto videoCallSize = getResolution(newpad);
-                nhlog::ui()->info("WebRTC: incoming video resolution: {}x{}",
-                                  videoCallSize.first,
-                                  videoCallSize.second);
-                addLocalPiP(pipe, videoCallSize);
-        } else {
-                g_free(mediaType);
-                nhlog::ui()->error("WebRTC: unknown pad type: {}", GST_PAD_NAME(newpad));
-                return;
+    GstPad *sinkpad               = gst_element_get_static_pad(decodebin, "sink");
+    GstCaps *sinkcaps             = gst_pad_get_current_caps(sinkpad);
+    const GstStructure *structure = gst_caps_get_structure(sinkcaps, 0);
+
+    gchar *mediaType = nullptr;
+    guint ssrc       = 0;
+    gst_structure_get(
+      structure, "media", G_TYPE_STRING, &mediaType, "ssrc", G_TYPE_UINT, &ssrc, nullptr);
+    gst_caps_unref(sinkcaps);
+    gst_object_unref(sinkpad);
+
+    WebRTCSession *session = &WebRTCSession::instance();
+    GstElement *queue      = nullptr;
+    if (!std::strcmp(mediaType, "audio")) {
+        nhlog::ui()->debug("WebRTC: received incoming audio stream");
+        haveAudioStream_ = true;
+        queue            = newAudioSinkChain(pipe);
+    } else if (!std::strcmp(mediaType, "video")) {
+        nhlog::ui()->debug("WebRTC: received incoming video stream");
+        if (!session->getVideoItem()) {
+            g_free(mediaType);
+            nhlog::ui()->error("WebRTC: video call item not set");
+            return;
         }
-
-        GstPad *queuepad = gst_element_get_static_pad(queue, "sink");
-        if (queuepad) {
-                if (GST_PAD_LINK_FAILED(gst_pad_link(newpad, queuepad)))
-                        nhlog::ui()->error("WebRTC: unable to link new pad");
-                else {
-                        if (session->callType() == CallType::VOICE ||
-                            (haveAudioStream_ &&
-                             (haveVideoStream_ || session->isRemoteVideoRecvOnly()))) {
-                                emit session->stateChanged(State::CONNECTED);
-                                if (haveVideoStream_) {
-                                        keyFrameRequestData_.pipe      = pipe;
-                                        keyFrameRequestData_.decodebin = decodebin;
-                                        keyFrameRequestData_.timerid =
-                                          g_timeout_add_seconds(3, testPacketLoss, nullptr);
-                                }
-                                addRemotePiP(pipe);
-                                if (session->isRemoteVideoRecvOnly())
-                                        addLocalVideo(pipe);
-                        }
+        haveVideoStream_ = true;
+        keyFrameRequestData_.statsField =
+          std::string("rtp-inbound-stream-stats_") + std::to_string(ssrc);
+        queue              = newVideoSinkChain(pipe);
+        auto videoCallSize = getResolution(newpad);
+        nhlog::ui()->info(
+          "WebRTC: incoming video resolution: {}x{}", videoCallSize.first, videoCallSize.second);
+        addLocalPiP(pipe, videoCallSize);
+    } else {
+        g_free(mediaType);
+        nhlog::ui()->error("WebRTC: unknown pad type: {}", GST_PAD_NAME(newpad));
+        return;
+    }
+
+    GstPad *queuepad = gst_element_get_static_pad(queue, "sink");
+    if (queuepad) {
+        if (GST_PAD_LINK_FAILED(gst_pad_link(newpad, queuepad)))
+            nhlog::ui()->error("WebRTC: unable to link new pad");
+        else {
+            if (session->callType() == CallType::VOICE ||
+                (haveAudioStream_ && (haveVideoStream_ || session->isRemoteVideoRecvOnly()))) {
+                emit session->stateChanged(State::CONNECTED);
+                if (haveVideoStream_) {
+                    keyFrameRequestData_.pipe      = pipe;
+                    keyFrameRequestData_.decodebin = decodebin;
+                    keyFrameRequestData_.timerid =
+                      g_timeout_add_seconds(3, testPacketLoss, nullptr);
                 }
-                gst_object_unref(queuepad);
+                addRemotePiP(pipe);
+                if (session->isRemoteVideoRecvOnly())
+                    addLocalVideo(pipe);
+            }
         }
-        g_free(mediaType);
+        gst_object_unref(queuepad);
+    }
+    g_free(mediaType);
 }
 
 void
 addDecodeBin(GstElement *webrtc G_GNUC_UNUSED, GstPad *newpad, GstElement *pipe)
 {
-        if (GST_PAD_DIRECTION(newpad) != GST_PAD_SRC)
-                return;
-
-        nhlog::ui()->debug("WebRTC: received incoming stream");
-        GstElement *decodebin = gst_element_factory_make("decodebin", nullptr);
-        // hardware decoding needs investigation; eg rendering fails if vaapi plugin installed
-        g_object_set(decodebin, "force-sw-decoders", TRUE, nullptr);
-        g_signal_connect(decodebin, "pad-added", G_CALLBACK(linkNewPad), pipe);
-        g_signal_connect(decodebin, "element-added", G_CALLBACK(setWaitForKeyFrame), nullptr);
-        gst_bin_add(GST_BIN(pipe), decodebin);
-        gst_element_sync_state_with_parent(decodebin);
-        GstPad *sinkpad = gst_element_get_static_pad(decodebin, "sink");
-        if (GST_PAD_LINK_FAILED(gst_pad_link(newpad, sinkpad)))
-                nhlog::ui()->error("WebRTC: unable to link decodebin");
-        gst_object_unref(sinkpad);
+    if (GST_PAD_DIRECTION(newpad) != GST_PAD_SRC)
+        return;
+
+    nhlog::ui()->debug("WebRTC: received incoming stream");
+    GstElement *decodebin = gst_element_factory_make("decodebin", nullptr);
+    // hardware decoding needs investigation; eg rendering fails if vaapi plugin installed
+    g_object_set(decodebin, "force-sw-decoders", TRUE, nullptr);
+    g_signal_connect(decodebin, "pad-added", G_CALLBACK(linkNewPad), pipe);
+    g_signal_connect(decodebin, "element-added", G_CALLBACK(setWaitForKeyFrame), nullptr);
+    gst_bin_add(GST_BIN(pipe), decodebin);
+    gst_element_sync_state_with_parent(decodebin);
+    GstPad *sinkpad = gst_element_get_static_pad(decodebin, "sink");
+    if (GST_PAD_LINK_FAILED(gst_pad_link(newpad, sinkpad)))
+        nhlog::ui()->error("WebRTC: unable to link decodebin");
+    gst_object_unref(sinkpad);
 }
 
 bool
 contains(std::string_view str1, std::string_view str2)
 {
-        return std::search(str1.cbegin(),
-                           str1.cend(),
-                           str2.cbegin(),
-                           str2.cend(),
-                           [](unsigned char c1, unsigned char c2) {
-                                   return std::tolower(c1) == std::tolower(c2);
-                           }) != str1.cend();
+    return std::search(str1.cbegin(),
+                       str1.cend(),
+                       str2.cbegin(),
+                       str2.cend(),
+                       [](unsigned char c1, unsigned char c2) {
+                           return std::tolower(c1) == std::tolower(c2);
+                       }) != str1.cend();
 }
 
 bool
@@ -552,582 +538,566 @@ getMediaAttributes(const GstSDPMessage *sdp,
                    bool &recvOnly,
                    bool &sendOnly)
 {
-        payloadType = -1;
-        recvOnly    = false;
-        sendOnly    = false;
-        for (guint mlineIndex = 0; mlineIndex < gst_sdp_message_medias_len(sdp); ++mlineIndex) {
-                const GstSDPMedia *media = gst_sdp_message_get_media(sdp, mlineIndex);
-                if (!std::strcmp(gst_sdp_media_get_media(media), mediaType)) {
-                        recvOnly = gst_sdp_media_get_attribute_val(media, "recvonly") != nullptr;
-                        sendOnly = gst_sdp_media_get_attribute_val(media, "sendonly") != nullptr;
-                        const gchar *rtpval = nullptr;
-                        for (guint n = 0; n == 0 || rtpval; ++n) {
-                                rtpval = gst_sdp_media_get_attribute_val_n(media, "rtpmap", n);
-                                if (rtpval && contains(rtpval, encoding)) {
-                                        payloadType = std::atoi(rtpval);
-                                        break;
-                                }
-                        }
-                        return true;
+    payloadType = -1;
+    recvOnly    = false;
+    sendOnly    = false;
+    for (guint mlineIndex = 0; mlineIndex < gst_sdp_message_medias_len(sdp); ++mlineIndex) {
+        const GstSDPMedia *media = gst_sdp_message_get_media(sdp, mlineIndex);
+        if (!std::strcmp(gst_sdp_media_get_media(media), mediaType)) {
+            recvOnly            = gst_sdp_media_get_attribute_val(media, "recvonly") != nullptr;
+            sendOnly            = gst_sdp_media_get_attribute_val(media, "sendonly") != nullptr;
+            const gchar *rtpval = nullptr;
+            for (guint n = 0; n == 0 || rtpval; ++n) {
+                rtpval = gst_sdp_media_get_attribute_val_n(media, "rtpmap", n);
+                if (rtpval && contains(rtpval, encoding)) {
+                    payloadType = std::atoi(rtpval);
+                    break;
                 }
+            }
+            return true;
         }
-        return false;
+    }
+    return false;
 }
 }
 
 bool
 WebRTCSession::havePlugins(bool isVideo, std::string *errorMessage)
 {
-        if (!initialised_ && !init(errorMessage))
-                return false;
-        if (!isVideo && haveVoicePlugins_)
-                return true;
-        if (isVideo && haveVideoPlugins_)
-                return true;
-
-        const gchar *voicePlugins[] = {"audioconvert",
-                                       "audioresample",
-                                       "autodetect",
-                                       "dtls",
-                                       "nice",
-                                       "opus",
-                                       "playback",
-                                       "rtpmanager",
-                                       "srtp",
-                                       "volume",
-                                       "webrtc",
-                                       nullptr};
-
-        const gchar *videoPlugins[] = {
-          "compositor", "opengl", "qmlgl", "rtp", "videoconvert", "vpx", nullptr};
-
-        std::string strError("Missing GStreamer plugins: ");
-        const gchar **needed  = isVideo ? videoPlugins : voicePlugins;
-        bool &havePlugins     = isVideo ? haveVideoPlugins_ : haveVoicePlugins_;
-        havePlugins           = true;
-        GstRegistry *registry = gst_registry_get();
-        for (guint i = 0; i < g_strv_length((gchar **)needed); i++) {
-                GstPlugin *plugin = gst_registry_find_plugin(registry, needed[i]);
-                if (!plugin) {
-                        havePlugins = false;
-                        strError += std::string(needed[i]) + " ";
-                        continue;
-                }
-                gst_object_unref(plugin);
-        }
-        if (!havePlugins) {
-                nhlog::ui()->error(strError);
-                if (errorMessage)
-                        *errorMessage = strError;
-                return false;
-        }
+    if (!initialised_ && !init(errorMessage))
+        return false;
+    if (!isVideo && haveVoicePlugins_)
+        return true;
+    if (isVideo && haveVideoPlugins_)
+        return true;
 
-        if (isVideo) {
-                // load qmlglsink to register GStreamer's GstGLVideoItem QML type
-                GstElement *qmlglsink = gst_element_factory_make("qmlglsink", nullptr);
-                gst_object_unref(qmlglsink);
+    const gchar *voicePlugins[] = {"audioconvert",
+                                   "audioresample",
+                                   "autodetect",
+                                   "dtls",
+                                   "nice",
+                                   "opus",
+                                   "playback",
+                                   "rtpmanager",
+                                   "srtp",
+                                   "volume",
+                                   "webrtc",
+                                   nullptr};
+
+    const gchar *videoPlugins[] = {
+      "compositor", "opengl", "qmlgl", "rtp", "videoconvert", "vpx", nullptr};
+
+    std::string strError("Missing GStreamer plugins: ");
+    const gchar **needed  = isVideo ? videoPlugins : voicePlugins;
+    bool &havePlugins     = isVideo ? haveVideoPlugins_ : haveVoicePlugins_;
+    havePlugins           = true;
+    GstRegistry *registry = gst_registry_get();
+    for (guint i = 0; i < g_strv_length((gchar **)needed); i++) {
+        GstPlugin *plugin = gst_registry_find_plugin(registry, needed[i]);
+        if (!plugin) {
+            havePlugins = false;
+            strError += std::string(needed[i]) + " ";
+            continue;
         }
-        return true;
+        gst_object_unref(plugin);
+    }
+    if (!havePlugins) {
+        nhlog::ui()->error(strError);
+        if (errorMessage)
+            *errorMessage = strError;
+        return false;
+    }
+
+    if (isVideo) {
+        // load qmlglsink to register GStreamer's GstGLVideoItem QML type
+        GstElement *qmlglsink = gst_element_factory_make("qmlglsink", nullptr);
+        gst_object_unref(qmlglsink);
+    }
+    return true;
 }
 
 bool
 WebRTCSession::createOffer(CallType callType, uint32_t shareWindowId)
 {
-        clear();
-        isOffering_    = true;
-        callType_      = callType;
-        shareWindowId_ = shareWindowId;
-
-        // opus and vp8 rtp payload types must be defined dynamically
-        // therefore from the range [96-127]
-        // see for example https://tools.ietf.org/html/rfc7587
-        constexpr int opusPayloadType = 111;
-        constexpr int vp8PayloadType  = 96;
-        return startPipeline(opusPayloadType, vp8PayloadType);
+    clear();
+    isOffering_    = true;
+    callType_      = callType;
+    shareWindowId_ = shareWindowId;
+
+    // opus and vp8 rtp payload types must be defined dynamically
+    // therefore from the range [96-127]
+    // see for example https://tools.ietf.org/html/rfc7587
+    constexpr int opusPayloadType = 111;
+    constexpr int vp8PayloadType  = 96;
+    return startPipeline(opusPayloadType, vp8PayloadType);
 }
 
 bool
 WebRTCSession::acceptOffer(const std::string &sdp)
 {
-        nhlog::ui()->debug("WebRTC: received offer:\n{}", sdp);
-        if (state_ != State::DISCONNECTED)
-                return false;
+    nhlog::ui()->debug("WebRTC: received offer:\n{}", sdp);
+    if (state_ != State::DISCONNECTED)
+        return false;
 
-        clear();
-        GstWebRTCSessionDescription *offer = parseSDP(sdp, GST_WEBRTC_SDP_TYPE_OFFER);
-        if (!offer)
-                return false;
+    clear();
+    GstWebRTCSessionDescription *offer = parseSDP(sdp, GST_WEBRTC_SDP_TYPE_OFFER);
+    if (!offer)
+        return false;
 
-        int opusPayloadType;
-        bool recvOnly;
-        bool sendOnly;
-        if (getMediaAttributes(offer->sdp, "audio", "opus", opusPayloadType, recvOnly, sendOnly)) {
-                if (opusPayloadType == -1) {
-                        nhlog::ui()->error("WebRTC: remote audio offer - no opus encoding");
-                        gst_webrtc_session_description_free(offer);
-                        return false;
-                }
-        } else {
-                nhlog::ui()->error("WebRTC: remote offer - no audio media");
-                gst_webrtc_session_description_free(offer);
-                return false;
+    int opusPayloadType;
+    bool recvOnly;
+    bool sendOnly;
+    if (getMediaAttributes(offer->sdp, "audio", "opus", opusPayloadType, recvOnly, sendOnly)) {
+        if (opusPayloadType == -1) {
+            nhlog::ui()->error("WebRTC: remote audio offer - no opus encoding");
+            gst_webrtc_session_description_free(offer);
+            return false;
         }
+    } else {
+        nhlog::ui()->error("WebRTC: remote offer - no audio media");
+        gst_webrtc_session_description_free(offer);
+        return false;
+    }
 
-        int vp8PayloadType;
-        bool isVideo = getMediaAttributes(offer->sdp,
-                                          "video",
-                                          "vp8",
-                                          vp8PayloadType,
-                                          isRemoteVideoRecvOnly_,
-                                          isRemoteVideoSendOnly_);
-        if (isVideo && vp8PayloadType == -1) {
-                nhlog::ui()->error("WebRTC: remote video offer - no vp8 encoding");
-                gst_webrtc_session_description_free(offer);
-                return false;
-        }
-        callType_ = isVideo ? CallType::VIDEO : CallType::VOICE;
+    int vp8PayloadType;
+    bool isVideo = getMediaAttributes(
+      offer->sdp, "video", "vp8", vp8PayloadType, isRemoteVideoRecvOnly_, isRemoteVideoSendOnly_);
+    if (isVideo && vp8PayloadType == -1) {
+        nhlog::ui()->error("WebRTC: remote video offer - no vp8 encoding");
+        gst_webrtc_session_description_free(offer);
+        return false;
+    }
+    callType_ = isVideo ? CallType::VIDEO : CallType::VOICE;
 
-        if (!startPipeline(opusPayloadType, vp8PayloadType)) {
-                gst_webrtc_session_description_free(offer);
-                return false;
-        }
+    if (!startPipeline(opusPayloadType, vp8PayloadType)) {
+        gst_webrtc_session_description_free(offer);
+        return false;
+    }
 
-        // avoid a race that sometimes leaves the generated answer without media tracks (a=ssrc
-        // lines)
-        std::this_thread::sleep_for(std::chrono::milliseconds(200));
+    // avoid a race that sometimes leaves the generated answer without media tracks (a=ssrc
+    // lines)
+    std::this_thread::sleep_for(std::chrono::milliseconds(200));
 
-        // set-remote-description first, then create-answer
-        GstPromise *promise = gst_promise_new_with_change_func(createAnswer, webrtc_, nullptr);
-        g_signal_emit_by_name(webrtc_, "set-remote-description", offer, promise);
-        gst_webrtc_session_description_free(offer);
-        return true;
+    // set-remote-description first, then create-answer
+    GstPromise *promise = gst_promise_new_with_change_func(createAnswer, webrtc_, nullptr);
+    g_signal_emit_by_name(webrtc_, "set-remote-description", offer, promise);
+    gst_webrtc_session_description_free(offer);
+    return true;
 }
 
 bool
 WebRTCSession::acceptAnswer(const std::string &sdp)
 {
-        nhlog::ui()->debug("WebRTC: received answer:\n{}", sdp);
-        if (state_ != State::OFFERSENT)
-                return false;
-
-        GstWebRTCSessionDescription *answer = parseSDP(sdp, GST_WEBRTC_SDP_TYPE_ANSWER);
-        if (!answer) {
-                end();
-                return false;
-        }
-
-        if (callType_ != CallType::VOICE) {
-                int unused;
-                if (!getMediaAttributes(answer->sdp,
-                                        "video",
-                                        "vp8",
-                                        unused,
-                                        isRemoteVideoRecvOnly_,
-                                        isRemoteVideoSendOnly_))
-                        isRemoteVideoRecvOnly_ = true;
-        }
+    nhlog::ui()->debug("WebRTC: received answer:\n{}", sdp);
+    if (state_ != State::OFFERSENT)
+        return false;
 
-        g_signal_emit_by_name(webrtc_, "set-remote-description", answer, nullptr);
-        gst_webrtc_session_description_free(answer);
-        return true;
+    GstWebRTCSessionDescription *answer = parseSDP(sdp, GST_WEBRTC_SDP_TYPE_ANSWER);
+    if (!answer) {
+        end();
+        return false;
+    }
+
+    if (callType_ != CallType::VOICE) {
+        int unused;
+        if (!getMediaAttributes(
+              answer->sdp, "video", "vp8", unused, isRemoteVideoRecvOnly_, isRemoteVideoSendOnly_))
+            isRemoteVideoRecvOnly_ = true;
+    }
+
+    g_signal_emit_by_name(webrtc_, "set-remote-description", answer, nullptr);
+    gst_webrtc_session_description_free(answer);
+    return true;
 }
 
 void
 WebRTCSession::acceptICECandidates(
   const std::vector<mtx::events::msg::CallCandidates::Candidate> &candidates)
 {
-        if (state_ >= State::INITIATED) {
-                for (const auto &c : candidates) {
-                        nhlog::ui()->debug(
-                          "WebRTC: remote candidate: (m-line:{}):{}", c.sdpMLineIndex, c.candidate);
-                        if (!c.candidate.empty()) {
-                                g_signal_emit_by_name(webrtc_,
-                                                      "add-ice-candidate",
-                                                      c.sdpMLineIndex,
-                                                      c.candidate.c_str());
-                        }
-                }
+    if (state_ >= State::INITIATED) {
+        for (const auto &c : candidates) {
+            nhlog::ui()->debug(
+              "WebRTC: remote candidate: (m-line:{}):{}", c.sdpMLineIndex, c.candidate);
+            if (!c.candidate.empty()) {
+                g_signal_emit_by_name(
+                  webrtc_, "add-ice-candidate", c.sdpMLineIndex, c.candidate.c_str());
+            }
         }
+    }
 }
 
 bool
 WebRTCSession::startPipeline(int opusPayloadType, int vp8PayloadType)
 {
-        if (state_ != State::DISCONNECTED)
-                return false;
-
-        emit stateChanged(State::INITIATING);
-
-        if (!createPipeline(opusPayloadType, vp8PayloadType)) {
-                end();
-                return false;
-        }
-
-        webrtc_ = gst_bin_get_by_name(GST_BIN(pipe_), "webrtcbin");
-
-        if (ChatPage::instance()->userSettings()->useStunServer()) {
-                nhlog::ui()->info("WebRTC: setting STUN server: {}", STUN_SERVER);
-                g_object_set(webrtc_, "stun-server", STUN_SERVER, nullptr);
-        }
-
-        for (const auto &uri : turnServers_) {
-                nhlog::ui()->info("WebRTC: setting TURN server: {}", uri);
-                gboolean udata;
-                g_signal_emit_by_name(webrtc_, "add-turn-server", uri.c_str(), (gpointer)(&udata));
-        }
-        if (turnServers_.empty())
-                nhlog::ui()->warn("WebRTC: no TURN server provided");
-
-        // generate the offer when the pipeline goes to PLAYING
-        if (isOffering_)
-                g_signal_connect(
-                  webrtc_, "on-negotiation-needed", G_CALLBACK(::createOffer), nullptr);
-
-        // on-ice-candidate is emitted when a local ICE candidate has been gathered
-        g_signal_connect(webrtc_, "on-ice-candidate", G_CALLBACK(addLocalICECandidate), nullptr);
-
-        // capture ICE failure
-        g_signal_connect(
-          webrtc_, "notify::ice-connection-state", G_CALLBACK(iceConnectionStateChanged), nullptr);
-
-        // incoming streams trigger pad-added
-        gst_element_set_state(pipe_, GST_STATE_READY);
-        g_signal_connect(webrtc_, "pad-added", G_CALLBACK(addDecodeBin), pipe_);
-
-        // capture ICE gathering completion
-        g_signal_connect(
-          webrtc_, "notify::ice-gathering-state", G_CALLBACK(iceGatheringStateChanged), nullptr);
+    if (state_ != State::DISCONNECTED)
+        return false;
 
-        // webrtcbin lifetime is the same as that of the pipeline
-        gst_object_unref(webrtc_);
+    emit stateChanged(State::INITIATING);
 
-        // start the pipeline
-        GstStateChangeReturn ret = gst_element_set_state(pipe_, GST_STATE_PLAYING);
-        if (ret == GST_STATE_CHANGE_FAILURE) {
-                nhlog::ui()->error("WebRTC: unable to start pipeline");
-                end();
-                return false;
-        }
+    if (!createPipeline(opusPayloadType, vp8PayloadType)) {
+        end();
+        return false;
+    }
+
+    webrtc_ = gst_bin_get_by_name(GST_BIN(pipe_), "webrtcbin");
+
+    if (ChatPage::instance()->userSettings()->useStunServer()) {
+        nhlog::ui()->info("WebRTC: setting STUN server: {}", STUN_SERVER);
+        g_object_set(webrtc_, "stun-server", STUN_SERVER, nullptr);
+    }
+
+    for (const auto &uri : turnServers_) {
+        nhlog::ui()->info("WebRTC: setting TURN server: {}", uri);
+        gboolean udata;
+        g_signal_emit_by_name(webrtc_, "add-turn-server", uri.c_str(), (gpointer)(&udata));
+    }
+    if (turnServers_.empty())
+        nhlog::ui()->warn("WebRTC: no TURN server provided");
+
+    // generate the offer when the pipeline goes to PLAYING
+    if (isOffering_)
+        g_signal_connect(webrtc_, "on-negotiation-needed", G_CALLBACK(::createOffer), nullptr);
+
+    // on-ice-candidate is emitted when a local ICE candidate has been gathered
+    g_signal_connect(webrtc_, "on-ice-candidate", G_CALLBACK(addLocalICECandidate), nullptr);
+
+    // capture ICE failure
+    g_signal_connect(
+      webrtc_, "notify::ice-connection-state", G_CALLBACK(iceConnectionStateChanged), nullptr);
+
+    // incoming streams trigger pad-added
+    gst_element_set_state(pipe_, GST_STATE_READY);
+    g_signal_connect(webrtc_, "pad-added", G_CALLBACK(addDecodeBin), pipe_);
+
+    // capture ICE gathering completion
+    g_signal_connect(
+      webrtc_, "notify::ice-gathering-state", G_CALLBACK(iceGatheringStateChanged), nullptr);
+
+    // webrtcbin lifetime is the same as that of the pipeline
+    gst_object_unref(webrtc_);
+
+    // start the pipeline
+    GstStateChangeReturn ret = gst_element_set_state(pipe_, GST_STATE_PLAYING);
+    if (ret == GST_STATE_CHANGE_FAILURE) {
+        nhlog::ui()->error("WebRTC: unable to start pipeline");
+        end();
+        return false;
+    }
 
-        GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(pipe_));
-        busWatchId_ = gst_bus_add_watch(bus, newBusMessage, this);
-        gst_object_unref(bus);
-        emit stateChanged(State::INITIATED);
-        return true;
+    GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(pipe_));
+    busWatchId_ = gst_bus_add_watch(bus, newBusMessage, this);
+    gst_object_unref(bus);
+    emit stateChanged(State::INITIATED);
+    return true;
 }
 
 bool
 WebRTCSession::createPipeline(int opusPayloadType, int vp8PayloadType)
 {
-        GstDevice *device = devices_.audioDevice();
-        if (!device)
-                return false;
-
-        GstElement *source     = gst_device_create_element(device, nullptr);
-        GstElement *volume     = gst_element_factory_make("volume", "srclevel");
-        GstElement *convert    = gst_element_factory_make("audioconvert", nullptr);
-        GstElement *resample   = gst_element_factory_make("audioresample", nullptr);
-        GstElement *queue1     = gst_element_factory_make("queue", nullptr);
-        GstElement *opusenc    = gst_element_factory_make("opusenc", nullptr);
-        GstElement *rtp        = gst_element_factory_make("rtpopuspay", nullptr);
-        GstElement *queue2     = gst_element_factory_make("queue", nullptr);
-        GstElement *capsfilter = gst_element_factory_make("capsfilter", nullptr);
+    GstDevice *device = devices_.audioDevice();
+    if (!device)
+        return false;
 
-        GstCaps *rtpcaps = gst_caps_new_simple("application/x-rtp",
-                                               "media",
-                                               G_TYPE_STRING,
-                                               "audio",
-                                               "encoding-name",
-                                               G_TYPE_STRING,
-                                               "OPUS",
-                                               "payload",
-                                               G_TYPE_INT,
-                                               opusPayloadType,
-                                               nullptr);
-        g_object_set(capsfilter, "caps", rtpcaps, nullptr);
-        gst_caps_unref(rtpcaps);
-
-        GstElement *webrtcbin = gst_element_factory_make("webrtcbin", "webrtcbin");
-        g_object_set(webrtcbin, "bundle-policy", GST_WEBRTC_BUNDLE_POLICY_MAX_BUNDLE, nullptr);
-
-        pipe_ = gst_pipeline_new(nullptr);
-        gst_bin_add_many(GST_BIN(pipe_),
-                         source,
-                         volume,
-                         convert,
-                         resample,
-                         queue1,
-                         opusenc,
-                         rtp,
-                         queue2,
-                         capsfilter,
-                         webrtcbin,
-                         nullptr);
-
-        if (!gst_element_link_many(source,
-                                   volume,
-                                   convert,
-                                   resample,
-                                   queue1,
-                                   opusenc,
-                                   rtp,
-                                   queue2,
-                                   capsfilter,
-                                   webrtcbin,
-                                   nullptr)) {
-                nhlog::ui()->error("WebRTC: failed to link audio pipeline elements");
-                return false;
-        }
+    GstElement *source     = gst_device_create_element(device, nullptr);
+    GstElement *volume     = gst_element_factory_make("volume", "srclevel");
+    GstElement *convert    = gst_element_factory_make("audioconvert", nullptr);
+    GstElement *resample   = gst_element_factory_make("audioresample", nullptr);
+    GstElement *queue1     = gst_element_factory_make("queue", nullptr);
+    GstElement *opusenc    = gst_element_factory_make("opusenc", nullptr);
+    GstElement *rtp        = gst_element_factory_make("rtpopuspay", nullptr);
+    GstElement *queue2     = gst_element_factory_make("queue", nullptr);
+    GstElement *capsfilter = gst_element_factory_make("capsfilter", nullptr);
+
+    GstCaps *rtpcaps = gst_caps_new_simple("application/x-rtp",
+                                           "media",
+                                           G_TYPE_STRING,
+                                           "audio",
+                                           "encoding-name",
+                                           G_TYPE_STRING,
+                                           "OPUS",
+                                           "payload",
+                                           G_TYPE_INT,
+                                           opusPayloadType,
+                                           nullptr);
+    g_object_set(capsfilter, "caps", rtpcaps, nullptr);
+    gst_caps_unref(rtpcaps);
+
+    GstElement *webrtcbin = gst_element_factory_make("webrtcbin", "webrtcbin");
+    g_object_set(webrtcbin, "bundle-policy", GST_WEBRTC_BUNDLE_POLICY_MAX_BUNDLE, nullptr);
+
+    pipe_ = gst_pipeline_new(nullptr);
+    gst_bin_add_many(GST_BIN(pipe_),
+                     source,
+                     volume,
+                     convert,
+                     resample,
+                     queue1,
+                     opusenc,
+                     rtp,
+                     queue2,
+                     capsfilter,
+                     webrtcbin,
+                     nullptr);
+
+    if (!gst_element_link_many(source,
+                               volume,
+                               convert,
+                               resample,
+                               queue1,
+                               opusenc,
+                               rtp,
+                               queue2,
+                               capsfilter,
+                               webrtcbin,
+                               nullptr)) {
+        nhlog::ui()->error("WebRTC: failed to link audio pipeline elements");
+        return false;
+    }
 
-        return callType_ == CallType::VOICE || isRemoteVideoSendOnly_
-                 ? true
-                 : addVideoPipeline(vp8PayloadType);
+    return callType_ == CallType::VOICE || isRemoteVideoSendOnly_
+             ? true
+             : addVideoPipeline(vp8PayloadType);
 }
 
 bool
 WebRTCSession::addVideoPipeline(int vp8PayloadType)
 {
-        // allow incoming video calls despite localUser having no webcam
-        if (callType_ == CallType::VIDEO && !devices_.haveCamera())
-                return !isOffering_;
-
-        auto settings            = ChatPage::instance()->userSettings();
-        GstElement *camerafilter = nullptr;
-        GstElement *videoconvert = gst_element_factory_make("videoconvert", nullptr);
-        GstElement *tee          = gst_element_factory_make("tee", "videosrctee");
-        gst_bin_add_many(GST_BIN(pipe_), videoconvert, tee, nullptr);
-        if (callType_ == CallType::VIDEO || (settings->screenSharePiP() && devices_.haveCamera())) {
-                std::pair<int, int> resolution;
-                std::pair<int, int> frameRate;
-                GstDevice *device = devices_.videoDevice(resolution, frameRate);
-                if (!device)
-                        return false;
-
-                GstElement *camera = gst_device_create_element(device, nullptr);
-                GstCaps *caps      = gst_caps_new_simple("video/x-raw",
-                                                    "width",
-                                                    G_TYPE_INT,
-                                                    resolution.first,
-                                                    "height",
-                                                    G_TYPE_INT,
-                                                    resolution.second,
-                                                    "framerate",
-                                                    GST_TYPE_FRACTION,
-                                                    frameRate.first,
-                                                    frameRate.second,
-                                                    nullptr);
-                camerafilter       = gst_element_factory_make("capsfilter", "camerafilter");
-                g_object_set(camerafilter, "caps", caps, nullptr);
-                gst_caps_unref(caps);
-
-                gst_bin_add_many(GST_BIN(pipe_), camera, camerafilter, nullptr);
-                if (!gst_element_link_many(camera, videoconvert, camerafilter, nullptr)) {
-                        nhlog::ui()->error("WebRTC: failed to link camera elements");
-                        return false;
-                }
-                if (callType_ == CallType::VIDEO && !gst_element_link(camerafilter, tee)) {
-                        nhlog::ui()->error("WebRTC: failed to link camerafilter -> tee");
-                        return false;
-                }
-        }
+    // allow incoming video calls despite localUser having no webcam
+    if (callType_ == CallType::VIDEO && !devices_.haveCamera())
+        return !isOffering_;
+
+    auto settings            = ChatPage::instance()->userSettings();
+    GstElement *camerafilter = nullptr;
+    GstElement *videoconvert = gst_element_factory_make("videoconvert", nullptr);
+    GstElement *tee          = gst_element_factory_make("tee", "videosrctee");
+    gst_bin_add_many(GST_BIN(pipe_), videoconvert, tee, nullptr);
+    if (callType_ == CallType::VIDEO || (settings->screenSharePiP() && devices_.haveCamera())) {
+        std::pair<int, int> resolution;
+        std::pair<int, int> frameRate;
+        GstDevice *device = devices_.videoDevice(resolution, frameRate);
+        if (!device)
+            return false;
+
+        GstElement *camera = gst_device_create_element(device, nullptr);
+        GstCaps *caps      = gst_caps_new_simple("video/x-raw",
+                                            "width",
+                                            G_TYPE_INT,
+                                            resolution.first,
+                                            "height",
+                                            G_TYPE_INT,
+                                            resolution.second,
+                                            "framerate",
+                                            GST_TYPE_FRACTION,
+                                            frameRate.first,
+                                            frameRate.second,
+                                            nullptr);
+        camerafilter       = gst_element_factory_make("capsfilter", "camerafilter");
+        g_object_set(camerafilter, "caps", caps, nullptr);
+        gst_caps_unref(caps);
 
-        if (callType_ == CallType::SCREEN) {
-                nhlog::ui()->debug("WebRTC: screen share frame rate: {} fps",
-                                   settings->screenShareFrameRate());
-                nhlog::ui()->debug("WebRTC: screen share picture-in-picture: {}",
-                                   settings->screenSharePiP());
-                nhlog::ui()->debug("WebRTC: screen share request remote camera: {}",
-                                   settings->screenShareRemoteVideo());
-                nhlog::ui()->debug("WebRTC: screen share hide mouse cursor: {}",
-                                   settings->screenShareHideCursor());
-
-                GstElement *ximagesrc = gst_element_factory_make("ximagesrc", "screenshare");
-                if (!ximagesrc) {
-                        nhlog::ui()->error("WebRTC: failed to create ximagesrc");
-                        return false;
-                }
-                g_object_set(ximagesrc, "use-damage", FALSE, nullptr);
-                g_object_set(ximagesrc, "xid", shareWindowId_, nullptr);
-                g_object_set(
-                  ximagesrc, "show-pointer", !settings->screenShareHideCursor(), nullptr);
-
-                GstCaps *caps          = gst_caps_new_simple("video/x-raw",
-                                                    "framerate",
-                                                    GST_TYPE_FRACTION,
-                                                    settings->screenShareFrameRate(),
-                                                    1,
-                                                    nullptr);
-                GstElement *capsfilter = gst_element_factory_make("capsfilter", nullptr);
-                g_object_set(capsfilter, "caps", caps, nullptr);
-                gst_caps_unref(caps);
-                gst_bin_add_many(GST_BIN(pipe_), ximagesrc, capsfilter, nullptr);
-
-                if (settings->screenSharePiP() && devices_.haveCamera()) {
-                        GstElement *compositor = gst_element_factory_make("compositor", nullptr);
-                        g_object_set(compositor, "background", 1, nullptr);
-                        gst_bin_add(GST_BIN(pipe_), compositor);
-                        if (!gst_element_link_many(
-                              ximagesrc, compositor, capsfilter, tee, nullptr)) {
-                                nhlog::ui()->error("WebRTC: failed to link screen share elements");
-                                return false;
-                        }
-
-                        GstPad *srcpad    = gst_element_get_static_pad(camerafilter, "src");
-                        remotePiPSinkPad_ = gst_element_get_request_pad(compositor, "sink_%u");
-                        if (GST_PAD_LINK_FAILED(gst_pad_link(srcpad, remotePiPSinkPad_))) {
-                                nhlog::ui()->error(
-                                  "WebRTC: failed to link camerafilter -> compositor");
-                                gst_object_unref(srcpad);
-                                return false;
-                        }
-                        gst_object_unref(srcpad);
-                } else if (!gst_element_link_many(
-                             ximagesrc, videoconvert, capsfilter, tee, nullptr)) {
-                        nhlog::ui()->error("WebRTC: failed to link screen share elements");
-                        return false;
-                }
+        gst_bin_add_many(GST_BIN(pipe_), camera, camerafilter, nullptr);
+        if (!gst_element_link_many(camera, videoconvert, camerafilter, nullptr)) {
+            nhlog::ui()->error("WebRTC: failed to link camera elements");
+            return false;
         }
-
-        GstElement *queue  = gst_element_factory_make("queue", nullptr);
-        GstElement *vp8enc = gst_element_factory_make("vp8enc", nullptr);
-        g_object_set(vp8enc, "deadline", 1, nullptr);
-        g_object_set(vp8enc, "error-resilient", 1, nullptr);
-        GstElement *rtpvp8pay     = gst_element_factory_make("rtpvp8pay", nullptr);
-        GstElement *rtpqueue      = gst_element_factory_make("queue", nullptr);
-        GstElement *rtpcapsfilter = gst_element_factory_make("capsfilter", nullptr);
-        GstCaps *rtpcaps          = gst_caps_new_simple("application/x-rtp",
-                                               "media",
-                                               G_TYPE_STRING,
-                                               "video",
-                                               "encoding-name",
-                                               G_TYPE_STRING,
-                                               "VP8",
-                                               "payload",
-                                               G_TYPE_INT,
-                                               vp8PayloadType,
-                                               nullptr);
-        g_object_set(rtpcapsfilter, "caps", rtpcaps, nullptr);
-        gst_caps_unref(rtpcaps);
-
-        gst_bin_add_many(
-          GST_BIN(pipe_), queue, vp8enc, rtpvp8pay, rtpqueue, rtpcapsfilter, nullptr);
-
-        GstElement *webrtcbin = gst_bin_get_by_name(GST_BIN(pipe_), "webrtcbin");
-        if (!gst_element_link_many(
-              tee, queue, vp8enc, rtpvp8pay, rtpqueue, rtpcapsfilter, webrtcbin, nullptr)) {
-                nhlog::ui()->error("WebRTC: failed to link rtp video elements");
-                gst_object_unref(webrtcbin);
-                return false;
+        if (callType_ == CallType::VIDEO && !gst_element_link(camerafilter, tee)) {
+            nhlog::ui()->error("WebRTC: failed to link camerafilter -> tee");
+            return false;
         }
-
-        if (callType_ == CallType::SCREEN &&
-            !ChatPage::instance()->userSettings()->screenShareRemoteVideo()) {
-                GArray *transceivers;
-                g_signal_emit_by_name(webrtcbin, "get-transceivers", &transceivers);
-                GstWebRTCRTPTransceiver *transceiver =
-                  g_array_index(transceivers, GstWebRTCRTPTransceiver *, 1);
-                transceiver->direction = GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDONLY;
-                g_array_unref(transceivers);
+    }
+
+    if (callType_ == CallType::SCREEN) {
+        nhlog::ui()->debug("WebRTC: screen share frame rate: {} fps",
+                           settings->screenShareFrameRate());
+        nhlog::ui()->debug("WebRTC: screen share picture-in-picture: {}",
+                           settings->screenSharePiP());
+        nhlog::ui()->debug("WebRTC: screen share request remote camera: {}",
+                           settings->screenShareRemoteVideo());
+        nhlog::ui()->debug("WebRTC: screen share hide mouse cursor: {}",
+                           settings->screenShareHideCursor());
+
+        GstElement *ximagesrc = gst_element_factory_make("ximagesrc", "screenshare");
+        if (!ximagesrc) {
+            nhlog::ui()->error("WebRTC: failed to create ximagesrc");
+            return false;
         }
+        g_object_set(ximagesrc, "use-damage", FALSE, nullptr);
+        g_object_set(ximagesrc, "xid", shareWindowId_, nullptr);
+        g_object_set(ximagesrc, "show-pointer", !settings->screenShareHideCursor(), nullptr);
+
+        GstCaps *caps          = gst_caps_new_simple("video/x-raw",
+                                            "framerate",
+                                            GST_TYPE_FRACTION,
+                                            settings->screenShareFrameRate(),
+                                            1,
+                                            nullptr);
+        GstElement *capsfilter = gst_element_factory_make("capsfilter", nullptr);
+        g_object_set(capsfilter, "caps", caps, nullptr);
+        gst_caps_unref(caps);
+        gst_bin_add_many(GST_BIN(pipe_), ximagesrc, capsfilter, nullptr);
+
+        if (settings->screenSharePiP() && devices_.haveCamera()) {
+            GstElement *compositor = gst_element_factory_make("compositor", nullptr);
+            g_object_set(compositor, "background", 1, nullptr);
+            gst_bin_add(GST_BIN(pipe_), compositor);
+            if (!gst_element_link_many(ximagesrc, compositor, capsfilter, tee, nullptr)) {
+                nhlog::ui()->error("WebRTC: failed to link screen share elements");
+                return false;
+            }
 
+            GstPad *srcpad    = gst_element_get_static_pad(camerafilter, "src");
+            remotePiPSinkPad_ = gst_element_get_request_pad(compositor, "sink_%u");
+            if (GST_PAD_LINK_FAILED(gst_pad_link(srcpad, remotePiPSinkPad_))) {
+                nhlog::ui()->error("WebRTC: failed to link camerafilter -> compositor");
+                gst_object_unref(srcpad);
+                return false;
+            }
+            gst_object_unref(srcpad);
+        } else if (!gst_element_link_many(ximagesrc, videoconvert, capsfilter, tee, nullptr)) {
+            nhlog::ui()->error("WebRTC: failed to link screen share elements");
+            return false;
+        }
+    }
+
+    GstElement *queue  = gst_element_factory_make("queue", nullptr);
+    GstElement *vp8enc = gst_element_factory_make("vp8enc", nullptr);
+    g_object_set(vp8enc, "deadline", 1, nullptr);
+    g_object_set(vp8enc, "error-resilient", 1, nullptr);
+    GstElement *rtpvp8pay     = gst_element_factory_make("rtpvp8pay", nullptr);
+    GstElement *rtpqueue      = gst_element_factory_make("queue", nullptr);
+    GstElement *rtpcapsfilter = gst_element_factory_make("capsfilter", nullptr);
+    GstCaps *rtpcaps          = gst_caps_new_simple("application/x-rtp",
+                                           "media",
+                                           G_TYPE_STRING,
+                                           "video",
+                                           "encoding-name",
+                                           G_TYPE_STRING,
+                                           "VP8",
+                                           "payload",
+                                           G_TYPE_INT,
+                                           vp8PayloadType,
+                                           nullptr);
+    g_object_set(rtpcapsfilter, "caps", rtpcaps, nullptr);
+    gst_caps_unref(rtpcaps);
+
+    gst_bin_add_many(GST_BIN(pipe_), queue, vp8enc, rtpvp8pay, rtpqueue, rtpcapsfilter, nullptr);
+
+    GstElement *webrtcbin = gst_bin_get_by_name(GST_BIN(pipe_), "webrtcbin");
+    if (!gst_element_link_many(
+          tee, queue, vp8enc, rtpvp8pay, rtpqueue, rtpcapsfilter, webrtcbin, nullptr)) {
+        nhlog::ui()->error("WebRTC: failed to link rtp video elements");
         gst_object_unref(webrtcbin);
-        return true;
+        return false;
+    }
+
+    if (callType_ == CallType::SCREEN &&
+        !ChatPage::instance()->userSettings()->screenShareRemoteVideo()) {
+        GArray *transceivers;
+        g_signal_emit_by_name(webrtcbin, "get-transceivers", &transceivers);
+        GstWebRTCRTPTransceiver *transceiver =
+          g_array_index(transceivers, GstWebRTCRTPTransceiver *, 1);
+        transceiver->direction = GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDONLY;
+        g_array_unref(transceivers);
+    }
+
+    gst_object_unref(webrtcbin);
+    return true;
 }
 
 bool
 WebRTCSession::haveLocalPiP() const
 {
-        if (state_ >= State::INITIATED) {
-                if (callType_ == CallType::VOICE || isRemoteVideoRecvOnly_)
-                        return false;
-                else if (callType_ == CallType::SCREEN)
-                        return true;
-                else {
-                        GstElement *tee = gst_bin_get_by_name(GST_BIN(pipe_), "videosrctee");
-                        if (tee) {
-                                gst_object_unref(tee);
-                                return true;
-                        }
-                }
+    if (state_ >= State::INITIATED) {
+        if (callType_ == CallType::VOICE || isRemoteVideoRecvOnly_)
+            return false;
+        else if (callType_ == CallType::SCREEN)
+            return true;
+        else {
+            GstElement *tee = gst_bin_get_by_name(GST_BIN(pipe_), "videosrctee");
+            if (tee) {
+                gst_object_unref(tee);
+                return true;
+            }
         }
-        return false;
+    }
+    return false;
 }
 
 bool
 WebRTCSession::isMicMuted() const
 {
-        if (state_ < State::INITIATED)
-                return false;
+    if (state_ < State::INITIATED)
+        return false;
 
-        GstElement *srclevel = gst_bin_get_by_name(GST_BIN(pipe_), "srclevel");
-        gboolean muted;
-        g_object_get(srclevel, "mute", &muted, nullptr);
-        gst_object_unref(srclevel);
-        return muted;
+    GstElement *srclevel = gst_bin_get_by_name(GST_BIN(pipe_), "srclevel");
+    gboolean muted;
+    g_object_get(srclevel, "mute", &muted, nullptr);
+    gst_object_unref(srclevel);
+    return muted;
 }
 
 bool
 WebRTCSession::toggleMicMute()
 {
-        if (state_ < State::INITIATED)
-                return false;
+    if (state_ < State::INITIATED)
+        return false;
 
-        GstElement *srclevel = gst_bin_get_by_name(GST_BIN(pipe_), "srclevel");
-        gboolean muted;
-        g_object_get(srclevel, "mute", &muted, nullptr);
-        g_object_set(srclevel, "mute", !muted, nullptr);
-        gst_object_unref(srclevel);
-        return !muted;
+    GstElement *srclevel = gst_bin_get_by_name(GST_BIN(pipe_), "srclevel");
+    gboolean muted;
+    g_object_get(srclevel, "mute", &muted, nullptr);
+    g_object_set(srclevel, "mute", !muted, nullptr);
+    gst_object_unref(srclevel);
+    return !muted;
 }
 
 void
 WebRTCSession::toggleLocalPiP()
 {
-        if (localPiPSinkPad_) {
-                guint zorder;
-                g_object_get(localPiPSinkPad_, "zorder", &zorder, nullptr);
-                g_object_set(localPiPSinkPad_, "zorder", zorder ? 0 : 2, nullptr);
-        }
+    if (localPiPSinkPad_) {
+        guint zorder;
+        g_object_get(localPiPSinkPad_, "zorder", &zorder, nullptr);
+        g_object_set(localPiPSinkPad_, "zorder", zorder ? 0 : 2, nullptr);
+    }
 }
 
 void
 WebRTCSession::clear()
 {
-        callType_              = webrtc::CallType::VOICE;
-        isOffering_            = false;
-        isRemoteVideoRecvOnly_ = false;
-        isRemoteVideoSendOnly_ = false;
-        videoItem_             = nullptr;
-        pipe_                  = nullptr;
-        webrtc_                = nullptr;
-        busWatchId_            = 0;
-        shareWindowId_         = 0;
-        haveAudioStream_       = false;
-        haveVideoStream_       = false;
-        localPiPSinkPad_       = nullptr;
-        remotePiPSinkPad_      = nullptr;
-        localsdp_.clear();
-        localcandidates_.clear();
+    callType_              = webrtc::CallType::VOICE;
+    isOffering_            = false;
+    isRemoteVideoRecvOnly_ = false;
+    isRemoteVideoSendOnly_ = false;
+    videoItem_             = nullptr;
+    pipe_                  = nullptr;
+    webrtc_                = nullptr;
+    busWatchId_            = 0;
+    shareWindowId_         = 0;
+    haveAudioStream_       = false;
+    haveVideoStream_       = false;
+    localPiPSinkPad_       = nullptr;
+    remotePiPSinkPad_      = nullptr;
+    localsdp_.clear();
+    localcandidates_.clear();
 }
 
 void
 WebRTCSession::end()
 {
-        nhlog::ui()->debug("WebRTC: ending session");
-        keyFrameRequestData_ = KeyFrameRequestData{};
-        if (pipe_) {
-                gst_element_set_state(pipe_, GST_STATE_NULL);
-                gst_object_unref(pipe_);
-                pipe_ = nullptr;
-                if (busWatchId_) {
-                        g_source_remove(busWatchId_);
-                        busWatchId_ = 0;
-                }
+    nhlog::ui()->debug("WebRTC: ending session");
+    keyFrameRequestData_ = KeyFrameRequestData{};
+    if (pipe_) {
+        gst_element_set_state(pipe_, GST_STATE_NULL);
+        gst_object_unref(pipe_);
+        pipe_ = nullptr;
+        if (busWatchId_) {
+            g_source_remove(busWatchId_);
+            busWatchId_ = 0;
         }
+    }
 
-        clear();
-        if (state_ != State::DISCONNECTED)
-                emit stateChanged(State::DISCONNECTED);
+    clear();
+    if (state_ != State::DISCONNECTED)
+        emit stateChanged(State::DISCONNECTED);
 }
 
 #else
@@ -1135,13 +1105,13 @@ WebRTCSession::end()
 bool
 WebRTCSession::havePlugins(bool, std::string *)
 {
-        return false;
+    return false;
 }
 
 bool
 WebRTCSession::haveLocalPiP() const
 {
-        return false;
+    return false;
 }
 
 bool WebRTCSession::createOffer(webrtc::CallType, uint32_t) { return false; }
@@ -1149,13 +1119,13 @@ bool WebRTCSession::createOffer(webrtc::CallType, uint32_t) { return false; }
 bool
 WebRTCSession::acceptOffer(const std::string &)
 {
-        return false;
+    return false;
 }
 
 bool
 WebRTCSession::acceptAnswer(const std::string &)
 {
-        return false;
+    return false;
 }
 
 void
@@ -1165,13 +1135,13 @@ WebRTCSession::acceptICECandidates(const std::vector<mtx::events::msg::CallCandi
 bool
 WebRTCSession::isMicMuted() const
 {
-        return false;
+    return false;
 }
 
 bool
 WebRTCSession::toggleMicMute()
 {
-        return false;
+    return false;
 }
 
 void
diff --git a/src/WebRTCSession.h b/src/WebRTCSession.h
index 97487c5c..56c0a295 100644
--- a/src/WebRTCSession.h
+++ b/src/WebRTCSession.h
@@ -20,22 +20,22 @@ Q_NAMESPACE
 
 enum class CallType
 {
-        VOICE,
-        VIDEO,
-        SCREEN // localUser is sharing screen
+    VOICE,
+    VIDEO,
+    SCREEN // localUser is sharing screen
 };
 Q_ENUM_NS(CallType)
 
 enum class State
 {
-        DISCONNECTED,
-        ICEFAILED,
-        INITIATING,
-        INITIATED,
-        OFFERSENT,
-        ANSWERSENT,
-        CONNECTING,
-        CONNECTED
+    DISCONNECTED,
+    ICEFAILED,
+    INITIATING,
+    INITIATED,
+    OFFERSENT,
+    ANSWERSENT,
+    CONNECTING,
+    CONNECTED
 
 };
 Q_ENUM_NS(State)
@@ -43,75 +43,75 @@ Q_ENUM_NS(State)
 
 class WebRTCSession : public QObject
 {
-        Q_OBJECT
+    Q_OBJECT
 
 public:
-        static WebRTCSession &instance()
-        {
-                static WebRTCSession instance;
-                return instance;
-        }
-
-        bool havePlugins(bool isVideo, std::string *errorMessage = nullptr);
-        webrtc::CallType callType() const { return callType_; }
-        webrtc::State state() const { return state_; }
-        bool haveLocalPiP() const;
-        bool isOffering() const { return isOffering_; }
-        bool isRemoteVideoRecvOnly() const { return isRemoteVideoRecvOnly_; }
-        bool isRemoteVideoSendOnly() const { return isRemoteVideoSendOnly_; }
-
-        bool createOffer(webrtc::CallType, uint32_t shareWindowId);
-        bool acceptOffer(const std::string &sdp);
-        bool acceptAnswer(const std::string &sdp);
-        void acceptICECandidates(const std::vector<mtx::events::msg::CallCandidates::Candidate> &);
-
-        bool isMicMuted() const;
-        bool toggleMicMute();
-        void toggleLocalPiP();
-        void end();
-
-        void setTurnServers(const std::vector<std::string> &uris) { turnServers_ = uris; }
-
-        void setVideoItem(QQuickItem *item) { videoItem_ = item; }
-        QQuickItem *getVideoItem() const { return videoItem_; }
+    static WebRTCSession &instance()
+    {
+        static WebRTCSession instance;
+        return instance;
+    }
+
+    bool havePlugins(bool isVideo, std::string *errorMessage = nullptr);
+    webrtc::CallType callType() const { return callType_; }
+    webrtc::State state() const { return state_; }
+    bool haveLocalPiP() const;
+    bool isOffering() const { return isOffering_; }
+    bool isRemoteVideoRecvOnly() const { return isRemoteVideoRecvOnly_; }
+    bool isRemoteVideoSendOnly() const { return isRemoteVideoSendOnly_; }
+
+    bool createOffer(webrtc::CallType, uint32_t shareWindowId);
+    bool acceptOffer(const std::string &sdp);
+    bool acceptAnswer(const std::string &sdp);
+    void acceptICECandidates(const std::vector<mtx::events::msg::CallCandidates::Candidate> &);
+
+    bool isMicMuted() const;
+    bool toggleMicMute();
+    void toggleLocalPiP();
+    void end();
+
+    void setTurnServers(const std::vector<std::string> &uris) { turnServers_ = uris; }
+
+    void setVideoItem(QQuickItem *item) { videoItem_ = item; }
+    QQuickItem *getVideoItem() const { return videoItem_; }
 
 signals:
-        void offerCreated(const std::string &sdp,
-                          const std::vector<mtx::events::msg::CallCandidates::Candidate> &);
-        void answerCreated(const std::string &sdp,
-                           const std::vector<mtx::events::msg::CallCandidates::Candidate> &);
-        void newICECandidate(const mtx::events::msg::CallCandidates::Candidate &);
-        void stateChanged(webrtc::State);
+    void offerCreated(const std::string &sdp,
+                      const std::vector<mtx::events::msg::CallCandidates::Candidate> &);
+    void answerCreated(const std::string &sdp,
+                       const std::vector<mtx::events::msg::CallCandidates::Candidate> &);
+    void newICECandidate(const mtx::events::msg::CallCandidates::Candidate &);
+    void stateChanged(webrtc::State);
 
 private slots:
-        void setState(webrtc::State state) { state_ = state; }
+    void setState(webrtc::State state) { state_ = state; }
 
 private:
-        WebRTCSession();
-
-        CallDevices &devices_;
-        bool initialised_           = false;
-        bool haveVoicePlugins_      = false;
-        bool haveVideoPlugins_      = false;
-        webrtc::CallType callType_  = webrtc::CallType::VOICE;
-        webrtc::State state_        = webrtc::State::DISCONNECTED;
-        bool isOffering_            = false;
-        bool isRemoteVideoRecvOnly_ = false;
-        bool isRemoteVideoSendOnly_ = false;
-        QQuickItem *videoItem_      = nullptr;
-        GstElement *pipe_           = nullptr;
-        GstElement *webrtc_         = nullptr;
-        unsigned int busWatchId_    = 0;
-        std::vector<std::string> turnServers_;
-        uint32_t shareWindowId_ = 0;
-
-        bool init(std::string *errorMessage = nullptr);
-        bool startPipeline(int opusPayloadType, int vp8PayloadType);
-        bool createPipeline(int opusPayloadType, int vp8PayloadType);
-        bool addVideoPipeline(int vp8PayloadType);
-        void clear();
+    WebRTCSession();
+
+    CallDevices &devices_;
+    bool initialised_           = false;
+    bool haveVoicePlugins_      = false;
+    bool haveVideoPlugins_      = false;
+    webrtc::CallType callType_  = webrtc::CallType::VOICE;
+    webrtc::State state_        = webrtc::State::DISCONNECTED;
+    bool isOffering_            = false;
+    bool isRemoteVideoRecvOnly_ = false;
+    bool isRemoteVideoSendOnly_ = false;
+    QQuickItem *videoItem_      = nullptr;
+    GstElement *pipe_           = nullptr;
+    GstElement *webrtc_         = nullptr;
+    unsigned int busWatchId_    = 0;
+    std::vector<std::string> turnServers_;
+    uint32_t shareWindowId_ = 0;
+
+    bool init(std::string *errorMessage = nullptr);
+    bool startPipeline(int opusPayloadType, int vp8PayloadType);
+    bool createPipeline(int opusPayloadType, int vp8PayloadType);
+    bool addVideoPipeline(int vp8PayloadType);
+    void clear();
 
 public:
-        WebRTCSession(WebRTCSession const &) = delete;
-        void operator=(WebRTCSession const &) = delete;
+    WebRTCSession(WebRTCSession const &) = delete;
+    void operator=(WebRTCSession const &) = delete;
 };
diff --git a/src/WelcomePage.cpp b/src/WelcomePage.cpp
index 2cce7b8d..c7168789 100644
--- a/src/WelcomePage.cpp
+++ b/src/WelcomePage.cpp
@@ -16,72 +16,72 @@
 WelcomePage::WelcomePage(QWidget *parent)
   : QWidget(parent)
 {
-        auto topLayout_ = new QVBoxLayout(this);
-        topLayout_->setSpacing(20);
-        topLayout_->setAlignment(Qt::AlignCenter);
+    auto topLayout_ = new QVBoxLayout(this);
+    topLayout_->setSpacing(20);
+    topLayout_->setAlignment(Qt::AlignCenter);
 
-        QFont headingFont;
-        headingFont.setPointSizeF(headingFont.pointSizeF() * 2);
-        QFont subTitleFont;
-        subTitleFont.setPointSizeF(subTitleFont.pointSizeF() * 1.5);
+    QFont headingFont;
+    headingFont.setPointSizeF(headingFont.pointSizeF() * 2);
+    QFont subTitleFont;
+    subTitleFont.setPointSizeF(subTitleFont.pointSizeF() * 1.5);
 
-        QIcon icon{QIcon::fromTheme("nheko", QIcon{":/logos/splash.png"})};
+    QIcon icon{QIcon::fromTheme("nheko", QIcon{":/logos/splash.png"})};
 
-        auto logo_ = new QLabel(this);
-        logo_->setPixmap(icon.pixmap(256));
-        logo_->setAlignment(Qt::AlignCenter);
+    auto logo_ = new QLabel(this);
+    logo_->setPixmap(icon.pixmap(256));
+    logo_->setAlignment(Qt::AlignCenter);
 
-        QString heading(tr("Welcome to nheko! The desktop client for the Matrix protocol."));
-        QString main(tr("Enjoy your stay!"));
+    QString heading(tr("Welcome to nheko! The desktop client for the Matrix protocol."));
+    QString main(tr("Enjoy your stay!"));
 
-        auto intoTxt_ = new TextLabel(heading, this);
-        intoTxt_->setFont(headingFont);
-        intoTxt_->setAlignment(Qt::AlignCenter);
+    auto intoTxt_ = new TextLabel(heading, this);
+    intoTxt_->setFont(headingFont);
+    intoTxt_->setAlignment(Qt::AlignCenter);
 
-        auto subTitle = new TextLabel(main, this);
-        subTitle->setFont(subTitleFont);
-        subTitle->setAlignment(Qt::AlignCenter);
+    auto subTitle = new TextLabel(main, this);
+    subTitle->setFont(subTitleFont);
+    subTitle->setAlignment(Qt::AlignCenter);
 
-        topLayout_->addStretch(1);
-        topLayout_->addWidget(logo_);
-        topLayout_->addWidget(intoTxt_);
-        topLayout_->addWidget(subTitle);
+    topLayout_->addStretch(1);
+    topLayout_->addWidget(logo_);
+    topLayout_->addWidget(intoTxt_);
+    topLayout_->addWidget(subTitle);
 
-        auto btnLayout_ = new QHBoxLayout();
-        btnLayout_->setSpacing(20);
-        btnLayout_->setContentsMargins(0, 20, 0, 20);
+    auto btnLayout_ = new QHBoxLayout();
+    btnLayout_->setSpacing(20);
+    btnLayout_->setContentsMargins(0, 20, 0, 20);
 
-        const int fontHeight   = QFontMetrics{subTitleFont}.height();
-        const int buttonHeight = fontHeight * 2.5;
-        const int buttonWidth  = fontHeight * 8;
+    const int fontHeight   = QFontMetrics{subTitleFont}.height();
+    const int buttonHeight = fontHeight * 2.5;
+    const int buttonWidth  = fontHeight * 8;
 
-        auto registerBtn = new RaisedButton(tr("REGISTER"), this);
-        registerBtn->setMinimumSize(buttonWidth, buttonHeight);
-        registerBtn->setFontSize(subTitleFont.pointSizeF());
-        registerBtn->setCornerRadius(conf::btn::cornerRadius);
+    auto registerBtn = new RaisedButton(tr("REGISTER"), this);
+    registerBtn->setMinimumSize(buttonWidth, buttonHeight);
+    registerBtn->setFontSize(subTitleFont.pointSizeF());
+    registerBtn->setCornerRadius(conf::btn::cornerRadius);
 
-        auto loginBtn = new RaisedButton(tr("LOGIN"), this);
-        loginBtn->setMinimumSize(buttonWidth, buttonHeight);
-        loginBtn->setFontSize(subTitleFont.pointSizeF());
-        loginBtn->setCornerRadius(conf::btn::cornerRadius);
+    auto loginBtn = new RaisedButton(tr("LOGIN"), this);
+    loginBtn->setMinimumSize(buttonWidth, buttonHeight);
+    loginBtn->setFontSize(subTitleFont.pointSizeF());
+    loginBtn->setCornerRadius(conf::btn::cornerRadius);
 
-        btnLayout_->addStretch(1);
-        btnLayout_->addWidget(registerBtn);
-        btnLayout_->addWidget(loginBtn);
-        btnLayout_->addStretch(1);
+    btnLayout_->addStretch(1);
+    btnLayout_->addWidget(registerBtn);
+    btnLayout_->addWidget(loginBtn);
+    btnLayout_->addStretch(1);
 
-        topLayout_->addLayout(btnLayout_);
-        topLayout_->addStretch(1);
+    topLayout_->addLayout(btnLayout_);
+    topLayout_->addStretch(1);
 
-        connect(registerBtn, &QPushButton::clicked, this, &WelcomePage::userRegister);
-        connect(loginBtn, &QPushButton::clicked, this, &WelcomePage::userLogin);
+    connect(registerBtn, &QPushButton::clicked, this, &WelcomePage::userRegister);
+    connect(loginBtn, &QPushButton::clicked, this, &WelcomePage::userLogin);
 }
 
 void
 WelcomePage::paintEvent(QPaintEvent *)
 {
-        QStyleOption opt;
-        opt.init(this);
-        QPainter p(this);
-        style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
+    QStyleOption opt;
+    opt.init(this);
+    QPainter p(this);
+    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
 }
diff --git a/src/WelcomePage.h b/src/WelcomePage.h
index d2dcc0c9..aa531a03 100644
--- a/src/WelcomePage.h
+++ b/src/WelcomePage.h
@@ -8,18 +8,18 @@
 
 class WelcomePage : public QWidget
 {
-        Q_OBJECT
+    Q_OBJECT
 
 public:
-        explicit WelcomePage(QWidget *parent = nullptr);
+    explicit WelcomePage(QWidget *parent = nullptr);
 
 protected:
-        void paintEvent(QPaintEvent *) override;
+    void paintEvent(QPaintEvent *) override;
 
 signals:
-        // Notify that the user wants to login in.
-        void userLogin();
+    // Notify that the user wants to login in.
+    void userLogin();
 
-        // Notify that the user wants to register.
-        void userRegister();
+    // Notify that the user wants to register.
+    void userRegister();
 };
diff --git a/src/dialogs/CreateRoom.cpp b/src/dialogs/CreateRoom.cpp
index ba385436..30dbf83d 100644
--- a/src/dialogs/CreateRoom.cpp
+++ b/src/dialogs/CreateRoom.cpp
@@ -18,142 +18,142 @@ using namespace dialogs;
 CreateRoom::CreateRoom(QWidget *parent)
   : QFrame(parent)
 {
-        setAutoFillBackground(true);
-        setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
-        setWindowModality(Qt::WindowModal);
-        setAttribute(Qt::WA_DeleteOnClose, true);
-
-        QFont largeFont;
-        largeFont.setPointSizeF(largeFont.pointSizeF() * 1.5);
-
-        setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
-        setMinimumHeight(conf::modals::MIN_WIDGET_HEIGHT);
-        setMinimumWidth(conf::window::minModalWidth);
-
-        auto layout = new QVBoxLayout(this);
-        layout->setSpacing(conf::modals::WIDGET_SPACING);
-        layout->setMargin(conf::modals::WIDGET_MARGIN);
-
-        auto buttonLayout = new QHBoxLayout();
-        buttonLayout->setSpacing(15);
-
-        confirmBtn_ = new QPushButton(tr("Create room"), this);
-        confirmBtn_->setDefault(true);
-        cancelBtn_ = new QPushButton(tr("Cancel"), this);
-
-        buttonLayout->addStretch(1);
-        buttonLayout->addWidget(cancelBtn_);
-        buttonLayout->addWidget(confirmBtn_);
-
-        QFont font;
-        font.setPointSizeF(font.pointSizeF() * 1.3);
-
-        nameInput_ = new TextField(this);
-        nameInput_->setLabel(tr("Name"));
-
-        topicInput_ = new TextField(this);
-        topicInput_->setLabel(tr("Topic"));
-
-        aliasInput_ = new TextField(this);
-        aliasInput_->setLabel(tr("Alias"));
-
-        auto visibilityLayout = new QHBoxLayout;
-        visibilityLayout->setContentsMargins(0, 10, 0, 10);
-
-        auto presetLayout = new QHBoxLayout;
-        presetLayout->setContentsMargins(0, 10, 0, 10);
-
-        auto visibilityLabel = new QLabel(tr("Room Visibility"), this);
-        visibilityCombo_     = new QComboBox(this);
-        visibilityCombo_->addItem("Private");
-        visibilityCombo_->addItem("Public");
-
-        visibilityLayout->addWidget(visibilityLabel);
-        visibilityLayout->addWidget(visibilityCombo_, 0, Qt::AlignBottom | Qt::AlignRight);
-
-        auto presetLabel = new QLabel(tr("Room Preset"), this);
-        presetCombo_     = new QComboBox(this);
-        presetCombo_->addItem("Private Chat");
-        presetCombo_->addItem("Public Chat");
-        presetCombo_->addItem("Trusted Private Chat");
-
-        presetLayout->addWidget(presetLabel);
-        presetLayout->addWidget(presetCombo_, 0, Qt::AlignBottom | Qt::AlignRight);
-
-        auto directLabel_ = new QLabel(tr("Direct Chat"), this);
-        directToggle_     = new Toggle(this);
-        directToggle_->setActiveColor(QColor("#38A3D8"));
-        directToggle_->setInactiveColor(QColor("gray"));
-        directToggle_->setState(false);
-
-        auto directLayout = new QHBoxLayout;
-        directLayout->setContentsMargins(0, 10, 0, 10);
-        directLayout->addWidget(directLabel_);
-        directLayout->addWidget(directToggle_, 0, Qt::AlignBottom | Qt::AlignRight);
-
-        layout->addWidget(nameInput_);
-        layout->addWidget(topicInput_);
-        layout->addWidget(aliasInput_);
-        layout->addLayout(visibilityLayout);
-        layout->addLayout(presetLayout);
-        layout->addLayout(directLayout);
-        layout->addLayout(buttonLayout);
-
-        connect(confirmBtn_, &QPushButton::clicked, this, [this]() {
-                request_.name            = nameInput_->text().toStdString();
-                request_.topic           = topicInput_->text().toStdString();
-                request_.room_alias_name = aliasInput_->text().toStdString();
-
-                emit createRoom(request_);
-
-                clearFields();
-                emit close();
-        });
-
-        connect(cancelBtn_, &QPushButton::clicked, this, [this]() {
-                clearFields();
-                emit close();
-        });
-
-        connect(visibilityCombo_,
-                static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
-                [this](const QString &text) {
-                        if (text == "Private") {
-                                request_.visibility = mtx::common::RoomVisibility::Private;
-                        } else {
-                                request_.visibility = mtx::common::RoomVisibility::Public;
-                        }
-                });
-
-        connect(presetCombo_,
-                static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
-                [this](const QString &text) {
-                        if (text == "Private Chat") {
-                                request_.preset = mtx::requests::Preset::PrivateChat;
-                        } else if (text == "Public Chat") {
-                                request_.preset = mtx::requests::Preset::PublicChat;
-                        } else {
-                                request_.preset = mtx::requests::Preset::TrustedPrivateChat;
-                        }
-                });
-
-        connect(directToggle_, &Toggle::toggled, this, [this](bool isEnabled) {
-                request_.is_direct = isEnabled;
-        });
+    setAutoFillBackground(true);
+    setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
+    setWindowModality(Qt::WindowModal);
+    setAttribute(Qt::WA_DeleteOnClose, true);
+
+    QFont largeFont;
+    largeFont.setPointSizeF(largeFont.pointSizeF() * 1.5);
+
+    setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
+    setMinimumHeight(conf::modals::MIN_WIDGET_HEIGHT);
+    setMinimumWidth(conf::window::minModalWidth);
+
+    auto layout = new QVBoxLayout(this);
+    layout->setSpacing(conf::modals::WIDGET_SPACING);
+    layout->setMargin(conf::modals::WIDGET_MARGIN);
+
+    auto buttonLayout = new QHBoxLayout();
+    buttonLayout->setSpacing(15);
+
+    confirmBtn_ = new QPushButton(tr("Create room"), this);
+    confirmBtn_->setDefault(true);
+    cancelBtn_ = new QPushButton(tr("Cancel"), this);
+
+    buttonLayout->addStretch(1);
+    buttonLayout->addWidget(cancelBtn_);
+    buttonLayout->addWidget(confirmBtn_);
+
+    QFont font;
+    font.setPointSizeF(font.pointSizeF() * 1.3);
+
+    nameInput_ = new TextField(this);
+    nameInput_->setLabel(tr("Name"));
+
+    topicInput_ = new TextField(this);
+    topicInput_->setLabel(tr("Topic"));
+
+    aliasInput_ = new TextField(this);
+    aliasInput_->setLabel(tr("Alias"));
+
+    auto visibilityLayout = new QHBoxLayout;
+    visibilityLayout->setContentsMargins(0, 10, 0, 10);
+
+    auto presetLayout = new QHBoxLayout;
+    presetLayout->setContentsMargins(0, 10, 0, 10);
+
+    auto visibilityLabel = new QLabel(tr("Room Visibility"), this);
+    visibilityCombo_     = new QComboBox(this);
+    visibilityCombo_->addItem("Private");
+    visibilityCombo_->addItem("Public");
+
+    visibilityLayout->addWidget(visibilityLabel);
+    visibilityLayout->addWidget(visibilityCombo_, 0, Qt::AlignBottom | Qt::AlignRight);
+
+    auto presetLabel = new QLabel(tr("Room Preset"), this);
+    presetCombo_     = new QComboBox(this);
+    presetCombo_->addItem("Private Chat");
+    presetCombo_->addItem("Public Chat");
+    presetCombo_->addItem("Trusted Private Chat");
+
+    presetLayout->addWidget(presetLabel);
+    presetLayout->addWidget(presetCombo_, 0, Qt::AlignBottom | Qt::AlignRight);
+
+    auto directLabel_ = new QLabel(tr("Direct Chat"), this);
+    directToggle_     = new Toggle(this);
+    directToggle_->setActiveColor(QColor("#38A3D8"));
+    directToggle_->setInactiveColor(QColor("gray"));
+    directToggle_->setState(false);
+
+    auto directLayout = new QHBoxLayout;
+    directLayout->setContentsMargins(0, 10, 0, 10);
+    directLayout->addWidget(directLabel_);
+    directLayout->addWidget(directToggle_, 0, Qt::AlignBottom | Qt::AlignRight);
+
+    layout->addWidget(nameInput_);
+    layout->addWidget(topicInput_);
+    layout->addWidget(aliasInput_);
+    layout->addLayout(visibilityLayout);
+    layout->addLayout(presetLayout);
+    layout->addLayout(directLayout);
+    layout->addLayout(buttonLayout);
+
+    connect(confirmBtn_, &QPushButton::clicked, this, [this]() {
+        request_.name            = nameInput_->text().toStdString();
+        request_.topic           = topicInput_->text().toStdString();
+        request_.room_alias_name = aliasInput_->text().toStdString();
+
+        emit createRoom(request_);
+
+        clearFields();
+        emit close();
+    });
+
+    connect(cancelBtn_, &QPushButton::clicked, this, [this]() {
+        clearFields();
+        emit close();
+    });
+
+    connect(visibilityCombo_,
+            static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
+            [this](const QString &text) {
+                if (text == "Private") {
+                    request_.visibility = mtx::common::RoomVisibility::Private;
+                } else {
+                    request_.visibility = mtx::common::RoomVisibility::Public;
+                }
+            });
+
+    connect(presetCombo_,
+            static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
+            [this](const QString &text) {
+                if (text == "Private Chat") {
+                    request_.preset = mtx::requests::Preset::PrivateChat;
+                } else if (text == "Public Chat") {
+                    request_.preset = mtx::requests::Preset::PublicChat;
+                } else {
+                    request_.preset = mtx::requests::Preset::TrustedPrivateChat;
+                }
+            });
+
+    connect(directToggle_, &Toggle::toggled, this, [this](bool isEnabled) {
+        request_.is_direct = isEnabled;
+    });
 }
 
 void
 CreateRoom::clearFields()
 {
-        nameInput_->clear();
-        topicInput_->clear();
-        aliasInput_->clear();
+    nameInput_->clear();
+    topicInput_->clear();
+    aliasInput_->clear();
 }
 
 void
 CreateRoom::showEvent(QShowEvent *event)
 {
-        nameInput_->setFocus();
+    nameInput_->setFocus();
 
-        QFrame::showEvent(event);
+    QFrame::showEvent(event);
 }
diff --git a/src/dialogs/CreateRoom.h b/src/dialogs/CreateRoom.h
index d4c6474d..d9d90a10 100644
--- a/src/dialogs/CreateRoom.h
+++ b/src/dialogs/CreateRoom.h
@@ -17,32 +17,32 @@ namespace dialogs {
 
 class CreateRoom : public QFrame
 {
-        Q_OBJECT
+    Q_OBJECT
 public:
-        CreateRoom(QWidget *parent = nullptr);
+    CreateRoom(QWidget *parent = nullptr);
 
 signals:
-        void createRoom(const mtx::requests::CreateRoom &request);
+    void createRoom(const mtx::requests::CreateRoom &request);
 
 protected:
-        void showEvent(QShowEvent *event) override;
+    void showEvent(QShowEvent *event) override;
 
 private:
-        void clearFields();
+    void clearFields();
 
-        QComboBox *visibilityCombo_;
-        QComboBox *presetCombo_;
+    QComboBox *visibilityCombo_;
+    QComboBox *presetCombo_;
 
-        Toggle *directToggle_;
+    Toggle *directToggle_;
 
-        QPushButton *confirmBtn_;
-        QPushButton *cancelBtn_;
+    QPushButton *confirmBtn_;
+    QPushButton *cancelBtn_;
 
-        TextField *nameInput_;
-        TextField *topicInput_;
-        TextField *aliasInput_;
+    TextField *nameInput_;
+    TextField *topicInput_;
+    TextField *aliasInput_;
 
-        mtx::requests::CreateRoom request_;
+    mtx::requests::CreateRoom request_;
 };
 
 } // dialogs
diff --git a/src/dialogs/FallbackAuth.cpp b/src/dialogs/FallbackAuth.cpp
index c7b179f4..2b8dfed9 100644
--- a/src/dialogs/FallbackAuth.cpp
+++ b/src/dialogs/FallbackAuth.cpp
@@ -18,56 +18,56 @@ using namespace dialogs;
 FallbackAuth::FallbackAuth(const QString &authType, const QString &session, QWidget *parent)
   : QWidget(parent)
 {
-        setAutoFillBackground(true);
-        setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
-        setWindowModality(Qt::WindowModal);
-        setAttribute(Qt::WA_DeleteOnClose, true);
+    setAutoFillBackground(true);
+    setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
+    setWindowModality(Qt::WindowModal);
+    setAttribute(Qt::WA_DeleteOnClose, true);
 
-        auto layout = new QVBoxLayout(this);
-        layout->setSpacing(conf::modals::WIDGET_SPACING);
-        layout->setMargin(conf::modals::WIDGET_MARGIN);
+    auto layout = new QVBoxLayout(this);
+    layout->setSpacing(conf::modals::WIDGET_SPACING);
+    layout->setMargin(conf::modals::WIDGET_MARGIN);
 
-        auto buttonLayout = new QHBoxLayout();
-        buttonLayout->setSpacing(8);
-        buttonLayout->setMargin(0);
+    auto buttonLayout = new QHBoxLayout();
+    buttonLayout->setSpacing(8);
+    buttonLayout->setMargin(0);
 
-        openBtn_    = new QPushButton(tr("Open Fallback in Browser"), this);
-        cancelBtn_  = new QPushButton(tr("Cancel"), this);
-        confirmBtn_ = new QPushButton(tr("Confirm"), this);
-        confirmBtn_->setDefault(true);
+    openBtn_    = new QPushButton(tr("Open Fallback in Browser"), this);
+    cancelBtn_  = new QPushButton(tr("Cancel"), this);
+    confirmBtn_ = new QPushButton(tr("Confirm"), this);
+    confirmBtn_->setDefault(true);
 
-        buttonLayout->addStretch(1);
-        buttonLayout->addWidget(openBtn_);
-        buttonLayout->addWidget(cancelBtn_);
-        buttonLayout->addWidget(confirmBtn_);
+    buttonLayout->addStretch(1);
+    buttonLayout->addWidget(openBtn_);
+    buttonLayout->addWidget(cancelBtn_);
+    buttonLayout->addWidget(confirmBtn_);
 
-        QFont font;
-        font.setPointSizeF(font.pointSizeF() * conf::modals::LABEL_MEDIUM_SIZE_RATIO);
+    QFont font;
+    font.setPointSizeF(font.pointSizeF() * conf::modals::LABEL_MEDIUM_SIZE_RATIO);
 
-        auto label = new QLabel(
-          tr("Open the fallback, follow the steps and confirm after completing them."), this);
-        label->setFont(font);
+    auto label = new QLabel(
+      tr("Open the fallback, follow the steps and confirm after completing them."), this);
+    label->setFont(font);
 
-        layout->addWidget(label);
-        layout->addLayout(buttonLayout);
+    layout->addWidget(label);
+    layout->addLayout(buttonLayout);
 
-        connect(openBtn_, &QPushButton::clicked, [session, authType]() {
-                const auto url = QString("https://%1:%2/_matrix/client/r0/auth/%4/"
-                                         "fallback/web?session=%3")
-                                   .arg(QString::fromStdString(http::client()->server()))
-                                   .arg(http::client()->port())
-                                   .arg(session)
-                                   .arg(authType);
+    connect(openBtn_, &QPushButton::clicked, [session, authType]() {
+        const auto url = QString("https://%1:%2/_matrix/client/r0/auth/%4/"
+                                 "fallback/web?session=%3")
+                           .arg(QString::fromStdString(http::client()->server()))
+                           .arg(http::client()->port())
+                           .arg(session)
+                           .arg(authType);
 
-                QDesktopServices::openUrl(url);
-        });
+        QDesktopServices::openUrl(url);
+    });
 
-        connect(confirmBtn_, &QPushButton::clicked, this, [this]() {
-                emit confirmation();
-                emit close();
-        });
-        connect(cancelBtn_, &QPushButton::clicked, this, [this]() {
-                emit cancel();
-                emit close();
-        });
+    connect(confirmBtn_, &QPushButton::clicked, this, [this]() {
+        emit confirmation();
+        emit close();
+    });
+    connect(cancelBtn_, &QPushButton::clicked, this, [this]() {
+        emit cancel();
+        emit close();
+    });
 }
diff --git a/src/dialogs/FallbackAuth.h b/src/dialogs/FallbackAuth.h
index 8e4e28ea..6bfd59f7 100644
--- a/src/dialogs/FallbackAuth.h
+++ b/src/dialogs/FallbackAuth.h
@@ -13,18 +13,18 @@ namespace dialogs {
 
 class FallbackAuth : public QWidget
 {
-        Q_OBJECT
+    Q_OBJECT
 
 public:
-        FallbackAuth(const QString &authType, const QString &session, QWidget *parent = nullptr);
+    FallbackAuth(const QString &authType, const QString &session, QWidget *parent = nullptr);
 
 signals:
-        void confirmation();
-        void cancel();
+    void confirmation();
+    void cancel();
 
 private:
-        QPushButton *openBtn_;
-        QPushButton *confirmBtn_;
-        QPushButton *cancelBtn_;
+    QPushButton *openBtn_;
+    QPushButton *confirmBtn_;
+    QPushButton *cancelBtn_;
 };
 } // dialogs
diff --git a/src/dialogs/ImageOverlay.cpp b/src/dialogs/ImageOverlay.cpp
index 12813d57..8c90a744 100644
--- a/src/dialogs/ImageOverlay.cpp
+++ b/src/dialogs/ImageOverlay.cpp
@@ -19,84 +19,83 @@ ImageOverlay::ImageOverlay(QPixmap image, QWidget *parent)
   : QWidget{parent}
   , originalImage_{image}
 {
-        setMouseTracking(true);
-        setParent(nullptr);
+    setMouseTracking(true);
+    setParent(nullptr);
 
-        setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
+    setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
 
-        setAttribute(Qt::WA_NoSystemBackground, true);
-        setAttribute(Qt::WA_TranslucentBackground, true);
-        setAttribute(Qt::WA_DeleteOnClose, true);
-        setWindowState(Qt::WindowFullScreen);
-        close_shortcut_ = new QShortcut(QKeySequence(Qt::Key_Escape), this);
+    setAttribute(Qt::WA_NoSystemBackground, true);
+    setAttribute(Qt::WA_TranslucentBackground, true);
+    setAttribute(Qt::WA_DeleteOnClose, true);
+    setWindowState(Qt::WindowFullScreen);
+    close_shortcut_ = new QShortcut(QKeySequence(Qt::Key_Escape), this);
 
-        connect(close_shortcut_, &QShortcut::activated, this, &ImageOverlay::closing);
-        connect(this, &ImageOverlay::closing, this, &ImageOverlay::close);
+    connect(close_shortcut_, &QShortcut::activated, this, &ImageOverlay::closing);
+    connect(this, &ImageOverlay::closing, this, &ImageOverlay::close);
 
-        raise();
+    raise();
 }
 
 void
 ImageOverlay::paintEvent(QPaintEvent *event)
 {
-        Q_UNUSED(event);
+    Q_UNUSED(event);
 
-        QPainter painter(this);
-        painter.setRenderHint(QPainter::Antialiasing);
+    QPainter painter(this);
+    painter.setRenderHint(QPainter::Antialiasing);
 
-        // Full screen overlay.
-        painter.fillRect(QRect(0, 0, width(), height()), QColor(55, 55, 55, 170));
+    // Full screen overlay.
+    painter.fillRect(QRect(0, 0, width(), height()), QColor(55, 55, 55, 170));
 
-        // Left and Right margins
-        int outer_margin = width() * 0.12;
-        int buttonSize   = 36;
-        int margin       = outer_margin * 0.1;
+    // Left and Right margins
+    int outer_margin = width() * 0.12;
+    int buttonSize   = 36;
+    int margin       = outer_margin * 0.1;
 
-        int max_width  = width() - 2 * outer_margin;
-        int max_height = height();
+    int max_width  = width() - 2 * outer_margin;
+    int max_height = height();
 
-        image_ = utils::scaleDown(max_width, max_height, originalImage_);
+    image_ = utils::scaleDown(max_width, max_height, originalImage_);
 
-        int diff_x = max_width - image_.width();
-        int diff_y = max_height - image_.height();
+    int diff_x = max_width - image_.width();
+    int diff_y = max_height - image_.height();
 
-        content_ = QRect(outer_margin + diff_x / 2, diff_y / 2, image_.width(), image_.height());
-        close_button_ = QRect(width() - margin - buttonSize, margin, buttonSize, buttonSize);
-        save_button_ =
-          QRect(width() - (2 * margin) - (2 * buttonSize), margin, buttonSize, buttonSize);
+    content_      = QRect(outer_margin + diff_x / 2, diff_y / 2, image_.width(), image_.height());
+    close_button_ = QRect(width() - margin - buttonSize, margin, buttonSize, buttonSize);
+    save_button_ = QRect(width() - (2 * margin) - (2 * buttonSize), margin, buttonSize, buttonSize);
 
-        // Draw main content_.
-        painter.drawPixmap(content_, image_);
+    // Draw main content_.
+    painter.drawPixmap(content_, image_);
 
-        // Draw top right corner X.
-        QPen pen;
-        pen.setCapStyle(Qt::RoundCap);
-        pen.setWidthF(5);
-        pen.setColor("gray");
+    // Draw top right corner X.
+    QPen pen;
+    pen.setCapStyle(Qt::RoundCap);
+    pen.setWidthF(5);
+    pen.setColor("gray");
 
-        auto center = close_button_.center();
+    auto center = close_button_.center();
 
-        painter.setPen(pen);
-        painter.drawLine(center - QPointF(15, 15), center + QPointF(15, 15));
-        painter.drawLine(center + QPointF(15, -15), center - QPointF(15, -15));
+    painter.setPen(pen);
+    painter.drawLine(center - QPointF(15, 15), center + QPointF(15, 15));
+    painter.drawLine(center + QPointF(15, -15), center - QPointF(15, -15));
 
-        // Draw download button
-        center = save_button_.center();
-        painter.drawLine(center - QPointF(0, 15), center + QPointF(0, 15));
-        painter.drawLine(center - QPointF(15, 0), center + QPointF(0, 15));
-        painter.drawLine(center + QPointF(0, 15), center + QPointF(15, 0));
+    // Draw download button
+    center = save_button_.center();
+    painter.drawLine(center - QPointF(0, 15), center + QPointF(0, 15));
+    painter.drawLine(center - QPointF(15, 0), center + QPointF(0, 15));
+    painter.drawLine(center + QPointF(0, 15), center + QPointF(15, 0));
 }
 
 void
 ImageOverlay::mousePressEvent(QMouseEvent *event)
 {
-        if (event->button() != Qt::LeftButton)
-                return;
-
-        if (close_button_.contains(event->pos()))
-                emit closing();
-        else if (save_button_.contains(event->pos()))
-                emit saving();
-        else if (!content_.contains(event->pos()))
-                emit closing();
+    if (event->button() != Qt::LeftButton)
+        return;
+
+    if (close_button_.contains(event->pos()))
+        emit closing();
+    else if (save_button_.contains(event->pos()))
+        emit saving();
+    else if (!content_.contains(event->pos()))
+        emit closing();
 }
diff --git a/src/dialogs/ImageOverlay.h b/src/dialogs/ImageOverlay.h
index 9d4187bf..2174279f 100644
--- a/src/dialogs/ImageOverlay.h
+++ b/src/dialogs/ImageOverlay.h
@@ -14,25 +14,25 @@ namespace dialogs {
 
 class ImageOverlay : public QWidget
 {
-        Q_OBJECT
+    Q_OBJECT
 public:
-        ImageOverlay(QPixmap image, QWidget *parent = nullptr);
+    ImageOverlay(QPixmap image, QWidget *parent = nullptr);
 
 protected:
-        void mousePressEvent(QMouseEvent *event) override;
-        void paintEvent(QPaintEvent *event) override;
+    void mousePressEvent(QMouseEvent *event) override;
+    void paintEvent(QPaintEvent *event) override;
 
 signals:
-        void closing();
-        void saving();
+    void closing();
+    void saving();
 
 private:
-        QPixmap originalImage_;
-        QPixmap image_;
+    QPixmap originalImage_;
+    QPixmap image_;
 
-        QRect content_;
-        QRect close_button_;
-        QRect save_button_;
-        QShortcut *close_shortcut_;
+    QRect content_;
+    QRect close_button_;
+    QRect save_button_;
+    QShortcut *close_shortcut_;
 };
 } // dialogs
diff --git a/src/dialogs/JoinRoom.cpp b/src/dialogs/JoinRoom.cpp
index dc2e4804..76baf857 100644
--- a/src/dialogs/JoinRoom.cpp
+++ b/src/dialogs/JoinRoom.cpp
@@ -16,58 +16,58 @@ using namespace dialogs;
 JoinRoom::JoinRoom(QWidget *parent)
   : QFrame(parent)
 {
-        setAutoFillBackground(true);
-        setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
-        setWindowModality(Qt::WindowModal);
-        setAttribute(Qt::WA_DeleteOnClose, true);
+    setAutoFillBackground(true);
+    setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
+    setWindowModality(Qt::WindowModal);
+    setAttribute(Qt::WA_DeleteOnClose, true);
 
-        setMinimumWidth(conf::modals::MIN_WIDGET_WIDTH);
-        setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
+    setMinimumWidth(conf::modals::MIN_WIDGET_WIDTH);
+    setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
 
-        auto layout = new QVBoxLayout(this);
-        layout->setSpacing(conf::modals::WIDGET_SPACING);
-        layout->setMargin(conf::modals::WIDGET_MARGIN);
+    auto layout = new QVBoxLayout(this);
+    layout->setSpacing(conf::modals::WIDGET_SPACING);
+    layout->setMargin(conf::modals::WIDGET_MARGIN);
 
-        auto buttonLayout = new QHBoxLayout();
-        buttonLayout->setSpacing(15);
+    auto buttonLayout = new QHBoxLayout();
+    buttonLayout->setSpacing(15);
 
-        confirmBtn_ = new QPushButton(tr("Join"), this);
-        confirmBtn_->setDefault(true);
-        cancelBtn_ = new QPushButton(tr("Cancel"), this);
+    confirmBtn_ = new QPushButton(tr("Join"), this);
+    confirmBtn_->setDefault(true);
+    cancelBtn_ = new QPushButton(tr("Cancel"), this);
 
-        buttonLayout->addStretch(1);
-        buttonLayout->addWidget(cancelBtn_);
-        buttonLayout->addWidget(confirmBtn_);
+    buttonLayout->addStretch(1);
+    buttonLayout->addWidget(cancelBtn_);
+    buttonLayout->addWidget(confirmBtn_);
 
-        roomInput_ = new TextField(this);
-        roomInput_->setLabel(tr("Room ID or alias"));
+    roomInput_ = new TextField(this);
+    roomInput_->setLabel(tr("Room ID or alias"));
 
-        layout->addWidget(roomInput_);
-        layout->addLayout(buttonLayout);
-        layout->addStretch(1);
+    layout->addWidget(roomInput_);
+    layout->addLayout(buttonLayout);
+    layout->addStretch(1);
 
-        connect(roomInput_, &QLineEdit::returnPressed, this, &JoinRoom::handleInput);
-        connect(confirmBtn_, &QPushButton::clicked, this, &JoinRoom::handleInput);
-        connect(cancelBtn_, &QPushButton::clicked, this, &JoinRoom::close);
+    connect(roomInput_, &QLineEdit::returnPressed, this, &JoinRoom::handleInput);
+    connect(confirmBtn_, &QPushButton::clicked, this, &JoinRoom::handleInput);
+    connect(cancelBtn_, &QPushButton::clicked, this, &JoinRoom::close);
 }
 
 void
 JoinRoom::handleInput()
 {
-        if (roomInput_->text().isEmpty())
-                return;
+    if (roomInput_->text().isEmpty())
+        return;
 
-        // TODO: input validation with error messages.
-        emit joinRoom(roomInput_->text());
-        roomInput_->clear();
+    // TODO: input validation with error messages.
+    emit joinRoom(roomInput_->text());
+    roomInput_->clear();
 
-        emit close();
+    emit close();
 }
 
 void
 JoinRoom::showEvent(QShowEvent *event)
 {
-        roomInput_->setFocus();
+    roomInput_->setFocus();
 
-        QFrame::showEvent(event);
+    QFrame::showEvent(event);
 }
diff --git a/src/dialogs/JoinRoom.h b/src/dialogs/JoinRoom.h
index f399f1fb..11c54d7c 100644
--- a/src/dialogs/JoinRoom.h
+++ b/src/dialogs/JoinRoom.h
@@ -13,24 +13,24 @@ namespace dialogs {
 
 class JoinRoom : public QFrame
 {
-        Q_OBJECT
+    Q_OBJECT
 public:
-        JoinRoom(QWidget *parent = nullptr);
+    JoinRoom(QWidget *parent = nullptr);
 
 signals:
-        void joinRoom(const QString &room);
+    void joinRoom(const QString &room);
 
 protected:
-        void showEvent(QShowEvent *event) override;
+    void showEvent(QShowEvent *event) override;
 
 private slots:
-        void handleInput();
+    void handleInput();
 
 private:
-        QPushButton *confirmBtn_;
-        QPushButton *cancelBtn_;
+    QPushButton *confirmBtn_;
+    QPushButton *cancelBtn_;
 
-        TextField *roomInput_;
+    TextField *roomInput_;
 };
 
 } // dialogs
diff --git a/src/dialogs/LeaveRoom.cpp b/src/dialogs/LeaveRoom.cpp
index 5246d693..9eb431da 100644
--- a/src/dialogs/LeaveRoom.cpp
+++ b/src/dialogs/LeaveRoom.cpp
@@ -15,39 +15,39 @@ using namespace dialogs;
 LeaveRoom::LeaveRoom(QWidget *parent)
   : QFrame(parent)
 {
-        setAutoFillBackground(true);
-        setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
-        setWindowModality(Qt::WindowModal);
-        setAttribute(Qt::WA_DeleteOnClose, true);
+    setAutoFillBackground(true);
+    setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
+    setWindowModality(Qt::WindowModal);
+    setAttribute(Qt::WA_DeleteOnClose, true);
 
-        setMinimumWidth(conf::modals::MIN_WIDGET_WIDTH);
-        setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
+    setMinimumWidth(conf::modals::MIN_WIDGET_WIDTH);
+    setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
 
-        auto layout = new QVBoxLayout(this);
-        layout->setSpacing(conf::modals::WIDGET_SPACING);
-        layout->setMargin(conf::modals::WIDGET_MARGIN);
+    auto layout = new QVBoxLayout(this);
+    layout->setSpacing(conf::modals::WIDGET_SPACING);
+    layout->setMargin(conf::modals::WIDGET_MARGIN);
 
-        auto buttonLayout = new QHBoxLayout();
-        buttonLayout->setSpacing(0);
-        buttonLayout->setMargin(0);
+    auto buttonLayout = new QHBoxLayout();
+    buttonLayout->setSpacing(0);
+    buttonLayout->setMargin(0);
 
-        confirmBtn_ = new QPushButton("Leave", this);
-        cancelBtn_  = new QPushButton(tr("Cancel"), this);
-        cancelBtn_->setDefault(true);
+    confirmBtn_ = new QPushButton("Leave", this);
+    cancelBtn_  = new QPushButton(tr("Cancel"), this);
+    cancelBtn_->setDefault(true);
 
-        buttonLayout->addStretch(1);
-        buttonLayout->setSpacing(15);
-        buttonLayout->addWidget(cancelBtn_);
-        buttonLayout->addWidget(confirmBtn_);
+    buttonLayout->addStretch(1);
+    buttonLayout->setSpacing(15);
+    buttonLayout->addWidget(cancelBtn_);
+    buttonLayout->addWidget(confirmBtn_);
 
-        auto label = new QLabel(tr("Are you sure you want to leave?"), this);
+    auto label = new QLabel(tr("Are you sure you want to leave?"), this);
 
-        layout->addWidget(label);
-        layout->addLayout(buttonLayout);
+    layout->addWidget(label);
+    layout->addLayout(buttonLayout);
 
-        connect(confirmBtn_, &QPushButton::clicked, this, [this]() {
-                emit leaving();
-                emit close();
-        });
-        connect(cancelBtn_, &QPushButton::clicked, this, &LeaveRoom::close);
+    connect(confirmBtn_, &QPushButton::clicked, this, [this]() {
+        emit leaving();
+        emit close();
+    });
+    connect(cancelBtn_, &QPushButton::clicked, this, &LeaveRoom::close);
 }
diff --git a/src/dialogs/LeaveRoom.h b/src/dialogs/LeaveRoom.h
index e9465579..edf88282 100644
--- a/src/dialogs/LeaveRoom.h
+++ b/src/dialogs/LeaveRoom.h
@@ -12,15 +12,15 @@ namespace dialogs {
 
 class LeaveRoom : public QFrame
 {
-        Q_OBJECT
+    Q_OBJECT
 public:
-        explicit LeaveRoom(QWidget *parent = nullptr);
+    explicit LeaveRoom(QWidget *parent = nullptr);
 
 signals:
-        void leaving();
+    void leaving();
 
 private:
-        QPushButton *confirmBtn_;
-        QPushButton *cancelBtn_;
+    QPushButton *confirmBtn_;
+    QPushButton *cancelBtn_;
 };
 } // dialogs
diff --git a/src/dialogs/Logout.cpp b/src/dialogs/Logout.cpp
index fdfc3338..d10e4cdf 100644
--- a/src/dialogs/Logout.cpp
+++ b/src/dialogs/Logout.cpp
@@ -15,40 +15,40 @@ using namespace dialogs;
 Logout::Logout(QWidget *parent)
   : QFrame(parent)
 {
-        setAutoFillBackground(true);
-        setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
-        setWindowModality(Qt::WindowModal);
-        setAttribute(Qt::WA_DeleteOnClose, true);
-
-        setMinimumWidth(conf::modals::MIN_WIDGET_WIDTH);
-        setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
-
-        auto layout = new QVBoxLayout(this);
-        layout->setSpacing(conf::modals::WIDGET_SPACING);
-        layout->setMargin(conf::modals::WIDGET_MARGIN);
-
-        auto buttonLayout = new QHBoxLayout();
-        buttonLayout->setSpacing(0);
-        buttonLayout->setMargin(0);
-
-        confirmBtn_ = new QPushButton("Logout", this);
-        cancelBtn_  = new QPushButton(tr("Cancel"), this);
-        cancelBtn_->setDefault(true);
-
-        buttonLayout->addStretch(1);
-        buttonLayout->setSpacing(15);
-        buttonLayout->addWidget(cancelBtn_);
-        buttonLayout->addWidget(confirmBtn_);
-
-        auto label = new QLabel(tr("Logout. Are you sure?"), this);
-
-        layout->addWidget(label);
-        layout->addLayout(buttonLayout);
-        layout->addStretch(1);
-
-        connect(confirmBtn_, &QPushButton::clicked, this, [this]() {
-                emit loggingOut();
-                emit close();
-        });
-        connect(cancelBtn_, &QPushButton::clicked, this, &Logout::close);
+    setAutoFillBackground(true);
+    setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
+    setWindowModality(Qt::WindowModal);
+    setAttribute(Qt::WA_DeleteOnClose, true);
+
+    setMinimumWidth(conf::modals::MIN_WIDGET_WIDTH);
+    setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
+
+    auto layout = new QVBoxLayout(this);
+    layout->setSpacing(conf::modals::WIDGET_SPACING);
+    layout->setMargin(conf::modals::WIDGET_MARGIN);
+
+    auto buttonLayout = new QHBoxLayout();
+    buttonLayout->setSpacing(0);
+    buttonLayout->setMargin(0);
+
+    confirmBtn_ = new QPushButton("Logout", this);
+    cancelBtn_  = new QPushButton(tr("Cancel"), this);
+    cancelBtn_->setDefault(true);
+
+    buttonLayout->addStretch(1);
+    buttonLayout->setSpacing(15);
+    buttonLayout->addWidget(cancelBtn_);
+    buttonLayout->addWidget(confirmBtn_);
+
+    auto label = new QLabel(tr("Logout. Are you sure?"), this);
+
+    layout->addWidget(label);
+    layout->addLayout(buttonLayout);
+    layout->addStretch(1);
+
+    connect(confirmBtn_, &QPushButton::clicked, this, [this]() {
+        emit loggingOut();
+        emit close();
+    });
+    connect(cancelBtn_, &QPushButton::clicked, this, &Logout::close);
 }
diff --git a/src/dialogs/Logout.h b/src/dialogs/Logout.h
index 9d8d0f4b..7783c68f 100644
--- a/src/dialogs/Logout.h
+++ b/src/dialogs/Logout.h
@@ -13,15 +13,15 @@ namespace dialogs {
 
 class Logout : public QFrame
 {
-        Q_OBJECT
+    Q_OBJECT
 public:
-        explicit Logout(QWidget *parent = nullptr);
+    explicit Logout(QWidget *parent = nullptr);
 
 signals:
-        void loggingOut();
+    void loggingOut();
 
 private:
-        QPushButton *confirmBtn_;
-        QPushButton *cancelBtn_;
+    QPushButton *confirmBtn_;
+    QPushButton *cancelBtn_;
 };
 } // dialogs
diff --git a/src/dialogs/PreviewUploadOverlay.cpp b/src/dialogs/PreviewUploadOverlay.cpp
index 66fa1b37..e850c03b 100644
--- a/src/dialogs/PreviewUploadOverlay.cpp
+++ b/src/dialogs/PreviewUploadOverlay.cpp
@@ -29,188 +29,185 @@ PreviewUploadOverlay::PreviewUploadOverlay(QWidget *parent)
   , upload_{tr("Upload"), this}
   , cancel_{tr("Cancel"), this}
 {
-        auto hlayout = new QHBoxLayout;
-        hlayout->addStretch(1);
-        hlayout->addWidget(&cancel_);
-        hlayout->addWidget(&upload_);
-        hlayout->setMargin(0);
-
-        auto vlayout = new QVBoxLayout{this};
-        vlayout->addWidget(&titleLabel_);
-        vlayout->addWidget(&infoLabel_);
-        vlayout->addWidget(&fileName_);
-        vlayout->addLayout(hlayout);
-        vlayout->setSpacing(conf::modals::WIDGET_SPACING);
-        vlayout->setMargin(conf::modals::WIDGET_MARGIN);
-
-        upload_.setDefault(true);
-        connect(&upload_, &QPushButton::clicked, [this]() {
-                emit confirmUpload(data_, mediaType_, fileName_.text());
-                close();
-        });
-
-        connect(&fileName_, &QLineEdit::returnPressed, this, [this]() {
-                emit confirmUpload(data_, mediaType_, fileName_.text());
-                close();
-        });
-
-        connect(&cancel_, &QPushButton::clicked, this, [this]() {
-                emit aborted();
-                close();
-        });
+    auto hlayout = new QHBoxLayout;
+    hlayout->addStretch(1);
+    hlayout->addWidget(&cancel_);
+    hlayout->addWidget(&upload_);
+    hlayout->setMargin(0);
+
+    auto vlayout = new QVBoxLayout{this};
+    vlayout->addWidget(&titleLabel_);
+    vlayout->addWidget(&infoLabel_);
+    vlayout->addWidget(&fileName_);
+    vlayout->addLayout(hlayout);
+    vlayout->setSpacing(conf::modals::WIDGET_SPACING);
+    vlayout->setMargin(conf::modals::WIDGET_MARGIN);
+
+    upload_.setDefault(true);
+    connect(&upload_, &QPushButton::clicked, [this]() {
+        emit confirmUpload(data_, mediaType_, fileName_.text());
+        close();
+    });
+
+    connect(&fileName_, &QLineEdit::returnPressed, this, [this]() {
+        emit confirmUpload(data_, mediaType_, fileName_.text());
+        close();
+    });
+
+    connect(&cancel_, &QPushButton::clicked, this, [this]() {
+        emit aborted();
+        close();
+    });
 }
 
 void
 PreviewUploadOverlay::init()
 {
-        QSize winsize;
-        QPoint center;
-
-        auto window = MainWindow::instance();
-        if (window) {
-                winsize = window->frameGeometry().size();
-                center  = window->frameGeometry().center();
-        } else {
-                nhlog::ui()->warn("unable to retrieve MainWindow's size");
-        }
-
-        fileName_.setText(QFileInfo{filePath_}.fileName());
-
-        setAutoFillBackground(true);
-        setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
-        setWindowModality(Qt::WindowModal);
-
-        QFont font;
-        font.setPointSizeF(font.pointSizeF() * conf::modals::LABEL_MEDIUM_SIZE_RATIO);
-
-        titleLabel_.setFont(font);
-        titleLabel_.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
-        titleLabel_.setAlignment(Qt::AlignCenter);
-        infoLabel_.setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
-        fileName_.setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
-        fileName_.setAlignment(Qt::AlignCenter);
-        upload_.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
-        cancel_.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
-
-        if (isImage_) {
-                infoLabel_.setAlignment(Qt::AlignCenter);
-
-                const auto maxWidth  = winsize.width() * 0.8;
-                const auto maxHeight = winsize.height() * 0.8;
-
-                // Scale image preview to fit into the application window.
-                infoLabel_.setPixmap(utils::scaleDown(maxWidth, maxHeight, image_));
-                move(center.x() - (width() * 0.5), center.y() - (height() * 0.5));
-        } else {
-                infoLabel_.setAlignment(Qt::AlignLeft);
-        }
-        infoLabel_.setScaledContents(false);
-
-        show();
+    QSize winsize;
+    QPoint center;
+
+    auto window = MainWindow::instance();
+    if (window) {
+        winsize = window->frameGeometry().size();
+        center  = window->frameGeometry().center();
+    } else {
+        nhlog::ui()->warn("unable to retrieve MainWindow's size");
+    }
+
+    fileName_.setText(QFileInfo{filePath_}.fileName());
+
+    setAutoFillBackground(true);
+    setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
+    setWindowModality(Qt::WindowModal);
+
+    QFont font;
+    font.setPointSizeF(font.pointSizeF() * conf::modals::LABEL_MEDIUM_SIZE_RATIO);
+
+    titleLabel_.setFont(font);
+    titleLabel_.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+    titleLabel_.setAlignment(Qt::AlignCenter);
+    infoLabel_.setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
+    fileName_.setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
+    fileName_.setAlignment(Qt::AlignCenter);
+    upload_.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+    cancel_.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+
+    if (isImage_) {
+        infoLabel_.setAlignment(Qt::AlignCenter);
+
+        const auto maxWidth  = winsize.width() * 0.8;
+        const auto maxHeight = winsize.height() * 0.8;
+
+        // Scale image preview to fit into the application window.
+        infoLabel_.setPixmap(utils::scaleDown(maxWidth, maxHeight, image_));
+        move(center.x() - (width() * 0.5), center.y() - (height() * 0.5));
+    } else {
+        infoLabel_.setAlignment(Qt::AlignLeft);
+    }
+    infoLabel_.setScaledContents(false);
+
+    show();
 }
 
 void
 PreviewUploadOverlay::setLabels(const QString &type, const QString &mime, uint64_t upload_size)
 {
-        if (mediaType_.split('/')[0] == "image") {
-                if (!image_.loadFromData(data_)) {
-                        titleLabel_.setText(QString{tr(ERR_MSG)}.arg(type));
-                } else {
-                        titleLabel_.setText(QString{tr(DEFAULT)}.arg(mediaType_));
-                }
-                isImage_ = true;
+    if (mediaType_.split('/')[0] == "image") {
+        if (!image_.loadFromData(data_)) {
+            titleLabel_.setText(QString{tr(ERR_MSG)}.arg(type));
         } else {
-                auto const info = QString{tr("Media type: %1\n"
-                                             "Media size: %2\n")}
-                                    .arg(mime)
-                                    .arg(utils::humanReadableFileSize(upload_size));
-
-                titleLabel_.setText(QString{tr(DEFAULT)}.arg("file"));
-                infoLabel_.setText(info);
+            titleLabel_.setText(QString{tr(DEFAULT)}.arg(mediaType_));
         }
+        isImage_ = true;
+    } else {
+        auto const info = QString{tr("Media type: %1\n"
+                                     "Media size: %2\n")}
+                            .arg(mime)
+                            .arg(utils::humanReadableFileSize(upload_size));
+
+        titleLabel_.setText(QString{tr(DEFAULT)}.arg("file"));
+        infoLabel_.setText(info);
+    }
 }
 
 void
 PreviewUploadOverlay::setPreview(const QImage &src, const QString &mime)
 {
-        nhlog::ui()->info("Pasting image with size: {}x{}, format: {}",
-                          src.height(),
-                          src.width(),
-                          mime.toStdString());
-
-        auto const &split = mime.split('/');
-        auto const &type  = split[1];
-
-        QBuffer buffer(&data_);
-        buffer.open(QIODevice::WriteOnly);
-        if (src.save(&buffer, type.toStdString().c_str()))
-                titleLabel_.setText(QString{tr(DEFAULT)}.arg("image"));
-        else
-                titleLabel_.setText(QString{tr(ERR_MSG)}.arg(type));
-
-        mediaType_ = mime;
-        filePath_  = "clipboard." + type;
-        image_.convertFromImage(src);
-        isImage_ = true;
+    nhlog::ui()->info(
+      "Pasting image with size: {}x{}, format: {}", src.height(), src.width(), mime.toStdString());
+
+    auto const &split = mime.split('/');
+    auto const &type  = split[1];
 
+    QBuffer buffer(&data_);
+    buffer.open(QIODevice::WriteOnly);
+    if (src.save(&buffer, type.toStdString().c_str()))
         titleLabel_.setText(QString{tr(DEFAULT)}.arg("image"));
-        init();
+    else
+        titleLabel_.setText(QString{tr(ERR_MSG)}.arg(type));
+
+    mediaType_ = mime;
+    filePath_  = "clipboard." + type;
+    image_.convertFromImage(src);
+    isImage_ = true;
+
+    titleLabel_.setText(QString{tr(DEFAULT)}.arg("image"));
+    init();
 }
 
 void
 PreviewUploadOverlay::setPreview(const QByteArray data, const QString &mime)
 {
-        auto const &split = mime.split('/');
-        auto const &type  = split[1];
+    auto const &split = mime.split('/');
+    auto const &type  = split[1];
 
-        data_      = data;
-        mediaType_ = mime;
-        filePath_  = "clipboard." + type;
-        isImage_   = false;
+    data_      = data;
+    mediaType_ = mime;
+    filePath_  = "clipboard." + type;
+    isImage_   = false;
 
-        setLabels(type, mime, data_.size());
-        init();
+    setLabels(type, mime, data_.size());
+    init();
 }
 
 void
 PreviewUploadOverlay::setPreview(const QString &path)
 {
-        QFile file{path};
-
-        if (!file.open(QIODevice::ReadOnly)) {
-                nhlog::ui()->warn("Failed to open file ({}): {}",
-                                  path.toStdString(),
-                                  file.errorString().toStdString());
-                close();
-                return;
-        }
+    QFile file{path};
 
-        QMimeDatabase db;
-        auto mime = db.mimeTypeForFileNameAndData(path, &file);
+    if (!file.open(QIODevice::ReadOnly)) {
+        nhlog::ui()->warn(
+          "Failed to open file ({}): {}", path.toStdString(), file.errorString().toStdString());
+        close();
+        return;
+    }
 
-        if ((data_ = file.readAll()).isEmpty()) {
-                nhlog::ui()->warn("Failed to read media: {}", file.errorString().toStdString());
-                close();
-                return;
-        }
+    QMimeDatabase db;
+    auto mime = db.mimeTypeForFileNameAndData(path, &file);
 
-        auto const &split = mime.name().split('/');
+    if ((data_ = file.readAll()).isEmpty()) {
+        nhlog::ui()->warn("Failed to read media: {}", file.errorString().toStdString());
+        close();
+        return;
+    }
 
-        mediaType_ = mime.name();
-        filePath_  = file.fileName();
-        isImage_   = false;
+    auto const &split = mime.name().split('/');
 
-        setLabels(split[1], mime.name(), data_.size());
-        init();
+    mediaType_ = mime.name();
+    filePath_  = file.fileName();
+    isImage_   = false;
+
+    setLabels(split[1], mime.name(), data_.size());
+    init();
 }
 
 void
 PreviewUploadOverlay::keyPressEvent(QKeyEvent *event)
 {
-        if (event->matches(QKeySequence::Cancel)) {
-                emit aborted();
-                close();
-        } else {
-                QWidget::keyPressEvent(event);
-        }
+    if (event->matches(QKeySequence::Cancel)) {
+        emit aborted();
+        close();
+    } else {
+        QWidget::keyPressEvent(event);
+    }
 }
\ No newline at end of file
diff --git a/src/dialogs/PreviewUploadOverlay.h b/src/dialogs/PreviewUploadOverlay.h
index d23ea0ae..e9078069 100644
--- a/src/dialogs/PreviewUploadOverlay.h
+++ b/src/dialogs/PreviewUploadOverlay.h
@@ -18,35 +18,35 @@ namespace dialogs {
 
 class PreviewUploadOverlay : public QWidget
 {
-        Q_OBJECT
+    Q_OBJECT
 public:
-        PreviewUploadOverlay(QWidget *parent = nullptr);
+    PreviewUploadOverlay(QWidget *parent = nullptr);
 
-        void setPreview(const QImage &src, const QString &mime);
-        void setPreview(const QByteArray data, const QString &mime);
-        void setPreview(const QString &path);
-        void keyPressEvent(QKeyEvent *event);
+    void setPreview(const QImage &src, const QString &mime);
+    void setPreview(const QByteArray data, const QString &mime);
+    void setPreview(const QString &path);
+    void keyPressEvent(QKeyEvent *event);
 
 signals:
-        void confirmUpload(const QByteArray data, const QString &media, const QString &filename);
-        void aborted();
+    void confirmUpload(const QByteArray data, const QString &media, const QString &filename);
+    void aborted();
 
 private:
-        void init();
-        void setLabels(const QString &type, const QString &mime, uint64_t upload_size);
+    void init();
+    void setLabels(const QString &type, const QString &mime, uint64_t upload_size);
 
-        bool isImage_;
-        QPixmap image_;
+    bool isImage_;
+    QPixmap image_;
 
-        QByteArray data_;
-        QString filePath_;
-        QString mediaType_;
+    QByteArray data_;
+    QString filePath_;
+    QString mediaType_;
 
-        QLabel titleLabel_;
-        QLabel infoLabel_;
-        QLineEdit fileName_;
+    QLabel titleLabel_;
+    QLabel infoLabel_;
+    QLineEdit fileName_;
 
-        QPushButton upload_;
-        QPushButton cancel_;
+    QPushButton upload_;
+    QPushButton cancel_;
 };
 } // dialogs
diff --git a/src/dialogs/ReCaptcha.cpp b/src/dialogs/ReCaptcha.cpp
index c7b95f1a..0ae46bba 100644
--- a/src/dialogs/ReCaptcha.cpp
+++ b/src/dialogs/ReCaptcha.cpp
@@ -18,54 +18,54 @@ using namespace dialogs;
 ReCaptcha::ReCaptcha(const QString &session, QWidget *parent)
   : QWidget(parent)
 {
-        setAutoFillBackground(true);
-        setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
-        setWindowModality(Qt::WindowModal);
-        setAttribute(Qt::WA_DeleteOnClose, true);
+    setAutoFillBackground(true);
+    setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
+    setWindowModality(Qt::WindowModal);
+    setAttribute(Qt::WA_DeleteOnClose, true);
 
-        auto layout = new QVBoxLayout(this);
-        layout->setSpacing(conf::modals::WIDGET_SPACING);
-        layout->setMargin(conf::modals::WIDGET_MARGIN);
+    auto layout = new QVBoxLayout(this);
+    layout->setSpacing(conf::modals::WIDGET_SPACING);
+    layout->setMargin(conf::modals::WIDGET_MARGIN);
 
-        auto buttonLayout = new QHBoxLayout();
-        buttonLayout->setSpacing(8);
-        buttonLayout->setMargin(0);
+    auto buttonLayout = new QHBoxLayout();
+    buttonLayout->setSpacing(8);
+    buttonLayout->setMargin(0);
 
-        openCaptchaBtn_ = new QPushButton("Open reCAPTCHA", this);
-        cancelBtn_      = new QPushButton(tr("Cancel"), this);
-        confirmBtn_     = new QPushButton(tr("Confirm"), this);
-        confirmBtn_->setDefault(true);
+    openCaptchaBtn_ = new QPushButton("Open reCAPTCHA", this);
+    cancelBtn_      = new QPushButton(tr("Cancel"), this);
+    confirmBtn_     = new QPushButton(tr("Confirm"), this);
+    confirmBtn_->setDefault(true);
 
-        buttonLayout->addStretch(1);
-        buttonLayout->addWidget(openCaptchaBtn_);
-        buttonLayout->addWidget(cancelBtn_);
-        buttonLayout->addWidget(confirmBtn_);
+    buttonLayout->addStretch(1);
+    buttonLayout->addWidget(openCaptchaBtn_);
+    buttonLayout->addWidget(cancelBtn_);
+    buttonLayout->addWidget(confirmBtn_);
 
-        QFont font;
-        font.setPointSizeF(font.pointSizeF() * conf::modals::LABEL_MEDIUM_SIZE_RATIO);
+    QFont font;
+    font.setPointSizeF(font.pointSizeF() * conf::modals::LABEL_MEDIUM_SIZE_RATIO);
 
-        auto label = new QLabel(tr("Solve the reCAPTCHA and press the confirm button"), this);
-        label->setFont(font);
+    auto label = new QLabel(tr("Solve the reCAPTCHA and press the confirm button"), this);
+    label->setFont(font);
 
-        layout->addWidget(label);
-        layout->addLayout(buttonLayout);
+    layout->addWidget(label);
+    layout->addLayout(buttonLayout);
 
-        connect(openCaptchaBtn_, &QPushButton::clicked, [session]() {
-                const auto url = QString("https://%1:%2/_matrix/client/r0/auth/m.login.recaptcha/"
-                                         "fallback/web?session=%3")
-                                   .arg(QString::fromStdString(http::client()->server()))
-                                   .arg(http::client()->port())
-                                   .arg(session);
+    connect(openCaptchaBtn_, &QPushButton::clicked, [session]() {
+        const auto url = QString("https://%1:%2/_matrix/client/r0/auth/m.login.recaptcha/"
+                                 "fallback/web?session=%3")
+                           .arg(QString::fromStdString(http::client()->server()))
+                           .arg(http::client()->port())
+                           .arg(session);
 
-                QDesktopServices::openUrl(url);
-        });
+        QDesktopServices::openUrl(url);
+    });
 
-        connect(confirmBtn_, &QPushButton::clicked, this, [this]() {
-                emit confirmation();
-                emit close();
-        });
-        connect(cancelBtn_, &QPushButton::clicked, this, [this]() {
-                emit cancel();
-                emit close();
-        });
+    connect(confirmBtn_, &QPushButton::clicked, this, [this]() {
+        emit confirmation();
+        emit close();
+    });
+    connect(cancelBtn_, &QPushButton::clicked, this, [this]() {
+        emit cancel();
+        emit close();
+    });
 }
diff --git a/src/dialogs/ReCaptcha.h b/src/dialogs/ReCaptcha.h
index 0c9f7539..1e69de66 100644
--- a/src/dialogs/ReCaptcha.h
+++ b/src/dialogs/ReCaptcha.h
@@ -12,18 +12,18 @@ namespace dialogs {
 
 class ReCaptcha : public QWidget
 {
-        Q_OBJECT
+    Q_OBJECT
 
 public:
-        ReCaptcha(const QString &session, QWidget *parent = nullptr);
+    ReCaptcha(const QString &session, QWidget *parent = nullptr);
 
 signals:
-        void confirmation();
-        void cancel();
+    void confirmation();
+    void cancel();
 
 private:
-        QPushButton *openCaptchaBtn_;
-        QPushButton *confirmBtn_;
-        QPushButton *cancelBtn_;
+    QPushButton *openCaptchaBtn_;
+    QPushButton *confirmBtn_;
+    QPushButton *cancelBtn_;
 };
 } // dialogs
diff --git a/src/emoji/EmojiModel.cpp b/src/emoji/EmojiModel.cpp
index 66e7aeda..07e6fdbd 100644
--- a/src/emoji/EmojiModel.cpp
+++ b/src/emoji/EmojiModel.cpp
@@ -14,63 +14,60 @@ using namespace emoji;
 int
 EmojiModel::categoryToIndex(int category)
 {
-        auto dist = std::distance(Provider::emoji.begin(),
-                                  std::lower_bound(Provider::emoji.begin(),
-                                                   Provider::emoji.end(),
-                                                   static_cast<Emoji::Category>(category),
-                                                   [](const struct Emoji &e, Emoji::Category c) {
-                                                           return e.category < c;
-                                                   }));
+    auto dist = std::distance(
+      Provider::emoji.begin(),
+      std::lower_bound(Provider::emoji.begin(),
+                       Provider::emoji.end(),
+                       static_cast<Emoji::Category>(category),
+                       [](const struct Emoji &e, Emoji::Category c) { return e.category < c; }));
 
-        return static_cast<int>(dist);
+    return static_cast<int>(dist);
 }
 
 QHash<int, QByteArray>
 EmojiModel::roleNames() const
 {
-        static QHash<int, QByteArray> roles;
+    static QHash<int, QByteArray> roles;
 
-        if (roles.isEmpty()) {
-                roles = QAbstractListModel::roleNames();
-                roles[static_cast<int>(EmojiModel::Roles::Unicode)] = QByteArrayLiteral("unicode");
-                roles[static_cast<int>(EmojiModel::Roles::ShortName)] =
-                  QByteArrayLiteral("shortName");
-                roles[static_cast<int>(EmojiModel::Roles::Category)] =
-                  QByteArrayLiteral("category");
-                roles[static_cast<int>(EmojiModel::Roles::Emoji)] = QByteArrayLiteral("emoji");
-        }
+    if (roles.isEmpty()) {
+        roles                                                 = QAbstractListModel::roleNames();
+        roles[static_cast<int>(EmojiModel::Roles::Unicode)]   = QByteArrayLiteral("unicode");
+        roles[static_cast<int>(EmojiModel::Roles::ShortName)] = QByteArrayLiteral("shortName");
+        roles[static_cast<int>(EmojiModel::Roles::Category)]  = QByteArrayLiteral("category");
+        roles[static_cast<int>(EmojiModel::Roles::Emoji)]     = QByteArrayLiteral("emoji");
+    }
 
-        return roles;
+    return roles;
 }
 
 int
 EmojiModel::rowCount(const QModelIndex &parent) const
 {
-        return parent == QModelIndex() ? Provider::emoji.count() : 0;
+    return parent == QModelIndex() ? Provider::emoji.count() : 0;
 }
 
 QVariant
 EmojiModel::data(const QModelIndex &index, int role) const
 {
-        if (hasIndex(index.row(), index.column(), index.parent())) {
-                switch (role) {
-                case Qt::DisplayRole:
-                case CompletionModel::CompletionRole:
-                case static_cast<int>(EmojiModel::Roles::Unicode):
-                        return Provider::emoji[index.row()].unicode;
+    if (hasIndex(index.row(), index.column(), index.parent())) {
+        switch (role) {
+        case Qt::DisplayRole:
+        case CompletionModel::CompletionRole:
+        case static_cast<int>(EmojiModel::Roles::Unicode):
+            return Provider::emoji[index.row()].unicode;
 
-                case Qt::ToolTipRole:
-                case CompletionModel::SearchRole:
-                case static_cast<int>(EmojiModel::Roles::ShortName):
-                        return Provider::emoji[index.row()].shortName;
+        case Qt::ToolTipRole:
+        case CompletionModel::SearchRole:
+        case static_cast<int>(EmojiModel::Roles::ShortName):
+            return Provider::emoji[index.row()].shortName;
 
-                case static_cast<int>(EmojiModel::Roles::Category):
-                        return QVariant::fromValue(Provider::emoji[index.row()].category);
+        case static_cast<int>(EmojiModel::Roles::Category):
+            return QVariant::fromValue(Provider::emoji[index.row()].category);
 
-                case static_cast<int>(EmojiModel::Roles::Emoji):
-                        return QVariant::fromValue(Provider::emoji[index.row()]);
-                }
+        case static_cast<int>(EmojiModel::Roles::Emoji):
+            return QVariant::fromValue(Provider::emoji[index.row()]);
         }
+    }
 
-        return {};
+    return {};
 }
diff --git a/src/emoji/EmojiModel.h b/src/emoji/EmojiModel.h
index 679563f1..882d3eb8 100644
--- a/src/emoji/EmojiModel.h
+++ b/src/emoji/EmojiModel.h
@@ -18,22 +18,22 @@ namespace emoji {
  */
 class EmojiModel : public QAbstractListModel
 {
-        Q_OBJECT
+    Q_OBJECT
 public:
-        enum Roles
-        {
-                Unicode = Qt::UserRole, // unicode of emoji
-                Category,               // category of emoji
-                ShortName,              // shortext of the emoji
-                Emoji,                  // Contains everything from the Emoji
-        };
+    enum Roles
+    {
+        Unicode = Qt::UserRole, // unicode of emoji
+        Category,               // category of emoji
+        ShortName,              // shortext of the emoji
+        Emoji,                  // Contains everything from the Emoji
+    };
 
-        using QAbstractListModel::QAbstractListModel;
+    using QAbstractListModel::QAbstractListModel;
 
-        Q_INVOKABLE int categoryToIndex(int category);
+    Q_INVOKABLE int categoryToIndex(int category);
 
-        QHash<int, QByteArray> roleNames() const override;
-        int rowCount(const QModelIndex &parent = QModelIndex()) const override;
-        QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+    QHash<int, QByteArray> roleNames() const override;
+    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
 };
 }
diff --git a/src/emoji/MacHelper.h b/src/emoji/MacHelper.h
index b3e2e631..ff49f9ba 100644
--- a/src/emoji/MacHelper.h
+++ b/src/emoji/MacHelper.h
@@ -9,6 +9,6 @@
 class MacHelper
 {
 public:
-        static void showEmojiWindow();
-        static void initializeMenus();
+    static void showEmojiWindow();
+    static void initializeMenus();
 };
diff --git a/src/emoji/Provider.h b/src/emoji/Provider.h
index 43c880a2..965329f9 100644
--- a/src/emoji/Provider.h
+++ b/src/emoji/Provider.h
@@ -16,37 +16,37 @@ Q_NAMESPACE
 
 struct Emoji
 {
-        Q_GADGET
+    Q_GADGET
 public:
-        enum class Category
-        {
-                People,
-                Nature,
-                Food,
-                Activity,
-                Travel,
-                Objects,
-                Symbols,
-                Flags,
-                Search
-        };
-        Q_ENUM(Category)
-
-        Q_PROPERTY(const QString &unicode MEMBER unicode)
-        Q_PROPERTY(const QString &shortName MEMBER shortName)
-        Q_PROPERTY(emoji::Emoji::Category category MEMBER category)
+    enum class Category
+    {
+        People,
+        Nature,
+        Food,
+        Activity,
+        Travel,
+        Objects,
+        Symbols,
+        Flags,
+        Search
+    };
+    Q_ENUM(Category)
+
+    Q_PROPERTY(const QString &unicode MEMBER unicode)
+    Q_PROPERTY(const QString &shortName MEMBER shortName)
+    Q_PROPERTY(emoji::Emoji::Category category MEMBER category)
 
 public:
-        QString unicode;
-        QString shortName;
-        Category category;
+    QString unicode;
+    QString shortName;
+    Category category;
 };
 
 class Provider
 {
 public:
-        // all emoji for QML purposes
-        static const QVector<Emoji> emoji;
+    // all emoji for QML purposes
+    static const QVector<Emoji> emoji;
 };
 
 } // namespace emoji
diff --git a/src/main.cpp b/src/main.cpp
index 09168e0c..cf7e29e6 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -48,47 +48,47 @@ QQmlDebuggingEnabler enabler;
 void
 stacktraceHandler(int signum)
 {
-        std::signal(signum, SIG_DFL);
+    std::signal(signum, SIG_DFL);
 
-        // boost::stacktrace::safe_dump_to("./nheko-backtrace.dump");
+    // boost::stacktrace::safe_dump_to("./nheko-backtrace.dump");
 
-        // see
-        // https://stackoverflow.com/questions/77005/how-to-automatically-generate-a-stacktrace-when-my-program-crashes/77336#77336
-        void *array[50];
-        size_t size;
+    // see
+    // https://stackoverflow.com/questions/77005/how-to-automatically-generate-a-stacktrace-when-my-program-crashes/77336#77336
+    void *array[50];
+    size_t size;
 
-        // get void*'s for all entries on the stack
-        size = backtrace(array, 50);
+    // get void*'s for all entries on the stack
+    size = backtrace(array, 50);
 
-        // print out all the frames to stderr
-        fprintf(stderr, "Error: signal %d:\n", signum);
-        backtrace_symbols_fd(array, size, STDERR_FILENO);
+    // print out all the frames to stderr
+    fprintf(stderr, "Error: signal %d:\n", signum);
+    backtrace_symbols_fd(array, size, STDERR_FILENO);
 
-        int file = ::open("/tmp/nheko-crash.dump",
-                          O_CREAT | O_WRONLY | O_TRUNC
+    int file = ::open("/tmp/nheko-crash.dump",
+                      O_CREAT | O_WRONLY | O_TRUNC
 #if defined(S_IWUSR) && defined(S_IRUSR)
-                          ,
-                          S_IWUSR | S_IRUSR
+                      ,
+                      S_IWUSR | S_IRUSR
 #elif defined(S_IWRITE) && defined(S_IREAD)
-                          ,
-                          S_IWRITE | S_IREAD
+                      ,
+                      S_IWRITE | S_IREAD
 #endif
-        );
-        if (file != -1) {
-                constexpr char header[]   = "Error: signal\n";
-                [[maybe_unused]] auto ret = write(file, header, std::size(header) - 1);
-                backtrace_symbols_fd(array, size, file);
-                close(file);
-        }
-
-        std::raise(SIGABRT);
+    );
+    if (file != -1) {
+        constexpr char header[]   = "Error: signal\n";
+        [[maybe_unused]] auto ret = write(file, header, std::size(header) - 1);
+        backtrace_symbols_fd(array, size, file);
+        close(file);
+    }
+
+    std::raise(SIGABRT);
 }
 
 void
 registerSignalHandlers()
 {
-        std::signal(SIGSEGV, &stacktraceHandler);
-        std::signal(SIGABRT, &stacktraceHandler);
+    std::signal(SIGSEGV, &stacktraceHandler);
+    std::signal(SIGABRT, &stacktraceHandler);
 }
 
 #else
@@ -103,203 +103,200 @@ registerSignalHandlers()
 QPoint
 screenCenter(int width, int height)
 {
-        // Deprecated in 5.13: QRect screenGeometry = QApplication::desktop()->screenGeometry();
-        QRect screenGeometry = QGuiApplication::primaryScreen()->geometry();
+    // Deprecated in 5.13: QRect screenGeometry = QApplication::desktop()->screenGeometry();
+    QRect screenGeometry = QGuiApplication::primaryScreen()->geometry();
 
-        int x = (screenGeometry.width() - width) / 2;
-        int y = (screenGeometry.height() - height) / 2;
+    int x = (screenGeometry.width() - width) / 2;
+    int y = (screenGeometry.height() - height) / 2;
 
-        return QPoint(x, y);
+    return QPoint(x, y);
 }
 
 void
 createStandardDirectory(QStandardPaths::StandardLocation path)
 {
-        auto dir = QStandardPaths::writableLocation(path);
+    auto dir = QStandardPaths::writableLocation(path);
 
-        if (!QDir().mkpath(dir)) {
-                throw std::runtime_error(
-                  ("Unable to create state directory:" + dir).toStdString().c_str());
-        }
+    if (!QDir().mkpath(dir)) {
+        throw std::runtime_error(("Unable to create state directory:" + dir).toStdString().c_str());
+    }
 }
 
 int
 main(int argc, char *argv[])
 {
-        QCoreApplication::setApplicationName("nheko");
-        QCoreApplication::setApplicationVersion(nheko::version);
-        QCoreApplication::setOrganizationName("nheko");
-        QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
-        QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
-        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
-
-        // this needs to be after setting the application name. Or how would we find our settings
-        // file then?
+    QCoreApplication::setApplicationName("nheko");
+    QCoreApplication::setApplicationVersion(nheko::version);
+    QCoreApplication::setOrganizationName("nheko");
+    QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
+    QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
+    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+
+    // this needs to be after setting the application name. Or how would we find our settings
+    // file then?
 #if defined(Q_OS_LINUX) || defined(Q_OS_WIN) || defined(Q_OS_FREEBSD)
-        if (qgetenv("QT_SCALE_FACTOR").size() == 0) {
-                float factor = utils::scaleFactor();
+    if (qgetenv("QT_SCALE_FACTOR").size() == 0) {
+        float factor = utils::scaleFactor();
 
-                if (factor != -1)
-                        qputenv("QT_SCALE_FACTOR", QString::number(factor).toUtf8());
-        }
+        if (factor != -1)
+            qputenv("QT_SCALE_FACTOR", QString::number(factor).toUtf8());
+    }
 #endif
 
-        // This is some hacky programming, but it's necessary (AFAIK?) to get the unique config name
-        // parsed before the SingleApplication userdata is set.
-        QString userdata{""};
-        QString matrixUri;
-        for (int i = 1; i < argc; ++i) {
-                QString arg{argv[i]};
-                if (arg.startsWith("--profile=")) {
-                        arg.remove("--profile=");
-                        userdata = arg;
-                } else if (arg.startsWith("--p=")) {
-                        arg.remove("-p=");
-                        userdata = arg;
-                } else if (arg == "--profile" || arg == "-p") {
-                        if (i < argc - 1) // if i is less than argc - 1, we still have a parameter
-                                          // left to process as the name
-                        {
-                                ++i; // the next arg is the name, so increment
-                                userdata = QString{argv[i]};
-                        }
-                } else if (arg.startsWith("matrix:")) {
-                        matrixUri = arg;
-                }
-        }
-
-        SingleApplication app(argc,
-                              argv,
-                              true,
-                              SingleApplication::Mode::User |
-                                SingleApplication::Mode::ExcludeAppPath |
-                                SingleApplication::Mode::ExcludeAppVersion |
-                                SingleApplication::Mode::SecondaryNotification,
-                              100,
-                              userdata);
-
-        if (app.isSecondary()) {
-                // open uri in main instance
-                app.sendMessage(matrixUri.toUtf8());
-                return 0;
-        }
-
-        QCommandLineParser parser;
-        parser.addHelpOption();
-        parser.addVersionOption();
-        QCommandLineOption debugOption("debug", "Enable debug output");
-        parser.addOption(debugOption);
-
-        // This option is not actually parsed via Qt due to the need to parse it before the app
-        // name is set. It only exists to keep Qt from complaining about the --profile/-p
-        // option and thereby crashing the app.
-        QCommandLineOption configName(
-          QStringList() << "p"
-                        << "profile",
-          QCoreApplication::tr("Create a unique profile, which allows you to log into several "
-                               "accounts at the same time and start multiple instances of nheko."),
-          QCoreApplication::tr("profile"),
-          QCoreApplication::tr("profile name"));
-        parser.addOption(configName);
-
-        parser.process(app);
-
-        app.setWindowIcon(QIcon::fromTheme("nheko", QIcon{":/logos/nheko.png"}));
-
-        http::init();
-
-        createStandardDirectory(QStandardPaths::CacheLocation);
-        createStandardDirectory(QStandardPaths::AppDataLocation);
-
-        registerSignalHandlers();
-
-        if (parser.isSet(debugOption))
-                nhlog::enable_debug_log_from_commandline = true;
-
-        try {
-                nhlog::init(QString("%1/nheko.log")
-                              .arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))
-                              .toStdString());
-        } catch (const spdlog::spdlog_ex &ex) {
-                std::cout << "Log initialization failed: " << ex.what() << std::endl;
-                std::exit(1);
-        }
-
-        if (parser.isSet(configName))
-                UserSettings::initialize(parser.value(configName));
-        else
-                UserSettings::initialize(std::nullopt);
-
-        auto settings = UserSettings::instance().toWeakRef();
-
-        QFont font;
-        QString userFontFamily = settings.lock()->font();
-        if (!userFontFamily.isEmpty() && userFontFamily != "default") {
-                font.setFamily(userFontFamily);
+    // This is some hacky programming, but it's necessary (AFAIK?) to get the unique config name
+    // parsed before the SingleApplication userdata is set.
+    QString userdata{""};
+    QString matrixUri;
+    for (int i = 1; i < argc; ++i) {
+        QString arg{argv[i]};
+        if (arg.startsWith("--profile=")) {
+            arg.remove("--profile=");
+            userdata = arg;
+        } else if (arg.startsWith("--p=")) {
+            arg.remove("-p=");
+            userdata = arg;
+        } else if (arg == "--profile" || arg == "-p") {
+            if (i < argc - 1) // if i is less than argc - 1, we still have a parameter
+                              // left to process as the name
+            {
+                ++i; // the next arg is the name, so increment
+                userdata = QString{argv[i]};
+            }
+        } else if (arg.startsWith("matrix:")) {
+            matrixUri = arg;
         }
-        font.setPointSizeF(settings.lock()->fontSize());
-
-        app.setFont(font);
-
-        QString lang = QLocale::system().name();
-
-        QTranslator qtTranslator;
-        qtTranslator.load(
-          QLocale(), "qt", "_", QLibraryInfo::location(QLibraryInfo::TranslationsPath));
-        app.installTranslator(&qtTranslator);
-
-        QTranslator appTranslator;
-        appTranslator.load(QLocale(), "nheko", "_", ":/translations");
-        app.installTranslator(&appTranslator);
-
-        MainWindow w;
-
-        // Move the MainWindow to the center
-        w.move(screenCenter(w.width(), w.height()));
-
-        if (!(settings.lock()->startInTray() && settings.lock()->tray()))
-                w.show();
-
-        QObject::connect(&app, &QApplication::aboutToQuit, &w, [&w]() {
-                w.saveCurrentWindowSize();
-                if (http::client() != nullptr) {
-                        nhlog::net()->debug("shutting down all I/O threads & open connections");
-                        http::client()->close(true);
-                        nhlog::net()->debug("bye");
-                }
-        });
-        QObject::connect(&app, &SingleApplication::instanceStarted, &w, [&w]() {
-                w.show();
-                w.raise();
-                w.activateWindow();
-        });
-
-        QObject::connect(
-          &app,
-          &SingleApplication::receivedMessage,
-          ChatPage::instance(),
-          [&](quint32, QByteArray message) { ChatPage::instance()->handleMatrixUri(message); });
-
-        QMetaObject::Connection uriConnection;
-        if (app.isPrimary() && !matrixUri.isEmpty()) {
-                uriConnection = QObject::connect(ChatPage::instance(),
-                                                 &ChatPage::contentLoaded,
-                                                 ChatPage::instance(),
-                                                 [&uriConnection, matrixUri]() {
-                                                         ChatPage::instance()->handleMatrixUri(
-                                                           matrixUri.toUtf8());
-                                                         QObject::disconnect(uriConnection);
-                                                 });
+    }
+
+    SingleApplication app(argc,
+                          argv,
+                          true,
+                          SingleApplication::Mode::User | SingleApplication::Mode::ExcludeAppPath |
+                            SingleApplication::Mode::ExcludeAppVersion |
+                            SingleApplication::Mode::SecondaryNotification,
+                          100,
+                          userdata);
+
+    if (app.isSecondary()) {
+        // open uri in main instance
+        app.sendMessage(matrixUri.toUtf8());
+        return 0;
+    }
+
+    QCommandLineParser parser;
+    parser.addHelpOption();
+    parser.addVersionOption();
+    QCommandLineOption debugOption("debug", "Enable debug output");
+    parser.addOption(debugOption);
+
+    // This option is not actually parsed via Qt due to the need to parse it before the app
+    // name is set. It only exists to keep Qt from complaining about the --profile/-p
+    // option and thereby crashing the app.
+    QCommandLineOption configName(
+      QStringList() << "p"
+                    << "profile",
+      QCoreApplication::tr("Create a unique profile, which allows you to log into several "
+                           "accounts at the same time and start multiple instances of nheko."),
+      QCoreApplication::tr("profile"),
+      QCoreApplication::tr("profile name"));
+    parser.addOption(configName);
+
+    parser.process(app);
+
+    app.setWindowIcon(QIcon::fromTheme("nheko", QIcon{":/logos/nheko.png"}));
+
+    http::init();
+
+    createStandardDirectory(QStandardPaths::CacheLocation);
+    createStandardDirectory(QStandardPaths::AppDataLocation);
+
+    registerSignalHandlers();
+
+    if (parser.isSet(debugOption))
+        nhlog::enable_debug_log_from_commandline = true;
+
+    try {
+        nhlog::init(QString("%1/nheko.log")
+                      .arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))
+                      .toStdString());
+    } catch (const spdlog::spdlog_ex &ex) {
+        std::cout << "Log initialization failed: " << ex.what() << std::endl;
+        std::exit(1);
+    }
+
+    if (parser.isSet(configName))
+        UserSettings::initialize(parser.value(configName));
+    else
+        UserSettings::initialize(std::nullopt);
+
+    auto settings = UserSettings::instance().toWeakRef();
+
+    QFont font;
+    QString userFontFamily = settings.lock()->font();
+    if (!userFontFamily.isEmpty() && userFontFamily != "default") {
+        font.setFamily(userFontFamily);
+    }
+    font.setPointSizeF(settings.lock()->fontSize());
+
+    app.setFont(font);
+
+    QString lang = QLocale::system().name();
+
+    QTranslator qtTranslator;
+    qtTranslator.load(QLocale(), "qt", "_", QLibraryInfo::location(QLibraryInfo::TranslationsPath));
+    app.installTranslator(&qtTranslator);
+
+    QTranslator appTranslator;
+    appTranslator.load(QLocale(), "nheko", "_", ":/translations");
+    app.installTranslator(&appTranslator);
+
+    MainWindow w;
+
+    // Move the MainWindow to the center
+    w.move(screenCenter(w.width(), w.height()));
+
+    if (!(settings.lock()->startInTray() && settings.lock()->tray()))
+        w.show();
+
+    QObject::connect(&app, &QApplication::aboutToQuit, &w, [&w]() {
+        w.saveCurrentWindowSize();
+        if (http::client() != nullptr) {
+            nhlog::net()->debug("shutting down all I/O threads & open connections");
+            http::client()->close(true);
+            nhlog::net()->debug("bye");
         }
-        QDesktopServices::setUrlHandler("matrix", ChatPage::instance(), "handleMatrixUri");
+    });
+    QObject::connect(&app, &SingleApplication::instanceStarted, &w, [&w]() {
+        w.show();
+        w.raise();
+        w.activateWindow();
+    });
+
+    QObject::connect(
+      &app,
+      &SingleApplication::receivedMessage,
+      ChatPage::instance(),
+      [&](quint32, QByteArray message) { ChatPage::instance()->handleMatrixUri(message); });
+
+    QMetaObject::Connection uriConnection;
+    if (app.isPrimary() && !matrixUri.isEmpty()) {
+        uriConnection =
+          QObject::connect(ChatPage::instance(),
+                           &ChatPage::contentLoaded,
+                           ChatPage::instance(),
+                           [&uriConnection, matrixUri]() {
+                               ChatPage::instance()->handleMatrixUri(matrixUri.toUtf8());
+                               QObject::disconnect(uriConnection);
+                           });
+    }
+    QDesktopServices::setUrlHandler("matrix", ChatPage::instance(), "handleMatrixUri");
 
 #if defined(Q_OS_MAC)
-        // Temporary solution for the emoji picker until
-        // nheko has a proper menu bar with more functionality.
-        MacHelper::initializeMenus();
+    // Temporary solution for the emoji picker until
+    // nheko has a proper menu bar with more functionality.
+    MacHelper::initializeMenus();
 #endif
 
-        nhlog::ui()->info("starting nheko {}", nheko::version);
+    nhlog::ui()->info("starting nheko {}", nheko::version);
 
-        return app.exec();
+    return app.exec();
 }
diff --git a/src/notifications/Manager.cpp b/src/notifications/Manager.cpp
index be580b08..f24a48ff 100644
--- a/src/notifications/Manager.cpp
+++ b/src/notifications/Manager.cpp
@@ -11,30 +11,30 @@
 QString
 NotificationsManager::getMessageTemplate(const mtx::responses::Notification &notification)
 {
-        const auto sender =
-          cache::displayName(QString::fromStdString(notification.room_id),
-                             QString::fromStdString(mtx::accessors::sender(notification.event)));
+    const auto sender =
+      cache::displayName(QString::fromStdString(notification.room_id),
+                         QString::fromStdString(mtx::accessors::sender(notification.event)));
 
-        // TODO: decrypt this message if the decryption setting is on in the UserSettings
-        if (auto msg = std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(
-              &notification.event);
-            msg != nullptr) {
-                return tr("%1 sent an encrypted message").arg(sender);
-        }
+    // TODO: decrypt this message if the decryption setting is on in the UserSettings
+    if (auto msg = std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(
+          &notification.event);
+        msg != nullptr) {
+        return tr("%1 sent an encrypted message").arg(sender);
+    }
 
-        if (mtx::accessors::msg_type(notification.event) == mtx::events::MessageType::Emote) {
-                return tr("* %1 %2",
-                          "Format an emote message in a notification, %1 is the sender, %2 the "
-                          "message")
-                  .arg(sender);
-        } else if (utils::isReply(notification.event)) {
-                return tr("%1 replied: %2",
-                          "Format a reply in a notification. %1 is the sender, %2 the message")
-                  .arg(sender);
-        } else {
-                return tr("%1: %2",
-                          "Format a normal message in a notification. %1 is the sender, %2 the "
-                          "message")
-                  .arg(sender);
-        }
+    if (mtx::accessors::msg_type(notification.event) == mtx::events::MessageType::Emote) {
+        return tr("* %1 %2",
+                  "Format an emote message in a notification, %1 is the sender, %2 the "
+                  "message")
+          .arg(sender);
+    } else if (utils::isReply(notification.event)) {
+        return tr("%1 replied: %2",
+                  "Format a reply in a notification. %1 is the sender, %2 the message")
+          .arg(sender);
+    } else {
+        return tr("%1: %2",
+                  "Format a normal message in a notification. %1 is the sender, %2 the "
+                  "message")
+          .arg(sender);
+    }
 }
diff --git a/src/notifications/Manager.h b/src/notifications/Manager.h
index 416530e0..4e24dd1b 100644
--- a/src/notifications/Manager.h
+++ b/src/notifications/Manager.h
@@ -22,83 +22,83 @@
 
 struct roomEventId
 {
-        QString roomId;
-        QString eventId;
+    QString roomId;
+    QString eventId;
 };
 
 inline bool
 operator==(const roomEventId &a, const roomEventId &b)
 {
-        return a.roomId == b.roomId && a.eventId == b.eventId;
+    return a.roomId == b.roomId && a.eventId == b.eventId;
 }
 
 class NotificationsManager : public QObject
 {
-        Q_OBJECT
+    Q_OBJECT
 public:
-        NotificationsManager(QObject *parent = nullptr);
+    NotificationsManager(QObject *parent = nullptr);
 
-        void postNotification(const mtx::responses::Notification &notification, const QImage &icon);
+    void postNotification(const mtx::responses::Notification &notification, const QImage &icon);
 
 signals:
-        void notificationClicked(const QString roomId, const QString eventId);
-        void sendNotificationReply(const QString roomId, const QString eventId, const QString body);
-        void systemPostNotificationCb(const QString &room_id,
-                                      const QString &event_id,
-                                      const QString &roomName,
-                                      const QString &text,
-                                      const QImage &icon);
+    void notificationClicked(const QString roomId, const QString eventId);
+    void sendNotificationReply(const QString roomId, const QString eventId, const QString body);
+    void systemPostNotificationCb(const QString &room_id,
+                                  const QString &event_id,
+                                  const QString &roomName,
+                                  const QString &text,
+                                  const QImage &icon);
 
 public slots:
-        void removeNotification(const QString &roomId, const QString &eventId);
+    void removeNotification(const QString &roomId, const QString &eventId);
 
 #if defined(NHEKO_DBUS_SYS)
 public:
-        void closeNotifications(QString roomId);
+    void closeNotifications(QString roomId);
 
 private:
-        QDBusInterface dbus;
+    QDBusInterface dbus;
 
-        void systemPostNotification(const QString &room_id,
-                                    const QString &event_id,
-                                    const QString &roomName,
-                                    const QString &text,
-                                    const QImage &icon);
-        void closeNotification(uint id);
+    void systemPostNotification(const QString &room_id,
+                                const QString &event_id,
+                                const QString &roomName,
+                                const QString &text,
+                                const QImage &icon);
+    void closeNotification(uint id);
 
-        // notification ID to (room ID, event ID)
-        QMap<uint, roomEventId> notificationIds;
+    // notification ID to (room ID, event ID)
+    QMap<uint, roomEventId> notificationIds;
 
-        const bool hasMarkup_;
-        const bool hasImages_;
+    const bool hasMarkup_;
+    const bool hasImages_;
 #endif
 
 #if defined(Q_OS_MACOS)
 private:
-        // Objective-C(++) doesn't like to do lots of regular C++, so the actual notification
-        // posting is split out
-        void objCxxPostNotification(const QString &title,
-                                    const QString &subtitle,
-                                    const QString &informativeText,
-                                    const QImage &bodyImage);
+    // Objective-C(++) doesn't like to do lots of regular C++, so the actual notification
+    // posting is split out
+    void objCxxPostNotification(const QString &title,
+                                const QString &subtitle,
+                                const QString &informativeText,
+                                const QImage &bodyImage);
 #endif
 
 #if defined(Q_OS_WINDOWS)
 private:
-        void systemPostNotification(const QString &line1,
-                                    const QString &line2,
-                                    const QString &iconPath);
+    void systemPostNotification(const QString &line1,
+                                const QString &line2,
+                                const QString &iconPath);
 #endif
 
-        // these slots are platform specific (D-Bus only)
-        // but Qt slot declarations can not be inside an ifdef!
+    // these slots are platform specific (D-Bus only)
+    // but Qt slot declarations can not be inside an ifdef!
 private slots:
-        void actionInvoked(uint id, QString action);
-        void notificationClosed(uint id, uint reason);
-        void notificationReplied(uint id, QString reply);
+    void actionInvoked(uint id, QString action);
+    void notificationClosed(uint id, uint reason);
+    void notificationReplied(uint id, QString reply);
 
 private:
-        QString getMessageTemplate(const mtx::responses::Notification &notification);
+    QString getMessageTemplate(const mtx::responses::Notification &notification);
 };
 
 #if defined(NHEKO_DBUS_SYS)
diff --git a/src/notifications/ManagerLinux.cpp b/src/notifications/ManagerLinux.cpp
index 2809de87..758cb615 100644
--- a/src/notifications/ManagerLinux.cpp
+++ b/src/notifications/ManagerLinux.cpp
@@ -34,109 +34,100 @@ NotificationsManager::NotificationsManager(QObject *parent)
          QDBusConnection::sessionBus(),
          this)
   , hasMarkup_{std::invoke([this]() -> bool {
-          for (auto x : dbus.call("GetCapabilities").arguments())
-                  if (x.toStringList().contains("body-markup"))
-                          return true;
-          return false;
+      for (auto x : dbus.call("GetCapabilities").arguments())
+          if (x.toStringList().contains("body-markup"))
+              return true;
+      return false;
   })}
   , hasImages_{std::invoke([this]() -> bool {
-          for (auto x : dbus.call("GetCapabilities").arguments())
-                  if (x.toStringList().contains("body-images"))
-                          return true;
-          return false;
+      for (auto x : dbus.call("GetCapabilities").arguments())
+          if (x.toStringList().contains("body-images"))
+              return true;
+      return false;
   })}
 {
-        qDBusRegisterMetaType<QImage>();
+    qDBusRegisterMetaType<QImage>();
 
-        QDBusConnection::sessionBus().connect("org.freedesktop.Notifications",
-                                              "/org/freedesktop/Notifications",
-                                              "org.freedesktop.Notifications",
-                                              "ActionInvoked",
-                                              this,
-                                              SLOT(actionInvoked(uint, QString)));
-        QDBusConnection::sessionBus().connect("org.freedesktop.Notifications",
-                                              "/org/freedesktop/Notifications",
-                                              "org.freedesktop.Notifications",
-                                              "NotificationClosed",
-                                              this,
-                                              SLOT(notificationClosed(uint, uint)));
-        QDBusConnection::sessionBus().connect("org.freedesktop.Notifications",
-                                              "/org/freedesktop/Notifications",
-                                              "org.freedesktop.Notifications",
-                                              "NotificationReplied",
-                                              this,
-                                              SLOT(notificationReplied(uint, QString)));
+    QDBusConnection::sessionBus().connect("org.freedesktop.Notifications",
+                                          "/org/freedesktop/Notifications",
+                                          "org.freedesktop.Notifications",
+                                          "ActionInvoked",
+                                          this,
+                                          SLOT(actionInvoked(uint, QString)));
+    QDBusConnection::sessionBus().connect("org.freedesktop.Notifications",
+                                          "/org/freedesktop/Notifications",
+                                          "org.freedesktop.Notifications",
+                                          "NotificationClosed",
+                                          this,
+                                          SLOT(notificationClosed(uint, uint)));
+    QDBusConnection::sessionBus().connect("org.freedesktop.Notifications",
+                                          "/org/freedesktop/Notifications",
+                                          "org.freedesktop.Notifications",
+                                          "NotificationReplied",
+                                          this,
+                                          SLOT(notificationReplied(uint, QString)));
 
-        connect(this,
-                &NotificationsManager::systemPostNotificationCb,
-                this,
-                &NotificationsManager::systemPostNotification,
-                Qt::QueuedConnection);
+    connect(this,
+            &NotificationsManager::systemPostNotificationCb,
+            this,
+            &NotificationsManager::systemPostNotification,
+            Qt::QueuedConnection);
 }
 
 void
 NotificationsManager::postNotification(const mtx::responses::Notification &notification,
                                        const QImage &icon)
 {
-        const auto room_id  = QString::fromStdString(notification.room_id);
-        const auto event_id = QString::fromStdString(mtx::accessors::event_id(notification.event));
-        const auto room_name =
-          QString::fromStdString(cache::singleRoomInfo(notification.room_id).name);
+    const auto room_id   = QString::fromStdString(notification.room_id);
+    const auto event_id  = QString::fromStdString(mtx::accessors::event_id(notification.event));
+    const auto room_name = QString::fromStdString(cache::singleRoomInfo(notification.room_id).name);
 
-        auto postNotif = [this, room_id, event_id, room_name, icon](QString text) {
-                emit systemPostNotificationCb(room_id, event_id, room_name, text, icon);
-        };
-
-        QString template_ = getMessageTemplate(notification);
-        // TODO: decrypt this message if the decryption setting is on in the UserSettings
-        if (std::holds_alternative<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(
-              notification.event)) {
-                postNotif(template_);
-                return;
-        }
+    auto postNotif = [this, room_id, event_id, room_name, icon](QString text) {
+        emit systemPostNotificationCb(room_id, event_id, room_name, text, icon);
+    };
 
-        if (hasMarkup_) {
-                if (hasImages_ && mtx::accessors::msg_type(notification.event) ==
-                                    mtx::events::MessageType::Image) {
-                        MxcImageProvider::download(
-                          QString::fromStdString(mtx::accessors::url(notification.event))
-                            .remove("mxc://"),
-                          QSize(200, 80),
-                          [postNotif, notification, template_](
-                            QString, QSize, QImage, QString imgPath) {
-                                  if (imgPath.isEmpty())
-                                          postNotif(template_
-                                                      .arg(utils::stripReplyFallbacks(
-                                                             notification.event, {}, {})
-                                                             .quoted_formatted_body)
-                                                      .replace("<em>", "<i>")
-                                                      .replace("</em>", "</i>")
-                                                      .replace("<strong>", "<b>")
-                                                      .replace("</strong>", "</b>"));
-                                  else
-                                          postNotif(template_.arg(
-                                            QStringLiteral("<br><img src=\"file:///") % imgPath %
-                                            "\" alt=\"" %
-                                            mtx::accessors::formattedBodyWithFallback(
-                                              notification.event) %
-                                            "\">"));
-                          });
-                        return;
-                }
+    QString template_ = getMessageTemplate(notification);
+    // TODO: decrypt this message if the decryption setting is on in the UserSettings
+    if (std::holds_alternative<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(
+          notification.event)) {
+        postNotif(template_);
+        return;
+    }
 
-                postNotif(
-                  template_
-                    .arg(
-                      utils::stripReplyFallbacks(notification.event, {}, {}).quoted_formatted_body)
-                    .replace("<em>", "<i>")
-                    .replace("</em>", "</i>")
-                    .replace("<strong>", "<b>")
-                    .replace("</strong>", "</b>"));
-                return;
+    if (hasMarkup_) {
+        if (hasImages_ &&
+            mtx::accessors::msg_type(notification.event) == mtx::events::MessageType::Image) {
+            MxcImageProvider::download(
+              QString::fromStdString(mtx::accessors::url(notification.event)).remove("mxc://"),
+              QSize(200, 80),
+              [postNotif, notification, template_](QString, QSize, QImage, QString imgPath) {
+                  if (imgPath.isEmpty())
+                      postNotif(template_
+                                  .arg(utils::stripReplyFallbacks(notification.event, {}, {})
+                                         .quoted_formatted_body)
+                                  .replace("<em>", "<i>")
+                                  .replace("</em>", "</i>")
+                                  .replace("<strong>", "<b>")
+                                  .replace("</strong>", "</b>"));
+                  else
+                      postNotif(template_.arg(
+                        QStringLiteral("<br><img src=\"file:///") % imgPath % "\" alt=\"" %
+                        mtx::accessors::formattedBodyWithFallback(notification.event) % "\">"));
+              });
+            return;
         }
 
         postNotif(
-          template_.arg(utils::stripReplyFallbacks(notification.event, {}, {}).quoted_body));
+          template_
+            .arg(utils::stripReplyFallbacks(notification.event, {}, {}).quoted_formatted_body)
+            .replace("<em>", "<i>")
+            .replace("</em>", "</i>")
+            .replace("<strong>", "<b>")
+            .replace("</strong>", "</b>"));
+        return;
+    }
+
+    postNotif(template_.arg(utils::stripReplyFallbacks(notification.event, {}, {}).quoted_body));
 }
 
 /**
@@ -152,99 +143,99 @@ NotificationsManager::systemPostNotification(const QString &room_id,
                                              const QString &text,
                                              const QImage &icon)
 {
-        QVariantMap hints;
-        hints["image-data"] = icon;
-        hints["sound-name"] = "message-new-instant";
-        QList<QVariant> argumentList;
-        argumentList << "nheko";  // app_name
-        argumentList << (uint)0;  // replace_id
-        argumentList << "";       // app_icon
-        argumentList << roomName; // summary
-        argumentList << text;     // body
+    QVariantMap hints;
+    hints["image-data"] = icon;
+    hints["sound-name"] = "message-new-instant";
+    QList<QVariant> argumentList;
+    argumentList << "nheko";  // app_name
+    argumentList << (uint)0;  // replace_id
+    argumentList << "";       // app_icon
+    argumentList << roomName; // summary
+    argumentList << text;     // body
 
-        // The list of actions has always the action name and then a localized version of that
-        // action. Currently we just use an empty string for that.
-        // TODO(Nico): Look into what to actually put there.
-        argumentList << (QStringList("default") << ""
-                                                << "inline-reply"
-                                                << ""); // actions
-        argumentList << hints;                          // hints
-        argumentList << (int)-1;                        // timeout in ms
+    // The list of actions has always the action name and then a localized version of that
+    // action. Currently we just use an empty string for that.
+    // TODO(Nico): Look into what to actually put there.
+    argumentList << (QStringList("default") << ""
+                                            << "inline-reply"
+                                            << ""); // actions
+    argumentList << hints;                          // hints
+    argumentList << (int)-1;                        // timeout in ms
 
-        QDBusPendingCall call = dbus.asyncCallWithArgumentList("Notify", argumentList);
-        auto watcher          = new QDBusPendingCallWatcher{call, this};
-        connect(
-          watcher, &QDBusPendingCallWatcher::finished, this, [watcher, this, room_id, event_id]() {
-                  if (watcher->reply().type() == QDBusMessage::ErrorMessage)
-                          qDebug() << "D-Bus Error:" << watcher->reply().errorMessage();
-                  else
-                          notificationIds[watcher->reply().arguments().first().toUInt()] =
-                            roomEventId{room_id, event_id};
-                  watcher->deleteLater();
-          });
+    QDBusPendingCall call = dbus.asyncCallWithArgumentList("Notify", argumentList);
+    auto watcher          = new QDBusPendingCallWatcher{call, this};
+    connect(
+      watcher, &QDBusPendingCallWatcher::finished, this, [watcher, this, room_id, event_id]() {
+          if (watcher->reply().type() == QDBusMessage::ErrorMessage)
+              qDebug() << "D-Bus Error:" << watcher->reply().errorMessage();
+          else
+              notificationIds[watcher->reply().arguments().first().toUInt()] =
+                roomEventId{room_id, event_id};
+          watcher->deleteLater();
+      });
 }
 
 void
 NotificationsManager::closeNotification(uint id)
 {
-        auto call    = dbus.asyncCall("CloseNotification", (uint)id); // replace_id
-        auto watcher = new QDBusPendingCallWatcher{call, this};
-        connect(watcher, &QDBusPendingCallWatcher::finished, this, [watcher]() {
-                if (watcher->reply().type() == QDBusMessage::ErrorMessage) {
-                        qDebug() << "D-Bus Error:" << watcher->reply().errorMessage();
-                };
-                watcher->deleteLater();
-        });
+    auto call    = dbus.asyncCall("CloseNotification", (uint)id); // replace_id
+    auto watcher = new QDBusPendingCallWatcher{call, this};
+    connect(watcher, &QDBusPendingCallWatcher::finished, this, [watcher]() {
+        if (watcher->reply().type() == QDBusMessage::ErrorMessage) {
+            qDebug() << "D-Bus Error:" << watcher->reply().errorMessage();
+        };
+        watcher->deleteLater();
+    });
 }
 
 void
 NotificationsManager::removeNotification(const QString &roomId, const QString &eventId)
 {
-        roomEventId reId = {roomId, eventId};
-        for (auto elem = notificationIds.begin(); elem != notificationIds.end(); ++elem) {
-                if (elem.value().roomId != roomId)
-                        continue;
+    roomEventId reId = {roomId, eventId};
+    for (auto elem = notificationIds.begin(); elem != notificationIds.end(); ++elem) {
+        if (elem.value().roomId != roomId)
+            continue;
 
-                // close all notifications matching the eventId or having a lower
-                // notificationId
-                // This relies on the notificationId not wrapping around. This allows for
-                // approximately 2,147,483,647 notifications, so it is a bit unlikely.
-                // Otherwise we would need to store a 64bit counter instead.
-                closeNotification(elem.key());
+        // close all notifications matching the eventId or having a lower
+        // notificationId
+        // This relies on the notificationId not wrapping around. This allows for
+        // approximately 2,147,483,647 notifications, so it is a bit unlikely.
+        // Otherwise we would need to store a 64bit counter instead.
+        closeNotification(elem.key());
 
-                // FIXME: compare index of event id of the read receipt and the notification instead
-                // of just the id to prevent read receipts of events without notification clearing
-                // all notifications in that room!
-                if (elem.value() == reId)
-                        break;
-        }
+        // FIXME: compare index of event id of the read receipt and the notification instead
+        // of just the id to prevent read receipts of events without notification clearing
+        // all notifications in that room!
+        if (elem.value() == reId)
+            break;
+    }
 }
 
 void
 NotificationsManager::actionInvoked(uint id, QString action)
 {
-        if (notificationIds.contains(id)) {
-                roomEventId idEntry = notificationIds[id];
-                if (action == "default") {
-                        emit notificationClicked(idEntry.roomId, idEntry.eventId);
-                }
+    if (notificationIds.contains(id)) {
+        roomEventId idEntry = notificationIds[id];
+        if (action == "default") {
+            emit notificationClicked(idEntry.roomId, idEntry.eventId);
         }
+    }
 }
 
 void
 NotificationsManager::notificationReplied(uint id, QString reply)
 {
-        if (notificationIds.contains(id)) {
-                roomEventId idEntry = notificationIds[id];
-                emit sendNotificationReply(idEntry.roomId, idEntry.eventId, reply);
-        }
+    if (notificationIds.contains(id)) {
+        roomEventId idEntry = notificationIds[id];
+        emit sendNotificationReply(idEntry.roomId, idEntry.eventId, reply);
+    }
 }
 
 void
 NotificationsManager::notificationClosed(uint id, uint reason)
 {
-        Q_UNUSED(reason);
-        notificationIds.remove(id);
+    Q_UNUSED(reason);
+    notificationIds.remove(id);
 }
 
 /**
@@ -259,52 +250,52 @@ NotificationsManager::notificationClosed(uint id, uint reason)
 QDBusArgument &
 operator<<(QDBusArgument &arg, const QImage &image)
 {
-        if (image.isNull()) {
-                arg.beginStructure();
-                arg << 0 << 0 << 0 << false << 0 << 0 << QByteArray();
-                arg.endStructure();
-                return arg;
-        }
+    if (image.isNull()) {
+        arg.beginStructure();
+        arg << 0 << 0 << 0 << false << 0 << 0 << QByteArray();
+        arg.endStructure();
+        return arg;
+    }
 
-        QImage scaled = image.scaledToHeight(100, Qt::SmoothTransformation);
-        scaled        = scaled.convertToFormat(QImage::Format_ARGB32);
+    QImage scaled = image.scaledToHeight(100, Qt::SmoothTransformation);
+    scaled        = scaled.convertToFormat(QImage::Format_ARGB32);
 
 #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
-        // ABGR -> ARGB
-        QImage i = scaled.rgbSwapped();
+    // ABGR -> ARGB
+    QImage i = scaled.rgbSwapped();
 #else
-        // ABGR -> GBAR
-        QImage i(scaled.size(), scaled.format());
-        for (int y = 0; y < i.height(); ++y) {
-                QRgb *p   = (QRgb *)scaled.scanLine(y);
-                QRgb *q   = (QRgb *)i.scanLine(y);
-                QRgb *end = p + scaled.width();
-                while (p < end) {
-                        *q = qRgba(qGreen(*p), qBlue(*p), qAlpha(*p), qRed(*p));
-                        p++;
-                        q++;
-                }
+    // ABGR -> GBAR
+    QImage i(scaled.size(), scaled.format());
+    for (int y = 0; y < i.height(); ++y) {
+        QRgb *p   = (QRgb *)scaled.scanLine(y);
+        QRgb *q   = (QRgb *)i.scanLine(y);
+        QRgb *end = p + scaled.width();
+        while (p < end) {
+            *q = qRgba(qGreen(*p), qBlue(*p), qAlpha(*p), qRed(*p));
+            p++;
+            q++;
         }
+    }
 #endif
 
-        arg.beginStructure();
-        arg << i.width();
-        arg << i.height();
-        arg << i.bytesPerLine();
-        arg << i.hasAlphaChannel();
-        int channels = i.isGrayscale() ? 1 : (i.hasAlphaChannel() ? 4 : 3);
-        arg << i.depth() / channels;
-        arg << channels;
-        arg << QByteArray(reinterpret_cast<const char *>(i.bits()), i.sizeInBytes());
-        arg.endStructure();
+    arg.beginStructure();
+    arg << i.width();
+    arg << i.height();
+    arg << i.bytesPerLine();
+    arg << i.hasAlphaChannel();
+    int channels = i.isGrayscale() ? 1 : (i.hasAlphaChannel() ? 4 : 3);
+    arg << i.depth() / channels;
+    arg << channels;
+    arg << QByteArray(reinterpret_cast<const char *>(i.bits()), i.sizeInBytes());
+    arg.endStructure();
 
-        return arg;
+    return arg;
 }
 
 const QDBusArgument &
 operator>>(const QDBusArgument &arg, QImage &)
 {
-        // This is needed to link but shouldn't be called.
-        Q_ASSERT(0);
-        return arg;
+    // This is needed to link but shouldn't be called.
+    Q_ASSERT(0);
+    return arg;
 }
diff --git a/src/notifications/ManagerMac.cpp b/src/notifications/ManagerMac.cpp
index 8e36985c..f69cec2c 100644
--- a/src/notifications/ManagerMac.cpp
+++ b/src/notifications/ManagerMac.cpp
@@ -19,48 +19,42 @@
 static QString
 formatNotification(const mtx::responses::Notification &notification)
 {
-        return utils::stripReplyFallbacks(notification.event, {}, {}).quoted_body;
+    return utils::stripReplyFallbacks(notification.event, {}, {}).quoted_body;
 }
 
 void
 NotificationsManager::postNotification(const mtx::responses::Notification &notification,
                                        const QImage &icon)
 {
-        Q_UNUSED(icon)
-
-        const auto room_name =
-          QString::fromStdString(cache::singleRoomInfo(notification.room_id).name);
-        const auto sender =
-          cache::displayName(QString::fromStdString(notification.room_id),
-                             QString::fromStdString(mtx::accessors::sender(notification.event)));
-
-        const auto isEncrypted =
-          std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(
-            &notification.event) != nullptr;
-        const auto isReply = utils::isReply(notification.event);
-        if (isEncrypted) {
-                // TODO: decrypt this message if the decryption setting is on in the UserSettings
-                const QString messageInfo = (isReply ? tr("%1 replied with an encrypted message")
-                                                     : tr("%1 sent an encrypted message"))
-                                              .arg(sender);
-                objCxxPostNotification(room_name, messageInfo, "", QImage());
-        } else {
-                const QString messageInfo =
-                  (isReply ? tr("%1 replied to a message") : tr("%1 sent a message")).arg(sender);
-                if (mtx::accessors::msg_type(notification.event) == mtx::events::MessageType::Image)
-                        MxcImageProvider::download(
-                          QString::fromStdString(mtx::accessors::url(notification.event))
-                            .remove("mxc://"),
-                          QSize(200, 80),
-                          [this, notification, room_name, messageInfo](
-                            QString, QSize, QImage image, QString) {
-                                  objCxxPostNotification(room_name,
-                                                         messageInfo,
-                                                         formatNotification(notification),
-                                                         image);
-                          });
-                else
-                        objCxxPostNotification(
-                          room_name, messageInfo, formatNotification(notification), QImage());
-        }
+    Q_UNUSED(icon)
+
+    const auto room_name = QString::fromStdString(cache::singleRoomInfo(notification.room_id).name);
+    const auto sender =
+      cache::displayName(QString::fromStdString(notification.room_id),
+                         QString::fromStdString(mtx::accessors::sender(notification.event)));
+
+    const auto isEncrypted = std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(
+                               &notification.event) != nullptr;
+    const auto isReply = utils::isReply(notification.event);
+    if (isEncrypted) {
+        // TODO: decrypt this message if the decryption setting is on in the UserSettings
+        const QString messageInfo = (isReply ? tr("%1 replied with an encrypted message")
+                                             : tr("%1 sent an encrypted message"))
+                                      .arg(sender);
+        objCxxPostNotification(room_name, messageInfo, "", QImage());
+    } else {
+        const QString messageInfo =
+          (isReply ? tr("%1 replied to a message") : tr("%1 sent a message")).arg(sender);
+        if (mtx::accessors::msg_type(notification.event) == mtx::events::MessageType::Image)
+            MxcImageProvider::download(
+              QString::fromStdString(mtx::accessors::url(notification.event)).remove("mxc://"),
+              QSize(200, 80),
+              [this, notification, room_name, messageInfo](QString, QSize, QImage image, QString) {
+                  objCxxPostNotification(
+                    room_name, messageInfo, formatNotification(notification), image);
+              });
+        else
+            objCxxPostNotification(
+              room_name, messageInfo, formatNotification(notification), QImage());
+    }
 }
diff --git a/src/notifications/ManagerWin.cpp b/src/notifications/ManagerWin.cpp
index fe7830a7..4376e4d8 100644
--- a/src/notifications/ManagerWin.cpp
+++ b/src/notifications/ManagerWin.cpp
@@ -20,10 +20,10 @@ using namespace WinToastLib;
 class CustomHandler : public IWinToastHandler
 {
 public:
-        void toastActivated() const {}
-        void toastActivated(int) const {}
-        void toastFailed() const { std::wcout << L"Error showing current toast" << std::endl; }
-        void toastDismissed(WinToastDismissalReason) const {}
+    void toastActivated() const {}
+    void toastActivated(int) const {}
+    void toastFailed() const { std::wcout << L"Error showing current toast" << std::endl; }
+    void toastDismissed(WinToastDismissalReason) const {}
 };
 
 namespace {
@@ -32,12 +32,12 @@ bool isInitialized = false;
 void
 init()
 {
-        isInitialized = true;
+    isInitialized = true;
 
-        WinToast::instance()->setAppName(L"Nheko");
-        WinToast::instance()->setAppUserModelId(WinToast::configureAUMI(L"nheko", L"nheko"));
-        if (!WinToast::instance()->initialize())
-                std::wcout << "Your system is not compatible with toast notifications\n";
+    WinToast::instance()->setAppName(L"Nheko");
+    WinToast::instance()->setAppUserModelId(WinToast::configureAUMI(L"nheko", L"nheko"));
+    if (!WinToast::instance()->initialize())
+        std::wcout << "Your system is not compatible with toast notifications\n";
 }
 }
 
@@ -49,41 +49,37 @@ void
 NotificationsManager::postNotification(const mtx::responses::Notification &notification,
                                        const QImage &icon)
 {
-        const auto room_name =
-          QString::fromStdString(cache::singleRoomInfo(notification.room_id).name);
-        const auto sender =
-          cache::displayName(QString::fromStdString(notification.room_id),
-                             QString::fromStdString(mtx::accessors::sender(notification.event)));
-
-        const auto isEncrypted =
-          std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(
-            &notification.event) != nullptr;
-        const auto isReply = utils::isReply(notification.event);
-
-        auto formatNotification = [this, notification, sender] {
-                const auto template_ = getMessageTemplate(notification);
-                if (std::holds_alternative<
-                      mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(
-                      notification.event)) {
-                        return template_;
-                }
-
-                return template_.arg(
-                  utils::stripReplyFallbacks(notification.event, {}, {}).quoted_body);
-        };
-
-        const auto line1 =
-          (room_name == sender) ? sender : QString("%1 - %2").arg(sender).arg(room_name);
-        const auto line2 = (isEncrypted ? (isReply ? tr("%1 replied with an encrypted message")
-                                                   : tr("%1 sent an encrypted message"))
-                                        : formatNotification());
-
-        auto iconPath = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) +
-                        room_name + "-room-avatar.png";
-        if (!icon.save(iconPath))
-                iconPath.clear();
-
-        systemPostNotification(line1, line2, iconPath);
+    const auto room_name = QString::fromStdString(cache::singleRoomInfo(notification.room_id).name);
+    const auto sender =
+      cache::displayName(QString::fromStdString(notification.room_id),
+                         QString::fromStdString(mtx::accessors::sender(notification.event)));
+
+    const auto isEncrypted = std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(
+                               &notification.event) != nullptr;
+    const auto isReply = utils::isReply(notification.event);
+
+    auto formatNotification = [this, notification, sender] {
+        const auto template_ = getMessageTemplate(notification);
+        if (std::holds_alternative<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(
+              notification.event)) {
+            return template_;
+        }
+
+        return template_.arg(utils::stripReplyFallbacks(notification.event, {}, {}).quoted_body);
+    };
+
+    const auto line1 =
+      (room_name == sender) ? sender : QString("%1 - %2").arg(sender).arg(room_name);
+    const auto line2 = (isEncrypted ? (isReply ? tr("%1 replied with an encrypted message")
+                                               : tr("%1 sent an encrypted message"))
+                                    : formatNotification());
+
+    auto iconPath = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + room_name +
+                    "-room-avatar.png";
+    if (!icon.save(iconPath))
+        iconPath.clear();
+
+    systemPostNotification(line1, line2, iconPath);
 }
 
 void
@@ -91,17 +87,17 @@ NotificationsManager::systemPostNotification(const QString &line1,
                                              const QString &line2,
                                              const QString &iconPath)
 {
-        if (!isInitialized)
-                init();
+    if (!isInitialized)
+        init();
 
-        auto templ = WinToastTemplate(WinToastTemplate::ImageAndText02);
-        templ.setTextField(line1.toStdWString(), WinToastTemplate::FirstLine);
-        templ.setTextField(line2.toStdWString(), WinToastTemplate::SecondLine);
+    auto templ = WinToastTemplate(WinToastTemplate::ImageAndText02);
+    templ.setTextField(line1.toStdWString(), WinToastTemplate::FirstLine);
+    templ.setTextField(line2.toStdWString(), WinToastTemplate::SecondLine);
 
-        if (!iconPath.isNull())
-                templ.setImagePath(iconPath.toStdWString());
+    if (!iconPath.isNull())
+        templ.setImagePath(iconPath.toStdWString());
 
-        WinToast::instance()->showToast(templ, new CustomHandler());
+    WinToast::instance()->showToast(templ, new CustomHandler());
 }
 
 void NotificationsManager::actionInvoked(uint, QString) {}
diff --git a/src/timeline/CommunitiesModel.cpp b/src/timeline/CommunitiesModel.cpp
index 97bfa76d..77bed387 100644
--- a/src/timeline/CommunitiesModel.cpp
+++ b/src/timeline/CommunitiesModel.cpp
@@ -16,231 +16,230 @@ CommunitiesModel::CommunitiesModel(QObject *parent)
 QHash<int, QByteArray>
 CommunitiesModel::roleNames() const
 {
-        return {
-          {AvatarUrl, "avatarUrl"},
-          {DisplayName, "displayName"},
-          {Tooltip, "tooltip"},
-          {ChildrenHidden, "childrenHidden"},
-          {Hidden, "hidden"},
-          {Id, "id"},
-        };
+    return {
+      {AvatarUrl, "avatarUrl"},
+      {DisplayName, "displayName"},
+      {Tooltip, "tooltip"},
+      {ChildrenHidden, "childrenHidden"},
+      {Hidden, "hidden"},
+      {Id, "id"},
+    };
 }
 
 QVariant
 CommunitiesModel::data(const QModelIndex &index, int role) const
 {
-        if (index.row() == 0) {
-                switch (role) {
-                case CommunitiesModel::Roles::AvatarUrl:
-                        return QString(":/icons/icons/ui/world.png");
-                case CommunitiesModel::Roles::DisplayName:
-                        return tr("All rooms");
-                case CommunitiesModel::Roles::Tooltip:
-                        return tr("Shows all rooms without filtering.");
-                case CommunitiesModel::Roles::ChildrenHidden:
-                        return false;
-                case CommunitiesModel::Roles::Hidden:
-                        return false;
-                case CommunitiesModel::Roles::Id:
-                        return "";
-                }
-        } else if (index.row() - 1 < spaceOrder_.size()) {
-                auto id = spaceOrder_.at(index.row() - 1);
-                switch (role) {
-                case CommunitiesModel::Roles::AvatarUrl:
-                        return QString::fromStdString(spaces_.at(id).avatar_url);
-                case CommunitiesModel::Roles::DisplayName:
-                case CommunitiesModel::Roles::Tooltip:
-                        return QString::fromStdString(spaces_.at(id).name);
-                case CommunitiesModel::Roles::ChildrenHidden:
-                        return true;
-                case CommunitiesModel::Roles::Hidden:
-                        return hiddentTagIds_.contains("space:" + id);
-                case CommunitiesModel::Roles::Id:
-                        return "space:" + id;
-                }
-        } else if (index.row() - 1 < tags_.size() + spaceOrder_.size()) {
-                auto tag = tags_.at(index.row() - 1 - spaceOrder_.size());
-                if (tag == "m.favourite") {
-                        switch (role) {
-                        case CommunitiesModel::Roles::AvatarUrl:
-                                return QString(":/icons/icons/ui/star.png");
-                        case CommunitiesModel::Roles::DisplayName:
-                                return tr("Favourites");
-                        case CommunitiesModel::Roles::Tooltip:
-                                return tr("Rooms you have favourited.");
-                        }
-                } else if (tag == "m.lowpriority") {
-                        switch (role) {
-                        case CommunitiesModel::Roles::AvatarUrl:
-                                return QString(":/icons/icons/ui/lowprio.png");
-                        case CommunitiesModel::Roles::DisplayName:
-                                return tr("Low Priority");
-                        case CommunitiesModel::Roles::Tooltip:
-                                return tr("Rooms with low priority.");
-                        }
-                } else if (tag == "m.server_notice") {
-                        switch (role) {
-                        case CommunitiesModel::Roles::AvatarUrl:
-                                return QString(":/icons/icons/ui/tag.png");
-                        case CommunitiesModel::Roles::DisplayName:
-                                return tr("Server Notices");
-                        case CommunitiesModel::Roles::Tooltip:
-                                return tr("Messages from your server or administrator.");
-                        }
-                } else {
-                        switch (role) {
-                        case CommunitiesModel::Roles::AvatarUrl:
-                                return QString(":/icons/icons/ui/tag.png");
-                        case CommunitiesModel::Roles::DisplayName:
-                        case CommunitiesModel::Roles::Tooltip:
-                                return tag.mid(2);
-                        }
-                }
+    if (index.row() == 0) {
+        switch (role) {
+        case CommunitiesModel::Roles::AvatarUrl:
+            return QString(":/icons/icons/ui/world.png");
+        case CommunitiesModel::Roles::DisplayName:
+            return tr("All rooms");
+        case CommunitiesModel::Roles::Tooltip:
+            return tr("Shows all rooms without filtering.");
+        case CommunitiesModel::Roles::ChildrenHidden:
+            return false;
+        case CommunitiesModel::Roles::Hidden:
+            return false;
+        case CommunitiesModel::Roles::Id:
+            return "";
+        }
+    } else if (index.row() - 1 < spaceOrder_.size()) {
+        auto id = spaceOrder_.at(index.row() - 1);
+        switch (role) {
+        case CommunitiesModel::Roles::AvatarUrl:
+            return QString::fromStdString(spaces_.at(id).avatar_url);
+        case CommunitiesModel::Roles::DisplayName:
+        case CommunitiesModel::Roles::Tooltip:
+            return QString::fromStdString(spaces_.at(id).name);
+        case CommunitiesModel::Roles::ChildrenHidden:
+            return true;
+        case CommunitiesModel::Roles::Hidden:
+            return hiddentTagIds_.contains("space:" + id);
+        case CommunitiesModel::Roles::Id:
+            return "space:" + id;
+        }
+    } else if (index.row() - 1 < tags_.size() + spaceOrder_.size()) {
+        auto tag = tags_.at(index.row() - 1 - spaceOrder_.size());
+        if (tag == "m.favourite") {
+            switch (role) {
+            case CommunitiesModel::Roles::AvatarUrl:
+                return QString(":/icons/icons/ui/star.png");
+            case CommunitiesModel::Roles::DisplayName:
+                return tr("Favourites");
+            case CommunitiesModel::Roles::Tooltip:
+                return tr("Rooms you have favourited.");
+            }
+        } else if (tag == "m.lowpriority") {
+            switch (role) {
+            case CommunitiesModel::Roles::AvatarUrl:
+                return QString(":/icons/icons/ui/lowprio.png");
+            case CommunitiesModel::Roles::DisplayName:
+                return tr("Low Priority");
+            case CommunitiesModel::Roles::Tooltip:
+                return tr("Rooms with low priority.");
+            }
+        } else if (tag == "m.server_notice") {
+            switch (role) {
+            case CommunitiesModel::Roles::AvatarUrl:
+                return QString(":/icons/icons/ui/tag.png");
+            case CommunitiesModel::Roles::DisplayName:
+                return tr("Server Notices");
+            case CommunitiesModel::Roles::Tooltip:
+                return tr("Messages from your server or administrator.");
+            }
+        } else {
+            switch (role) {
+            case CommunitiesModel::Roles::AvatarUrl:
+                return QString(":/icons/icons/ui/tag.png");
+            case CommunitiesModel::Roles::DisplayName:
+            case CommunitiesModel::Roles::Tooltip:
+                return tag.mid(2);
+            }
+        }
 
-                switch (role) {
-                case CommunitiesModel::Roles::Hidden:
-                        return hiddentTagIds_.contains("tag:" + tag);
-                case CommunitiesModel::Roles::ChildrenHidden:
-                        return true;
-                case CommunitiesModel::Roles::Id:
-                        return "tag:" + tag;
-                }
+        switch (role) {
+        case CommunitiesModel::Roles::Hidden:
+            return hiddentTagIds_.contains("tag:" + tag);
+        case CommunitiesModel::Roles::ChildrenHidden:
+            return true;
+        case CommunitiesModel::Roles::Id:
+            return "tag:" + tag;
         }
-        return QVariant();
+    }
+    return QVariant();
 }
 
 void
 CommunitiesModel::initializeSidebar()
 {
-        beginResetModel();
-        tags_.clear();
-        spaceOrder_.clear();
-        spaces_.clear();
-
-        std::set<std::string> ts;
-        std::vector<RoomInfo> tempSpaces;
-        auto infos = cache::roomInfo();
-        for (auto it = infos.begin(); it != infos.end(); it++) {
-                if (it.value().is_space) {
-                        spaceOrder_.push_back(it.key());
-                        spaces_[it.key()] = it.value();
-                } else {
-                        for (const auto &t : it.value().tags) {
-                                if (t.find("u.") == 0 || t.find("m." == 0)) {
-                                        ts.insert(t);
-                                }
-                        }
+    beginResetModel();
+    tags_.clear();
+    spaceOrder_.clear();
+    spaces_.clear();
+
+    std::set<std::string> ts;
+    std::vector<RoomInfo> tempSpaces;
+    auto infos = cache::roomInfo();
+    for (auto it = infos.begin(); it != infos.end(); it++) {
+        if (it.value().is_space) {
+            spaceOrder_.push_back(it.key());
+            spaces_[it.key()] = it.value();
+        } else {
+            for (const auto &t : it.value().tags) {
+                if (t.find("u.") == 0 || t.find("m." == 0)) {
+                    ts.insert(t);
                 }
+            }
         }
+    }
 
-        for (const auto &t : ts)
-                tags_.push_back(QString::fromStdString(t));
+    for (const auto &t : ts)
+        tags_.push_back(QString::fromStdString(t));
 
-        hiddentTagIds_ = UserSettings::instance()->hiddenTags();
-        endResetModel();
+    hiddentTagIds_ = UserSettings::instance()->hiddenTags();
+    endResetModel();
 
-        emit tagsChanged();
-        emit hiddenTagsChanged();
+    emit tagsChanged();
+    emit hiddenTagsChanged();
 }
 
 void
 CommunitiesModel::clear()
 {
-        beginResetModel();
-        tags_.clear();
-        endResetModel();
-        resetCurrentTagId();
+    beginResetModel();
+    tags_.clear();
+    endResetModel();
+    resetCurrentTagId();
 
-        emit tagsChanged();
+    emit tagsChanged();
 }
 
 void
 CommunitiesModel::sync(const mtx::responses::Rooms &rooms)
 {
-        bool tagsUpdated = false;
-
-        for (const auto &[roomid, room] : rooms.join) {
-                (void)roomid;
-                for (const auto &e : room.account_data.events)
-                        if (std::holds_alternative<
-                              mtx::events::AccountDataEvent<mtx::events::account_data::Tags>>(e)) {
-                                tagsUpdated = true;
-                        }
-                for (const auto &e : room.state.events)
-                        if (std::holds_alternative<
-                              mtx::events::StateEvent<mtx::events::state::space::Child>>(e) ||
-                            std::holds_alternative<
-                              mtx::events::StateEvent<mtx::events::state::space::Parent>>(e)) {
-                                tagsUpdated = true;
-                        }
-                for (const auto &e : room.timeline.events)
-                        if (std::holds_alternative<
-                              mtx::events::StateEvent<mtx::events::state::space::Child>>(e) ||
-                            std::holds_alternative<
-                              mtx::events::StateEvent<mtx::events::state::space::Parent>>(e)) {
-                                tagsUpdated = true;
-                        }
-        }
-        for (const auto &[roomid, room] : rooms.leave) {
-                (void)room;
-                if (spaceOrder_.contains(QString::fromStdString(roomid)))
-                        tagsUpdated = true;
-        }
-
-        if (tagsUpdated)
-                initializeSidebar();
+    bool tagsUpdated = false;
+
+    for (const auto &[roomid, room] : rooms.join) {
+        (void)roomid;
+        for (const auto &e : room.account_data.events)
+            if (std::holds_alternative<
+                  mtx::events::AccountDataEvent<mtx::events::account_data::Tags>>(e)) {
+                tagsUpdated = true;
+            }
+        for (const auto &e : room.state.events)
+            if (std::holds_alternative<mtx::events::StateEvent<mtx::events::state::space::Child>>(
+                  e) ||
+                std::holds_alternative<mtx::events::StateEvent<mtx::events::state::space::Parent>>(
+                  e)) {
+                tagsUpdated = true;
+            }
+        for (const auto &e : room.timeline.events)
+            if (std::holds_alternative<mtx::events::StateEvent<mtx::events::state::space::Child>>(
+                  e) ||
+                std::holds_alternative<mtx::events::StateEvent<mtx::events::state::space::Parent>>(
+                  e)) {
+                tagsUpdated = true;
+            }
+    }
+    for (const auto &[roomid, room] : rooms.leave) {
+        (void)room;
+        if (spaceOrder_.contains(QString::fromStdString(roomid)))
+            tagsUpdated = true;
+    }
+
+    if (tagsUpdated)
+        initializeSidebar();
 }
 
 void
 CommunitiesModel::setCurrentTagId(QString tagId)
 {
-        if (tagId.startsWith("tag:")) {
-                auto tag = tagId.mid(4);
-                for (const auto &t : tags_) {
-                        if (t == tag) {
-                                this->currentTagId_ = tagId;
-                                emit currentTagIdChanged(currentTagId_);
-                                return;
-                        }
-                }
-        } else if (tagId.startsWith("space:")) {
-                auto tag = tagId.mid(6);
-                for (const auto &t : spaceOrder_) {
-                        if (t == tag) {
-                                this->currentTagId_ = tagId;
-                                emit currentTagIdChanged(currentTagId_);
-                                return;
-                        }
-                }
+    if (tagId.startsWith("tag:")) {
+        auto tag = tagId.mid(4);
+        for (const auto &t : tags_) {
+            if (t == tag) {
+                this->currentTagId_ = tagId;
+                emit currentTagIdChanged(currentTagId_);
+                return;
+            }
+        }
+    } else if (tagId.startsWith("space:")) {
+        auto tag = tagId.mid(6);
+        for (const auto &t : spaceOrder_) {
+            if (t == tag) {
+                this->currentTagId_ = tagId;
+                emit currentTagIdChanged(currentTagId_);
+                return;
+            }
         }
+    }
 
-        this->currentTagId_ = "";
-        emit currentTagIdChanged(currentTagId_);
+    this->currentTagId_ = "";
+    emit currentTagIdChanged(currentTagId_);
 }
 
 void
 CommunitiesModel::toggleTagId(QString tagId)
 {
-        if (hiddentTagIds_.contains(tagId)) {
-                hiddentTagIds_.removeOne(tagId);
-                UserSettings::instance()->setHiddenTags(hiddentTagIds_);
-        } else {
-                hiddentTagIds_.push_back(tagId);
-                UserSettings::instance()->setHiddenTags(hiddentTagIds_);
-        }
-
-        if (tagId.startsWith("tag:")) {
-                auto idx = tags_.indexOf(tagId.mid(4));
-                if (idx != -1)
-                        emit dataChanged(index(idx + 1 + spaceOrder_.size()),
-                                         index(idx + 1 + spaceOrder_.size()),
-                                         {Hidden});
-        } else if (tagId.startsWith("space:")) {
-                auto idx = spaceOrder_.indexOf(tagId.mid(6));
-                if (idx != -1)
-                        emit dataChanged(index(idx + 1), index(idx + 1), {Hidden});
-        }
-
-        emit hiddenTagsChanged();
+    if (hiddentTagIds_.contains(tagId)) {
+        hiddentTagIds_.removeOne(tagId);
+        UserSettings::instance()->setHiddenTags(hiddentTagIds_);
+    } else {
+        hiddentTagIds_.push_back(tagId);
+        UserSettings::instance()->setHiddenTags(hiddentTagIds_);
+    }
+
+    if (tagId.startsWith("tag:")) {
+        auto idx = tags_.indexOf(tagId.mid(4));
+        if (idx != -1)
+            emit dataChanged(
+              index(idx + 1 + spaceOrder_.size()), index(idx + 1 + spaceOrder_.size()), {Hidden});
+    } else if (tagId.startsWith("space:")) {
+        auto idx = spaceOrder_.indexOf(tagId.mid(6));
+        if (idx != -1)
+            emit dataChanged(index(idx + 1), index(idx + 1), {Hidden});
+    }
+
+    emit hiddenTagsChanged();
 }
diff --git a/src/timeline/CommunitiesModel.h b/src/timeline/CommunitiesModel.h
index 677581dc..0440d17f 100644
--- a/src/timeline/CommunitiesModel.h
+++ b/src/timeline/CommunitiesModel.h
@@ -15,64 +15,64 @@
 
 class CommunitiesModel : public QAbstractListModel
 {
-        Q_OBJECT
-        Q_PROPERTY(QString currentTagId READ currentTagId WRITE setCurrentTagId NOTIFY
-                     currentTagIdChanged RESET resetCurrentTagId)
-        Q_PROPERTY(QStringList tags READ tags NOTIFY tagsChanged)
-        Q_PROPERTY(QStringList tagsWithDefault READ tagsWithDefault NOTIFY tagsChanged)
+    Q_OBJECT
+    Q_PROPERTY(QString currentTagId READ currentTagId WRITE setCurrentTagId NOTIFY
+                 currentTagIdChanged RESET resetCurrentTagId)
+    Q_PROPERTY(QStringList tags READ tags NOTIFY tagsChanged)
+    Q_PROPERTY(QStringList tagsWithDefault READ tagsWithDefault NOTIFY tagsChanged)
 
 public:
-        enum Roles
-        {
-                AvatarUrl = Qt::UserRole,
-                DisplayName,
-                Tooltip,
-                ChildrenHidden,
-                Hidden,
-                Id,
-        };
+    enum Roles
+    {
+        AvatarUrl = Qt::UserRole,
+        DisplayName,
+        Tooltip,
+        ChildrenHidden,
+        Hidden,
+        Id,
+    };
 
-        CommunitiesModel(QObject *parent = nullptr);
-        QHash<int, QByteArray> roleNames() const override;
-        int rowCount(const QModelIndex &parent = QModelIndex()) const override
-        {
-                (void)parent;
-                return 1 + tags_.size() + spaceOrder_.size();
-        }
-        QVariant data(const QModelIndex &index, int role) const override;
+    CommunitiesModel(QObject *parent = nullptr);
+    QHash<int, QByteArray> roleNames() const override;
+    int rowCount(const QModelIndex &parent = QModelIndex()) const override
+    {
+        (void)parent;
+        return 1 + tags_.size() + spaceOrder_.size();
+    }
+    QVariant data(const QModelIndex &index, int role) const override;
 
 public slots:
-        void initializeSidebar();
-        void sync(const mtx::responses::Rooms &rooms);
-        void clear();
-        QString currentTagId() const { return currentTagId_; }
-        void setCurrentTagId(QString tagId);
-        void resetCurrentTagId()
-        {
-                currentTagId_.clear();
-                emit currentTagIdChanged(currentTagId_);
-        }
-        QStringList tags() const { return tags_; }
-        QStringList tagsWithDefault() const
-        {
-                QStringList tagsWD = tags_;
-                tagsWD.prepend("m.lowpriority");
-                tagsWD.prepend("m.favourite");
-                tagsWD.removeOne("m.server_notice");
-                tagsWD.removeDuplicates();
-                return tagsWD;
-        }
-        void toggleTagId(QString tagId);
+    void initializeSidebar();
+    void sync(const mtx::responses::Rooms &rooms);
+    void clear();
+    QString currentTagId() const { return currentTagId_; }
+    void setCurrentTagId(QString tagId);
+    void resetCurrentTagId()
+    {
+        currentTagId_.clear();
+        emit currentTagIdChanged(currentTagId_);
+    }
+    QStringList tags() const { return tags_; }
+    QStringList tagsWithDefault() const
+    {
+        QStringList tagsWD = tags_;
+        tagsWD.prepend("m.lowpriority");
+        tagsWD.prepend("m.favourite");
+        tagsWD.removeOne("m.server_notice");
+        tagsWD.removeDuplicates();
+        return tagsWD;
+    }
+    void toggleTagId(QString tagId);
 
 signals:
-        void currentTagIdChanged(QString tagId);
-        void hiddenTagsChanged();
-        void tagsChanged();
+    void currentTagIdChanged(QString tagId);
+    void hiddenTagsChanged();
+    void tagsChanged();
 
 private:
-        QStringList tags_;
-        QString currentTagId_;
-        QStringList hiddentTagIds_;
-        QStringList spaceOrder_;
-        std::map<QString, RoomInfo> spaces_;
+    QStringList tags_;
+    QString currentTagId_;
+    QStringList hiddentTagIds_;
+    QStringList spaceOrder_;
+    std::map<QString, RoomInfo> spaces_;
 };
diff --git a/src/timeline/DelegateChooser.cpp b/src/timeline/DelegateChooser.cpp
index 39c8fa17..682077ae 100644
--- a/src/timeline/DelegateChooser.cpp
+++ b/src/timeline/DelegateChooser.cpp
@@ -13,127 +13,126 @@
 QQmlComponent *
 DelegateChoice::delegate() const
 {
-        return delegate_;
+    return delegate_;
 }
 
 void
 DelegateChoice::setDelegate(QQmlComponent *delegate)
 {
-        if (delegate != delegate_) {
-                delegate_ = delegate;
-                emit delegateChanged();
-                emit changed();
-        }
+    if (delegate != delegate_) {
+        delegate_ = delegate;
+        emit delegateChanged();
+        emit changed();
+    }
 }
 
 QVariant
 DelegateChoice::roleValue() const
 {
-        return roleValue_;
+    return roleValue_;
 }
 
 void
 DelegateChoice::setRoleValue(const QVariant &value)
 {
-        if (value != roleValue_) {
-                roleValue_ = value;
-                emit roleValueChanged();
-                emit changed();
-        }
+    if (value != roleValue_) {
+        roleValue_ = value;
+        emit roleValueChanged();
+        emit changed();
+    }
 }
 
 QVariant
 DelegateChooser::roleValue() const
 {
-        return roleValue_;
+    return roleValue_;
 }
 
 void
 DelegateChooser::setRoleValue(const QVariant &value)
 {
-        if (value != roleValue_) {
-                roleValue_ = value;
-                recalcChild();
-                emit roleValueChanged();
-        }
+    if (value != roleValue_) {
+        roleValue_ = value;
+        recalcChild();
+        emit roleValueChanged();
+    }
 }
 
 QQmlListProperty<DelegateChoice>
 DelegateChooser::choices()
 {
-        return QQmlListProperty<DelegateChoice>(this,
-                                                this,
-                                                &DelegateChooser::appendChoice,
-                                                &DelegateChooser::choiceCount,
-                                                &DelegateChooser::choice,
-                                                &DelegateChooser::clearChoices);
+    return QQmlListProperty<DelegateChoice>(this,
+                                            this,
+                                            &DelegateChooser::appendChoice,
+                                            &DelegateChooser::choiceCount,
+                                            &DelegateChooser::choice,
+                                            &DelegateChooser::clearChoices);
 }
 
 void
 DelegateChooser::appendChoice(QQmlListProperty<DelegateChoice> *p, DelegateChoice *c)
 {
-        DelegateChooser *dc = static_cast<DelegateChooser *>(p->object);
-        dc->choices_.append(c);
+    DelegateChooser *dc = static_cast<DelegateChooser *>(p->object);
+    dc->choices_.append(c);
 }
 
 int
 DelegateChooser::choiceCount(QQmlListProperty<DelegateChoice> *p)
 {
-        return static_cast<DelegateChooser *>(p->object)->choices_.count();
+    return static_cast<DelegateChooser *>(p->object)->choices_.count();
 }
 DelegateChoice *
 DelegateChooser::choice(QQmlListProperty<DelegateChoice> *p, int index)
 {
-        return static_cast<DelegateChooser *>(p->object)->choices_.at(index);
+    return static_cast<DelegateChooser *>(p->object)->choices_.at(index);
 }
 void
 DelegateChooser::clearChoices(QQmlListProperty<DelegateChoice> *p)
 {
-        static_cast<DelegateChooser *>(p->object)->choices_.clear();
+    static_cast<DelegateChooser *>(p->object)->choices_.clear();
 }
 
 void
 DelegateChooser::recalcChild()
 {
-        for (const auto choice : qAsConst(choices_)) {
-                auto choiceValue = choice->roleValue();
-                if (!roleValue_.isValid() || !choiceValue.isValid() || choiceValue == roleValue_) {
-                        if (child_) {
-                                child_->setParentItem(nullptr);
-                                child_ = nullptr;
-                        }
-
-                        choice->delegate()->create(incubator, QQmlEngine::contextForObject(this));
-                        return;
-                }
+    for (const auto choice : qAsConst(choices_)) {
+        auto choiceValue = choice->roleValue();
+        if (!roleValue_.isValid() || !choiceValue.isValid() || choiceValue == roleValue_) {
+            if (child_) {
+                child_->setParentItem(nullptr);
+                child_ = nullptr;
+            }
+
+            choice->delegate()->create(incubator, QQmlEngine::contextForObject(this));
+            return;
         }
+    }
 }
 
 void
 DelegateChooser::componentComplete()
 {
-        QQuickItem::componentComplete();
-        recalcChild();
+    QQuickItem::componentComplete();
+    recalcChild();
 }
 
 void
 DelegateChooser::DelegateIncubator::statusChanged(QQmlIncubator::Status status)
 {
-        if (status == QQmlIncubator::Ready) {
-                chooser.child_ = dynamic_cast<QQuickItem *>(object());
-                if (chooser.child_ == nullptr) {
-                        nhlog::ui()->error("Delegate has to be derived of Item!");
-                        return;
-                }
-
-                chooser.child_->setParentItem(&chooser);
-                QQmlEngine::setObjectOwnership(chooser.child_,
-                                               QQmlEngine::ObjectOwnership::JavaScriptOwnership);
-                emit chooser.childChanged();
-
-        } else if (status == QQmlIncubator::Error) {
-                for (const auto &e : errors())
-                        nhlog::ui()->error("Error instantiating delegate: {}",
-                                           e.toString().toStdString());
+    if (status == QQmlIncubator::Ready) {
+        chooser.child_ = dynamic_cast<QQuickItem *>(object());
+        if (chooser.child_ == nullptr) {
+            nhlog::ui()->error("Delegate has to be derived of Item!");
+            return;
         }
+
+        chooser.child_->setParentItem(&chooser);
+        QQmlEngine::setObjectOwnership(chooser.child_,
+                                       QQmlEngine::ObjectOwnership::JavaScriptOwnership);
+        emit chooser.childChanged();
+
+    } else if (status == QQmlIncubator::Error) {
+        for (const auto &e : errors())
+            nhlog::ui()->error("Error instantiating delegate: {}", e.toString().toStdString());
+    }
 }
diff --git a/src/timeline/DelegateChooser.h b/src/timeline/DelegateChooser.h
index 22e423a2..3e4b16d7 100644
--- a/src/timeline/DelegateChooser.h
+++ b/src/timeline/DelegateChooser.h
@@ -18,73 +18,73 @@ class QQmlAdaptorModel;
 
 class DelegateChoice : public QObject
 {
-        Q_OBJECT
-        Q_CLASSINFO("DefaultProperty", "delegate")
+    Q_OBJECT
+    Q_CLASSINFO("DefaultProperty", "delegate")
 
 public:
-        Q_PROPERTY(QVariant roleValue READ roleValue WRITE setRoleValue NOTIFY roleValueChanged)
-        Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
+    Q_PROPERTY(QVariant roleValue READ roleValue WRITE setRoleValue NOTIFY roleValueChanged)
+    Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
 
-        QQmlComponent *delegate() const;
-        void setDelegate(QQmlComponent *delegate);
+    QQmlComponent *delegate() const;
+    void setDelegate(QQmlComponent *delegate);
 
-        QVariant roleValue() const;
-        void setRoleValue(const QVariant &value);
+    QVariant roleValue() const;
+    void setRoleValue(const QVariant &value);
 
 signals:
-        void delegateChanged();
-        void roleValueChanged();
-        void changed();
+    void delegateChanged();
+    void roleValueChanged();
+    void changed();
 
 private:
-        QVariant roleValue_;
-        QQmlComponent *delegate_ = nullptr;
+    QVariant roleValue_;
+    QQmlComponent *delegate_ = nullptr;
 };
 
 class DelegateChooser : public QQuickItem
 {
-        Q_OBJECT
-        Q_CLASSINFO("DefaultProperty", "choices")
+    Q_OBJECT
+    Q_CLASSINFO("DefaultProperty", "choices")
 
 public:
-        Q_PROPERTY(QQmlListProperty<DelegateChoice> choices READ choices CONSTANT)
-        Q_PROPERTY(QVariant roleValue READ roleValue WRITE setRoleValue NOTIFY roleValueChanged)
-        Q_PROPERTY(QQuickItem *child READ child NOTIFY childChanged)
+    Q_PROPERTY(QQmlListProperty<DelegateChoice> choices READ choices CONSTANT)
+    Q_PROPERTY(QVariant roleValue READ roleValue WRITE setRoleValue NOTIFY roleValueChanged)
+    Q_PROPERTY(QQuickItem *child READ child NOTIFY childChanged)
 
-        QQmlListProperty<DelegateChoice> choices();
+    QQmlListProperty<DelegateChoice> choices();
 
-        QVariant roleValue() const;
-        void setRoleValue(const QVariant &value);
+    QVariant roleValue() const;
+    void setRoleValue(const QVariant &value);
 
-        QQuickItem *child() const { return child_; }
+    QQuickItem *child() const { return child_; }
 
-        void recalcChild();
-        void componentComplete() override;
+    void recalcChild();
+    void componentComplete() override;
 
 signals:
-        void roleChanged();
-        void roleValueChanged();
-        void childChanged();
+    void roleChanged();
+    void roleValueChanged();
+    void childChanged();
 
 private:
-        struct DelegateIncubator : public QQmlIncubator
-        {
-                DelegateIncubator(DelegateChooser &parent)
-                  : QQmlIncubator(QQmlIncubator::AsynchronousIfNested)
-                  , chooser(parent)
-                {}
-                void statusChanged(QQmlIncubator::Status status) override;
-
-                DelegateChooser &chooser;
-        };
-
-        QVariant roleValue_;
-        QList<DelegateChoice *> choices_;
-        QQuickItem *child_ = nullptr;
-        DelegateIncubator incubator{*this};
-
-        static void appendChoice(QQmlListProperty<DelegateChoice> *, DelegateChoice *);
-        static int choiceCount(QQmlListProperty<DelegateChoice> *);
-        static DelegateChoice *choice(QQmlListProperty<DelegateChoice> *, int index);
-        static void clearChoices(QQmlListProperty<DelegateChoice> *);
+    struct DelegateIncubator : public QQmlIncubator
+    {
+        DelegateIncubator(DelegateChooser &parent)
+          : QQmlIncubator(QQmlIncubator::AsynchronousIfNested)
+          , chooser(parent)
+        {}
+        void statusChanged(QQmlIncubator::Status status) override;
+
+        DelegateChooser &chooser;
+    };
+
+    QVariant roleValue_;
+    QList<DelegateChoice *> choices_;
+    QQuickItem *child_ = nullptr;
+    DelegateIncubator incubator{*this};
+
+    static void appendChoice(QQmlListProperty<DelegateChoice> *, DelegateChoice *);
+    static int choiceCount(QQmlListProperty<DelegateChoice> *);
+    static DelegateChoice *choice(QQmlListProperty<DelegateChoice> *, int index);
+    static void clearChoices(QQmlListProperty<DelegateChoice> *);
 };
diff --git a/src/timeline/EventStore.cpp b/src/timeline/EventStore.cpp
index 881fd5bb..7144424a 100644
--- a/src/timeline/EventStore.cpp
+++ b/src/timeline/EventStore.cpp
@@ -28,393 +28,373 @@ QCache<EventStore::Index, mtx::events::collections::TimelineEvents> EventStore::
 EventStore::EventStore(std::string room_id, QObject *)
   : room_id_(std::move(room_id))
 {
-        static auto reactionType = qRegisterMetaType<Reaction>();
-        (void)reactionType;
-
-        auto range = cache::client()->getTimelineRange(room_id_);
-
-        if (range) {
-                this->first = range->first;
-                this->last  = range->last;
-        }
-
-        connect(
-          this,
-          &EventStore::eventFetched,
-          this,
-          [this](std::string id,
-                 std::string relatedTo,
-                 mtx::events::collections::TimelineEvents timeline) {
-                  cache::client()->storeEvent(room_id_, id, {timeline});
-
-                  if (!relatedTo.empty()) {
-                          auto idx = idToIndex(relatedTo);
-                          if (idx)
-                                  emit dataChanged(*idx, *idx);
-                  }
-          },
-          Qt::QueuedConnection);
-
-        connect(
-          this,
-          &EventStore::oldMessagesRetrieved,
-          this,
-          [this](const mtx::responses::Messages &res) {
-                  if (res.end.empty() || cache::client()->previousBatchToken(room_id_) == res.end) {
-                          noMoreMessages = true;
-                          emit fetchedMore();
-                          return;
+    static auto reactionType = qRegisterMetaType<Reaction>();
+    (void)reactionType;
+
+    auto range = cache::client()->getTimelineRange(room_id_);
+
+    if (range) {
+        this->first = range->first;
+        this->last  = range->last;
+    }
+
+    connect(
+      this,
+      &EventStore::eventFetched,
+      this,
+      [this](
+        std::string id, std::string relatedTo, mtx::events::collections::TimelineEvents timeline) {
+          cache::client()->storeEvent(room_id_, id, {timeline});
+
+          if (!relatedTo.empty()) {
+              auto idx = idToIndex(relatedTo);
+              if (idx)
+                  emit dataChanged(*idx, *idx);
+          }
+      },
+      Qt::QueuedConnection);
+
+    connect(
+      this,
+      &EventStore::oldMessagesRetrieved,
+      this,
+      [this](const mtx::responses::Messages &res) {
+          if (res.end.empty() || cache::client()->previousBatchToken(room_id_) == res.end) {
+              noMoreMessages = true;
+              emit fetchedMore();
+              return;
+          }
+
+          uint64_t newFirst = cache::client()->saveOldMessages(room_id_, res);
+          if (newFirst == first)
+              fetchMore();
+          else {
+              if (this->last != std::numeric_limits<uint64_t>::max()) {
+                  auto oldFirst = this->first;
+                  emit beginInsertRows(toExternalIdx(newFirst), toExternalIdx(this->first - 1));
+                  this->first = newFirst;
+                  emit endInsertRows();
+                  emit fetchedMore();
+                  emit dataChanged(toExternalIdx(oldFirst), toExternalIdx(oldFirst));
+              } else {
+                  auto range = cache::client()->getTimelineRange(room_id_);
+
+                  if (range && range->last - range->first != 0) {
+                      emit beginInsertRows(0, int(range->last - range->first));
+                      this->first = range->first;
+                      this->last  = range->last;
+                      emit endInsertRows();
+                      emit fetchedMore();
+                  } else {
+                      fetchMore();
                   }
+              }
+          }
+      },
+      Qt::QueuedConnection);
+
+    connect(this, &EventStore::processPending, this, [this]() {
+        if (!current_txn.empty()) {
+            nhlog::ui()->debug("Already processing {}", current_txn);
+            return;
+        }
 
-                  uint64_t newFirst = cache::client()->saveOldMessages(room_id_, res);
-                  if (newFirst == first)
-                          fetchMore();
-                  else {
-                          if (this->last != std::numeric_limits<uint64_t>::max()) {
-                                  auto oldFirst = this->first;
-                                  emit beginInsertRows(toExternalIdx(newFirst),
-                                                       toExternalIdx(this->first - 1));
-                                  this->first = newFirst;
-                                  emit endInsertRows();
-                                  emit fetchedMore();
-                                  emit dataChanged(toExternalIdx(oldFirst),
-                                                   toExternalIdx(oldFirst));
-                          } else {
-                                  auto range = cache::client()->getTimelineRange(room_id_);
-
-                                  if (range && range->last - range->first != 0) {
-                                          emit beginInsertRows(0, int(range->last - range->first));
-                                          this->first = range->first;
-                                          this->last  = range->last;
-                                          emit endInsertRows();
-                                          emit fetchedMore();
-                                  } else {
-                                          fetchMore();
-                                  }
-                          }
-                  }
-          },
-          Qt::QueuedConnection);
+        auto event = cache::client()->firstPendingMessage(room_id_);
 
-        connect(this, &EventStore::processPending, this, [this]() {
-                if (!current_txn.empty()) {
-                        nhlog::ui()->debug("Already processing {}", current_txn);
-                        return;
-                }
+        if (!event) {
+            nhlog::ui()->debug("No event to send");
+            return;
+        }
 
-                auto event = cache::client()->firstPendingMessage(room_id_);
+        std::visit(
+          [this](auto e) {
+              auto txn_id       = e.event_id;
+              this->current_txn = txn_id;
 
-                if (!event) {
-                        nhlog::ui()->debug("No event to send");
-                        return;
-                }
+              if (txn_id.empty() || txn_id[0] != 'm') {
+                  nhlog::ui()->debug("Invalid txn id '{}'", txn_id);
+                  cache::client()->removePendingStatus(room_id_, txn_id);
+                  return;
+              }
+
+              if constexpr (mtx::events::message_content_to_type<decltype(e.content)> !=
+                            mtx::events::EventType::Unsupported)
+                  http::client()->send_room_message(
+                    room_id_,
+                    txn_id,
+                    e.content,
+                    [this, txn_id, e](const mtx::responses::EventId &event_id,
+                                      mtx::http::RequestErr err) {
+                        if (err) {
+                            const int status_code = static_cast<int>(err->status_code);
+                            nhlog::net()->warn("[{}] failed to send message: {} {}",
+                                               txn_id,
+                                               err->matrix_error.error,
+                                               status_code);
+                            emit messageFailed(txn_id);
+                            return;
+                        }
 
-                std::visit(
-                  [this](auto e) {
-                          auto txn_id       = e.event_id;
-                          this->current_txn = txn_id;
-
-                          if (txn_id.empty() || txn_id[0] != 'm') {
-                                  nhlog::ui()->debug("Invalid txn id '{}'", txn_id);
-                                  cache::client()->removePendingStatus(room_id_, txn_id);
-                                  return;
-                          }
-
-                          if constexpr (mtx::events::message_content_to_type<decltype(e.content)> !=
-                                        mtx::events::EventType::Unsupported)
-                                  http::client()->send_room_message(
-                                    room_id_,
-                                    txn_id,
-                                    e.content,
-                                    [this, txn_id, e](const mtx::responses::EventId &event_id,
-                                                      mtx::http::RequestErr err) {
-                                            if (err) {
-                                                    const int status_code =
-                                                      static_cast<int>(err->status_code);
-                                                    nhlog::net()->warn(
-                                                      "[{}] failed to send message: {} {}",
-                                                      txn_id,
-                                                      err->matrix_error.error,
-                                                      status_code);
-                                                    emit messageFailed(txn_id);
-                                                    return;
-                                            }
-
-                                            emit messageSent(txn_id, event_id.event_id.to_string());
-                                            if constexpr (std::is_same_v<
-                                                            decltype(e.content),
-                                                            mtx::events::msg::Encrypted>) {
-                                                    auto event =
-                                                      decryptEvent({room_id_, e.event_id}, e);
-                                                    if (event->event) {
-                                                            if (auto dec = std::get_if<
-                                                                  mtx::events::RoomEvent<
-                                                                    mtx::events::msg::
-                                                                      KeyVerificationRequest>>(
-                                                                  &event->event.value())) {
-                                                                    emit updateFlowEventId(
-                                                                      event_id.event_id
-                                                                        .to_string());
-                                                            }
-                                                    }
-                                            }
-                                    });
-                  },
-                  event->data);
-        });
-
-        connect(
-          this,
-          &EventStore::messageFailed,
-          this,
-          [this](std::string txn_id) {
-                  if (current_txn == txn_id) {
-                          current_txn_error_count++;
-                          if (current_txn_error_count > 10) {
-                                  nhlog::ui()->debug("failing txn id '{}'", txn_id);
-                                  cache::client()->removePendingStatus(room_id_, txn_id);
-                                  current_txn_error_count = 0;
-                          }
-                  }
-                  QTimer::singleShot(1000, this, [this]() {
-                          nhlog::ui()->debug("timeout");
-                          this->current_txn = "";
-                          emit processPending();
-                  });
+                        emit messageSent(txn_id, event_id.event_id.to_string());
+                        if constexpr (std::is_same_v<decltype(e.content),
+                                                     mtx::events::msg::Encrypted>) {
+                            auto event = decryptEvent({room_id_, e.event_id}, e);
+                            if (event->event) {
+                                if (auto dec = std::get_if<mtx::events::RoomEvent<
+                                      mtx::events::msg::KeyVerificationRequest>>(
+                                      &event->event.value())) {
+                                    emit updateFlowEventId(event_id.event_id.to_string());
+                                }
+                            }
+                        }
+                    });
           },
-          Qt::QueuedConnection);
-
-        connect(
-          this,
-          &EventStore::messageSent,
-          this,
-          [this](std::string txn_id, std::string event_id) {
-                  nhlog::ui()->debug("sent {}", txn_id);
-
-                  // Replace the event_id in pending edits/replies/redactions with the actual
-                  // event_id of this event. This allows one to edit and reply to events that are
-                  // currently pending.
-
-                  // FIXME (introduced by balsoft): this doesn't work for encrypted events, but
-                  // allegedly it's hard to fix so I'll leave my first contribution at that
-                  for (auto related_event_id : cache::client()->relatedEvents(room_id_, txn_id)) {
-                          if (cache::client()->getEvent(room_id_, related_event_id)) {
-                                  auto related_event =
-                                    cache::client()->getEvent(room_id_, related_event_id).value();
-                                  auto relations = mtx::accessors::relations(related_event.data);
-
-                                  // Replace the blockquote in fallback reply
-                                  auto related_text =
-                                    std::get_if<mtx::events::RoomEvent<mtx::events::msg::Text>>(
-                                      &related_event.data);
-                                  if (related_text && relations.reply_to() == txn_id) {
-                                          size_t index =
-                                            related_text->content.formatted_body.find(txn_id);
-                                          if (index != std::string::npos) {
-                                                  related_text->content.formatted_body.replace(
-                                                    index, event_id.length(), event_id);
-                                          }
-                                  }
+          event->data);
+    });
+
+    connect(
+      this,
+      &EventStore::messageFailed,
+      this,
+      [this](std::string txn_id) {
+          if (current_txn == txn_id) {
+              current_txn_error_count++;
+              if (current_txn_error_count > 10) {
+                  nhlog::ui()->debug("failing txn id '{}'", txn_id);
+                  cache::client()->removePendingStatus(room_id_, txn_id);
+                  current_txn_error_count = 0;
+              }
+          }
+          QTimer::singleShot(1000, this, [this]() {
+              nhlog::ui()->debug("timeout");
+              this->current_txn = "";
+              emit processPending();
+          });
+      },
+      Qt::QueuedConnection);
+
+    connect(
+      this,
+      &EventStore::messageSent,
+      this,
+      [this](std::string txn_id, std::string event_id) {
+          nhlog::ui()->debug("sent {}", txn_id);
+
+          // Replace the event_id in pending edits/replies/redactions with the actual
+          // event_id of this event. This allows one to edit and reply to events that are
+          // currently pending.
+
+          // FIXME (introduced by balsoft): this doesn't work for encrypted events, but
+          // allegedly it's hard to fix so I'll leave my first contribution at that
+          for (auto related_event_id : cache::client()->relatedEvents(room_id_, txn_id)) {
+              if (cache::client()->getEvent(room_id_, related_event_id)) {
+                  auto related_event =
+                    cache::client()->getEvent(room_id_, related_event_id).value();
+                  auto relations = mtx::accessors::relations(related_event.data);
+
+                  // Replace the blockquote in fallback reply
+                  auto related_text = std::get_if<mtx::events::RoomEvent<mtx::events::msg::Text>>(
+                    &related_event.data);
+                  if (related_text && relations.reply_to() == txn_id) {
+                      size_t index = related_text->content.formatted_body.find(txn_id);
+                      if (index != std::string::npos) {
+                          related_text->content.formatted_body.replace(
+                            index, event_id.length(), event_id);
+                      }
+                  }
 
-                                  for (mtx::common::Relation &rel : relations.relations) {
-                                          if (rel.event_id == txn_id)
-                                                  rel.event_id = event_id;
-                                  }
+                  for (mtx::common::Relation &rel : relations.relations) {
+                      if (rel.event_id == txn_id)
+                          rel.event_id = event_id;
+                  }
 
-                                  mtx::accessors::set_relations(related_event.data, relations);
+                  mtx::accessors::set_relations(related_event.data, relations);
 
-                                  cache::client()->replaceEvent(
-                                    room_id_, related_event_id, related_event);
+                  cache::client()->replaceEvent(room_id_, related_event_id, related_event);
 
-                                  auto idx = idToIndex(related_event_id);
+                  auto idx = idToIndex(related_event_id);
 
-                                  events_by_id_.remove({room_id_, related_event_id});
-                                  events_.remove({room_id_, toInternalIdx(*idx)});
-                          }
-                  }
+                  events_by_id_.remove({room_id_, related_event_id});
+                  events_.remove({room_id_, toInternalIdx(*idx)});
+              }
+          }
 
-                  http::client()->read_event(
-                    room_id_, event_id, [this, event_id](mtx::http::RequestErr err) {
-                            if (err) {
-                                    nhlog::net()->warn(
-                                      "failed to read_event ({}, {})", room_id_, event_id);
-                            }
-                    });
+          http::client()->read_event(
+            room_id_, event_id, [this, event_id](mtx::http::RequestErr err) {
+                if (err) {
+                    nhlog::net()->warn("failed to read_event ({}, {})", room_id_, event_id);
+                }
+            });
 
-                  auto idx = idToIndex(event_id);
+          auto idx = idToIndex(event_id);
 
-                  if (idx)
-                          emit dataChanged(*idx, *idx);
+          if (idx)
+              emit dataChanged(*idx, *idx);
 
-                  cache::client()->removePendingStatus(room_id_, txn_id);
-                  this->current_txn             = "";
-                  this->current_txn_error_count = 0;
-                  emit processPending();
-          },
-          Qt::QueuedConnection);
+          cache::client()->removePendingStatus(room_id_, txn_id);
+          this->current_txn             = "";
+          this->current_txn_error_count = 0;
+          emit processPending();
+      },
+      Qt::QueuedConnection);
 }
 
 void
 EventStore::addPending(mtx::events::collections::TimelineEvents event)
 {
-        if (this->thread() != QThread::currentThread())
-                nhlog::db()->warn("{} called from a different thread!", __func__);
+    if (this->thread() != QThread::currentThread())
+        nhlog::db()->warn("{} called from a different thread!", __func__);
 
-        cache::client()->savePendingMessage(this->room_id_, {event});
-        mtx::responses::Timeline events;
-        events.limited = false;
-        events.events.emplace_back(event);
-        handleSync(events);
+    cache::client()->savePendingMessage(this->room_id_, {event});
+    mtx::responses::Timeline events;
+    events.limited = false;
+    events.events.emplace_back(event);
+    handleSync(events);
 
-        emit processPending();
+    emit processPending();
 }
 
 void
 EventStore::clearTimeline()
 {
-        emit beginResetModel();
-
-        cache::client()->clearTimeline(room_id_);
-        auto range = cache::client()->getTimelineRange(room_id_);
-        if (range) {
-                nhlog::db()->info("Range {} {}", range->last, range->first);
-                this->last  = range->last;
-                this->first = range->first;
-        } else {
-                this->first = std::numeric_limits<uint64_t>::max();
-                this->last  = std::numeric_limits<uint64_t>::max();
-        }
-        nhlog::ui()->info("Range {} {}", this->last, this->first);
-
-        decryptedEvents_.clear();
-        events_.clear();
-
-        emit endResetModel();
+    emit beginResetModel();
+
+    cache::client()->clearTimeline(room_id_);
+    auto range = cache::client()->getTimelineRange(room_id_);
+    if (range) {
+        nhlog::db()->info("Range {} {}", range->last, range->first);
+        this->last  = range->last;
+        this->first = range->first;
+    } else {
+        this->first = std::numeric_limits<uint64_t>::max();
+        this->last  = std::numeric_limits<uint64_t>::max();
+    }
+    nhlog::ui()->info("Range {} {}", this->last, this->first);
+
+    decryptedEvents_.clear();
+    events_.clear();
+
+    emit endResetModel();
 }
 
 void
 EventStore::receivedSessionKey(const std::string &session_id)
 {
-        if (!pending_key_requests.count(session_id))
-                return;
+    if (!pending_key_requests.count(session_id))
+        return;
 
-        auto request = pending_key_requests.at(session_id);
+    auto request = pending_key_requests.at(session_id);
 
-        // Don't request keys again until Nheko is restarted (for now)
-        pending_key_requests[session_id].events.clear();
+    // Don't request keys again until Nheko is restarted (for now)
+    pending_key_requests[session_id].events.clear();
 
-        if (!request.events.empty())
-                olm::send_key_request_for(request.events.front(), request.request_id, true);
+    if (!request.events.empty())
+        olm::send_key_request_for(request.events.front(), request.request_id, true);
 
-        for (const auto &e : request.events) {
-                auto idx = idToIndex(e.event_id);
-                if (idx) {
-                        decryptedEvents_.remove({room_id_, e.event_id});
-                        events_by_id_.remove({room_id_, e.event_id});
-                        events_.remove({room_id_, toInternalIdx(*idx)});
-                        emit dataChanged(*idx, *idx);
-                }
+    for (const auto &e : request.events) {
+        auto idx = idToIndex(e.event_id);
+        if (idx) {
+            decryptedEvents_.remove({room_id_, e.event_id});
+            events_by_id_.remove({room_id_, e.event_id});
+            events_.remove({room_id_, toInternalIdx(*idx)});
+            emit dataChanged(*idx, *idx);
         }
+    }
 }
 
 void
 EventStore::handleSync(const mtx::responses::Timeline &events)
 {
-        if (this->thread() != QThread::currentThread())
-                nhlog::db()->warn("{} called from a different thread!", __func__);
-
-        auto range = cache::client()->getTimelineRange(room_id_);
-        if (!range) {
-                emit beginResetModel();
-                this->first = std::numeric_limits<uint64_t>::max();
-                this->last  = std::numeric_limits<uint64_t>::max();
-
-                decryptedEvents_.clear();
-                events_.clear();
-                emit endResetModel();
-                return;
-        }
+    if (this->thread() != QThread::currentThread())
+        nhlog::db()->warn("{} called from a different thread!", __func__);
 
-        if (events.limited) {
-                emit beginResetModel();
-                this->last  = range->last;
-                this->first = range->first;
-
-                decryptedEvents_.clear();
-                events_.clear();
-                emit endResetModel();
-        } else if (range->last > this->last) {
-                emit beginInsertRows(toExternalIdx(this->last + 1), toExternalIdx(range->last));
-                this->last = range->last;
-                emit endInsertRows();
-        }
+    auto range = cache::client()->getTimelineRange(room_id_);
+    if (!range) {
+        emit beginResetModel();
+        this->first = std::numeric_limits<uint64_t>::max();
+        this->last  = std::numeric_limits<uint64_t>::max();
 
-        for (const auto &event : events.events) {
-                std::set<std::string> relates_to;
-                if (auto redaction =
-                      std::get_if<mtx::events::RedactionEvent<mtx::events::msg::Redaction>>(
-                        &event)) {
-                        // fixup reactions
-                        auto redacted = events_by_id_.object({room_id_, redaction->redacts});
-                        if (redacted) {
-                                auto id = mtx::accessors::relations(*redacted);
-                                if (id.annotates()) {
-                                        auto idx = idToIndex(id.annotates()->event_id);
-                                        if (idx) {
-                                                events_by_id_.remove(
-                                                  {room_id_, redaction->redacts});
-                                                events_.remove({room_id_, toInternalIdx(*idx)});
-                                                emit dataChanged(*idx, *idx);
-                                        }
-                                }
-                        }
+        decryptedEvents_.clear();
+        events_.clear();
+        emit endResetModel();
+        return;
+    }
 
-                        relates_to.insert(redaction->redacts);
-                } else {
-                        for (const auto &r : mtx::accessors::relations(event).relations)
-                                relates_to.insert(r.event_id);
-                }
+    if (events.limited) {
+        emit beginResetModel();
+        this->last  = range->last;
+        this->first = range->first;
 
-                for (const auto &relates_to_id : relates_to) {
-                        auto idx = cache::client()->getTimelineIndex(room_id_, relates_to_id);
-                        if (idx) {
-                                events_by_id_.remove({room_id_, relates_to_id});
-                                decryptedEvents_.remove({room_id_, relates_to_id});
-                                events_.remove({room_id_, *idx});
-                                emit dataChanged(toExternalIdx(*idx), toExternalIdx(*idx));
-                        }
+        decryptedEvents_.clear();
+        events_.clear();
+        emit endResetModel();
+    } else if (range->last > this->last) {
+        emit beginInsertRows(toExternalIdx(this->last + 1), toExternalIdx(range->last));
+        this->last = range->last;
+        emit endInsertRows();
+    }
+
+    for (const auto &event : events.events) {
+        std::set<std::string> relates_to;
+        if (auto redaction =
+              std::get_if<mtx::events::RedactionEvent<mtx::events::msg::Redaction>>(&event)) {
+            // fixup reactions
+            auto redacted = events_by_id_.object({room_id_, redaction->redacts});
+            if (redacted) {
+                auto id = mtx::accessors::relations(*redacted);
+                if (id.annotates()) {
+                    auto idx = idToIndex(id.annotates()->event_id);
+                    if (idx) {
+                        events_by_id_.remove({room_id_, redaction->redacts});
+                        events_.remove({room_id_, toInternalIdx(*idx)});
+                        emit dataChanged(*idx, *idx);
+                    }
                 }
+            }
 
-                if (auto txn_id = mtx::accessors::transaction_id(event); !txn_id.empty()) {
-                        auto idx = cache::client()->getTimelineIndex(
-                          room_id_, mtx::accessors::event_id(event));
-                        if (idx) {
-                                Index index{room_id_, *idx};
-                                events_.remove(index);
-                                emit dataChanged(toExternalIdx(*idx), toExternalIdx(*idx));
-                        }
-                }
+            relates_to.insert(redaction->redacts);
+        } else {
+            for (const auto &r : mtx::accessors::relations(event).relations)
+                relates_to.insert(r.event_id);
+        }
 
-                // decrypting and checking some encrypted messages
-                if (auto encrypted =
-                      std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(
-                        &event)) {
-                        auto d_event = decryptEvent({room_id_, encrypted->event_id}, *encrypted);
-                        if (d_event->event &&
-                            std::visit(
-                              [](auto e) { return (e.sender != utils::localUser().toStdString()); },
-                              *d_event->event)) {
-                                handle_room_verification(*d_event->event);
-                        }
-                }
+        for (const auto &relates_to_id : relates_to) {
+            auto idx = cache::client()->getTimelineIndex(room_id_, relates_to_id);
+            if (idx) {
+                events_by_id_.remove({room_id_, relates_to_id});
+                decryptedEvents_.remove({room_id_, relates_to_id});
+                events_.remove({room_id_, *idx});
+                emit dataChanged(toExternalIdx(*idx), toExternalIdx(*idx));
+            }
+        }
+
+        if (auto txn_id = mtx::accessors::transaction_id(event); !txn_id.empty()) {
+            auto idx = cache::client()->getTimelineIndex(room_id_, mtx::accessors::event_id(event));
+            if (idx) {
+                Index index{room_id_, *idx};
+                events_.remove(index);
+                emit dataChanged(toExternalIdx(*idx), toExternalIdx(*idx));
+            }
         }
+
+        // decrypting and checking some encrypted messages
+        if (auto encrypted =
+              std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(&event)) {
+            auto d_event = decryptEvent({room_id_, encrypted->event_id}, *encrypted);
+            if (d_event->event &&
+                std::visit([](auto e) { return (e.sender != utils::localUser().toStdString()); },
+                           *d_event->event)) {
+                handle_room_verification(*d_event->event);
+            }
+        }
+    }
 }
 
 namespace {
 template<class... Ts>
 struct overloaded : Ts...
 {
-        using Ts::operator()...;
+    using Ts::operator()...;
 };
 template<class... Ts>
 overloaded(Ts...) -> overloaded<Ts...>;
@@ -423,462 +403,451 @@ overloaded(Ts...) -> overloaded<Ts...>;
 void
 EventStore::handle_room_verification(mtx::events::collections::TimelineEvents event)
 {
-        std::visit(
-          overloaded{
-            [this](const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest> &msg) {
-                    nhlog::db()->debug("handle_room_verification: Request");
-                    emit startDMVerification(msg);
-            },
-            [](const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationCancel> &msg) {
-                    nhlog::db()->debug("handle_room_verification: Cancel");
-                    ChatPage::instance()->receivedDeviceVerificationCancel(msg.content);
-            },
-            [](const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationAccept> &msg) {
-                    nhlog::db()->debug("handle_room_verification: Accept");
-                    ChatPage::instance()->receivedDeviceVerificationAccept(msg.content);
-            },
-            [](const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationKey> &msg) {
-                    nhlog::db()->debug("handle_room_verification: Key");
-                    ChatPage::instance()->receivedDeviceVerificationKey(msg.content);
-            },
-            [](const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationMac> &msg) {
-                    nhlog::db()->debug("handle_room_verification: Mac");
-                    ChatPage::instance()->receivedDeviceVerificationMac(msg.content);
-            },
-            [](const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationReady> &msg) {
-                    nhlog::db()->debug("handle_room_verification: Ready");
-                    ChatPage::instance()->receivedDeviceVerificationReady(msg.content);
-            },
-            [](const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationDone> &msg) {
-                    nhlog::db()->debug("handle_room_verification: Done");
-                    ChatPage::instance()->receivedDeviceVerificationDone(msg.content);
-            },
-            [](const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationStart> &msg) {
-                    nhlog::db()->debug("handle_room_verification: Start");
-                    ChatPage::instance()->receivedDeviceVerificationStart(msg.content, msg.sender);
-            },
-            [](const auto &) {},
-          },
-          event);
+    std::visit(
+      overloaded{
+        [this](const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest> &msg) {
+            nhlog::db()->debug("handle_room_verification: Request");
+            emit startDMVerification(msg);
+        },
+        [](const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationCancel> &msg) {
+            nhlog::db()->debug("handle_room_verification: Cancel");
+            ChatPage::instance()->receivedDeviceVerificationCancel(msg.content);
+        },
+        [](const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationAccept> &msg) {
+            nhlog::db()->debug("handle_room_verification: Accept");
+            ChatPage::instance()->receivedDeviceVerificationAccept(msg.content);
+        },
+        [](const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationKey> &msg) {
+            nhlog::db()->debug("handle_room_verification: Key");
+            ChatPage::instance()->receivedDeviceVerificationKey(msg.content);
+        },
+        [](const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationMac> &msg) {
+            nhlog::db()->debug("handle_room_verification: Mac");
+            ChatPage::instance()->receivedDeviceVerificationMac(msg.content);
+        },
+        [](const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationReady> &msg) {
+            nhlog::db()->debug("handle_room_verification: Ready");
+            ChatPage::instance()->receivedDeviceVerificationReady(msg.content);
+        },
+        [](const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationDone> &msg) {
+            nhlog::db()->debug("handle_room_verification: Done");
+            ChatPage::instance()->receivedDeviceVerificationDone(msg.content);
+        },
+        [](const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationStart> &msg) {
+            nhlog::db()->debug("handle_room_verification: Start");
+            ChatPage::instance()->receivedDeviceVerificationStart(msg.content, msg.sender);
+        },
+        [](const auto &) {},
+      },
+      event);
 }
 
 std::vector<mtx::events::collections::TimelineEvents>
 EventStore::edits(const std::string &event_id)
 {
-        auto event_ids = cache::client()->relatedEvents(room_id_, event_id);
-
-        auto original_event = get(event_id, "", false, false);
-        if (!original_event)
-                return {};
-
-        auto original_sender    = mtx::accessors::sender(*original_event);
-        auto original_relations = mtx::accessors::relations(*original_event);
-
-        std::vector<mtx::events::collections::TimelineEvents> edits;
-        for (const auto &id : event_ids) {
-                auto related_event = get(id, event_id, false, false);
-                if (!related_event)
-                        continue;
-
-                auto related_ev = *related_event;
-
-                auto edit_rel = mtx::accessors::relations(related_ev);
-                if (edit_rel.replaces() == event_id &&
-                    original_sender == mtx::accessors::sender(related_ev)) {
-                        if (edit_rel.synthesized && original_relations.reply_to() &&
-                            !edit_rel.reply_to()) {
-                                edit_rel.relations.push_back(
-                                  {mtx::common::RelationType::InReplyTo,
-                                   original_relations.reply_to().value()});
-                                mtx::accessors::set_relations(related_ev, std::move(edit_rel));
-                        }
-                        edits.push_back(std::move(related_ev));
-                }
+    auto event_ids = cache::client()->relatedEvents(room_id_, event_id);
+
+    auto original_event = get(event_id, "", false, false);
+    if (!original_event)
+        return {};
+
+    auto original_sender    = mtx::accessors::sender(*original_event);
+    auto original_relations = mtx::accessors::relations(*original_event);
+
+    std::vector<mtx::events::collections::TimelineEvents> edits;
+    for (const auto &id : event_ids) {
+        auto related_event = get(id, event_id, false, false);
+        if (!related_event)
+            continue;
+
+        auto related_ev = *related_event;
+
+        auto edit_rel = mtx::accessors::relations(related_ev);
+        if (edit_rel.replaces() == event_id &&
+            original_sender == mtx::accessors::sender(related_ev)) {
+            if (edit_rel.synthesized && original_relations.reply_to() && !edit_rel.reply_to()) {
+                edit_rel.relations.push_back(
+                  {mtx::common::RelationType::InReplyTo, original_relations.reply_to().value()});
+                mtx::accessors::set_relations(related_ev, std::move(edit_rel));
+            }
+            edits.push_back(std::move(related_ev));
         }
-
-        auto c = cache::client();
-        std::sort(edits.begin(),
-                  edits.end(),
-                  [this, c](const mtx::events::collections::TimelineEvents &a,
-                            const mtx::events::collections::TimelineEvents &b) {
-                          return c->getArrivalIndex(this->room_id_, mtx::accessors::event_id(a)) <
-                                 c->getArrivalIndex(this->room_id_, mtx::accessors::event_id(b));
-                  });
-
-        return edits;
+    }
+
+    auto c = cache::client();
+    std::sort(edits.begin(),
+              edits.end(),
+              [this, c](const mtx::events::collections::TimelineEvents &a,
+                        const mtx::events::collections::TimelineEvents &b) {
+                  return c->getArrivalIndex(this->room_id_, mtx::accessors::event_id(a)) <
+                         c->getArrivalIndex(this->room_id_, mtx::accessors::event_id(b));
+              });
+
+    return edits;
 }
 
 QVariantList
 EventStore::reactions(const std::string &event_id)
 {
-        auto event_ids = cache::client()->relatedEvents(room_id_, event_id);
-
-        struct TempReaction
-        {
-                int count = 0;
-                std::vector<std::string> users;
-                std::string reactedBySelf;
-        };
-        std::map<std::string, TempReaction> aggregation;
-        std::vector<Reaction> reactions;
-
-        auto self = http::client()->user_id().to_string();
-        for (const auto &id : event_ids) {
-                auto related_event = get(id, event_id);
-                if (!related_event)
-                        continue;
-
-                if (auto reaction = std::get_if<mtx::events::RoomEvent<mtx::events::msg::Reaction>>(
-                      related_event);
-                    reaction && reaction->content.relations.annotates() &&
-                    reaction->content.relations.annotates()->key) {
-                        auto key  = reaction->content.relations.annotates()->key.value();
-                        auto &agg = aggregation[key];
-
-                        if (agg.count == 0) {
-                                Reaction temp{};
-                                temp.key_ = QString::fromStdString(key);
-                                reactions.push_back(temp);
-                        }
-
-                        agg.count++;
-                        agg.users.push_back(cache::displayName(room_id_, reaction->sender));
-                        if (reaction->sender == self)
-                                agg.reactedBySelf = reaction->event_id;
-                }
+    auto event_ids = cache::client()->relatedEvents(room_id_, event_id);
+
+    struct TempReaction
+    {
+        int count = 0;
+        std::vector<std::string> users;
+        std::string reactedBySelf;
+    };
+    std::map<std::string, TempReaction> aggregation;
+    std::vector<Reaction> reactions;
+
+    auto self = http::client()->user_id().to_string();
+    for (const auto &id : event_ids) {
+        auto related_event = get(id, event_id);
+        if (!related_event)
+            continue;
+
+        if (auto reaction =
+              std::get_if<mtx::events::RoomEvent<mtx::events::msg::Reaction>>(related_event);
+            reaction && reaction->content.relations.annotates() &&
+            reaction->content.relations.annotates()->key) {
+            auto key  = reaction->content.relations.annotates()->key.value();
+            auto &agg = aggregation[key];
+
+            if (agg.count == 0) {
+                Reaction temp{};
+                temp.key_ = QString::fromStdString(key);
+                reactions.push_back(temp);
+            }
+
+            agg.count++;
+            agg.users.push_back(cache::displayName(room_id_, reaction->sender));
+            if (reaction->sender == self)
+                agg.reactedBySelf = reaction->event_id;
         }
-
-        QVariantList temp;
-        for (auto &reaction : reactions) {
-                const auto &agg            = aggregation[reaction.key_.toStdString()];
-                reaction.count_            = agg.count;
-                reaction.selfReactedEvent_ = QString::fromStdString(agg.reactedBySelf);
-
-                bool firstReaction = true;
-                for (const auto &user : agg.users) {
-                        if (firstReaction)
-                                firstReaction = false;
-                        else
-                                reaction.users_ += ", ";
-
-                        reaction.users_ += QString::fromStdString(user);
-                }
-
-                nhlog::db()->debug("key: {}, count: {}, users: {}",
-                                   reaction.key_.toStdString(),
-                                   reaction.count_,
-                                   reaction.users_.toStdString());
-                temp.append(QVariant::fromValue(reaction));
+    }
+
+    QVariantList temp;
+    for (auto &reaction : reactions) {
+        const auto &agg            = aggregation[reaction.key_.toStdString()];
+        reaction.count_            = agg.count;
+        reaction.selfReactedEvent_ = QString::fromStdString(agg.reactedBySelf);
+
+        bool firstReaction = true;
+        for (const auto &user : agg.users) {
+            if (firstReaction)
+                firstReaction = false;
+            else
+                reaction.users_ += ", ";
+
+            reaction.users_ += QString::fromStdString(user);
         }
 
-        return temp;
+        nhlog::db()->debug("key: {}, count: {}, users: {}",
+                           reaction.key_.toStdString(),
+                           reaction.count_,
+                           reaction.users_.toStdString());
+        temp.append(QVariant::fromValue(reaction));
+    }
+
+    return temp;
 }
 
 mtx::events::collections::TimelineEvents *
 EventStore::get(int idx, bool decrypt)
 {
-        if (this->thread() != QThread::currentThread())
-                nhlog::db()->warn("{} called from a different thread!", __func__);
-
-        Index index{room_id_, toInternalIdx(idx)};
-        if (index.idx > last || index.idx < first)
-                return nullptr;
-
-        auto event_ptr = events_.object(index);
-        if (!event_ptr) {
-                auto event_id = cache::client()->getTimelineEventId(room_id_, index.idx);
-                if (!event_id)
-                        return nullptr;
-
-                std::optional<mtx::events::collections::TimelineEvent> event;
-                auto edits_ = edits(*event_id);
-                if (edits_.empty())
-                        event = cache::client()->getEvent(room_id_, *event_id);
-                else
-                        event = {edits_.back()};
-
-                if (!event)
-                        return nullptr;
-                else
-                        event_ptr =
-                          new mtx::events::collections::TimelineEvents(std::move(event->data));
-                events_.insert(index, event_ptr);
-        }
+    if (this->thread() != QThread::currentThread())
+        nhlog::db()->warn("{} called from a different thread!", __func__);
+
+    Index index{room_id_, toInternalIdx(idx)};
+    if (index.idx > last || index.idx < first)
+        return nullptr;
+
+    auto event_ptr = events_.object(index);
+    if (!event_ptr) {
+        auto event_id = cache::client()->getTimelineEventId(room_id_, index.idx);
+        if (!event_id)
+            return nullptr;
+
+        std::optional<mtx::events::collections::TimelineEvent> event;
+        auto edits_ = edits(*event_id);
+        if (edits_.empty())
+            event = cache::client()->getEvent(room_id_, *event_id);
+        else
+            event = {edits_.back()};
 
-        if (decrypt) {
-                if (auto encrypted =
-                      std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(
-                        event_ptr)) {
-                        auto decrypted = decryptEvent({room_id_, encrypted->event_id}, *encrypted);
-                        if (decrypted->event)
-                                return &*decrypted->event;
-                }
+        if (!event)
+            return nullptr;
+        else
+            event_ptr = new mtx::events::collections::TimelineEvents(std::move(event->data));
+        events_.insert(index, event_ptr);
+    }
+
+    if (decrypt) {
+        if (auto encrypted =
+              std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(event_ptr)) {
+            auto decrypted = decryptEvent({room_id_, encrypted->event_id}, *encrypted);
+            if (decrypted->event)
+                return &*decrypted->event;
         }
+    }
 
-        return event_ptr;
+    return event_ptr;
 }
 
 std::optional<int>
 EventStore::idToIndex(std::string_view id) const
 {
-        if (this->thread() != QThread::currentThread())
-                nhlog::db()->warn("{} called from a different thread!", __func__);
-
-        auto idx = cache::client()->getTimelineIndex(room_id_, id);
-        if (idx)
-                return toExternalIdx(*idx);
-        else
-                return std::nullopt;
+    if (this->thread() != QThread::currentThread())
+        nhlog::db()->warn("{} called from a different thread!", __func__);
+
+    auto idx = cache::client()->getTimelineIndex(room_id_, id);
+    if (idx)
+        return toExternalIdx(*idx);
+    else
+        return std::nullopt;
 }
 std::optional<std::string>
 EventStore::indexToId(int idx) const
 {
-        if (this->thread() != QThread::currentThread())
-                nhlog::db()->warn("{} called from a different thread!", __func__);
+    if (this->thread() != QThread::currentThread())
+        nhlog::db()->warn("{} called from a different thread!", __func__);
 
-        return cache::client()->getTimelineEventId(room_id_, toInternalIdx(idx));
+    return cache::client()->getTimelineEventId(room_id_, toInternalIdx(idx));
 }
 
 olm::DecryptionResult *
 EventStore::decryptEvent(const IdIndex &idx,
                          const mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> &e)
 {
-        if (auto cachedEvent = decryptedEvents_.object(idx))
-                return cachedEvent;
-
-        MegolmSessionIndex index(room_id_, e.content);
-
-        auto asCacheEntry = [&idx](olm::DecryptionResult &&event) {
-                auto event_ptr = new olm::DecryptionResult(std::move(event));
-                decryptedEvents_.insert(idx, event_ptr);
-                return event_ptr;
-        };
-
-        auto decryptionResult = olm::decryptEvent(index, e);
-
-        if (decryptionResult.error) {
-                switch (decryptionResult.error) {
-                case olm::DecryptionErrorCode::MissingSession:
-                case olm::DecryptionErrorCode::MissingSessionIndex: {
-                        nhlog::crypto()->info("Could not find inbound megolm session ({}, {}, {})",
-                                              index.room_id,
-                                              index.session_id,
-                                              e.sender);
-
-                        requestSession(e, false);
-                        break;
-                }
-                case olm::DecryptionErrorCode::DbError:
-                        nhlog::db()->critical(
-                          "failed to retrieve megolm session with index ({}, {}, {})",
-                          index.room_id,
-                          index.session_id,
-                          index.sender_key,
-                          decryptionResult.error_message.value_or(""));
-                        break;
-                case olm::DecryptionErrorCode::DecryptionFailed:
-                        nhlog::crypto()->critical(
-                          "failed to decrypt message with index ({}, {}, {}): {}",
-                          index.room_id,
-                          index.session_id,
-                          index.sender_key,
-                          decryptionResult.error_message.value_or(""));
-                        break;
-                case olm::DecryptionErrorCode::ParsingFailed:
-                        break;
-                case olm::DecryptionErrorCode::ReplayAttack:
-                        nhlog::crypto()->critical(
-                          "Reply attack while decryptiong event {} in room {} from {}!",
-                          e.event_id,
-                          room_id_,
-                          index.sender_key);
-                        break;
-                case olm::DecryptionErrorCode::NoError:
-                        // unreachable
-                        break;
-                }
-                return asCacheEntry(std::move(decryptionResult));
-        }
+    if (auto cachedEvent = decryptedEvents_.object(idx))
+        return cachedEvent;
+
+    MegolmSessionIndex index(room_id_, e.content);
+
+    auto asCacheEntry = [&idx](olm::DecryptionResult &&event) {
+        auto event_ptr = new olm::DecryptionResult(std::move(event));
+        decryptedEvents_.insert(idx, event_ptr);
+        return event_ptr;
+    };
 
-        auto encInfo = mtx::accessors::file(decryptionResult.event.value());
-        if (encInfo)
-                emit newEncryptedImage(encInfo.value());
+    auto decryptionResult = olm::decryptEvent(index, e);
 
+    if (decryptionResult.error) {
+        switch (decryptionResult.error) {
+        case olm::DecryptionErrorCode::MissingSession:
+        case olm::DecryptionErrorCode::MissingSessionIndex: {
+            nhlog::crypto()->info("Could not find inbound megolm session ({}, {}, {})",
+                                  index.room_id,
+                                  index.session_id,
+                                  e.sender);
+
+            requestSession(e, false);
+            break;
+        }
+        case olm::DecryptionErrorCode::DbError:
+            nhlog::db()->critical("failed to retrieve megolm session with index ({}, {}, {})",
+                                  index.room_id,
+                                  index.session_id,
+                                  index.sender_key,
+                                  decryptionResult.error_message.value_or(""));
+            break;
+        case olm::DecryptionErrorCode::DecryptionFailed:
+            nhlog::crypto()->critical("failed to decrypt message with index ({}, {}, {}): {}",
+                                      index.room_id,
+                                      index.session_id,
+                                      index.sender_key,
+                                      decryptionResult.error_message.value_or(""));
+            break;
+        case olm::DecryptionErrorCode::ParsingFailed:
+            break;
+        case olm::DecryptionErrorCode::ReplayAttack:
+            nhlog::crypto()->critical("Reply attack while decryptiong event {} in room {} from {}!",
+                                      e.event_id,
+                                      room_id_,
+                                      index.sender_key);
+            break;
+        case olm::DecryptionErrorCode::NoError:
+            // unreachable
+            break;
+        }
         return asCacheEntry(std::move(decryptionResult));
+    }
+
+    auto encInfo = mtx::accessors::file(decryptionResult.event.value());
+    if (encInfo)
+        emit newEncryptedImage(encInfo.value());
+
+    return asCacheEntry(std::move(decryptionResult));
 }
 
 void
 EventStore::requestSession(const mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> &ev,
                            bool manual)
 {
-        // we may not want to request keys during initial sync and such
-        if (suppressKeyRequests)
-                return;
-
-        // TODO: Look in key backup
-        auto copy    = ev;
-        copy.room_id = room_id_;
-        if (pending_key_requests.count(ev.content.session_id)) {
-                auto &r = pending_key_requests.at(ev.content.session_id);
-                r.events.push_back(copy);
-
-                // automatically request once every 10 min, manually every 1 min
-                qint64 delay = manual ? 60 : (60 * 10);
-                if (r.requested_at + delay < QDateTime::currentSecsSinceEpoch()) {
-                        r.requested_at = QDateTime::currentSecsSinceEpoch();
-                        olm::lookup_keybackup(room_id_, ev.content.session_id);
-                        olm::send_key_request_for(copy, r.request_id);
-                }
-        } else {
-                PendingKeyRequests request;
-                request.request_id   = "key_request." + http::client()->generate_txn_id();
-                request.requested_at = QDateTime::currentSecsSinceEpoch();
-                request.events.push_back(copy);
-                olm::lookup_keybackup(room_id_, ev.content.session_id);
-                olm::send_key_request_for(copy, request.request_id);
-                pending_key_requests[ev.content.session_id] = request;
+    // we may not want to request keys during initial sync and such
+    if (suppressKeyRequests)
+        return;
+
+    // TODO: Look in key backup
+    auto copy    = ev;
+    copy.room_id = room_id_;
+    if (pending_key_requests.count(ev.content.session_id)) {
+        auto &r = pending_key_requests.at(ev.content.session_id);
+        r.events.push_back(copy);
+
+        // automatically request once every 10 min, manually every 1 min
+        qint64 delay = manual ? 60 : (60 * 10);
+        if (r.requested_at + delay < QDateTime::currentSecsSinceEpoch()) {
+            r.requested_at = QDateTime::currentSecsSinceEpoch();
+            olm::lookup_keybackup(room_id_, ev.content.session_id);
+            olm::send_key_request_for(copy, r.request_id);
         }
+    } else {
+        PendingKeyRequests request;
+        request.request_id   = "key_request." + http::client()->generate_txn_id();
+        request.requested_at = QDateTime::currentSecsSinceEpoch();
+        request.events.push_back(copy);
+        olm::lookup_keybackup(room_id_, ev.content.session_id);
+        olm::send_key_request_for(copy, request.request_id);
+        pending_key_requests[ev.content.session_id] = request;
+    }
 }
 
 void
 EventStore::enableKeyRequests(bool suppressKeyRequests_)
 {
-        if (!suppressKeyRequests_) {
-                for (const auto &key : decryptedEvents_.keys())
-                        if (key.room == this->room_id_)
-                                decryptedEvents_.remove(key);
-                suppressKeyRequests = false;
-        } else
-                suppressKeyRequests = true;
+    if (!suppressKeyRequests_) {
+        for (const auto &key : decryptedEvents_.keys())
+            if (key.room == this->room_id_)
+                decryptedEvents_.remove(key);
+        suppressKeyRequests = false;
+    } else
+        suppressKeyRequests = true;
 }
 
 mtx::events::collections::TimelineEvents *
 EventStore::get(std::string id, std::string_view related_to, bool decrypt, bool resolve_edits)
 {
-        if (this->thread() != QThread::currentThread())
-                nhlog::db()->warn("{} called from a different thread!", __func__);
-
-        if (id.empty())
-                return nullptr;
-
-        IdIndex index{room_id_, std::move(id)};
-        if (resolve_edits) {
-                auto edits_ = edits(index.id);
-                if (!edits_.empty()) {
-                        index.id = mtx::accessors::event_id(edits_.back());
-                        auto event_ptr =
-                          new mtx::events::collections::TimelineEvents(std::move(edits_.back()));
-                        events_by_id_.insert(index, event_ptr);
-                }
-        }
+    if (this->thread() != QThread::currentThread())
+        nhlog::db()->warn("{} called from a different thread!", __func__);
 
-        auto event_ptr = events_by_id_.object(index);
-        if (!event_ptr) {
-                auto event = cache::client()->getEvent(room_id_, index.id);
-                if (!event) {
-                        http::client()->get_event(
-                          room_id_,
-                          index.id,
-                          [this, relatedTo = std::string(related_to), id = index.id](
-                            const mtx::events::collections::TimelineEvents &timeline,
-                            mtx::http::RequestErr err) {
-                                  if (err) {
-                                          nhlog::net()->error(
-                                            "Failed to retrieve event with id {}, which was "
-                                            "requested to show the replyTo for event {}",
-                                            relatedTo,
-                                            id);
-                                          return;
-                                  }
-                                  emit eventFetched(id, relatedTo, timeline);
-                          });
-                        return nullptr;
-                }
-                event_ptr = new mtx::events::collections::TimelineEvents(std::move(event->data));
-                events_by_id_.insert(index, event_ptr);
+    if (id.empty())
+        return nullptr;
+
+    IdIndex index{room_id_, std::move(id)};
+    if (resolve_edits) {
+        auto edits_ = edits(index.id);
+        if (!edits_.empty()) {
+            index.id       = mtx::accessors::event_id(edits_.back());
+            auto event_ptr = new mtx::events::collections::TimelineEvents(std::move(edits_.back()));
+            events_by_id_.insert(index, event_ptr);
         }
+    }
+
+    auto event_ptr = events_by_id_.object(index);
+    if (!event_ptr) {
+        auto event = cache::client()->getEvent(room_id_, index.id);
+        if (!event) {
+            http::client()->get_event(room_id_,
+                                      index.id,
+                                      [this, relatedTo = std::string(related_to), id = index.id](
+                                        const mtx::events::collections::TimelineEvents &timeline,
+                                        mtx::http::RequestErr err) {
+                                          if (err) {
+                                              nhlog::net()->error(
+                                                "Failed to retrieve event with id {}, which was "
+                                                "requested to show the replyTo for event {}",
+                                                relatedTo,
+                                                id);
+                                              return;
+                                          }
+                                          emit eventFetched(id, relatedTo, timeline);
+                                      });
+            return nullptr;
+        }
+        event_ptr = new mtx::events::collections::TimelineEvents(std::move(event->data));
+        events_by_id_.insert(index, event_ptr);
+    }
 
-        if (decrypt) {
-                if (auto encrypted =
-                      std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(
-                        event_ptr)) {
-                        auto decrypted = decryptEvent(index, *encrypted);
-                        if (decrypted->event)
-                                return &*decrypted->event;
-                }
+    if (decrypt) {
+        if (auto encrypted =
+              std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(event_ptr)) {
+            auto decrypted = decryptEvent(index, *encrypted);
+            if (decrypted->event)
+                return &*decrypted->event;
         }
+    }
 
-        return event_ptr;
+    return event_ptr;
 }
 
 olm::DecryptionErrorCode
 EventStore::decryptionError(std::string id)
 {
-        if (this->thread() != QThread::currentThread())
-                nhlog::db()->warn("{} called from a different thread!", __func__);
+    if (this->thread() != QThread::currentThread())
+        nhlog::db()->warn("{} called from a different thread!", __func__);
 
-        if (id.empty())
-                return olm::DecryptionErrorCode::NoError;
-
-        IdIndex index{room_id_, std::move(id)};
-        auto edits_ = edits(index.id);
-        if (!edits_.empty()) {
-                index.id = mtx::accessors::event_id(edits_.back());
-                auto event_ptr =
-                  new mtx::events::collections::TimelineEvents(std::move(edits_.back()));
-                events_by_id_.insert(index, event_ptr);
-        }
+    if (id.empty())
+        return olm::DecryptionErrorCode::NoError;
 
-        auto event_ptr = events_by_id_.object(index);
-        if (!event_ptr) {
-                auto event = cache::client()->getEvent(room_id_, index.id);
-                if (!event) {
-                        return olm::DecryptionErrorCode::NoError;
-                }
-                event_ptr = new mtx::events::collections::TimelineEvents(std::move(event->data));
-                events_by_id_.insert(index, event_ptr);
+    IdIndex index{room_id_, std::move(id)};
+    auto edits_ = edits(index.id);
+    if (!edits_.empty()) {
+        index.id       = mtx::accessors::event_id(edits_.back());
+        auto event_ptr = new mtx::events::collections::TimelineEvents(std::move(edits_.back()));
+        events_by_id_.insert(index, event_ptr);
+    }
+
+    auto event_ptr = events_by_id_.object(index);
+    if (!event_ptr) {
+        auto event = cache::client()->getEvent(room_id_, index.id);
+        if (!event) {
+            return olm::DecryptionErrorCode::NoError;
         }
+        event_ptr = new mtx::events::collections::TimelineEvents(std::move(event->data));
+        events_by_id_.insert(index, event_ptr);
+    }
 
-        if (auto encrypted =
-              std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(event_ptr)) {
-                auto decrypted = decryptEvent(index, *encrypted);
-                return decrypted->error;
-        }
+    if (auto encrypted =
+          std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(event_ptr)) {
+        auto decrypted = decryptEvent(index, *encrypted);
+        return decrypted->error;
+    }
 
-        return olm::DecryptionErrorCode::NoError;
+    return olm::DecryptionErrorCode::NoError;
 }
 
 void
 EventStore::fetchMore()
 {
-        if (noMoreMessages)
-                return;
-
-        mtx::http::MessagesOpts opts;
-        opts.room_id = room_id_;
-        opts.from    = cache::client()->previousBatchToken(room_id_);
-
-        nhlog::ui()->debug("Paginating room {}, token {}", opts.room_id, opts.from);
-
-        http::client()->messages(
-          opts, [this, opts](const mtx::responses::Messages &res, mtx::http::RequestErr err) {
-                  if (cache::client()->previousBatchToken(room_id_) != opts.from) {
-                          nhlog::net()->warn("Cache cleared while fetching more messages, dropping "
-                                             "/messages response");
-                          if (!opts.to.empty())
-                                  emit fetchedMore();
-                          return;
-                  }
-                  if (err) {
-                          nhlog::net()->error("failed to call /messages ({}): {} - {} - {}",
-                                              opts.room_id,
-                                              mtx::errors::to_string(err->matrix_error.errcode),
-                                              err->matrix_error.error,
-                                              err->parse_error);
-                          emit fetchedMore();
-                          return;
-                  }
-
-                  emit oldMessagesRetrieved(std::move(res));
-          });
+    if (noMoreMessages)
+        return;
+
+    mtx::http::MessagesOpts opts;
+    opts.room_id = room_id_;
+    opts.from    = cache::client()->previousBatchToken(room_id_);
+
+    nhlog::ui()->debug("Paginating room {}, token {}", opts.room_id, opts.from);
+
+    http::client()->messages(
+      opts, [this, opts](const mtx::responses::Messages &res, mtx::http::RequestErr err) {
+          if (cache::client()->previousBatchToken(room_id_) != opts.from) {
+              nhlog::net()->warn("Cache cleared while fetching more messages, dropping "
+                                 "/messages response");
+              if (!opts.to.empty())
+                  emit fetchedMore();
+              return;
+          }
+          if (err) {
+              nhlog::net()->error("failed to call /messages ({}): {} - {} - {}",
+                                  opts.room_id,
+                                  mtx::errors::to_string(err->matrix_error.errcode),
+                                  err->matrix_error.error,
+                                  err->parse_error);
+              emit fetchedMore();
+              return;
+          }
+
+          emit oldMessagesRetrieved(std::move(res));
+      });
 }
diff --git a/src/timeline/EventStore.h b/src/timeline/EventStore.h
index 59c1c7c0..53dbaff4 100644
--- a/src/timeline/EventStore.h
+++ b/src/timeline/EventStore.h
@@ -20,133 +20,131 @@
 
 class EventStore : public QObject
 {
-        Q_OBJECT
+    Q_OBJECT
 
 public:
-        EventStore(std::string room_id, QObject *parent);
-
-        // taken from QtPrivate::QHashCombine
-        static uint hashCombine(uint hash, uint seed)
-        {
-                return seed ^ (hash + 0x9e3779b9 + (seed << 6) + (seed >> 2));
-        };
-        struct Index
+    EventStore(std::string room_id, QObject *parent);
+
+    // taken from QtPrivate::QHashCombine
+    static uint hashCombine(uint hash, uint seed)
+    {
+        return seed ^ (hash + 0x9e3779b9 + (seed << 6) + (seed >> 2));
+    };
+    struct Index
+    {
+        std::string room;
+        uint64_t idx;
+
+        friend uint qHash(const Index &i, uint seed = 0) noexcept
         {
-                std::string room;
-                uint64_t idx;
-
-                friend uint qHash(const Index &i, uint seed = 0) noexcept
-                {
-                        seed =
-                          hashCombine(qHashBits(i.room.data(), (int)i.room.size(), seed), seed);
-                        seed = hashCombine(qHash(i.idx, seed), seed);
-                        return seed;
-                }
-
-                friend bool operator==(const Index &a, const Index &b) noexcept
-                {
-                        return a.idx == b.idx && a.room == b.room;
-                }
-        };
-        struct IdIndex
+            seed = hashCombine(qHashBits(i.room.data(), (int)i.room.size(), seed), seed);
+            seed = hashCombine(qHash(i.idx, seed), seed);
+            return seed;
+        }
+
+        friend bool operator==(const Index &a, const Index &b) noexcept
         {
-                std::string room, id;
-
-                friend uint qHash(const IdIndex &i, uint seed = 0) noexcept
-                {
-                        seed =
-                          hashCombine(qHashBits(i.room.data(), (int)i.room.size(), seed), seed);
-                        seed = hashCombine(qHashBits(i.id.data(), (int)i.id.size(), seed), seed);
-                        return seed;
-                }
-
-                friend bool operator==(const IdIndex &a, const IdIndex &b) noexcept
-                {
-                        return a.id == b.id && a.room == b.room;
-                }
-        };
-
-        void fetchMore();
-        void handleSync(const mtx::responses::Timeline &events);
-
-        // optionally returns the event or nullptr and fetches it, after which it emits a
-        // relatedFetched event
-        mtx::events::collections::TimelineEvents *get(std::string id,
-                                                      std::string_view related_to,
-                                                      bool decrypt       = true,
-                                                      bool resolve_edits = true);
-        // always returns a proper event as long as the idx is valid
-        mtx::events::collections::TimelineEvents *get(int idx, bool decrypt = true);
-
-        QVariantList reactions(const std::string &event_id);
-        olm::DecryptionErrorCode decryptionError(std::string id);
-        void requestSession(const mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> &ev,
-                            bool manual);
-
-        int size() const
+            return a.idx == b.idx && a.room == b.room;
+        }
+    };
+    struct IdIndex
+    {
+        std::string room, id;
+
+        friend uint qHash(const IdIndex &i, uint seed = 0) noexcept
         {
-                return (last != std::numeric_limits<uint64_t>::max() && last >= first)
-                         ? static_cast<int>(last - first) + 1
-                         : 0;
+            seed = hashCombine(qHashBits(i.room.data(), (int)i.room.size(), seed), seed);
+            seed = hashCombine(qHashBits(i.id.data(), (int)i.id.size(), seed), seed);
+            return seed;
         }
-        int toExternalIdx(uint64_t idx) const { return static_cast<int>(idx - first); }
-        uint64_t toInternalIdx(int idx) const { return first + idx; }
 
-        std::optional<int> idToIndex(std::string_view id) const;
-        std::optional<std::string> indexToId(int idx) const;
+        friend bool operator==(const IdIndex &a, const IdIndex &b) noexcept
+        {
+            return a.id == b.id && a.room == b.room;
+        }
+    };
+
+    void fetchMore();
+    void handleSync(const mtx::responses::Timeline &events);
+
+    // optionally returns the event or nullptr and fetches it, after which it emits a
+    // relatedFetched event
+    mtx::events::collections::TimelineEvents *get(std::string id,
+                                                  std::string_view related_to,
+                                                  bool decrypt       = true,
+                                                  bool resolve_edits = true);
+    // always returns a proper event as long as the idx is valid
+    mtx::events::collections::TimelineEvents *get(int idx, bool decrypt = true);
+
+    QVariantList reactions(const std::string &event_id);
+    olm::DecryptionErrorCode decryptionError(std::string id);
+    void requestSession(const mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> &ev,
+                        bool manual);
+
+    int size() const
+    {
+        return (last != std::numeric_limits<uint64_t>::max() && last >= first)
+                 ? static_cast<int>(last - first) + 1
+                 : 0;
+    }
+    int toExternalIdx(uint64_t idx) const { return static_cast<int>(idx - first); }
+    uint64_t toInternalIdx(int idx) const { return first + idx; }
+
+    std::optional<int> idToIndex(std::string_view id) const;
+    std::optional<std::string> indexToId(int idx) const;
 
 signals:
-        void beginInsertRows(int from, int to);
-        void endInsertRows();
-        void beginResetModel();
-        void endResetModel();
-        void dataChanged(int from, int to);
-        void newEncryptedImage(mtx::crypto::EncryptedFile encryptionInfo);
-        void eventFetched(std::string id,
-                          std::string relatedTo,
-                          mtx::events::collections::TimelineEvents timeline);
-        void oldMessagesRetrieved(const mtx::responses::Messages &);
-        void fetchedMore();
-
-        void processPending();
-        void messageSent(std::string txn_id, std::string event_id);
-        void messageFailed(std::string txn_id);
-        void startDMVerification(
-          const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest> &msg);
-        void updateFlowEventId(std::string event_id);
+    void beginInsertRows(int from, int to);
+    void endInsertRows();
+    void beginResetModel();
+    void endResetModel();
+    void dataChanged(int from, int to);
+    void newEncryptedImage(mtx::crypto::EncryptedFile encryptionInfo);
+    void eventFetched(std::string id,
+                      std::string relatedTo,
+                      mtx::events::collections::TimelineEvents timeline);
+    void oldMessagesRetrieved(const mtx::responses::Messages &);
+    void fetchedMore();
+
+    void processPending();
+    void messageSent(std::string txn_id, std::string event_id);
+    void messageFailed(std::string txn_id);
+    void startDMVerification(
+      const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest> &msg);
+    void updateFlowEventId(std::string event_id);
 
 public slots:
-        void addPending(mtx::events::collections::TimelineEvents event);
-        void receivedSessionKey(const std::string &session_id);
-        void clearTimeline();
-        void enableKeyRequests(bool suppressKeyRequests_);
+    void addPending(mtx::events::collections::TimelineEvents event);
+    void receivedSessionKey(const std::string &session_id);
+    void clearTimeline();
+    void enableKeyRequests(bool suppressKeyRequests_);
 
 private:
-        std::vector<mtx::events::collections::TimelineEvents> edits(const std::string &event_id);
-        olm::DecryptionResult *decryptEvent(
-          const IdIndex &idx,
-          const mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> &e);
-        void handle_room_verification(mtx::events::collections::TimelineEvents event);
-
-        std::string room_id_;
-
-        uint64_t first = std::numeric_limits<uint64_t>::max(),
-                 last  = std::numeric_limits<uint64_t>::max();
-
-        static QCache<IdIndex, olm::DecryptionResult> decryptedEvents_;
-        static QCache<Index, mtx::events::collections::TimelineEvents> events_;
-        static QCache<IdIndex, mtx::events::collections::TimelineEvents> events_by_id_;
-
-        struct PendingKeyRequests
-        {
-                std::string request_id;
-                std::vector<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>> events;
-                qint64 requested_at;
-        };
-        std::map<std::string, PendingKeyRequests> pending_key_requests;
-
-        std::string current_txn;
-        int current_txn_error_count = 0;
-        bool noMoreMessages         = false;
-        bool suppressKeyRequests    = true;
+    std::vector<mtx::events::collections::TimelineEvents> edits(const std::string &event_id);
+    olm::DecryptionResult *decryptEvent(
+      const IdIndex &idx,
+      const mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> &e);
+    void handle_room_verification(mtx::events::collections::TimelineEvents event);
+
+    std::string room_id_;
+
+    uint64_t first = std::numeric_limits<uint64_t>::max(),
+             last  = std::numeric_limits<uint64_t>::max();
+
+    static QCache<IdIndex, olm::DecryptionResult> decryptedEvents_;
+    static QCache<Index, mtx::events::collections::TimelineEvents> events_;
+    static QCache<IdIndex, mtx::events::collections::TimelineEvents> events_by_id_;
+
+    struct PendingKeyRequests
+    {
+        std::string request_id;
+        std::vector<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>> events;
+        qint64 requested_at;
+    };
+    std::map<std::string, PendingKeyRequests> pending_key_requests;
+
+    std::string current_txn;
+    int current_txn_error_count = 0;
+    bool noMoreMessages         = false;
+    bool suppressKeyRequests    = true;
 };
diff --git a/src/timeline/InputBar.cpp b/src/timeline/InputBar.cpp
index a6fbab78..f0c38c84 100644
--- a/src/timeline/InputBar.cpp
+++ b/src/timeline/InputBar.cpp
@@ -43,374 +43,370 @@ static constexpr size_t INPUT_HISTORY_SIZE = 10;
 void
 InputBar::paste(bool fromMouse)
 {
-        const QMimeData *md = nullptr;
+    const QMimeData *md = nullptr;
 
-        if (fromMouse) {
-                if (QGuiApplication::clipboard()->supportsSelection()) {
-                        md = QGuiApplication::clipboard()->mimeData(QClipboard::Selection);
-                }
-        } else {
-                md = QGuiApplication::clipboard()->mimeData(QClipboard::Clipboard);
+    if (fromMouse) {
+        if (QGuiApplication::clipboard()->supportsSelection()) {
+            md = QGuiApplication::clipboard()->mimeData(QClipboard::Selection);
         }
+    } else {
+        md = QGuiApplication::clipboard()->mimeData(QClipboard::Clipboard);
+    }
 
-        if (md)
-                insertMimeData(md);
+    if (md)
+        insertMimeData(md);
 }
 
 void
 InputBar::insertMimeData(const QMimeData *md)
 {
-        if (!md)
-                return;
-
-        nhlog::ui()->debug("Got mime formats: {}", md->formats().join(", ").toStdString());
-        const auto formats = md->formats().filter("/");
-        const auto image   = formats.filter("image/", Qt::CaseInsensitive);
-        const auto audio   = formats.filter("audio/", Qt::CaseInsensitive);
-        const auto video   = formats.filter("video/", Qt::CaseInsensitive);
-
-        if (!image.empty() && md->hasImage()) {
-                showPreview(*md, "", image);
-        } else if (!audio.empty()) {
-                showPreview(*md, "", audio);
-        } else if (!video.empty()) {
-                showPreview(*md, "", video);
-        } else if (md->hasUrls()) {
-                // Generic file path for any platform.
-                QString path;
-                for (auto &&u : md->urls()) {
-                        if (u.isLocalFile()) {
-                                path = u.toLocalFile();
-                                break;
-                        }
-                }
+    if (!md)
+        return;
+
+    nhlog::ui()->debug("Got mime formats: {}", md->formats().join(", ").toStdString());
+    const auto formats = md->formats().filter("/");
+    const auto image   = formats.filter("image/", Qt::CaseInsensitive);
+    const auto audio   = formats.filter("audio/", Qt::CaseInsensitive);
+    const auto video   = formats.filter("video/", Qt::CaseInsensitive);
+
+    if (!image.empty() && md->hasImage()) {
+        showPreview(*md, "", image);
+    } else if (!audio.empty()) {
+        showPreview(*md, "", audio);
+    } else if (!video.empty()) {
+        showPreview(*md, "", video);
+    } else if (md->hasUrls()) {
+        // Generic file path for any platform.
+        QString path;
+        for (auto &&u : md->urls()) {
+            if (u.isLocalFile()) {
+                path = u.toLocalFile();
+                break;
+            }
+        }
 
-                if (!path.isEmpty() && QFileInfo{path}.exists()) {
-                        showPreview(*md, path, formats);
-                } else {
-                        nhlog::ui()->warn("Clipboard does not contain any valid file paths.");
-                }
-        } else if (md->hasFormat("x-special/gnome-copied-files")) {
-                // Special case for X11 users. See "Notes for X11 Users" in md.
-                // Source: http://doc.qt.io/qt-5/qclipboard.html
-
-                // This MIME type returns a string with multiple lines separated by '\n'. The first
-                // line is the command to perform with the clipboard (not useful to us). The
-                // following lines are the file URIs.
-                //
-                // Source: the nautilus source code in file 'src/nautilus-clipboard.c' in function
-                // nautilus_clipboard_get_uri_list_from_selection_data()
-                // https://github.com/GNOME/nautilus/blob/master/src/nautilus-clipboard.c
-
-                auto data = md->data("x-special/gnome-copied-files").split('\n');
-                if (data.size() < 2) {
-                        nhlog::ui()->warn("MIME format is malformed, cannot perform paste.");
-                        return;
-                }
+        if (!path.isEmpty() && QFileInfo{path}.exists()) {
+            showPreview(*md, path, formats);
+        } else {
+            nhlog::ui()->warn("Clipboard does not contain any valid file paths.");
+        }
+    } else if (md->hasFormat("x-special/gnome-copied-files")) {
+        // Special case for X11 users. See "Notes for X11 Users" in md.
+        // Source: http://doc.qt.io/qt-5/qclipboard.html
+
+        // This MIME type returns a string with multiple lines separated by '\n'. The first
+        // line is the command to perform with the clipboard (not useful to us). The
+        // following lines are the file URIs.
+        //
+        // Source: the nautilus source code in file 'src/nautilus-clipboard.c' in function
+        // nautilus_clipboard_get_uri_list_from_selection_data()
+        // https://github.com/GNOME/nautilus/blob/master/src/nautilus-clipboard.c
+
+        auto data = md->data("x-special/gnome-copied-files").split('\n');
+        if (data.size() < 2) {
+            nhlog::ui()->warn("MIME format is malformed, cannot perform paste.");
+            return;
+        }
 
-                QString path;
-                for (int i = 1; i < data.size(); ++i) {
-                        QUrl url{data[i]};
-                        if (url.isLocalFile()) {
-                                path = url.toLocalFile();
-                                break;
-                        }
-                }
+        QString path;
+        for (int i = 1; i < data.size(); ++i) {
+            QUrl url{data[i]};
+            if (url.isLocalFile()) {
+                path = url.toLocalFile();
+                break;
+            }
+        }
 
-                if (!path.isEmpty()) {
-                        showPreview(*md, path, formats);
-                } else {
-                        nhlog::ui()->warn("Clipboard does not contain any valid file paths: {}",
-                                          data.join(", ").toStdString());
-                }
-        } else if (md->hasText()) {
-                emit insertText(md->text());
+        if (!path.isEmpty()) {
+            showPreview(*md, path, formats);
         } else {
-                nhlog::ui()->debug("formats: {}", md->formats().join(", ").toStdString());
+            nhlog::ui()->warn("Clipboard does not contain any valid file paths: {}",
+                              data.join(", ").toStdString());
         }
+    } else if (md->hasText()) {
+        emit insertText(md->text());
+    } else {
+        nhlog::ui()->debug("formats: {}", md->formats().join(", ").toStdString());
+    }
 }
 
 void
 InputBar::updateAtRoom(const QString &t)
 {
-        bool roomMention = false;
-
-        if (t.size() > 4) {
-                QTextBoundaryFinder finder(QTextBoundaryFinder::BoundaryType::Word, t);
-
-                finder.toStart();
-                do {
-                        auto start = finder.position();
-                        finder.toNextBoundary();
-                        auto end = finder.position();
-                        if (start > 0 && end - start >= 4 &&
-                            t.midRef(start, end - start) == "room" &&
-                            t.at(start - 1) == QChar('@')) {
-                                roomMention = true;
-                                break;
-                        }
-                } while (finder.position() < t.size());
-        }
-
-        if (roomMention != this->containsAtRoom_) {
-                this->containsAtRoom_ = roomMention;
-                emit containsAtRoomChanged();
-        }
+    bool roomMention = false;
+
+    if (t.size() > 4) {
+        QTextBoundaryFinder finder(QTextBoundaryFinder::BoundaryType::Word, t);
+
+        finder.toStart();
+        do {
+            auto start = finder.position();
+            finder.toNextBoundary();
+            auto end = finder.position();
+            if (start > 0 && end - start >= 4 && t.midRef(start, end - start) == "room" &&
+                t.at(start - 1) == QChar('@')) {
+                roomMention = true;
+                break;
+            }
+        } while (finder.position() < t.size());
+    }
+
+    if (roomMention != this->containsAtRoom_) {
+        this->containsAtRoom_ = roomMention;
+        emit containsAtRoomChanged();
+    }
 }
 
 void
 InputBar::setText(QString newText)
 {
-        if (history_.empty())
-                history_.push_front(newText);
-        else
-                history_.front() = newText;
-        history_index_ = 0;
+    if (history_.empty())
+        history_.push_front(newText);
+    else
+        history_.front() = newText;
+    history_index_ = 0;
 
-        if (history_.size() == INPUT_HISTORY_SIZE)
-                history_.pop_back();
+    if (history_.size() == INPUT_HISTORY_SIZE)
+        history_.pop_back();
 
-        emit textChanged(newText);
+    emit textChanged(newText);
 }
 void
 InputBar::updateState(int selectionStart_, int selectionEnd_, int cursorPosition_, QString text_)
 {
-        if (text_.isEmpty())
-                stopTyping();
-        else
-                startTyping();
+    if (text_.isEmpty())
+        stopTyping();
+    else
+        startTyping();
 
-        if (text_ != text()) {
-                if (history_.empty())
-                        history_.push_front(text_);
-                else
-                        history_.front() = text_;
-                history_index_ = 0;
+    if (text_ != text()) {
+        if (history_.empty())
+            history_.push_front(text_);
+        else
+            history_.front() = text_;
+        history_index_ = 0;
 
-                updateAtRoom(text_);
-        }
+        updateAtRoom(text_);
+    }
 
-        selectionStart = selectionStart_;
-        selectionEnd   = selectionEnd_;
-        cursorPosition = cursorPosition_;
+    selectionStart = selectionStart_;
+    selectionEnd   = selectionEnd_;
+    cursorPosition = cursorPosition_;
 }
 
 QString
 InputBar::text() const
 {
-        if (history_index_ < history_.size())
-                return history_.at(history_index_);
+    if (history_index_ < history_.size())
+        return history_.at(history_index_);
 
-        return "";
+    return "";
 }
 
 QString
 InputBar::previousText()
 {
-        history_index_++;
-        if (history_index_ >= INPUT_HISTORY_SIZE)
-                history_index_ = INPUT_HISTORY_SIZE;
-        else if (text().isEmpty())
-                history_index_--;
-
-        updateAtRoom(text());
-        return text();
+    history_index_++;
+    if (history_index_ >= INPUT_HISTORY_SIZE)
+        history_index_ = INPUT_HISTORY_SIZE;
+    else if (text().isEmpty())
+        history_index_--;
+
+    updateAtRoom(text());
+    return text();
 }
 
 QString
 InputBar::nextText()
 {
-        history_index_--;
-        if (history_index_ >= INPUT_HISTORY_SIZE)
-                history_index_ = 0;
+    history_index_--;
+    if (history_index_ >= INPUT_HISTORY_SIZE)
+        history_index_ = 0;
 
-        updateAtRoom(text());
-        return text();
+    updateAtRoom(text());
+    return text();
 }
 
 void
 InputBar::send()
 {
-        if (text().trimmed().isEmpty())
-                return;
-
-        nhlog::ui()->debug("Send: {}", text().toStdString());
-
-        auto wasEdit = !room->edit().isEmpty();
-
-        if (text().startsWith('/')) {
-                int command_end = text().indexOf(QRegularExpression("\\s"));
-                if (command_end == -1)
-                        command_end = text().size();
-                auto name = text().mid(1, command_end - 1);
-                auto args = text().mid(command_end + 1);
-                if (name.isEmpty() || name == "/") {
-                        message(args);
-                } else {
-                        command(name, args);
-                }
-        } else {
-                message(text());
-        }
+    if (text().trimmed().isEmpty())
+        return;
 
-        if (!wasEdit) {
-                history_.push_front("");
-                setText("");
+    nhlog::ui()->debug("Send: {}", text().toStdString());
+
+    auto wasEdit = !room->edit().isEmpty();
+
+    if (text().startsWith('/')) {
+        int command_end = text().indexOf(QRegularExpression("\\s"));
+        if (command_end == -1)
+            command_end = text().size();
+        auto name = text().mid(1, command_end - 1);
+        auto args = text().mid(command_end + 1);
+        if (name.isEmpty() || name == "/") {
+            message(args);
+        } else {
+            command(name, args);
         }
+    } else {
+        message(text());
+    }
+
+    if (!wasEdit) {
+        history_.push_front("");
+        setText("");
+    }
 }
 
 void
 InputBar::openFileSelection()
 {
-        const QString homeFolder = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
-        const auto fileName      = QFileDialog::getOpenFileName(
-          ChatPage::instance(), tr("Select a file"), homeFolder, tr("All Files (*)"));
+    const QString homeFolder = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
+    const auto fileName      = QFileDialog::getOpenFileName(
+      ChatPage::instance(), tr("Select a file"), homeFolder, tr("All Files (*)"));
 
-        if (fileName.isEmpty())
-                return;
+    if (fileName.isEmpty())
+        return;
 
-        QMimeDatabase db;
-        QMimeType mime = db.mimeTypeForFile(fileName, QMimeDatabase::MatchContent);
+    QMimeDatabase db;
+    QMimeType mime = db.mimeTypeForFile(fileName, QMimeDatabase::MatchContent);
 
-        QFile file{fileName};
+    QFile file{fileName};
 
-        if (!file.open(QIODevice::ReadOnly)) {
-                emit ChatPage::instance()->showNotification(
-                  QString("Error while reading media: %1").arg(file.errorString()));
-                return;
-        }
+    if (!file.open(QIODevice::ReadOnly)) {
+        emit ChatPage::instance()->showNotification(
+          QString("Error while reading media: %1").arg(file.errorString()));
+        return;
+    }
 
-        setUploading(true);
+    setUploading(true);
 
-        auto bin = file.readAll();
+    auto bin = file.readAll();
 
-        QMimeData data;
-        data.setData(mime.name(), bin);
+    QMimeData data;
+    data.setData(mime.name(), bin);
 
-        showPreview(data, fileName, QStringList{mime.name()});
+    showPreview(data, fileName, QStringList{mime.name()});
 }
 
 void
 InputBar::message(QString msg, MarkdownOverride useMarkdown, bool rainbowify)
 {
-        mtx::events::msg::Text text = {};
-        text.body                   = msg.trimmed().toStdString();
+    mtx::events::msg::Text text = {};
+    text.body                   = msg.trimmed().toStdString();
+
+    if ((ChatPage::instance()->userSettings()->markdown() &&
+         useMarkdown == MarkdownOverride::NOT_SPECIFIED) ||
+        useMarkdown == MarkdownOverride::ON) {
+        text.formatted_body = utils::markdownToHtml(msg, rainbowify).toStdString();
+        // Remove markdown links by completer
+        text.body = msg.trimmed().replace(conf::strings::matrixToMarkdownLink, "\\1").toStdString();
+
+        // Don't send formatted_body, when we don't need to
+        if (text.formatted_body.find("<") == std::string::npos)
+            text.formatted_body = "";
+        else
+            text.format = "org.matrix.custom.html";
+    }
 
-        if ((ChatPage::instance()->userSettings()->markdown() &&
-             useMarkdown == MarkdownOverride::NOT_SPECIFIED) ||
-            useMarkdown == MarkdownOverride::ON) {
-                text.formatted_body = utils::markdownToHtml(msg, rainbowify).toStdString();
-                // Remove markdown links by completer
-                text.body =
-                  msg.trimmed().replace(conf::strings::matrixToMarkdownLink, "\\1").toStdString();
-
-                // Don't send formatted_body, when we don't need to
-                if (text.formatted_body.find("<") == std::string::npos)
-                        text.formatted_body = "";
-                else
-                        text.format = "org.matrix.custom.html";
+    if (!room->edit().isEmpty()) {
+        if (!room->reply().isEmpty()) {
+            text.relations.relations.push_back(
+              {mtx::common::RelationType::InReplyTo, room->reply().toStdString()});
         }
 
-        if (!room->edit().isEmpty()) {
-                if (!room->reply().isEmpty()) {
-                        text.relations.relations.push_back(
-                          {mtx::common::RelationType::InReplyTo, room->reply().toStdString()});
-                }
-
-                text.relations.relations.push_back(
-                  {mtx::common::RelationType::Replace, room->edit().toStdString()});
-
-        } else if (!room->reply().isEmpty()) {
-                auto related = room->relatedInfo(room->reply());
-
-                QString body;
-                bool firstLine = true;
-                for (const auto &line : related.quoted_body.split("\n")) {
-                        if (firstLine) {
-                                firstLine = false;
-                                body = QString("> <%1> %2\n").arg(related.quoted_user).arg(line);
-                        } else {
-                                body += QString("> %1\n").arg(line);
-                        }
-                }
+        text.relations.relations.push_back(
+          {mtx::common::RelationType::Replace, room->edit().toStdString()});
+
+    } else if (!room->reply().isEmpty()) {
+        auto related = room->relatedInfo(room->reply());
+
+        QString body;
+        bool firstLine = true;
+        for (const auto &line : related.quoted_body.split("\n")) {
+            if (firstLine) {
+                firstLine = false;
+                body      = QString("> <%1> %2\n").arg(related.quoted_user).arg(line);
+            } else {
+                body += QString("> %1\n").arg(line);
+            }
+        }
 
-                text.body = QString("%1\n%2").arg(body).arg(msg).toStdString();
+        text.body = QString("%1\n%2").arg(body).arg(msg).toStdString();
 
-                // NOTE(Nico): rich replies always need a formatted_body!
-                text.format = "org.matrix.custom.html";
-                if ((ChatPage::instance()->userSettings()->markdown() &&
-                     useMarkdown == MarkdownOverride::NOT_SPECIFIED) ||
-                    useMarkdown == MarkdownOverride::ON)
-                        text.formatted_body = utils::getFormattedQuoteBody(
-                                                related, utils::markdownToHtml(msg, rainbowify))
-                                                .toStdString();
-                else
-                        text.formatted_body =
-                          utils::getFormattedQuoteBody(related, msg.toHtmlEscaped()).toStdString();
+        // NOTE(Nico): rich replies always need a formatted_body!
+        text.format = "org.matrix.custom.html";
+        if ((ChatPage::instance()->userSettings()->markdown() &&
+             useMarkdown == MarkdownOverride::NOT_SPECIFIED) ||
+            useMarkdown == MarkdownOverride::ON)
+            text.formatted_body =
+              utils::getFormattedQuoteBody(related, utils::markdownToHtml(msg, rainbowify))
+                .toStdString();
+        else
+            text.formatted_body =
+              utils::getFormattedQuoteBody(related, msg.toHtmlEscaped()).toStdString();
 
-                text.relations.relations.push_back(
-                  {mtx::common::RelationType::InReplyTo, related.related_event});
-        }
+        text.relations.relations.push_back(
+          {mtx::common::RelationType::InReplyTo, related.related_event});
+    }
 
-        room->sendMessageEvent(text, mtx::events::EventType::RoomMessage);
+    room->sendMessageEvent(text, mtx::events::EventType::RoomMessage);
 }
 
 void
 InputBar::emote(QString msg, bool rainbowify)
 {
-        auto html = utils::markdownToHtml(msg, rainbowify);
-
-        mtx::events::msg::Emote emote;
-        emote.body = msg.trimmed().toStdString();
-
-        if (html != msg.trimmed().toHtmlEscaped() &&
-            ChatPage::instance()->userSettings()->markdown()) {
-                emote.formatted_body = html.toStdString();
-                emote.format         = "org.matrix.custom.html";
-                // Remove markdown links by completer
-                emote.body =
-                  msg.trimmed().replace(conf::strings::matrixToMarkdownLink, "\\1").toStdString();
-        }
-
-        if (!room->reply().isEmpty()) {
-                emote.relations.relations.push_back(
-                  {mtx::common::RelationType::InReplyTo, room->reply().toStdString()});
-        }
-        if (!room->edit().isEmpty()) {
-                emote.relations.relations.push_back(
-                  {mtx::common::RelationType::Replace, room->edit().toStdString()});
-        }
-
-        room->sendMessageEvent(emote, mtx::events::EventType::RoomMessage);
+    auto html = utils::markdownToHtml(msg, rainbowify);
+
+    mtx::events::msg::Emote emote;
+    emote.body = msg.trimmed().toStdString();
+
+    if (html != msg.trimmed().toHtmlEscaped() && ChatPage::instance()->userSettings()->markdown()) {
+        emote.formatted_body = html.toStdString();
+        emote.format         = "org.matrix.custom.html";
+        // Remove markdown links by completer
+        emote.body =
+          msg.trimmed().replace(conf::strings::matrixToMarkdownLink, "\\1").toStdString();
+    }
+
+    if (!room->reply().isEmpty()) {
+        emote.relations.relations.push_back(
+          {mtx::common::RelationType::InReplyTo, room->reply().toStdString()});
+    }
+    if (!room->edit().isEmpty()) {
+        emote.relations.relations.push_back(
+          {mtx::common::RelationType::Replace, room->edit().toStdString()});
+    }
+
+    room->sendMessageEvent(emote, mtx::events::EventType::RoomMessage);
 }
 
 void
 InputBar::notice(QString msg, bool rainbowify)
 {
-        auto html = utils::markdownToHtml(msg, rainbowify);
-
-        mtx::events::msg::Notice notice;
-        notice.body = msg.trimmed().toStdString();
-
-        if (html != msg.trimmed().toHtmlEscaped() &&
-            ChatPage::instance()->userSettings()->markdown()) {
-                notice.formatted_body = html.toStdString();
-                notice.format         = "org.matrix.custom.html";
-                // Remove markdown links by completer
-                notice.body =
-                  msg.trimmed().replace(conf::strings::matrixToMarkdownLink, "\\1").toStdString();
-        }
-
-        if (!room->reply().isEmpty()) {
-                notice.relations.relations.push_back(
-                  {mtx::common::RelationType::InReplyTo, room->reply().toStdString()});
-        }
-        if (!room->edit().isEmpty()) {
-                notice.relations.relations.push_back(
-                  {mtx::common::RelationType::Replace, room->edit().toStdString()});
-        }
-
-        room->sendMessageEvent(notice, mtx::events::EventType::RoomMessage);
+    auto html = utils::markdownToHtml(msg, rainbowify);
+
+    mtx::events::msg::Notice notice;
+    notice.body = msg.trimmed().toStdString();
+
+    if (html != msg.trimmed().toHtmlEscaped() && ChatPage::instance()->userSettings()->markdown()) {
+        notice.formatted_body = html.toStdString();
+        notice.format         = "org.matrix.custom.html";
+        // Remove markdown links by completer
+        notice.body =
+          msg.trimmed().replace(conf::strings::matrixToMarkdownLink, "\\1").toStdString();
+    }
+
+    if (!room->reply().isEmpty()) {
+        notice.relations.relations.push_back(
+          {mtx::common::RelationType::InReplyTo, room->reply().toStdString()});
+    }
+    if (!room->edit().isEmpty()) {
+        notice.relations.relations.push_back(
+          {mtx::common::RelationType::Replace, room->edit().toStdString()});
+    }
+
+    room->sendMessageEvent(notice, mtx::events::EventType::RoomMessage);
 }
 
 void
@@ -422,29 +418,29 @@ InputBar::image(const QString &filename,
                 const QSize &dimensions,
                 const QString &blurhash)
 {
-        mtx::events::msg::Image image;
-        image.info.mimetype = mime.toStdString();
-        image.info.size     = dsize;
-        image.info.blurhash = blurhash.toStdString();
-        image.body          = filename.toStdString();
-        image.info.h        = dimensions.height();
-        image.info.w        = dimensions.width();
-
-        if (file)
-                image.file = file;
-        else
-                image.url = url.toStdString();
-
-        if (!room->reply().isEmpty()) {
-                image.relations.relations.push_back(
-                  {mtx::common::RelationType::InReplyTo, room->reply().toStdString()});
-        }
-        if (!room->edit().isEmpty()) {
-                image.relations.relations.push_back(
-                  {mtx::common::RelationType::Replace, room->edit().toStdString()});
-        }
-
-        room->sendMessageEvent(image, mtx::events::EventType::RoomMessage);
+    mtx::events::msg::Image image;
+    image.info.mimetype = mime.toStdString();
+    image.info.size     = dsize;
+    image.info.blurhash = blurhash.toStdString();
+    image.body          = filename.toStdString();
+    image.info.h        = dimensions.height();
+    image.info.w        = dimensions.width();
+
+    if (file)
+        image.file = file;
+    else
+        image.url = url.toStdString();
+
+    if (!room->reply().isEmpty()) {
+        image.relations.relations.push_back(
+          {mtx::common::RelationType::InReplyTo, room->reply().toStdString()});
+    }
+    if (!room->edit().isEmpty()) {
+        image.relations.relations.push_back(
+          {mtx::common::RelationType::Replace, room->edit().toStdString()});
+    }
+
+    room->sendMessageEvent(image, mtx::events::EventType::RoomMessage);
 }
 
 void
@@ -454,26 +450,26 @@ InputBar::file(const QString &filename,
                const QString &mime,
                uint64_t dsize)
 {
-        mtx::events::msg::File file;
-        file.info.mimetype = mime.toStdString();
-        file.info.size     = dsize;
-        file.body          = filename.toStdString();
-
-        if (encryptedFile)
-                file.file = encryptedFile;
-        else
-                file.url = url.toStdString();
-
-        if (!room->reply().isEmpty()) {
-                file.relations.relations.push_back(
-                  {mtx::common::RelationType::InReplyTo, room->reply().toStdString()});
-        }
-        if (!room->edit().isEmpty()) {
-                file.relations.relations.push_back(
-                  {mtx::common::RelationType::Replace, room->edit().toStdString()});
-        }
-
-        room->sendMessageEvent(file, mtx::events::EventType::RoomMessage);
+    mtx::events::msg::File file;
+    file.info.mimetype = mime.toStdString();
+    file.info.size     = dsize;
+    file.body          = filename.toStdString();
+
+    if (encryptedFile)
+        file.file = encryptedFile;
+    else
+        file.url = url.toStdString();
+
+    if (!room->reply().isEmpty()) {
+        file.relations.relations.push_back(
+          {mtx::common::RelationType::InReplyTo, room->reply().toStdString()});
+    }
+    if (!room->edit().isEmpty()) {
+        file.relations.relations.push_back(
+          {mtx::common::RelationType::Replace, room->edit().toStdString()});
+    }
+
+    room->sendMessageEvent(file, mtx::events::EventType::RoomMessage);
 }
 
 void
@@ -483,27 +479,27 @@ InputBar::audio(const QString &filename,
                 const QString &mime,
                 uint64_t dsize)
 {
-        mtx::events::msg::Audio audio;
-        audio.info.mimetype = mime.toStdString();
-        audio.info.size     = dsize;
-        audio.body          = filename.toStdString();
-        audio.url           = url.toStdString();
-
-        if (file)
-                audio.file = file;
-        else
-                audio.url = url.toStdString();
-
-        if (!room->reply().isEmpty()) {
-                audio.relations.relations.push_back(
-                  {mtx::common::RelationType::InReplyTo, room->reply().toStdString()});
-        }
-        if (!room->edit().isEmpty()) {
-                audio.relations.relations.push_back(
-                  {mtx::common::RelationType::Replace, room->edit().toStdString()});
-        }
-
-        room->sendMessageEvent(audio, mtx::events::EventType::RoomMessage);
+    mtx::events::msg::Audio audio;
+    audio.info.mimetype = mime.toStdString();
+    audio.info.size     = dsize;
+    audio.body          = filename.toStdString();
+    audio.url           = url.toStdString();
+
+    if (file)
+        audio.file = file;
+    else
+        audio.url = url.toStdString();
+
+    if (!room->reply().isEmpty()) {
+        audio.relations.relations.push_back(
+          {mtx::common::RelationType::InReplyTo, room->reply().toStdString()});
+    }
+    if (!room->edit().isEmpty()) {
+        audio.relations.relations.push_back(
+          {mtx::common::RelationType::Replace, room->edit().toStdString()});
+    }
+
+    room->sendMessageEvent(audio, mtx::events::EventType::RoomMessage);
 }
 
 void
@@ -513,320 +509,310 @@ InputBar::video(const QString &filename,
                 const QString &mime,
                 uint64_t dsize)
 {
-        mtx::events::msg::Video video;
-        video.info.mimetype = mime.toStdString();
-        video.info.size     = dsize;
-        video.body          = filename.toStdString();
-
-        if (file)
-                video.file = file;
-        else
-                video.url = url.toStdString();
-
-        if (!room->reply().isEmpty()) {
-                video.relations.relations.push_back(
-                  {mtx::common::RelationType::InReplyTo, room->reply().toStdString()});
-        }
-        if (!room->edit().isEmpty()) {
-                video.relations.relations.push_back(
-                  {mtx::common::RelationType::Replace, room->edit().toStdString()});
-        }
-
-        room->sendMessageEvent(video, mtx::events::EventType::RoomMessage);
+    mtx::events::msg::Video video;
+    video.info.mimetype = mime.toStdString();
+    video.info.size     = dsize;
+    video.body          = filename.toStdString();
+
+    if (file)
+        video.file = file;
+    else
+        video.url = url.toStdString();
+
+    if (!room->reply().isEmpty()) {
+        video.relations.relations.push_back(
+          {mtx::common::RelationType::InReplyTo, room->reply().toStdString()});
+    }
+    if (!room->edit().isEmpty()) {
+        video.relations.relations.push_back(
+          {mtx::common::RelationType::Replace, room->edit().toStdString()});
+    }
+
+    room->sendMessageEvent(video, mtx::events::EventType::RoomMessage);
 }
 
 void
 InputBar::sticker(CombinedImagePackModel *model, int row)
 {
-        if (!model || row < 0)
-                return;
-
-        auto img = model->imageAt(row);
-
-        mtx::events::msg::StickerImage sticker{};
-        sticker.info = img.info.value_or(mtx::common::ImageInfo{});
-        sticker.url  = img.url;
-        sticker.body = img.body;
-
-        // workaround for https://github.com/vector-im/element-ios/issues/2353
-        sticker.info.thumbnail_url           = sticker.url;
-        sticker.info.thumbnail_info.mimetype = sticker.info.mimetype;
-        sticker.info.thumbnail_info.size     = sticker.info.size;
-        sticker.info.thumbnail_info.h        = sticker.info.h;
-        sticker.info.thumbnail_info.w        = sticker.info.w;
-
-        if (!room->reply().isEmpty()) {
-                sticker.relations.relations.push_back(
-                  {mtx::common::RelationType::InReplyTo, room->reply().toStdString()});
-        }
-        if (!room->edit().isEmpty()) {
-                sticker.relations.relations.push_back(
-                  {mtx::common::RelationType::Replace, room->edit().toStdString()});
-        }
-
-        room->sendMessageEvent(sticker, mtx::events::EventType::Sticker);
+    if (!model || row < 0)
+        return;
+
+    auto img = model->imageAt(row);
+
+    mtx::events::msg::StickerImage sticker{};
+    sticker.info = img.info.value_or(mtx::common::ImageInfo{});
+    sticker.url  = img.url;
+    sticker.body = img.body;
+
+    // workaround for https://github.com/vector-im/element-ios/issues/2353
+    sticker.info.thumbnail_url           = sticker.url;
+    sticker.info.thumbnail_info.mimetype = sticker.info.mimetype;
+    sticker.info.thumbnail_info.size     = sticker.info.size;
+    sticker.info.thumbnail_info.h        = sticker.info.h;
+    sticker.info.thumbnail_info.w        = sticker.info.w;
+
+    if (!room->reply().isEmpty()) {
+        sticker.relations.relations.push_back(
+          {mtx::common::RelationType::InReplyTo, room->reply().toStdString()});
+    }
+    if (!room->edit().isEmpty()) {
+        sticker.relations.relations.push_back(
+          {mtx::common::RelationType::Replace, room->edit().toStdString()});
+    }
+
+    room->sendMessageEvent(sticker, mtx::events::EventType::Sticker);
 }
 
 void
 InputBar::command(QString command, QString args)
 {
-        if (command == "me") {
-                emote(args, false);
-        } else if (command == "react") {
-                auto eventId = room->reply();
-                if (!eventId.isEmpty())
-                        reaction(eventId, args.trimmed());
-        } else if (command == "join") {
-                ChatPage::instance()->joinRoom(args);
-        } else if (command == "part" || command == "leave") {
-                MainWindow::instance()->openLeaveRoomDialog(room->roomId());
-        } else if (command == "invite") {
-                ChatPage::instance()->inviteUser(args.section(' ', 0, 0), args.section(' ', 1, -1));
-        } else if (command == "kick") {
-                ChatPage::instance()->kickUser(args.section(' ', 0, 0), args.section(' ', 1, -1));
-        } else if (command == "ban") {
-                ChatPage::instance()->banUser(args.section(' ', 0, 0), args.section(' ', 1, -1));
-        } else if (command == "unban") {
-                ChatPage::instance()->unbanUser(args.section(' ', 0, 0), args.section(' ', 1, -1));
-        } else if (command == "roomnick") {
-                mtx::events::state::Member member;
-                member.display_name = args.toStdString();
-                member.avatar_url =
-                  cache::avatarUrl(room->roomId(),
-                                   QString::fromStdString(http::client()->user_id().to_string()))
-                    .toStdString();
-                member.membership = mtx::events::state::Membership::Join;
-
-                http::client()->send_state_event(
-                  room->roomId().toStdString(),
-                  http::client()->user_id().to_string(),
-                  member,
-                  [](mtx::responses::EventId, mtx::http::RequestErr err) {
-                          if (err)
-                                  nhlog::net()->error("Failed to set room displayname: {}",
-                                                      err->matrix_error.error);
-                  });
-        } else if (command == "shrug") {
-                message("¯\\_(ツ)_/¯" + (args.isEmpty() ? "" : " " + args));
-        } else if (command == "fliptable") {
-                message("(╯°□°)╯︵ ┻━┻");
-        } else if (command == "unfliptable") {
-                message(" ┯━┯╭( º _ º╭)");
-        } else if (command == "sovietflip") {
-                message("ノ┬─┬ノ ︵ ( \\o°o)\\");
-        } else if (command == "clear-timeline") {
-                room->clearTimeline();
-        } else if (command == "rotate-megolm-session") {
-                cache::dropOutboundMegolmSession(room->roomId().toStdString());
-        } else if (command == "md") {
-                message(args, MarkdownOverride::ON);
-        } else if (command == "plain") {
-                message(args, MarkdownOverride::OFF);
-        } else if (command == "rainbow") {
-                message(args, MarkdownOverride::ON, true);
-        } else if (command == "rainbowme") {
-                emote(args, true);
-        } else if (command == "notice") {
-                notice(args, false);
-        } else if (command == "rainbownotice") {
-                notice(args, true);
-        } else if (command == "goto") {
-                // Goto has three different modes:
-                // 1 - Going directly to a given event ID
-                if (args[0] == '$') {
-                        room->showEvent(args);
-                        return;
-                }
-                // 2 - Going directly to a given message index
-                if (args[0] >= '0' && args[0] <= '9') {
-                        room->showEvent(args);
-                        return;
-                }
-                // 3 - Matrix URI handler, as if you clicked the URI
-                if (ChatPage::instance()->handleMatrixUri(args)) {
-                        return;
-                }
-                nhlog::net()->error("Could not resolve goto: {}", args.toStdString());
+    if (command == "me") {
+        emote(args, false);
+    } else if (command == "react") {
+        auto eventId = room->reply();
+        if (!eventId.isEmpty())
+            reaction(eventId, args.trimmed());
+    } else if (command == "join") {
+        ChatPage::instance()->joinRoom(args);
+    } else if (command == "part" || command == "leave") {
+        MainWindow::instance()->openLeaveRoomDialog(room->roomId());
+    } else if (command == "invite") {
+        ChatPage::instance()->inviteUser(args.section(' ', 0, 0), args.section(' ', 1, -1));
+    } else if (command == "kick") {
+        ChatPage::instance()->kickUser(args.section(' ', 0, 0), args.section(' ', 1, -1));
+    } else if (command == "ban") {
+        ChatPage::instance()->banUser(args.section(' ', 0, 0), args.section(' ', 1, -1));
+    } else if (command == "unban") {
+        ChatPage::instance()->unbanUser(args.section(' ', 0, 0), args.section(' ', 1, -1));
+    } else if (command == "roomnick") {
+        mtx::events::state::Member member;
+        member.display_name = args.toStdString();
+        member.avatar_url =
+          cache::avatarUrl(room->roomId(),
+                           QString::fromStdString(http::client()->user_id().to_string()))
+            .toStdString();
+        member.membership = mtx::events::state::Membership::Join;
+
+        http::client()->send_state_event(room->roomId().toStdString(),
+                                         http::client()->user_id().to_string(),
+                                         member,
+                                         [](mtx::responses::EventId, mtx::http::RequestErr err) {
+                                             if (err)
+                                                 nhlog::net()->error(
+                                                   "Failed to set room displayname: {}",
+                                                   err->matrix_error.error);
+                                         });
+    } else if (command == "shrug") {
+        message("¯\\_(ツ)_/¯" + (args.isEmpty() ? "" : " " + args));
+    } else if (command == "fliptable") {
+        message("(╯°□°)╯︵ ┻━┻");
+    } else if (command == "unfliptable") {
+        message(" ┯━┯╭( º _ º╭)");
+    } else if (command == "sovietflip") {
+        message("ノ┬─┬ノ ︵ ( \\o°o)\\");
+    } else if (command == "clear-timeline") {
+        room->clearTimeline();
+    } else if (command == "rotate-megolm-session") {
+        cache::dropOutboundMegolmSession(room->roomId().toStdString());
+    } else if (command == "md") {
+        message(args, MarkdownOverride::ON);
+    } else if (command == "plain") {
+        message(args, MarkdownOverride::OFF);
+    } else if (command == "rainbow") {
+        message(args, MarkdownOverride::ON, true);
+    } else if (command == "rainbowme") {
+        emote(args, true);
+    } else if (command == "notice") {
+        notice(args, false);
+    } else if (command == "rainbownotice") {
+        notice(args, true);
+    } else if (command == "goto") {
+        // Goto has three different modes:
+        // 1 - Going directly to a given event ID
+        if (args[0] == '$') {
+            room->showEvent(args);
+            return;
+        }
+        // 2 - Going directly to a given message index
+        if (args[0] >= '0' && args[0] <= '9') {
+            room->showEvent(args);
+            return;
+        }
+        // 3 - Matrix URI handler, as if you clicked the URI
+        if (ChatPage::instance()->handleMatrixUri(args)) {
+            return;
         }
+        nhlog::net()->error("Could not resolve goto: {}", args.toStdString());
+    }
 }
 
 void
 InputBar::showPreview(const QMimeData &source, QString path, const QStringList &formats)
 {
-        dialogs::PreviewUploadOverlay *previewDialog_ =
-          new dialogs::PreviewUploadOverlay(ChatPage::instance());
-        previewDialog_->setAttribute(Qt::WA_DeleteOnClose);
-
-        if (source.hasImage())
-                previewDialog_->setPreview(qvariant_cast<QImage>(source.imageData()),
-                                           formats.front());
-        else if (!path.isEmpty())
-                previewDialog_->setPreview(path);
-        else if (!formats.isEmpty()) {
-                auto mime = formats.first();
-                previewDialog_->setPreview(source.data(mime), mime);
-        } else {
-                setUploading(false);
-                previewDialog_->deleteLater();
-                return;
-        }
-
-        connect(previewDialog_, &dialogs::PreviewUploadOverlay::aborted, this, [this]() {
-                setUploading(false);
-        });
-
-        connect(
-          previewDialog_,
-          &dialogs::PreviewUploadOverlay::confirmUpload,
-          this,
-          [this](const QByteArray data, const QString &mime, const QString &fn) {
-                  setUploading(true);
-
-                  setText("");
-
-                  auto payload = std::string(data.data(), data.size());
-                  std::optional<mtx::crypto::EncryptedFile> encryptedFile;
-                  if (cache::isRoomEncrypted(room->roomId().toStdString())) {
-                          mtx::crypto::BinaryBuf buf;
-                          std::tie(buf, encryptedFile) = mtx::crypto::encrypt_file(payload);
-                          payload                      = mtx::crypto::to_string(buf);
+    dialogs::PreviewUploadOverlay *previewDialog_ =
+      new dialogs::PreviewUploadOverlay(ChatPage::instance());
+    previewDialog_->setAttribute(Qt::WA_DeleteOnClose);
+
+    if (source.hasImage())
+        previewDialog_->setPreview(qvariant_cast<QImage>(source.imageData()), formats.front());
+    else if (!path.isEmpty())
+        previewDialog_->setPreview(path);
+    else if (!formats.isEmpty()) {
+        auto mime = formats.first();
+        previewDialog_->setPreview(source.data(mime), mime);
+    } else {
+        setUploading(false);
+        previewDialog_->deleteLater();
+        return;
+    }
+
+    connect(previewDialog_, &dialogs::PreviewUploadOverlay::aborted, this, [this]() {
+        setUploading(false);
+    });
+
+    connect(
+      previewDialog_,
+      &dialogs::PreviewUploadOverlay::confirmUpload,
+      this,
+      [this](const QByteArray data, const QString &mime, const QString &fn) {
+          setUploading(true);
+
+          setText("");
+
+          auto payload = std::string(data.data(), data.size());
+          std::optional<mtx::crypto::EncryptedFile> encryptedFile;
+          if (cache::isRoomEncrypted(room->roomId().toStdString())) {
+              mtx::crypto::BinaryBuf buf;
+              std::tie(buf, encryptedFile) = mtx::crypto::encrypt_file(payload);
+              payload                      = mtx::crypto::to_string(buf);
+          }
+
+          QSize dimensions;
+          QString blurhash;
+          auto mimeClass = mime.split("/")[0];
+          nhlog::ui()->debug("Mime: {}", mime.toStdString());
+          if (mimeClass == "image") {
+              QImage img = utils::readImage(data);
+
+              dimensions = img.size();
+              if (img.height() > 200 && img.width() > 360)
+                  img = img.scaled(360, 200, Qt::KeepAspectRatioByExpanding);
+              std::vector<unsigned char> data_;
+              for (int y = 0; y < img.height(); y++) {
+                  for (int x = 0; x < img.width(); x++) {
+                      auto p = img.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(), img.width(), img.height(), 4, 3));
+          }
+
+          http::client()->upload(
+            payload,
+            encryptedFile ? "application/octet-stream" : mime.toStdString(),
+            QFileInfo(fn).fileName().toStdString(),
+            [this,
+             filename      = fn,
+             encryptedFile = std::move(encryptedFile),
+             mimeClass,
+             mime,
+             size = payload.size(),
+             dimensions,
+             blurhash](const mtx::responses::ContentURI &res, mtx::http::RequestErr err) mutable {
+                if (err) {
+                    emit ChatPage::instance()->showNotification(
+                      tr("Failed to upload media. Please try again."));
+                    nhlog::net()->warn("failed to upload media: {} {} ({})",
+                                       err->matrix_error.error,
+                                       to_string(err->matrix_error.errcode),
+                                       static_cast<int>(err->status_code));
+                    setUploading(false);
+                    return;
+                }
 
-                  QSize dimensions;
-                  QString blurhash;
-                  auto mimeClass = mime.split("/")[0];
-                  nhlog::ui()->debug("Mime: {}", mime.toStdString());
-                  if (mimeClass == "image") {
-                          QImage img = utils::readImage(data);
-
-                          dimensions = img.size();
-                          if (img.height() > 200 && img.width() > 360)
-                                  img = img.scaled(360, 200, Qt::KeepAspectRatioByExpanding);
-                          std::vector<unsigned char> data_;
-                          for (int y = 0; y < img.height(); y++) {
-                                  for (int x = 0; x < img.width(); x++) {
-                                          auto p = img.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(), img.width(), img.height(), 4, 3));
-                  }
+                auto url = QString::fromStdString(res.content_uri);
+                if (encryptedFile)
+                    encryptedFile->url = res.content_uri;
+
+                if (mimeClass == "image")
+                    image(filename, encryptedFile, url, mime, size, dimensions, blurhash);
+                else if (mimeClass == "audio")
+                    audio(filename, encryptedFile, url, mime, size);
+                else if (mimeClass == "video")
+                    video(filename, encryptedFile, url, mime, size);
+                else
+                    file(filename, encryptedFile, url, mime, size);
 
-                  http::client()->upload(
-                    payload,
-                    encryptedFile ? "application/octet-stream" : mime.toStdString(),
-                    QFileInfo(fn).fileName().toStdString(),
-                    [this,
-                     filename      = fn,
-                     encryptedFile = std::move(encryptedFile),
-                     mimeClass,
-                     mime,
-                     size = payload.size(),
-                     dimensions,
-                     blurhash](const mtx::responses::ContentURI &res,
-                               mtx::http::RequestErr err) mutable {
-                            if (err) {
-                                    emit ChatPage::instance()->showNotification(
-                                      tr("Failed to upload media. Please try again."));
-                                    nhlog::net()->warn("failed to upload media: {} {} ({})",
-                                                       err->matrix_error.error,
-                                                       to_string(err->matrix_error.errcode),
-                                                       static_cast<int>(err->status_code));
-                                    setUploading(false);
-                                    return;
-                            }
-
-                            auto url = QString::fromStdString(res.content_uri);
-                            if (encryptedFile)
-                                    encryptedFile->url = res.content_uri;
-
-                            if (mimeClass == "image")
-                                    image(filename,
-                                          encryptedFile,
-                                          url,
-                                          mime,
-                                          size,
-                                          dimensions,
-                                          blurhash);
-                            else if (mimeClass == "audio")
-                                    audio(filename, encryptedFile, url, mime, size);
-                            else if (mimeClass == "video")
-                                    video(filename, encryptedFile, url, mime, size);
-                            else
-                                    file(filename, encryptedFile, url, mime, size);
-
-                            setUploading(false);
-                    });
-          });
+                setUploading(false);
+            });
+      });
 }
 
 void
 InputBar::startTyping()
 {
-        if (!typingRefresh_.isActive()) {
-                typingRefresh_.start();
-
-                if (ChatPage::instance()->userSettings()->typingNotifications()) {
-                        http::client()->start_typing(
-                          room->roomId().toStdString(), 10'000, [](mtx::http::RequestErr err) {
-                                  if (err) {
-                                          nhlog::net()->warn(
-                                            "failed to send typing notification: {}",
-                                            err->matrix_error.error);
-                                  }
-                          });
-                }
+    if (!typingRefresh_.isActive()) {
+        typingRefresh_.start();
+
+        if (ChatPage::instance()->userSettings()->typingNotifications()) {
+            http::client()->start_typing(
+              room->roomId().toStdString(), 10'000, [](mtx::http::RequestErr err) {
+                  if (err) {
+                      nhlog::net()->warn("failed to send typing notification: {}",
+                                         err->matrix_error.error);
+                  }
+              });
         }
-        typingTimeout_.start();
+    }
+    typingTimeout_.start();
 }
 void
 InputBar::stopTyping()
 {
-        typingRefresh_.stop();
-        typingTimeout_.stop();
+    typingRefresh_.stop();
+    typingTimeout_.stop();
 
-        if (!ChatPage::instance()->userSettings()->typingNotifications())
-                return;
+    if (!ChatPage::instance()->userSettings()->typingNotifications())
+        return;
 
-        http::client()->stop_typing(room->roomId().toStdString(), [](mtx::http::RequestErr err) {
-                if (err) {
-                        nhlog::net()->warn("failed to stop typing notifications: {}",
-                                           err->matrix_error.error);
-                }
-        });
+    http::client()->stop_typing(room->roomId().toStdString(), [](mtx::http::RequestErr err) {
+        if (err) {
+            nhlog::net()->warn("failed to stop typing notifications: {}", err->matrix_error.error);
+        }
+    });
 }
 
 void
 InputBar::reaction(const QString &reactedEvent, const QString &reactionKey)
 {
-        auto reactions = room->reactions(reactedEvent.toStdString());
-
-        QString selfReactedEvent;
-        for (const auto &reaction : reactions) {
-                if (reactionKey == reaction.key_) {
-                        selfReactedEvent = reaction.selfReactedEvent_;
-                        break;
-                }
-        }
+    auto reactions = room->reactions(reactedEvent.toStdString());
 
-        if (selfReactedEvent.startsWith("m"))
-                return;
-
-        // If selfReactedEvent is empty, that means we haven't previously reacted
-        if (selfReactedEvent.isEmpty()) {
-                mtx::events::msg::Reaction reaction;
-                mtx::common::Relation rel;
-                rel.rel_type = mtx::common::RelationType::Annotation;
-                rel.event_id = reactedEvent.toStdString();
-                rel.key      = reactionKey.toStdString();
-                reaction.relations.relations.push_back(rel);
-
-                room->sendMessageEvent(reaction, mtx::events::EventType::Reaction);
-                // Otherwise, we have previously reacted and the reaction should be redacted
-        } else {
-                room->redactEvent(selfReactedEvent);
+    QString selfReactedEvent;
+    for (const auto &reaction : reactions) {
+        if (reactionKey == reaction.key_) {
+            selfReactedEvent = reaction.selfReactedEvent_;
+            break;
         }
+    }
+
+    if (selfReactedEvent.startsWith("m"))
+        return;
+
+    // If selfReactedEvent is empty, that means we haven't previously reacted
+    if (selfReactedEvent.isEmpty()) {
+        mtx::events::msg::Reaction reaction;
+        mtx::common::Relation rel;
+        rel.rel_type = mtx::common::RelationType::Annotation;
+        rel.event_id = reactedEvent.toStdString();
+        rel.key      = reactionKey.toStdString();
+        reaction.relations.relations.push_back(rel);
+
+        room->sendMessageEvent(reaction, mtx::events::EventType::Reaction);
+        // Otherwise, we have previously reacted and the reaction should be redacted
+    } else {
+        room->redactEvent(selfReactedEvent);
+    }
 }
diff --git a/src/timeline/InputBar.h b/src/timeline/InputBar.h
index cdc66a06..4a0f4401 100644
--- a/src/timeline/InputBar.h
+++ b/src/timeline/InputBar.h
@@ -19,105 +19,105 @@ class QStringList;
 
 enum class MarkdownOverride
 {
-        NOT_SPECIFIED, // no override set
-        ON,
-        OFF,
+    NOT_SPECIFIED, // no override set
+    ON,
+    OFF,
 };
 
 class InputBar : public QObject
 {
-        Q_OBJECT
-        Q_PROPERTY(bool uploading READ uploading NOTIFY uploadingChanged)
-        Q_PROPERTY(bool containsAtRoom READ containsAtRoom NOTIFY containsAtRoomChanged)
-        Q_PROPERTY(QString text READ text NOTIFY textChanged)
+    Q_OBJECT
+    Q_PROPERTY(bool uploading READ uploading NOTIFY uploadingChanged)
+    Q_PROPERTY(bool containsAtRoom READ containsAtRoom NOTIFY containsAtRoomChanged)
+    Q_PROPERTY(QString text READ text NOTIFY textChanged)
 
 public:
-        InputBar(TimelineModel *parent)
-          : QObject()
-          , room(parent)
-        {
-                typingRefresh_.setInterval(10'000);
-                typingRefresh_.setSingleShot(true);
-                typingTimeout_.setInterval(5'000);
-                typingTimeout_.setSingleShot(true);
-                connect(&typingRefresh_, &QTimer::timeout, this, &InputBar::startTyping);
-                connect(&typingTimeout_, &QTimer::timeout, this, &InputBar::stopTyping);
-        }
+    InputBar(TimelineModel *parent)
+      : QObject()
+      , room(parent)
+    {
+        typingRefresh_.setInterval(10'000);
+        typingRefresh_.setSingleShot(true);
+        typingTimeout_.setInterval(5'000);
+        typingTimeout_.setSingleShot(true);
+        connect(&typingRefresh_, &QTimer::timeout, this, &InputBar::startTyping);
+        connect(&typingTimeout_, &QTimer::timeout, this, &InputBar::stopTyping);
+    }
 
 public slots:
-        QString text() const;
-        QString previousText();
-        QString nextText();
-        void setText(QString newText);
-
-        bool containsAtRoom() const { return containsAtRoom_; }
-
-        void send();
-        void paste(bool fromMouse);
-        void insertMimeData(const QMimeData *data);
-        void updateState(int selectionStart, int selectionEnd, int cursorPosition, QString text);
-        void openFileSelection();
-        bool uploading() const { return uploading_; }
-        void message(QString body,
-                     MarkdownOverride useMarkdown = MarkdownOverride::NOT_SPECIFIED,
-                     bool rainbowify              = false);
-        void reaction(const QString &reactedEvent, const QString &reactionKey);
-        void sticker(CombinedImagePackModel *model, int row);
+    QString text() const;
+    QString previousText();
+    QString nextText();
+    void setText(QString newText);
+
+    bool containsAtRoom() const { return containsAtRoom_; }
+
+    void send();
+    void paste(bool fromMouse);
+    void insertMimeData(const QMimeData *data);
+    void updateState(int selectionStart, int selectionEnd, int cursorPosition, QString text);
+    void openFileSelection();
+    bool uploading() const { return uploading_; }
+    void message(QString body,
+                 MarkdownOverride useMarkdown = MarkdownOverride::NOT_SPECIFIED,
+                 bool rainbowify              = false);
+    void reaction(const QString &reactedEvent, const QString &reactionKey);
+    void sticker(CombinedImagePackModel *model, int row);
 
 private slots:
-        void startTyping();
-        void stopTyping();
+    void startTyping();
+    void stopTyping();
 
 signals:
-        void insertText(QString text);
-        void textChanged(QString newText);
-        void uploadingChanged(bool value);
-        void containsAtRoomChanged();
+    void insertText(QString text);
+    void textChanged(QString newText);
+    void uploadingChanged(bool value);
+    void containsAtRoomChanged();
 
 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,
-                  const QString &mime,
-                  uint64_t dsize);
-        void audio(const QString &filename,
-                   const std::optional<mtx::crypto::EncryptedFile> &file,
-                   const QString &url,
-                   const QString &mime,
-                   uint64_t dsize);
-        void video(const QString &filename,
-                   const std::optional<mtx::crypto::EncryptedFile> &file,
-                   const QString &url,
-                   const QString &mime,
-                   uint64_t dsize);
-
-        void showPreview(const QMimeData &source, QString path, const QStringList &formats);
-        void setUploading(bool value)
-        {
-                if (value != uploading_) {
-                        uploading_ = value;
-                        emit uploadingChanged(value);
-                }
+    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,
+              const QString &mime,
+              uint64_t dsize);
+    void audio(const QString &filename,
+               const std::optional<mtx::crypto::EncryptedFile> &file,
+               const QString &url,
+               const QString &mime,
+               uint64_t dsize);
+    void video(const QString &filename,
+               const std::optional<mtx::crypto::EncryptedFile> &file,
+               const QString &url,
+               const QString &mime,
+               uint64_t dsize);
+
+    void showPreview(const QMimeData &source, QString path, const QStringList &formats);
+    void setUploading(bool value)
+    {
+        if (value != uploading_) {
+            uploading_ = value;
+            emit uploadingChanged(value);
         }
-
-        void updateAtRoom(const QString &t);
-
-        QTimer typingRefresh_;
-        QTimer typingTimeout_;
-        TimelineModel *room;
-        std::deque<QString> history_;
-        std::size_t history_index_ = 0;
-        int selectionStart = 0, selectionEnd = 0, cursorPosition = 0;
-        bool uploading_      = false;
-        bool containsAtRoom_ = false;
+    }
+
+    void updateAtRoom(const QString &t);
+
+    QTimer typingRefresh_;
+    QTimer typingTimeout_;
+    TimelineModel *room;
+    std::deque<QString> history_;
+    std::size_t history_index_ = 0;
+    int selectionStart = 0, selectionEnd = 0, cursorPosition = 0;
+    bool uploading_      = false;
+    bool containsAtRoom_ = false;
 };
diff --git a/src/timeline/Permissions.cpp b/src/timeline/Permissions.cpp
index 5dafc325..4e45f2e2 100644
--- a/src/timeline/Permissions.cpp
+++ b/src/timeline/Permissions.cpp
@@ -12,59 +12,59 @@ Permissions::Permissions(QString roomId, QObject *parent)
   : QObject(parent)
   , roomId_(roomId)
 {
-        invalidate();
+    invalidate();
 }
 
 void
 Permissions::invalidate()
 {
-        pl = cache::client()
-               ->getStateEvent<mtx::events::state::PowerLevels>(roomId_.toStdString())
-               .value_or(mtx::events::StateEvent<mtx::events::state::PowerLevels>{})
-               .content;
+    pl = cache::client()
+           ->getStateEvent<mtx::events::state::PowerLevels>(roomId_.toStdString())
+           .value_or(mtx::events::StateEvent<mtx::events::state::PowerLevels>{})
+           .content;
 }
 
 bool
 Permissions::canInvite()
 {
-        return pl.user_level(http::client()->user_id().to_string()) >= pl.invite;
+    return pl.user_level(http::client()->user_id().to_string()) >= pl.invite;
 }
 
 bool
 Permissions::canBan()
 {
-        return pl.user_level(http::client()->user_id().to_string()) >= pl.ban;
+    return pl.user_level(http::client()->user_id().to_string()) >= pl.ban;
 }
 
 bool
 Permissions::canKick()
 {
-        return pl.user_level(http::client()->user_id().to_string()) >= pl.kick;
+    return pl.user_level(http::client()->user_id().to_string()) >= pl.kick;
 }
 
 bool
 Permissions::canRedact()
 {
-        return pl.user_level(http::client()->user_id().to_string()) >= pl.redact;
+    return pl.user_level(http::client()->user_id().to_string()) >= pl.redact;
 }
 bool
 Permissions::canChange(int eventType)
 {
-        return pl.user_level(http::client()->user_id().to_string()) >=
-               pl.state_level(to_string(qml_mtx_events::fromRoomEventType(
-                 static_cast<qml_mtx_events::EventType>(eventType))));
+    return pl.user_level(http::client()->user_id().to_string()) >=
+           pl.state_level(to_string(
+             qml_mtx_events::fromRoomEventType(static_cast<qml_mtx_events::EventType>(eventType))));
 }
 bool
 Permissions::canSend(int eventType)
 {
-        return pl.user_level(http::client()->user_id().to_string()) >=
-               pl.event_level(to_string(qml_mtx_events::fromRoomEventType(
-                 static_cast<qml_mtx_events::EventType>(eventType))));
+    return pl.user_level(http::client()->user_id().to_string()) >=
+           pl.event_level(to_string(
+             qml_mtx_events::fromRoomEventType(static_cast<qml_mtx_events::EventType>(eventType))));
 }
 
 bool
 Permissions::canPingRoom()
 {
-        return pl.user_level(http::client()->user_id().to_string()) >=
-               pl.notification_level(mtx::events::state::notification_keys::room);
+    return pl.user_level(http::client()->user_id().to_string()) >=
+           pl.notification_level(mtx::events::state::notification_keys::room);
 }
diff --git a/src/timeline/Permissions.h b/src/timeline/Permissions.h
index 349520d5..b80a66aa 100644
--- a/src/timeline/Permissions.h
+++ b/src/timeline/Permissions.h
@@ -12,24 +12,24 @@ class TimelineModel;
 
 class Permissions : public QObject
 {
-        Q_OBJECT
+    Q_OBJECT
 
 public:
-        Permissions(QString roomId, QObject *parent = nullptr);
+    Permissions(QString roomId, QObject *parent = nullptr);
 
-        Q_INVOKABLE bool canInvite();
-        Q_INVOKABLE bool canBan();
-        Q_INVOKABLE bool canKick();
+    Q_INVOKABLE bool canInvite();
+    Q_INVOKABLE bool canBan();
+    Q_INVOKABLE bool canKick();
 
-        Q_INVOKABLE bool canRedact();
-        Q_INVOKABLE bool canChange(int eventType);
-        Q_INVOKABLE bool canSend(int eventType);
+    Q_INVOKABLE bool canRedact();
+    Q_INVOKABLE bool canChange(int eventType);
+    Q_INVOKABLE bool canSend(int eventType);
 
-        Q_INVOKABLE bool canPingRoom();
+    Q_INVOKABLE bool canPingRoom();
 
-        void invalidate();
+    void invalidate();
 
 private:
-        QString roomId_;
-        mtx::events::state::PowerLevels pl;
+    QString roomId_;
+    mtx::events::state::PowerLevels pl;
 };
diff --git a/src/timeline/Reaction.h b/src/timeline/Reaction.h
index 788e9ced..fcdd61a4 100644
--- a/src/timeline/Reaction.h
+++ b/src/timeline/Reaction.h
@@ -9,20 +9,20 @@
 
 struct Reaction
 {
-        Q_GADGET
-        Q_PROPERTY(QString key READ key)
-        Q_PROPERTY(QString users READ users)
-        Q_PROPERTY(QString selfReactedEvent READ selfReactedEvent)
-        Q_PROPERTY(int count READ count)
+    Q_GADGET
+    Q_PROPERTY(QString key READ key)
+    Q_PROPERTY(QString users READ users)
+    Q_PROPERTY(QString selfReactedEvent READ selfReactedEvent)
+    Q_PROPERTY(int count READ count)
 
 public:
-        QString key() const { return key_.toHtmlEscaped(); }
-        QString users() const { return users_.toHtmlEscaped(); }
-        QString selfReactedEvent() const { return selfReactedEvent_; }
-        int count() const { return count_; }
+    QString key() const { return key_.toHtmlEscaped(); }
+    QString users() const { return users_.toHtmlEscaped(); }
+    QString selfReactedEvent() const { return selfReactedEvent_; }
+    int count() const { return count_; }
 
-        QString key_;
-        QString users_;
-        QString selfReactedEvent_;
-        int count_;
+    QString key_;
+    QString users_;
+    QString selfReactedEvent_;
+    int count_;
 };
diff --git a/src/timeline/RoomlistModel.cpp b/src/timeline/RoomlistModel.cpp
index 2d1dd49d..2d60dcb3 100644
--- a/src/timeline/RoomlistModel.cpp
+++ b/src/timeline/RoomlistModel.cpp
@@ -17,978 +17,947 @@ RoomlistModel::RoomlistModel(TimelineViewManager *parent)
   : QAbstractListModel(parent)
   , manager(parent)
 {
-        [[maybe_unused]] static auto id = qRegisterMetaType<RoomPreview>();
-
-        connect(ChatPage::instance(), &ChatPage::decryptSidebarChanged, this, [this]() {
-                auto decrypt = ChatPage::instance()->userSettings()->decryptSidebar();
-                QHash<QString, QSharedPointer<TimelineModel>>::iterator i;
-                for (i = models.begin(); i != models.end(); ++i) {
-                        auto ptr = i.value();
-
-                        if (!ptr.isNull()) {
-                                ptr->setDecryptDescription(decrypt);
-                                ptr->updateLastMessage();
-                        }
-                }
-        });
-
-        connect(this,
-                &RoomlistModel::totalUnreadMessageCountUpdated,
-                ChatPage::instance(),
-                &ChatPage::unreadMessages);
-
-        connect(
-          this,
-          &RoomlistModel::fetchedPreview,
-          this,
-          [this](QString roomid, RoomInfo info) {
-                  if (this->previewedRooms.contains(roomid)) {
-                          this->previewedRooms.insert(roomid, std::move(info));
-                          auto idx = this->roomidToIndex(roomid);
-                          emit dataChanged(index(idx),
-                                           index(idx),
-                                           {
-                                             Roles::RoomName,
-                                             Roles::AvatarUrl,
-                                             Roles::IsSpace,
-                                             Roles::IsPreviewFetched,
-                                             Qt::DisplayRole,
-                                           });
-                  }
-          },
-          Qt::QueuedConnection);
+    [[maybe_unused]] static auto id = qRegisterMetaType<RoomPreview>();
+
+    connect(ChatPage::instance(), &ChatPage::decryptSidebarChanged, this, [this]() {
+        auto decrypt = ChatPage::instance()->userSettings()->decryptSidebar();
+        QHash<QString, QSharedPointer<TimelineModel>>::iterator i;
+        for (i = models.begin(); i != models.end(); ++i) {
+            auto ptr = i.value();
+
+            if (!ptr.isNull()) {
+                ptr->setDecryptDescription(decrypt);
+                ptr->updateLastMessage();
+            }
+        }
+    });
+
+    connect(this,
+            &RoomlistModel::totalUnreadMessageCountUpdated,
+            ChatPage::instance(),
+            &ChatPage::unreadMessages);
+
+    connect(
+      this,
+      &RoomlistModel::fetchedPreview,
+      this,
+      [this](QString roomid, RoomInfo info) {
+          if (this->previewedRooms.contains(roomid)) {
+              this->previewedRooms.insert(roomid, std::move(info));
+              auto idx = this->roomidToIndex(roomid);
+              emit dataChanged(index(idx),
+                               index(idx),
+                               {
+                                 Roles::RoomName,
+                                 Roles::AvatarUrl,
+                                 Roles::IsSpace,
+                                 Roles::IsPreviewFetched,
+                                 Qt::DisplayRole,
+                               });
+          }
+      },
+      Qt::QueuedConnection);
 }
 
 QHash<int, QByteArray>
 RoomlistModel::roleNames() const
 {
-        return {
-          {AvatarUrl, "avatarUrl"},
-          {RoomName, "roomName"},
-          {RoomId, "roomId"},
-          {LastMessage, "lastMessage"},
-          {Time, "time"},
-          {Timestamp, "timestamp"},
-          {HasUnreadMessages, "hasUnreadMessages"},
-          {HasLoudNotification, "hasLoudNotification"},
-          {NotificationCount, "notificationCount"},
-          {IsInvite, "isInvite"},
-          {IsSpace, "isSpace"},
-          {Tags, "tags"},
-          {ParentSpaces, "parentSpaces"},
-          {IsDirect, "isDirect"},
-          {DirectChatOtherUserId, "directChatOtherUserId"},
-        };
+    return {
+      {AvatarUrl, "avatarUrl"},
+      {RoomName, "roomName"},
+      {RoomId, "roomId"},
+      {LastMessage, "lastMessage"},
+      {Time, "time"},
+      {Timestamp, "timestamp"},
+      {HasUnreadMessages, "hasUnreadMessages"},
+      {HasLoudNotification, "hasLoudNotification"},
+      {NotificationCount, "notificationCount"},
+      {IsInvite, "isInvite"},
+      {IsSpace, "isSpace"},
+      {Tags, "tags"},
+      {ParentSpaces, "parentSpaces"},
+      {IsDirect, "isDirect"},
+      {DirectChatOtherUserId, "directChatOtherUserId"},
+    };
 }
 
 QVariant
 RoomlistModel::data(const QModelIndex &index, int role) const
 {
-        if (index.row() >= 0 && static_cast<size_t>(index.row()) < roomids.size()) {
-                auto roomid = roomids.at(index.row());
-
-                if (role == Roles::ParentSpaces) {
-                        auto parents = cache::client()->getParentRoomIds(roomid.toStdString());
-                        QStringList list;
-                        for (const auto &t : parents)
-                                list.push_back(QString::fromStdString(t));
-                        return list;
-                } else if (role == Roles::RoomId) {
-                        return roomid;
-                }
+    if (index.row() >= 0 && static_cast<size_t>(index.row()) < roomids.size()) {
+        auto roomid = roomids.at(index.row());
+
+        if (role == Roles::ParentSpaces) {
+            auto parents = cache::client()->getParentRoomIds(roomid.toStdString());
+            QStringList list;
+            for (const auto &t : parents)
+                list.push_back(QString::fromStdString(t));
+            return list;
+        } else if (role == Roles::RoomId) {
+            return roomid;
+        }
 
-                if (models.contains(roomid)) {
-                        auto room = models.value(roomid);
-                        switch (role) {
-                        case Roles::AvatarUrl:
-                                return room->roomAvatarUrl();
-                        case Roles::RoomName:
-                                return room->plainRoomName();
-                        case Roles::LastMessage:
-                                return room->lastMessage().body;
-                        case Roles::Time:
-                                return room->lastMessage().descriptiveTime;
-                        case Roles::Timestamp:
-                                return QVariant(
-                                  static_cast<quint64>(room->lastMessage().timestamp));
-                        case Roles::HasUnreadMessages:
-                                return this->roomReadStatus.count(roomid) &&
-                                       this->roomReadStatus.at(roomid);
-                        case Roles::HasLoudNotification:
-                                return room->hasMentions();
-                        case Roles::NotificationCount:
-                                return room->notificationCount();
-                        case Roles::IsInvite:
-                                return false;
-                        case Roles::IsSpace:
-                                return room->isSpace();
-                        case Roles::IsPreview:
-                                return false;
-                        case Roles::Tags: {
-                                auto info = cache::singleRoomInfo(roomid.toStdString());
-                                QStringList list;
-                                for (const auto &t : info.tags)
-                                        list.push_back(QString::fromStdString(t));
-                                return list;
-                        }
-                        case Roles::IsDirect:
-                                return room->isDirect();
-                        case Roles::DirectChatOtherUserId:
-                                return room->directChatOtherUserId();
-                        default:
-                                return {};
-                        }
-                } else if (invites.contains(roomid)) {
-                        auto room = invites.value(roomid);
-                        switch (role) {
-                        case Roles::AvatarUrl:
-                                return QString::fromStdString(room.avatar_url);
-                        case Roles::RoomName:
-                                return QString::fromStdString(room.name);
-                        case Roles::LastMessage:
-                                return tr("Pending invite.");
-                        case Roles::Time:
-                                return QString();
-                        case Roles::Timestamp:
-                                return QVariant(static_cast<quint64>(0));
-                        case Roles::HasUnreadMessages:
-                        case Roles::HasLoudNotification:
-                                return false;
-                        case Roles::NotificationCount:
-                                return 0;
-                        case Roles::IsInvite:
-                                return true;
-                        case Roles::IsSpace:
-                                return false;
-                        case Roles::IsPreview:
-                                return false;
-                        case Roles::Tags:
-                                return QStringList();
-                        case Roles::IsDirect:
-                                // The list of users from the room doesn't contain the invited
-                                // users, so we won't factor the invite into the count
-                                return room.member_count == 1;
-                        case Roles::DirectChatOtherUserId:
-                                return cache::getMembersFromInvite(roomid.toStdString(), 0, 1)
-                                  .front()
-                                  .user_id;
-                        default:
-                                return {};
-                        }
-                } else if (previewedRooms.contains(roomid) &&
-                           previewedRooms.value(roomid).has_value()) {
-                        auto room = previewedRooms.value(roomid).value();
-                        switch (role) {
-                        case Roles::AvatarUrl:
-                                return QString::fromStdString(room.avatar_url);
-                        case Roles::RoomName:
-                                return QString::fromStdString(room.name);
-                        case Roles::LastMessage:
-                                return tr("Previewing this room");
-                        case Roles::Time:
-                                return QString();
-                        case Roles::Timestamp:
-                                return QVariant(static_cast<quint64>(0));
-                        case Roles::HasUnreadMessages:
-                        case Roles::HasLoudNotification:
-                                return false;
-                        case Roles::NotificationCount:
-                                return 0;
-                        case Roles::IsInvite:
-                                return false;
-                        case Roles::IsSpace:
-                                return room.is_space;
-                        case Roles::IsPreview:
-                                return true;
-                        case Roles::IsPreviewFetched:
-                                return true;
-                        case Roles::Tags:
-                                return QStringList();
-                        case Roles::IsDirect:
-                                return false;
-                        case Roles::DirectChatOtherUserId:
-                                return QString{}; // should never be reached
-                        default:
-                                return {};
-                        }
-                } else {
-                        if (role == Roles::IsPreview)
-                                return true;
-                        else if (role == Roles::IsPreviewFetched)
-                                return false;
-
-                        fetchPreview(roomid);
-                        switch (role) {
-                        case Roles::AvatarUrl:
-                                return QString();
-                        case Roles::RoomName:
-                                return tr("No preview available");
-                        case Roles::LastMessage:
-                                return QString();
-                        case Roles::Time:
-                                return QString();
-                        case Roles::Timestamp:
-                                return QVariant(static_cast<quint64>(0));
-                        case Roles::HasUnreadMessages:
-                        case Roles::HasLoudNotification:
-                                return false;
-                        case Roles::NotificationCount:
-                                return 0;
-                        case Roles::IsInvite:
-                                return false;
-                        case Roles::IsSpace:
-                                return false;
-                        case Roles::Tags:
-                                return QStringList();
-                        default:
-                                return {};
-                        }
-                }
+        if (models.contains(roomid)) {
+            auto room = models.value(roomid);
+            switch (role) {
+            case Roles::AvatarUrl:
+                return room->roomAvatarUrl();
+            case Roles::RoomName:
+                return room->plainRoomName();
+            case Roles::LastMessage:
+                return room->lastMessage().body;
+            case Roles::Time:
+                return room->lastMessage().descriptiveTime;
+            case Roles::Timestamp:
+                return QVariant(static_cast<quint64>(room->lastMessage().timestamp));
+            case Roles::HasUnreadMessages:
+                return this->roomReadStatus.count(roomid) && this->roomReadStatus.at(roomid);
+            case Roles::HasLoudNotification:
+                return room->hasMentions();
+            case Roles::NotificationCount:
+                return room->notificationCount();
+            case Roles::IsInvite:
+                return false;
+            case Roles::IsSpace:
+                return room->isSpace();
+            case Roles::IsPreview:
+                return false;
+            case Roles::Tags: {
+                auto info = cache::singleRoomInfo(roomid.toStdString());
+                QStringList list;
+                for (const auto &t : info.tags)
+                    list.push_back(QString::fromStdString(t));
+                return list;
+            }
+            case Roles::IsDirect:
+                return room->isDirect();
+            case Roles::DirectChatOtherUserId:
+                return room->directChatOtherUserId();
+            default:
+                return {};
+            }
+        } else if (invites.contains(roomid)) {
+            auto room = invites.value(roomid);
+            switch (role) {
+            case Roles::AvatarUrl:
+                return QString::fromStdString(room.avatar_url);
+            case Roles::RoomName:
+                return QString::fromStdString(room.name);
+            case Roles::LastMessage:
+                return tr("Pending invite.");
+            case Roles::Time:
+                return QString();
+            case Roles::Timestamp:
+                return QVariant(static_cast<quint64>(0));
+            case Roles::HasUnreadMessages:
+            case Roles::HasLoudNotification:
+                return false;
+            case Roles::NotificationCount:
+                return 0;
+            case Roles::IsInvite:
+                return true;
+            case Roles::IsSpace:
+                return false;
+            case Roles::IsPreview:
+                return false;
+            case Roles::Tags:
+                return QStringList();
+            case Roles::IsDirect:
+                // The list of users from the room doesn't contain the invited
+                // users, so we won't factor the invite into the count
+                return room.member_count == 1;
+            case Roles::DirectChatOtherUserId:
+                return cache::getMembersFromInvite(roomid.toStdString(), 0, 1).front().user_id;
+            default:
+                return {};
+            }
+        } else if (previewedRooms.contains(roomid) && previewedRooms.value(roomid).has_value()) {
+            auto room = previewedRooms.value(roomid).value();
+            switch (role) {
+            case Roles::AvatarUrl:
+                return QString::fromStdString(room.avatar_url);
+            case Roles::RoomName:
+                return QString::fromStdString(room.name);
+            case Roles::LastMessage:
+                return tr("Previewing this room");
+            case Roles::Time:
+                return QString();
+            case Roles::Timestamp:
+                return QVariant(static_cast<quint64>(0));
+            case Roles::HasUnreadMessages:
+            case Roles::HasLoudNotification:
+                return false;
+            case Roles::NotificationCount:
+                return 0;
+            case Roles::IsInvite:
+                return false;
+            case Roles::IsSpace:
+                return room.is_space;
+            case Roles::IsPreview:
+                return true;
+            case Roles::IsPreviewFetched:
+                return true;
+            case Roles::Tags:
+                return QStringList();
+            case Roles::IsDirect:
+                return false;
+            case Roles::DirectChatOtherUserId:
+                return QString{}; // should never be reached
+            default:
+                return {};
+            }
         } else {
+            if (role == Roles::IsPreview)
+                return true;
+            else if (role == Roles::IsPreviewFetched)
+                return false;
+
+            fetchPreview(roomid);
+            switch (role) {
+            case Roles::AvatarUrl:
+                return QString();
+            case Roles::RoomName:
+                return tr("No preview available");
+            case Roles::LastMessage:
+                return QString();
+            case Roles::Time:
+                return QString();
+            case Roles::Timestamp:
+                return QVariant(static_cast<quint64>(0));
+            case Roles::HasUnreadMessages:
+            case Roles::HasLoudNotification:
+                return false;
+            case Roles::NotificationCount:
+                return 0;
+            case Roles::IsInvite:
+                return false;
+            case Roles::IsSpace:
+                return false;
+            case Roles::Tags:
+                return QStringList();
+            default:
                 return {};
+            }
         }
+    } else {
+        return {};
+    }
 }
 
 void
 RoomlistModel::updateReadStatus(const std::map<QString, bool> roomReadStatus_)
 {
-        std::vector<int> roomsToUpdate;
-        roomsToUpdate.resize(roomReadStatus_.size());
-        for (const auto &[roomid, roomUnread] : roomReadStatus_) {
-                if (roomUnread != roomReadStatus[roomid]) {
-                        roomsToUpdate.push_back(this->roomidToIndex(roomid));
-                }
-
-                this->roomReadStatus[roomid] = roomUnread;
+    std::vector<int> roomsToUpdate;
+    roomsToUpdate.resize(roomReadStatus_.size());
+    for (const auto &[roomid, roomUnread] : roomReadStatus_) {
+        if (roomUnread != roomReadStatus[roomid]) {
+            roomsToUpdate.push_back(this->roomidToIndex(roomid));
         }
 
-        for (auto idx : roomsToUpdate) {
-                emit dataChanged(index(idx),
-                                 index(idx),
-                                 {
-                                   Roles::HasUnreadMessages,
-                                 });
-        }
+        this->roomReadStatus[roomid] = roomUnread;
+    }
+
+    for (auto idx : roomsToUpdate) {
+        emit dataChanged(index(idx),
+                         index(idx),
+                         {
+                           Roles::HasUnreadMessages,
+                         });
+    }
 }
 void
 RoomlistModel::addRoom(const QString &room_id, bool suppressInsertNotification)
 {
-        if (!models.contains(room_id)) {
-                // ensure we get read status updates and are only connected once
-                connect(cache::client(),
-                        &Cache::roomReadStatus,
-                        this,
-                        &RoomlistModel::updateReadStatus,
-                        Qt::UniqueConnection);
-
-                QSharedPointer<TimelineModel> newRoom(new TimelineModel(manager, room_id));
-                newRoom->setDecryptDescription(
-                  ChatPage::instance()->userSettings()->decryptSidebar());
-
-                connect(newRoom.data(),
-                        &TimelineModel::newEncryptedImage,
-                        manager->imageProvider(),
-                        &MxcImageProvider::addEncryptionInfo);
-                connect(newRoom.data(),
-                        &TimelineModel::forwardToRoom,
-                        manager,
-                        &TimelineViewManager::forwardMessageToRoom);
-                connect(
-                  newRoom.data(), &TimelineModel::lastMessageChanged, this, [room_id, this]() {
-                          auto idx = this->roomidToIndex(room_id);
-                          emit dataChanged(index(idx),
-                                           index(idx),
-                                           {
-                                             Roles::HasLoudNotification,
-                                             Roles::LastMessage,
-                                             Roles::Timestamp,
-                                             Roles::NotificationCount,
-                                             Qt::DisplayRole,
-                                           });
-                  });
-                connect(
-                  newRoom.data(), &TimelineModel::roomAvatarUrlChanged, this, [room_id, this]() {
-                          auto idx = this->roomidToIndex(room_id);
-                          emit dataChanged(index(idx),
-                                           index(idx),
-                                           {
-                                             Roles::AvatarUrl,
-                                           });
-                  });
-                connect(newRoom.data(), &TimelineModel::roomNameChanged, this, [room_id, this]() {
-                        auto idx = this->roomidToIndex(room_id);
-                        emit dataChanged(index(idx),
-                                         index(idx),
-                                         {
-                                           Roles::RoomName,
-                                         });
-                });
-                connect(
-                  newRoom.data(), &TimelineModel::notificationsChanged, this, [room_id, this]() {
-                          auto idx = this->roomidToIndex(room_id);
-                          emit dataChanged(index(idx),
-                                           index(idx),
-                                           {
-                                             Roles::HasLoudNotification,
-                                             Roles::NotificationCount,
-                                             Qt::DisplayRole,
-                                           });
-
-                          int total_unread_msgs = 0;
-
-                          for (const auto &room : models) {
-                                  if (!room.isNull())
-                                          total_unread_msgs += room->notificationCount();
-                          }
-
-                          emit totalUnreadMessageCountUpdated(total_unread_msgs);
-                  });
-
-                newRoom->updateLastMessage();
-
-                std::vector<QString> previewsToAdd;
-                if (newRoom->isSpace()) {
-                        auto childs = cache::client()->getChildRoomIds(room_id.toStdString());
-                        for (const auto &c : childs) {
-                                auto id = QString::fromStdString(c);
-                                if (!(models.contains(id) || invites.contains(id) ||
-                                      previewedRooms.contains(id))) {
-                                        previewsToAdd.push_back(std::move(id));
-                                }
-                        }
-                }
+    if (!models.contains(room_id)) {
+        // ensure we get read status updates and are only connected once
+        connect(cache::client(),
+                &Cache::roomReadStatus,
+                this,
+                &RoomlistModel::updateReadStatus,
+                Qt::UniqueConnection);
+
+        QSharedPointer<TimelineModel> newRoom(new TimelineModel(manager, room_id));
+        newRoom->setDecryptDescription(ChatPage::instance()->userSettings()->decryptSidebar());
+
+        connect(newRoom.data(),
+                &TimelineModel::newEncryptedImage,
+                manager->imageProvider(),
+                &MxcImageProvider::addEncryptionInfo);
+        connect(newRoom.data(),
+                &TimelineModel::forwardToRoom,
+                manager,
+                &TimelineViewManager::forwardMessageToRoom);
+        connect(newRoom.data(), &TimelineModel::lastMessageChanged, this, [room_id, this]() {
+            auto idx = this->roomidToIndex(room_id);
+            emit dataChanged(index(idx),
+                             index(idx),
+                             {
+                               Roles::HasLoudNotification,
+                               Roles::LastMessage,
+                               Roles::Timestamp,
+                               Roles::NotificationCount,
+                               Qt::DisplayRole,
+                             });
+        });
+        connect(newRoom.data(), &TimelineModel::roomAvatarUrlChanged, this, [room_id, this]() {
+            auto idx = this->roomidToIndex(room_id);
+            emit dataChanged(index(idx),
+                             index(idx),
+                             {
+                               Roles::AvatarUrl,
+                             });
+        });
+        connect(newRoom.data(), &TimelineModel::roomNameChanged, this, [room_id, this]() {
+            auto idx = this->roomidToIndex(room_id);
+            emit dataChanged(index(idx),
+                             index(idx),
+                             {
+                               Roles::RoomName,
+                             });
+        });
+        connect(newRoom.data(), &TimelineModel::notificationsChanged, this, [room_id, this]() {
+            auto idx = this->roomidToIndex(room_id);
+            emit dataChanged(index(idx),
+                             index(idx),
+                             {
+                               Roles::HasLoudNotification,
+                               Roles::NotificationCount,
+                               Qt::DisplayRole,
+                             });
+
+            int total_unread_msgs = 0;
+
+            for (const auto &room : models) {
+                if (!room.isNull())
+                    total_unread_msgs += room->notificationCount();
+            }
+
+            emit totalUnreadMessageCountUpdated(total_unread_msgs);
+        });
 
-                bool wasInvite  = invites.contains(room_id);
-                bool wasPreview = previewedRooms.contains(room_id);
-                if (!suppressInsertNotification &&
-                    ((!wasInvite && !wasPreview) || !previewedRooms.empty()))
-                        // if the old room was already in the list, don't add it. Also add all
-                        // previews at the same time.
-                        beginInsertRows(QModelIndex(),
-                                        (int)roomids.size(),
-                                        (int)(roomids.size() + previewsToAdd.size() -
-                                              ((wasInvite || wasPreview) ? 1 : 0)));
-
-                models.insert(room_id, std::move(newRoom));
-                if (wasInvite) {
-                        auto idx = roomidToIndex(room_id);
-                        invites.remove(room_id);
-                        emit dataChanged(index(idx), index(idx));
-                } else if (wasPreview) {
-                        auto idx = roomidToIndex(room_id);
-                        previewedRooms.remove(room_id);
-                        emit dataChanged(index(idx), index(idx));
-                } else {
-                        roomids.push_back(room_id);
-                }
+        newRoom->updateLastMessage();
 
-                if ((wasInvite || wasPreview) && currentRoomPreview_ &&
-                    currentRoomPreview_->roomid() == room_id) {
-                        currentRoom_ = models.value(room_id);
-                        currentRoomPreview_.reset();
-                        emit currentRoomChanged();
+        std::vector<QString> previewsToAdd;
+        if (newRoom->isSpace()) {
+            auto childs = cache::client()->getChildRoomIds(room_id.toStdString());
+            for (const auto &c : childs) {
+                auto id = QString::fromStdString(c);
+                if (!(models.contains(id) || invites.contains(id) || previewedRooms.contains(id))) {
+                    previewsToAdd.push_back(std::move(id));
                 }
+            }
+        }
 
-                for (auto p : previewsToAdd) {
-                        previewedRooms.insert(p, std::nullopt);
-                        roomids.push_back(std::move(p));
-                }
+        bool wasInvite  = invites.contains(room_id);
+        bool wasPreview = previewedRooms.contains(room_id);
+        if (!suppressInsertNotification && ((!wasInvite && !wasPreview) || !previewedRooms.empty()))
+            // if the old room was already in the list, don't add it. Also add all
+            // previews at the same time.
+            beginInsertRows(
+              QModelIndex(),
+              (int)roomids.size(),
+              (int)(roomids.size() + previewsToAdd.size() - ((wasInvite || wasPreview) ? 1 : 0)));
+
+        models.insert(room_id, std::move(newRoom));
+        if (wasInvite) {
+            auto idx = roomidToIndex(room_id);
+            invites.remove(room_id);
+            emit dataChanged(index(idx), index(idx));
+        } else if (wasPreview) {
+            auto idx = roomidToIndex(room_id);
+            previewedRooms.remove(room_id);
+            emit dataChanged(index(idx), index(idx));
+        } else {
+            roomids.push_back(room_id);
+        }
 
-                if (!suppressInsertNotification &&
-                    ((!wasInvite && !wasPreview) || !previewedRooms.empty()))
-                        endInsertRows();
+        if ((wasInvite || wasPreview) && currentRoomPreview_ &&
+            currentRoomPreview_->roomid() == room_id) {
+            currentRoom_ = models.value(room_id);
+            currentRoomPreview_.reset();
+            emit currentRoomChanged();
+        }
 
-                emit ChatPage::instance()->newRoom(room_id);
+        for (auto p : previewsToAdd) {
+            previewedRooms.insert(p, std::nullopt);
+            roomids.push_back(std::move(p));
         }
+
+        if (!suppressInsertNotification && ((!wasInvite && !wasPreview) || !previewedRooms.empty()))
+            endInsertRows();
+
+        emit ChatPage::instance()->newRoom(room_id);
+    }
 }
 
 void
 RoomlistModel::fetchPreview(QString roomid_) const
 {
-        std::string roomid = roomid_.toStdString();
-        http::client()->get_state_event<mtx::events::state::Create>(
-          roomid,
-          "",
-          [this, roomid](const mtx::events::state::Create &c, mtx::http::RequestErr err) {
-                  bool is_space = false;
-                  if (!err) {
-                          is_space = c.type == mtx::events::state::room_type::space;
-                  }
-
-                  http::client()->get_state_event<mtx::events::state::Avatar>(
-                    roomid,
-                    "",
-                    [this, roomid, is_space](const mtx::events::state::Avatar &a,
-                                             mtx::http::RequestErr) {
-                            auto avatar_url = a.url;
-
-                            http::client()->get_state_event<mtx::events::state::Topic>(
-                              roomid,
-                              "",
-                              [this, roomid, avatar_url, is_space](
-                                const mtx::events::state::Topic &t, mtx::http::RequestErr) {
-                                      auto topic = t.topic;
-                                      http::client()->get_state_event<mtx::events::state::Name>(
-                                        roomid,
-                                        "",
-                                        [this, roomid, topic, avatar_url, is_space](
-                                          const mtx::events::state::Name &n,
-                                          mtx::http::RequestErr err) {
-                                                if (err) {
-                                                        nhlog::net()->warn(
-                                                          "Failed to fetch name event to "
-                                                          "create preview for {}",
-                                                          roomid);
-                                                }
-
-                                                // don't even add a preview, if we got not a single
-                                                // response
-                                                if (n.name.empty() && avatar_url.empty() &&
-                                                    topic.empty())
-                                                        return;
-
-                                                RoomInfo info{};
-                                                info.name       = n.name;
-                                                info.is_space   = is_space;
-                                                info.avatar_url = avatar_url;
-                                                info.topic      = topic;
-
-                                                const_cast<RoomlistModel *>(this)->fetchedPreview(
-                                                  QString::fromStdString(roomid), info);
-                                        });
-                              });
-                    });
-          });
+    std::string roomid = roomid_.toStdString();
+    http::client()->get_state_event<mtx::events::state::Create>(
+      roomid, "", [this, roomid](const mtx::events::state::Create &c, mtx::http::RequestErr err) {
+          bool is_space = false;
+          if (!err) {
+              is_space = c.type == mtx::events::state::room_type::space;
+          }
+
+          http::client()->get_state_event<mtx::events::state::Avatar>(
+            roomid,
+            "",
+            [this, roomid, is_space](const mtx::events::state::Avatar &a, mtx::http::RequestErr) {
+                auto avatar_url = a.url;
+
+                http::client()->get_state_event<mtx::events::state::Topic>(
+                  roomid,
+                  "",
+                  [this, roomid, avatar_url, is_space](const mtx::events::state::Topic &t,
+                                                       mtx::http::RequestErr) {
+                      auto topic = t.topic;
+                      http::client()->get_state_event<mtx::events::state::Name>(
+                        roomid,
+                        "",
+                        [this, roomid, topic, avatar_url, is_space](
+                          const mtx::events::state::Name &n, mtx::http::RequestErr err) {
+                            if (err) {
+                                nhlog::net()->warn("Failed to fetch name event to "
+                                                   "create preview for {}",
+                                                   roomid);
+                            }
+
+                            // don't even add a preview, if we got not a single
+                            // response
+                            if (n.name.empty() && avatar_url.empty() && topic.empty())
+                                return;
+
+                            RoomInfo info{};
+                            info.name       = n.name;
+                            info.is_space   = is_space;
+                            info.avatar_url = avatar_url;
+                            info.topic      = topic;
+
+                            const_cast<RoomlistModel *>(this)->fetchedPreview(
+                              QString::fromStdString(roomid), info);
+                        });
+                  });
+            });
+      });
 }
 
 void
 RoomlistModel::sync(const mtx::responses::Rooms &rooms)
 {
-        for (const auto &[room_id, room] : rooms.join) {
-                auto qroomid = QString::fromStdString(room_id);
-
-                // addRoom will only add the room, if it doesn't exist
-                addRoom(qroomid);
-                const auto &room_model = models.value(qroomid);
-                room_model->sync(room);
-                // room_model->addEvents(room.timeline);
-                connect(room_model.data(),
-                        &TimelineModel::newCallEvent,
-                        manager->callManager(),
-                        &CallManager::syncEvent,
-                        Qt::UniqueConnection);
-
-                if (ChatPage::instance()->userSettings()->typingNotifications()) {
-                        for (const auto &ev : room.ephemeral.events) {
-                                if (auto t = std::get_if<
-                                      mtx::events::EphemeralEvent<mtx::events::ephemeral::Typing>>(
-                                      &ev)) {
-                                        std::vector<QString> typing;
-                                        typing.reserve(t->content.user_ids.size());
-                                        for (const auto &user : t->content.user_ids) {
-                                                if (user != http::client()->user_id().to_string())
-                                                        typing.push_back(
-                                                          QString::fromStdString(user));
-                                        }
-                                        room_model->updateTypingUsers(typing);
-                                }
-                        }
+    for (const auto &[room_id, room] : rooms.join) {
+        auto qroomid = QString::fromStdString(room_id);
+
+        // addRoom will only add the room, if it doesn't exist
+        addRoom(qroomid);
+        const auto &room_model = models.value(qroomid);
+        room_model->sync(room);
+        // room_model->addEvents(room.timeline);
+        connect(room_model.data(),
+                &TimelineModel::newCallEvent,
+                manager->callManager(),
+                &CallManager::syncEvent,
+                Qt::UniqueConnection);
+
+        if (ChatPage::instance()->userSettings()->typingNotifications()) {
+            for (const auto &ev : room.ephemeral.events) {
+                if (auto t =
+                      std::get_if<mtx::events::EphemeralEvent<mtx::events::ephemeral::Typing>>(
+                        &ev)) {
+                    std::vector<QString> typing;
+                    typing.reserve(t->content.user_ids.size());
+                    for (const auto &user : t->content.user_ids) {
+                        if (user != http::client()->user_id().to_string())
+                            typing.push_back(QString::fromStdString(user));
+                    }
+                    room_model->updateTypingUsers(typing);
                 }
+            }
         }
-
-        for (const auto &[room_id, room] : rooms.leave) {
-                (void)room;
-                auto qroomid = QString::fromStdString(room_id);
-
-                if ((currentRoom_ && currentRoom_->roomId() == qroomid) ||
-                    (currentRoomPreview_ && currentRoomPreview_->roomid() == qroomid))
-                        resetCurrentRoom();
-
-                auto idx = this->roomidToIndex(qroomid);
-                if (idx != -1) {
-                        beginRemoveRows(QModelIndex(), idx, idx);
-                        roomids.erase(roomids.begin() + idx);
-                        if (models.contains(qroomid))
-                                models.remove(qroomid);
-                        else if (invites.contains(qroomid))
-                                invites.remove(qroomid);
-                        endRemoveRows();
-                }
+    }
+
+    for (const auto &[room_id, room] : rooms.leave) {
+        (void)room;
+        auto qroomid = QString::fromStdString(room_id);
+
+        if ((currentRoom_ && currentRoom_->roomId() == qroomid) ||
+            (currentRoomPreview_ && currentRoomPreview_->roomid() == qroomid))
+            resetCurrentRoom();
+
+        auto idx = this->roomidToIndex(qroomid);
+        if (idx != -1) {
+            beginRemoveRows(QModelIndex(), idx, idx);
+            roomids.erase(roomids.begin() + idx);
+            if (models.contains(qroomid))
+                models.remove(qroomid);
+            else if (invites.contains(qroomid))
+                invites.remove(qroomid);
+            endRemoveRows();
         }
+    }
 
-        for (const auto &[room_id, room] : rooms.invite) {
-                (void)room;
-                auto qroomid = QString::fromStdString(room_id);
-
-                auto invite = cache::client()->invite(room_id);
-                if (!invite)
-                        continue;
-
-                if (invites.contains(qroomid)) {
-                        invites[qroomid] = *invite;
-                        auto idx         = roomidToIndex(qroomid);
-                        emit dataChanged(index(idx), index(idx));
-                } else {
-                        beginInsertRows(QModelIndex(), (int)roomids.size(), (int)roomids.size());
-                        invites.insert(qroomid, *invite);
-                        roomids.push_back(std::move(qroomid));
-                        endInsertRows();
-                }
+    for (const auto &[room_id, room] : rooms.invite) {
+        (void)room;
+        auto qroomid = QString::fromStdString(room_id);
+
+        auto invite = cache::client()->invite(room_id);
+        if (!invite)
+            continue;
+
+        if (invites.contains(qroomid)) {
+            invites[qroomid] = *invite;
+            auto idx         = roomidToIndex(qroomid);
+            emit dataChanged(index(idx), index(idx));
+        } else {
+            beginInsertRows(QModelIndex(), (int)roomids.size(), (int)roomids.size());
+            invites.insert(qroomid, *invite);
+            roomids.push_back(std::move(qroomid));
+            endInsertRows();
         }
+    }
 }
 
 void
 RoomlistModel::initializeRooms()
 {
-        beginResetModel();
-        models.clear();
-        roomids.clear();
-        invites.clear();
-        currentRoom_ = nullptr;
+    beginResetModel();
+    models.clear();
+    roomids.clear();
+    invites.clear();
+    currentRoom_ = nullptr;
 
-        invites = cache::client()->invites();
-        for (const auto &id : invites.keys())
-                roomids.push_back(id);
+    invites = cache::client()->invites();
+    for (const auto &id : invites.keys())
+        roomids.push_back(id);
 
-        for (const auto &id : cache::client()->roomIds())
-                addRoom(id, true);
+    for (const auto &id : cache::client()->roomIds())
+        addRoom(id, true);
 
-        nhlog::db()->info("Restored {} rooms from cache", rowCount());
+    nhlog::db()->info("Restored {} rooms from cache", rowCount());
 
-        endResetModel();
+    endResetModel();
 }
 
 void
 RoomlistModel::clear()
 {
-        beginResetModel();
-        models.clear();
-        invites.clear();
-        roomids.clear();
-        currentRoom_ = nullptr;
-        emit currentRoomChanged();
-        endResetModel();
+    beginResetModel();
+    models.clear();
+    invites.clear();
+    roomids.clear();
+    currentRoom_ = nullptr;
+    emit currentRoomChanged();
+    endResetModel();
 }
 
 void
 RoomlistModel::joinPreview(QString roomid, QString parentSpace)
 {
-        if (previewedRooms.contains(roomid)) {
-                auto child = cache::client()->getStateEvent<mtx::events::state::space::Child>(
-                  parentSpace.toStdString(), roomid.toStdString());
-                ChatPage::instance()->joinRoomVia(roomid.toStdString(),
-                                                  (child && child->content.via)
-                                                    ? child->content.via.value()
-                                                    : std::vector<std::string>{},
-                                                  false);
-        }
+    if (previewedRooms.contains(roomid)) {
+        auto child = cache::client()->getStateEvent<mtx::events::state::space::Child>(
+          parentSpace.toStdString(), roomid.toStdString());
+        ChatPage::instance()->joinRoomVia(
+          roomid.toStdString(),
+          (child && child->content.via) ? child->content.via.value() : std::vector<std::string>{},
+          false);
+    }
 }
 void
 RoomlistModel::acceptInvite(QString roomid)
 {
-        if (invites.contains(roomid)) {
-                // Don't remove invite yet, so that we can switch to it
-                ChatPage::instance()->joinRoom(roomid);
-        }
+    if (invites.contains(roomid)) {
+        // Don't remove invite yet, so that we can switch to it
+        ChatPage::instance()->joinRoom(roomid);
+    }
 }
 void
 RoomlistModel::declineInvite(QString roomid)
 {
-        if (invites.contains(roomid)) {
-                auto idx = roomidToIndex(roomid);
-
-                if (idx != -1) {
-                        beginRemoveRows(QModelIndex(), idx, idx);
-                        roomids.erase(roomids.begin() + idx);
-                        invites.remove(roomid);
-                        endRemoveRows();
-                        ChatPage::instance()->leaveRoom(roomid);
-                }
+    if (invites.contains(roomid)) {
+        auto idx = roomidToIndex(roomid);
+
+        if (idx != -1) {
+            beginRemoveRows(QModelIndex(), idx, idx);
+            roomids.erase(roomids.begin() + idx);
+            invites.remove(roomid);
+            endRemoveRows();
+            ChatPage::instance()->leaveRoom(roomid);
         }
+    }
 }
 void
 RoomlistModel::leave(QString roomid)
 {
-        if (models.contains(roomid)) {
-                auto idx = roomidToIndex(roomid);
-
-                if (idx != -1) {
-                        beginRemoveRows(QModelIndex(), idx, idx);
-                        roomids.erase(roomids.begin() + idx);
-                        models.remove(roomid);
-                        endRemoveRows();
-                        ChatPage::instance()->leaveRoom(roomid);
-                }
+    if (models.contains(roomid)) {
+        auto idx = roomidToIndex(roomid);
+
+        if (idx != -1) {
+            beginRemoveRows(QModelIndex(), idx, idx);
+            roomids.erase(roomids.begin() + idx);
+            models.remove(roomid);
+            endRemoveRows();
+            ChatPage::instance()->leaveRoom(roomid);
         }
+    }
 }
 
 void
 RoomlistModel::setCurrentRoom(QString roomid)
 {
-        if ((currentRoom_ && currentRoom_->roomId() == roomid) ||
-            (currentRoomPreview_ && currentRoomPreview_->roomid() == roomid))
-                return;
+    if ((currentRoom_ && currentRoom_->roomId() == roomid) ||
+        (currentRoomPreview_ && currentRoomPreview_->roomid() == roomid))
+        return;
+
+    nhlog::ui()->debug("Trying to switch to: {}", roomid.toStdString());
+    if (models.contains(roomid)) {
+        currentRoom_ = models.value(roomid);
+        currentRoomPreview_.reset();
+        emit currentRoomChanged();
+        nhlog::ui()->debug("Switched to: {}", roomid.toStdString());
+    } else if (invites.contains(roomid) || previewedRooms.contains(roomid)) {
+        currentRoom_ = nullptr;
+        std::optional<RoomInfo> i;
 
-        nhlog::ui()->debug("Trying to switch to: {}", roomid.toStdString());
-        if (models.contains(roomid)) {
-                currentRoom_ = models.value(roomid);
-                currentRoomPreview_.reset();
-                emit currentRoomChanged();
-                nhlog::ui()->debug("Switched to: {}", roomid.toStdString());
-        } else if (invites.contains(roomid) || previewedRooms.contains(roomid)) {
-                currentRoom_ = nullptr;
-                std::optional<RoomInfo> i;
-
-                RoomPreview p;
-
-                if (invites.contains(roomid)) {
-                        i           = invites.value(roomid);
-                        p.isInvite_ = true;
-                } else {
-                        i           = previewedRooms.value(roomid);
-                        p.isInvite_ = false;
-                }
+        RoomPreview p;
 
-                if (i) {
-                        p.roomid_           = roomid;
-                        p.roomName_         = QString::fromStdString(i->name);
-                        p.roomTopic_        = QString::fromStdString(i->topic);
-                        p.roomAvatarUrl_    = QString::fromStdString(i->avatar_url);
-                        currentRoomPreview_ = std::move(p);
-                }
+        if (invites.contains(roomid)) {
+            i           = invites.value(roomid);
+            p.isInvite_ = true;
+        } else {
+            i           = previewedRooms.value(roomid);
+            p.isInvite_ = false;
+        }
 
-                emit currentRoomChanged();
-                nhlog::ui()->debug("Switched to: {}", roomid.toStdString());
+        if (i) {
+            p.roomid_           = roomid;
+            p.roomName_         = QString::fromStdString(i->name);
+            p.roomTopic_        = QString::fromStdString(i->topic);
+            p.roomAvatarUrl_    = QString::fromStdString(i->avatar_url);
+            currentRoomPreview_ = std::move(p);
         }
+
+        emit currentRoomChanged();
+        nhlog::ui()->debug("Switched to: {}", roomid.toStdString());
+    }
 }
 
 namespace {
 enum NotificationImportance : short
 {
-        ImportanceDisabled = -3,
-        NoPreview          = -2,
-        Preview            = -1,
-        AllEventsRead      = 0,
-        NewMessage         = 1,
-        NewMentions        = 2,
-        Invite             = 3,
-        SubSpace           = 4,
-        CurrentSpace       = 5,
+    ImportanceDisabled = -3,
+    NoPreview          = -2,
+    Preview            = -1,
+    AllEventsRead      = 0,
+    NewMessage         = 1,
+    NewMentions        = 2,
+    Invite             = 3,
+    SubSpace           = 4,
+    CurrentSpace       = 5,
 };
 }
 
 short int
 FilteredRoomlistModel::calculateImportance(const QModelIndex &idx) const
 {
-        // Returns the degree of importance of the unread messages in the room.
-        // If sorting by importance is disabled in settings, this only ever
-        // returns ImportanceDisabled or Invite
-        if (sourceModel()->data(idx, RoomlistModel::IsSpace).toBool()) {
-                if (filterType == FilterBy::Space &&
-                    filterStr == sourceModel()->data(idx, RoomlistModel::RoomId).toString())
-                        return CurrentSpace;
-                else
-                        return SubSpace;
-        } else if (sourceModel()->data(idx, RoomlistModel::IsPreview).toBool()) {
-                if (sourceModel()->data(idx, RoomlistModel::IsPreviewFetched).toBool())
-                        return Preview;
-                else
-                        return NoPreview;
-        } else if (sourceModel()->data(idx, RoomlistModel::IsInvite).toBool()) {
-                return Invite;
-        } else if (!this->sortByImportance) {
-                return ImportanceDisabled;
-        } else if (sourceModel()->data(idx, RoomlistModel::HasLoudNotification).toBool()) {
-                return NewMentions;
-        } else if (sourceModel()->data(idx, RoomlistModel::NotificationCount).toInt() > 0) {
-                return NewMessage;
-        } else {
-                return AllEventsRead;
-        }
+    // Returns the degree of importance of the unread messages in the room.
+    // If sorting by importance is disabled in settings, this only ever
+    // returns ImportanceDisabled or Invite
+    if (sourceModel()->data(idx, RoomlistModel::IsSpace).toBool()) {
+        if (filterType == FilterBy::Space &&
+            filterStr == sourceModel()->data(idx, RoomlistModel::RoomId).toString())
+            return CurrentSpace;
+        else
+            return SubSpace;
+    } else if (sourceModel()->data(idx, RoomlistModel::IsPreview).toBool()) {
+        if (sourceModel()->data(idx, RoomlistModel::IsPreviewFetched).toBool())
+            return Preview;
+        else
+            return NoPreview;
+    } else if (sourceModel()->data(idx, RoomlistModel::IsInvite).toBool()) {
+        return Invite;
+    } else if (!this->sortByImportance) {
+        return ImportanceDisabled;
+    } else if (sourceModel()->data(idx, RoomlistModel::HasLoudNotification).toBool()) {
+        return NewMentions;
+    } else if (sourceModel()->data(idx, RoomlistModel::NotificationCount).toInt() > 0) {
+        return NewMessage;
+    } else {
+        return AllEventsRead;
+    }
 }
 
 bool
 FilteredRoomlistModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
 {
-        QModelIndex const left_idx  = sourceModel()->index(left.row(), 0, QModelIndex());
-        QModelIndex const right_idx = sourceModel()->index(right.row(), 0, QModelIndex());
-
-        // Sort by "importance" (i.e. invites before mentions before
-        // notifs before new events before old events), then secondly
-        // by recency.
-
-        // Checking importance first
-        const auto a_importance = calculateImportance(left_idx);
-        const auto b_importance = calculateImportance(right_idx);
-        if (a_importance != b_importance) {
-                return a_importance > b_importance;
-        }
-
-        // Now sort by recency
-        // Zero if empty, otherwise the time that the event occured
-        uint64_t a_recency = sourceModel()->data(left_idx, RoomlistModel::Timestamp).toULongLong();
-        uint64_t b_recency = sourceModel()->data(right_idx, RoomlistModel::Timestamp).toULongLong();
-
-        if (a_recency != b_recency)
-                return a_recency > b_recency;
-        else
-                return left.row() < right.row();
+    QModelIndex const left_idx  = sourceModel()->index(left.row(), 0, QModelIndex());
+    QModelIndex const right_idx = sourceModel()->index(right.row(), 0, QModelIndex());
+
+    // Sort by "importance" (i.e. invites before mentions before
+    // notifs before new events before old events), then secondly
+    // by recency.
+
+    // Checking importance first
+    const auto a_importance = calculateImportance(left_idx);
+    const auto b_importance = calculateImportance(right_idx);
+    if (a_importance != b_importance) {
+        return a_importance > b_importance;
+    }
+
+    // Now sort by recency
+    // Zero if empty, otherwise the time that the event occured
+    uint64_t a_recency = sourceModel()->data(left_idx, RoomlistModel::Timestamp).toULongLong();
+    uint64_t b_recency = sourceModel()->data(right_idx, RoomlistModel::Timestamp).toULongLong();
+
+    if (a_recency != b_recency)
+        return a_recency > b_recency;
+    else
+        return left.row() < right.row();
 }
 
 FilteredRoomlistModel::FilteredRoomlistModel(RoomlistModel *model, QObject *parent)
   : QSortFilterProxyModel(parent)
   , roomlistmodel(model)
 {
-        this->sortByImportance = UserSettings::instance()->sortByImportance();
-        setSourceModel(model);
-        setDynamicSortFilter(true);
-
-        QObject::connect(UserSettings::instance().get(),
-                         &UserSettings::roomSortingChanged,
-                         this,
-                         [this](bool sortByImportance_) {
-                                 this->sortByImportance = sortByImportance_;
-                                 invalidate();
-                         });
-
-        connect(roomlistmodel,
-                &RoomlistModel::currentRoomChanged,
-                this,
-                &FilteredRoomlistModel::currentRoomChanged);
-
-        sort(0);
+    this->sortByImportance = UserSettings::instance()->sortByImportance();
+    setSourceModel(model);
+    setDynamicSortFilter(true);
+
+    QObject::connect(UserSettings::instance().get(),
+                     &UserSettings::roomSortingChanged,
+                     this,
+                     [this](bool sortByImportance_) {
+                         this->sortByImportance = sortByImportance_;
+                         invalidate();
+                     });
+
+    connect(roomlistmodel,
+            &RoomlistModel::currentRoomChanged,
+            this,
+            &FilteredRoomlistModel::currentRoomChanged);
+
+    sort(0);
 }
 
 void
 FilteredRoomlistModel::updateHiddenTagsAndSpaces()
 {
-        hiddenTags.clear();
-        hiddenSpaces.clear();
-        for (const auto &t : UserSettings::instance()->hiddenTags()) {
-                if (t.startsWith("tag:"))
-                        hiddenTags.push_back(t.mid(4));
-                else if (t.startsWith("space:"))
-                        hiddenSpaces.push_back(t.mid(6));
-        }
-
-        invalidateFilter();
+    hiddenTags.clear();
+    hiddenSpaces.clear();
+    for (const auto &t : UserSettings::instance()->hiddenTags()) {
+        if (t.startsWith("tag:"))
+            hiddenTags.push_back(t.mid(4));
+        else if (t.startsWith("space:"))
+            hiddenSpaces.push_back(t.mid(6));
+    }
+
+    invalidateFilter();
 }
 
 bool
 FilteredRoomlistModel::filterAcceptsRow(int sourceRow, const QModelIndex &) const
 {
-        if (filterType == FilterBy::Nothing) {
-                if (sourceModel()
-                      ->data(sourceModel()->index(sourceRow, 0), RoomlistModel::IsPreview)
-                      .toBool()) {
-                        return false;
-                }
+    if (filterType == FilterBy::Nothing) {
+        if (sourceModel()
+              ->data(sourceModel()->index(sourceRow, 0), RoomlistModel::IsPreview)
+              .toBool()) {
+            return false;
+        }
 
-                if (sourceModel()
-                      ->data(sourceModel()->index(sourceRow, 0), RoomlistModel::IsSpace)
-                      .toBool()) {
-                        return false;
-                }
+        if (sourceModel()
+              ->data(sourceModel()->index(sourceRow, 0), RoomlistModel::IsSpace)
+              .toBool()) {
+            return false;
+        }
 
-                if (!hiddenTags.empty()) {
-                        auto tags =
-                          sourceModel()
-                            ->data(sourceModel()->index(sourceRow, 0), RoomlistModel::Tags)
-                            .toStringList();
+        if (!hiddenTags.empty()) {
+            auto tags = sourceModel()
+                          ->data(sourceModel()->index(sourceRow, 0), RoomlistModel::Tags)
+                          .toStringList();
 
-                        for (const auto &t : tags)
-                                if (hiddenTags.contains(t))
-                                        return false;
-                }
+            for (const auto &t : tags)
+                if (hiddenTags.contains(t))
+                    return false;
+        }
 
-                if (!hiddenSpaces.empty()) {
-                        auto parents =
-                          sourceModel()
-                            ->data(sourceModel()->index(sourceRow, 0), RoomlistModel::ParentSpaces)
-                            .toStringList();
-                        for (const auto &t : parents)
-                                if (hiddenSpaces.contains(t))
-                                        return false;
-                }
+        if (!hiddenSpaces.empty()) {
+            auto parents = sourceModel()
+                             ->data(sourceModel()->index(sourceRow, 0), RoomlistModel::ParentSpaces)
+                             .toStringList();
+            for (const auto &t : parents)
+                if (hiddenSpaces.contains(t))
+                    return false;
+        }
 
-                return true;
-        } else if (filterType == FilterBy::Tag) {
-                if (sourceModel()
-                      ->data(sourceModel()->index(sourceRow, 0), RoomlistModel::IsPreview)
-                      .toBool()) {
-                        return false;
-                }
+        return true;
+    } else if (filterType == FilterBy::Tag) {
+        if (sourceModel()
+              ->data(sourceModel()->index(sourceRow, 0), RoomlistModel::IsPreview)
+              .toBool()) {
+            return false;
+        }
 
-                if (sourceModel()
-                      ->data(sourceModel()->index(sourceRow, 0), RoomlistModel::IsSpace)
-                      .toBool()) {
-                        return false;
-                }
+        if (sourceModel()
+              ->data(sourceModel()->index(sourceRow, 0), RoomlistModel::IsSpace)
+              .toBool()) {
+            return false;
+        }
 
-                auto tags = sourceModel()
-                              ->data(sourceModel()->index(sourceRow, 0), RoomlistModel::Tags)
-                              .toStringList();
+        auto tags = sourceModel()
+                      ->data(sourceModel()->index(sourceRow, 0), RoomlistModel::Tags)
+                      .toStringList();
 
-                if (!tags.contains(filterStr))
-                        return false;
+        if (!tags.contains(filterStr))
+            return false;
 
-                if (!hiddenTags.empty()) {
-                        for (const auto &t : tags)
-                                if (t != filterStr && hiddenTags.contains(t))
-                                        return false;
-                }
+        if (!hiddenTags.empty()) {
+            for (const auto &t : tags)
+                if (t != filterStr && hiddenTags.contains(t))
+                    return false;
+        }
 
-                if (!hiddenSpaces.empty()) {
-                        auto parents =
-                          sourceModel()
-                            ->data(sourceModel()->index(sourceRow, 0), RoomlistModel::ParentSpaces)
-                            .toStringList();
-                        for (const auto &t : parents)
-                                if (hiddenSpaces.contains(t))
-                                        return false;
-                }
+        if (!hiddenSpaces.empty()) {
+            auto parents = sourceModel()
+                             ->data(sourceModel()->index(sourceRow, 0), RoomlistModel::ParentSpaces)
+                             .toStringList();
+            for (const auto &t : parents)
+                if (hiddenSpaces.contains(t))
+                    return false;
+        }
 
-                return true;
-        } else if (filterType == FilterBy::Space) {
-                if (filterStr == sourceModel()
-                                   ->data(sourceModel()->index(sourceRow, 0), RoomlistModel::RoomId)
-                                   .toString())
-                        return true;
-
-                auto parents =
-                  sourceModel()
-                    ->data(sourceModel()->index(sourceRow, 0), RoomlistModel::ParentSpaces)
-                    .toStringList();
-
-                if (!parents.contains(filterStr))
-                        return false;
-
-                if (!hiddenTags.empty()) {
-                        auto tags =
-                          sourceModel()
-                            ->data(sourceModel()->index(sourceRow, 0), RoomlistModel::Tags)
-                            .toStringList();
-
-                        for (const auto &t : tags)
-                                if (hiddenTags.contains(t))
-                                        return false;
-                }
+        return true;
+    } else if (filterType == FilterBy::Space) {
+        if (filterStr == sourceModel()
+                           ->data(sourceModel()->index(sourceRow, 0), RoomlistModel::RoomId)
+                           .toString())
+            return true;
 
-                if (!hiddenSpaces.empty()) {
-                        for (const auto &t : parents)
-                                if (hiddenSpaces.contains(t))
-                                        return false;
-                }
+        auto parents = sourceModel()
+                         ->data(sourceModel()->index(sourceRow, 0), RoomlistModel::ParentSpaces)
+                         .toStringList();
 
-                if (sourceModel()
-                      ->data(sourceModel()->index(sourceRow, 0), RoomlistModel::IsSpace)
-                      .toBool() &&
-                    !parents.contains(filterStr)) {
-                        return false;
-                }
+        if (!parents.contains(filterStr))
+            return false;
 
-                return true;
-        } else {
-                return true;
+        if (!hiddenTags.empty()) {
+            auto tags = sourceModel()
+                          ->data(sourceModel()->index(sourceRow, 0), RoomlistModel::Tags)
+                          .toStringList();
+
+            for (const auto &t : tags)
+                if (hiddenTags.contains(t))
+                    return false;
+        }
+
+        if (!hiddenSpaces.empty()) {
+            for (const auto &t : parents)
+                if (hiddenSpaces.contains(t))
+                    return false;
+        }
+
+        if (sourceModel()
+              ->data(sourceModel()->index(sourceRow, 0), RoomlistModel::IsSpace)
+              .toBool() &&
+            !parents.contains(filterStr)) {
+            return false;
         }
+
+        return true;
+    } else {
+        return true;
+    }
 }
 
 void
 FilteredRoomlistModel::toggleTag(QString roomid, QString tag, bool on)
 {
-        if (on) {
-                http::client()->put_tag(
-                  roomid.toStdString(), tag.toStdString(), {}, [tag](mtx::http::RequestErr err) {
-                          if (err) {
-                                  nhlog::ui()->error("Failed to add tag: {}, {}",
-                                                     tag.toStdString(),
-                                                     err->matrix_error.error);
-                          }
-                  });
-        } else {
-                http::client()->delete_tag(
-                  roomid.toStdString(), tag.toStdString(), [tag](mtx::http::RequestErr err) {
-                          if (err) {
-                                  nhlog::ui()->error("Failed to delete tag: {}, {}",
-                                                     tag.toStdString(),
-                                                     err->matrix_error.error);
-                          }
-                  });
-        }
+    if (on) {
+        http::client()->put_tag(
+          roomid.toStdString(), tag.toStdString(), {}, [tag](mtx::http::RequestErr err) {
+              if (err) {
+                  nhlog::ui()->error(
+                    "Failed to add tag: {}, {}", tag.toStdString(), err->matrix_error.error);
+              }
+          });
+    } else {
+        http::client()->delete_tag(
+          roomid.toStdString(), tag.toStdString(), [tag](mtx::http::RequestErr err) {
+              if (err) {
+                  nhlog::ui()->error(
+                    "Failed to delete tag: {}, {}", tag.toStdString(), err->matrix_error.error);
+              }
+          });
+    }
 }
 
 void
 FilteredRoomlistModel::nextRoomWithActivity()
 {
-        int roomWithMention       = -1;
-        int roomWithNotification  = -1;
-        int roomWithUnreadMessage = -1;
-        auto r                    = currentRoom();
-        int currentRoomIdx        = r ? roomidToIndex(r->roomId()) : -1;
-        // first look for mentions
-        for (int i = 0; i < (int)roomlistmodel->roomids.size(); i++) {
-                if (i == currentRoomIdx)
-                        continue;
-                if (this->data(index(i, 0), RoomlistModel::HasLoudNotification).toBool()) {
-                        roomWithMention = i;
-                        break;
-                }
-                if (roomWithNotification == -1 &&
-                    this->data(index(i, 0), RoomlistModel::NotificationCount).toInt() > 0) {
-                        roomWithNotification = i;
-                        // don't break, we must continue looking for rooms with mentions
-                }
-                if (roomWithNotification == -1 && roomWithUnreadMessage == -1 &&
-                    this->data(index(i, 0), RoomlistModel::HasUnreadMessages).toBool()) {
-                        roomWithUnreadMessage = i;
-                        // don't break, we must continue looking for rooms with mentions
-                }
+    int roomWithMention       = -1;
+    int roomWithNotification  = -1;
+    int roomWithUnreadMessage = -1;
+    auto r                    = currentRoom();
+    int currentRoomIdx        = r ? roomidToIndex(r->roomId()) : -1;
+    // first look for mentions
+    for (int i = 0; i < (int)roomlistmodel->roomids.size(); i++) {
+        if (i == currentRoomIdx)
+            continue;
+        if (this->data(index(i, 0), RoomlistModel::HasLoudNotification).toBool()) {
+            roomWithMention = i;
+            break;
         }
-        QString targetRoomId = nullptr;
-        if (roomWithMention != -1) {
-                targetRoomId =
-                  this->data(index(roomWithMention, 0), RoomlistModel::RoomId).toString();
-                nhlog::ui()->debug("choosing {} for mentions", targetRoomId.toStdString());
-        } else if (roomWithNotification != -1) {
-                targetRoomId =
-                  this->data(index(roomWithNotification, 0), RoomlistModel::RoomId).toString();
-                nhlog::ui()->debug("choosing {} for notifications", targetRoomId.toStdString());
-        } else if (roomWithUnreadMessage != -1) {
-                targetRoomId =
-                  this->data(index(roomWithUnreadMessage, 0), RoomlistModel::RoomId).toString();
-                nhlog::ui()->debug("choosing {} for unread messages", targetRoomId.toStdString());
+        if (roomWithNotification == -1 &&
+            this->data(index(i, 0), RoomlistModel::NotificationCount).toInt() > 0) {
+            roomWithNotification = i;
+            // don't break, we must continue looking for rooms with mentions
         }
-        if (targetRoomId != nullptr) {
-                setCurrentRoom(targetRoomId);
+        if (roomWithNotification == -1 && roomWithUnreadMessage == -1 &&
+            this->data(index(i, 0), RoomlistModel::HasUnreadMessages).toBool()) {
+            roomWithUnreadMessage = i;
+            // don't break, we must continue looking for rooms with mentions
         }
+    }
+    QString targetRoomId = nullptr;
+    if (roomWithMention != -1) {
+        targetRoomId = this->data(index(roomWithMention, 0), RoomlistModel::RoomId).toString();
+        nhlog::ui()->debug("choosing {} for mentions", targetRoomId.toStdString());
+    } else if (roomWithNotification != -1) {
+        targetRoomId = this->data(index(roomWithNotification, 0), RoomlistModel::RoomId).toString();
+        nhlog::ui()->debug("choosing {} for notifications", targetRoomId.toStdString());
+    } else if (roomWithUnreadMessage != -1) {
+        targetRoomId =
+          this->data(index(roomWithUnreadMessage, 0), RoomlistModel::RoomId).toString();
+        nhlog::ui()->debug("choosing {} for unread messages", targetRoomId.toStdString());
+    }
+    if (targetRoomId != nullptr) {
+        setCurrentRoom(targetRoomId);
+    }
 }
 
 void
 FilteredRoomlistModel::nextRoom()
 {
-        auto r = currentRoom();
-
-        if (r) {
-                int idx = roomidToIndex(r->roomId());
-                idx++;
-                if (idx < rowCount()) {
-                        setCurrentRoom(
-                          data(index(idx, 0), RoomlistModel::Roles::RoomId).toString());
-                }
+    auto r = currentRoom();
+
+    if (r) {
+        int idx = roomidToIndex(r->roomId());
+        idx++;
+        if (idx < rowCount()) {
+            setCurrentRoom(data(index(idx, 0), RoomlistModel::Roles::RoomId).toString());
         }
+    }
 }
 
 void
 FilteredRoomlistModel::previousRoom()
 {
-        auto r = currentRoom();
-
-        if (r) {
-                int idx = roomidToIndex(r->roomId());
-                idx--;
-                if (idx >= 0) {
-                        setCurrentRoom(
-                          data(index(idx, 0), RoomlistModel::Roles::RoomId).toString());
-                }
+    auto r = currentRoom();
+
+    if (r) {
+        int idx = roomidToIndex(r->roomId());
+        idx--;
+        if (idx >= 0) {
+            setCurrentRoom(data(index(idx, 0), RoomlistModel::Roles::RoomId).toString());
         }
+    }
 }
diff --git a/src/timeline/RoomlistModel.h b/src/timeline/RoomlistModel.h
index 27c14bec..458e0fe7 100644
--- a/src/timeline/RoomlistModel.h
+++ b/src/timeline/RoomlistModel.h
@@ -20,195 +20,191 @@ class TimelineViewManager;
 
 class RoomPreview
 {
-        Q_GADGET
-        Q_PROPERTY(QString roomid READ roomid CONSTANT)
-        Q_PROPERTY(QString roomName READ roomName CONSTANT)
-        Q_PROPERTY(QString roomTopic READ roomTopic CONSTANT)
-        Q_PROPERTY(QString roomAvatarUrl READ roomAvatarUrl CONSTANT)
-        Q_PROPERTY(bool isInvite READ isInvite CONSTANT)
+    Q_GADGET
+    Q_PROPERTY(QString roomid READ roomid CONSTANT)
+    Q_PROPERTY(QString roomName READ roomName CONSTANT)
+    Q_PROPERTY(QString roomTopic READ roomTopic CONSTANT)
+    Q_PROPERTY(QString roomAvatarUrl READ roomAvatarUrl CONSTANT)
+    Q_PROPERTY(bool isInvite READ isInvite CONSTANT)
 
 public:
-        RoomPreview() {}
+    RoomPreview() {}
 
-        QString roomid() const { return roomid_; }
-        QString roomName() const { return roomName_; }
-        QString roomTopic() const { return roomTopic_; }
-        QString roomAvatarUrl() const { return roomAvatarUrl_; }
-        bool isInvite() const { return isInvite_; }
+    QString roomid() const { return roomid_; }
+    QString roomName() const { return roomName_; }
+    QString roomTopic() const { return roomTopic_; }
+    QString roomAvatarUrl() const { return roomAvatarUrl_; }
+    bool isInvite() const { return isInvite_; }
 
-        QString roomid_, roomName_, roomAvatarUrl_, roomTopic_;
-        bool isInvite_ = false;
+    QString roomid_, roomName_, roomAvatarUrl_, roomTopic_;
+    bool isInvite_ = false;
 };
 
 class RoomlistModel : public QAbstractListModel
 {
-        Q_OBJECT
-        Q_PROPERTY(TimelineModel *currentRoom READ currentRoom NOTIFY currentRoomChanged RESET
-                     resetCurrentRoom)
-        Q_PROPERTY(RoomPreview currentRoomPreview READ currentRoomPreview NOTIFY currentRoomChanged
-                     RESET resetCurrentRoom)
+    Q_OBJECT
+    Q_PROPERTY(
+      TimelineModel *currentRoom READ currentRoom NOTIFY currentRoomChanged RESET resetCurrentRoom)
+    Q_PROPERTY(RoomPreview currentRoomPreview READ currentRoomPreview NOTIFY currentRoomChanged
+                 RESET resetCurrentRoom)
 public:
-        enum Roles
-        {
-                AvatarUrl = Qt::UserRole,
-                RoomName,
-                RoomId,
-                LastMessage,
-                Time,
-                Timestamp,
-                HasUnreadMessages,
-                HasLoudNotification,
-                NotificationCount,
-                IsInvite,
-                IsSpace,
-                IsPreview,
-                IsPreviewFetched,
-                Tags,
-                ParentSpaces,
-                IsDirect,
-                DirectChatOtherUserId,
-        };
-
-        RoomlistModel(TimelineViewManager *parent = nullptr);
-        QHash<int, QByteArray> roleNames() const override;
-        int rowCount(const QModelIndex &parent = QModelIndex()) const override
-        {
-                (void)parent;
-                return (int)roomids.size();
-        }
-        QVariant data(const QModelIndex &index, int role) const override;
-        QSharedPointer<TimelineModel> getRoomById(QString id) const
-        {
-                if (models.contains(id))
-                        return models.value(id);
-                else
-                        return {};
-        }
+    enum Roles
+    {
+        AvatarUrl = Qt::UserRole,
+        RoomName,
+        RoomId,
+        LastMessage,
+        Time,
+        Timestamp,
+        HasUnreadMessages,
+        HasLoudNotification,
+        NotificationCount,
+        IsInvite,
+        IsSpace,
+        IsPreview,
+        IsPreviewFetched,
+        Tags,
+        ParentSpaces,
+        IsDirect,
+        DirectChatOtherUserId,
+    };
+
+    RoomlistModel(TimelineViewManager *parent = nullptr);
+    QHash<int, QByteArray> roleNames() const override;
+    int rowCount(const QModelIndex &parent = QModelIndex()) const override
+    {
+        (void)parent;
+        return (int)roomids.size();
+    }
+    QVariant data(const QModelIndex &index, int role) const override;
+    QSharedPointer<TimelineModel> getRoomById(QString id) const
+    {
+        if (models.contains(id))
+            return models.value(id);
+        else
+            return {};
+    }
 
 public slots:
-        void initializeRooms();
-        void sync(const mtx::responses::Rooms &rooms);
-        void clear();
-        int roomidToIndex(QString roomid)
-        {
-                for (int i = 0; i < (int)roomids.size(); i++) {
-                        if (roomids[i] == roomid)
-                                return i;
-                }
-
-                return -1;
-        }
-        void joinPreview(QString roomid, QString parentSpace);
-        void acceptInvite(QString roomid);
-        void declineInvite(QString roomid);
-        void leave(QString roomid);
-        TimelineModel *currentRoom() const { return currentRoom_.get(); }
-        RoomPreview currentRoomPreview() const
-        {
-                return currentRoomPreview_.value_or(RoomPreview{});
-        }
-        void setCurrentRoom(QString roomid);
-        void resetCurrentRoom()
-        {
-                currentRoom_ = nullptr;
-                currentRoomPreview_.reset();
-                emit currentRoomChanged();
+    void initializeRooms();
+    void sync(const mtx::responses::Rooms &rooms);
+    void clear();
+    int roomidToIndex(QString roomid)
+    {
+        for (int i = 0; i < (int)roomids.size(); i++) {
+            if (roomids[i] == roomid)
+                return i;
         }
 
+        return -1;
+    }
+    void joinPreview(QString roomid, QString parentSpace);
+    void acceptInvite(QString roomid);
+    void declineInvite(QString roomid);
+    void leave(QString roomid);
+    TimelineModel *currentRoom() const { return currentRoom_.get(); }
+    RoomPreview currentRoomPreview() const { return currentRoomPreview_.value_or(RoomPreview{}); }
+    void setCurrentRoom(QString roomid);
+    void resetCurrentRoom()
+    {
+        currentRoom_ = nullptr;
+        currentRoomPreview_.reset();
+        emit currentRoomChanged();
+    }
+
 private slots:
-        void updateReadStatus(const std::map<QString, bool> roomReadStatus_);
+    void updateReadStatus(const std::map<QString, bool> roomReadStatus_);
 
 signals:
-        void totalUnreadMessageCountUpdated(int unreadMessages);
-        void currentRoomChanged();
-        void fetchedPreview(QString roomid, RoomInfo info);
+    void totalUnreadMessageCountUpdated(int unreadMessages);
+    void currentRoomChanged();
+    void fetchedPreview(QString roomid, RoomInfo info);
 
 private:
-        void addRoom(const QString &room_id, bool suppressInsertNotification = false);
-        void fetchPreview(QString roomid) const;
+    void addRoom(const QString &room_id, bool suppressInsertNotification = false);
+    void fetchPreview(QString roomid) const;
 
-        TimelineViewManager *manager = nullptr;
-        std::vector<QString> roomids;
-        QHash<QString, RoomInfo> invites;
-        QHash<QString, QSharedPointer<TimelineModel>> models;
-        std::map<QString, bool> roomReadStatus;
-        QHash<QString, std::optional<RoomInfo>> previewedRooms;
+    TimelineViewManager *manager = nullptr;
+    std::vector<QString> roomids;
+    QHash<QString, RoomInfo> invites;
+    QHash<QString, QSharedPointer<TimelineModel>> models;
+    std::map<QString, bool> roomReadStatus;
+    QHash<QString, std::optional<RoomInfo>> previewedRooms;
 
-        QSharedPointer<TimelineModel> currentRoom_;
-        std::optional<RoomPreview> currentRoomPreview_;
+    QSharedPointer<TimelineModel> currentRoom_;
+    std::optional<RoomPreview> currentRoomPreview_;
 
-        friend class FilteredRoomlistModel;
+    friend class FilteredRoomlistModel;
 };
 
 class FilteredRoomlistModel : public QSortFilterProxyModel
 {
-        Q_OBJECT
-        Q_PROPERTY(TimelineModel *currentRoom READ currentRoom NOTIFY currentRoomChanged RESET
-                     resetCurrentRoom)
-        Q_PROPERTY(RoomPreview currentRoomPreview READ currentRoomPreview NOTIFY currentRoomChanged
-                     RESET resetCurrentRoom)
+    Q_OBJECT
+    Q_PROPERTY(
+      TimelineModel *currentRoom READ currentRoom NOTIFY currentRoomChanged RESET resetCurrentRoom)
+    Q_PROPERTY(RoomPreview currentRoomPreview READ currentRoomPreview NOTIFY currentRoomChanged
+                 RESET resetCurrentRoom)
 public:
-        FilteredRoomlistModel(RoomlistModel *model, QObject *parent = nullptr);
-        bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
-        bool filterAcceptsRow(int sourceRow, const QModelIndex &) const override;
+    FilteredRoomlistModel(RoomlistModel *model, QObject *parent = nullptr);
+    bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
+    bool filterAcceptsRow(int sourceRow, const QModelIndex &) const override;
 
 public slots:
-        int roomidToIndex(QString roomid)
-        {
-                return mapFromSource(roomlistmodel->index(roomlistmodel->roomidToIndex(roomid)))
-                  .row();
-        }
-        void joinPreview(QString roomid)
-        {
-                roomlistmodel->joinPreview(roomid, filterType == FilterBy::Space ? filterStr : "");
-        }
-        void acceptInvite(QString roomid) { roomlistmodel->acceptInvite(roomid); }
-        void declineInvite(QString roomid) { roomlistmodel->declineInvite(roomid); }
-        void leave(QString roomid) { roomlistmodel->leave(roomid); }
-        void toggleTag(QString roomid, QString tag, bool on);
-
-        TimelineModel *currentRoom() const { return roomlistmodel->currentRoom(); }
-        RoomPreview currentRoomPreview() const { return roomlistmodel->currentRoomPreview(); }
-        void setCurrentRoom(QString roomid) { roomlistmodel->setCurrentRoom(std::move(roomid)); }
-        void resetCurrentRoom() { roomlistmodel->resetCurrentRoom(); }
-
-        void nextRoomWithActivity();
-        void nextRoom();
-        void previousRoom();
-
-        void updateFilterTag(QString tagId)
-        {
-                if (tagId.startsWith("tag:")) {
-                        filterType = FilterBy::Tag;
-                        filterStr  = tagId.mid(4);
-                } else if (tagId.startsWith("space:")) {
-                        filterType = FilterBy::Space;
-                        filterStr  = tagId.mid(6);
-                } else {
-                        filterType = FilterBy::Nothing;
-                        filterStr.clear();
-                }
-
-                invalidateFilter();
+    int roomidToIndex(QString roomid)
+    {
+        return mapFromSource(roomlistmodel->index(roomlistmodel->roomidToIndex(roomid))).row();
+    }
+    void joinPreview(QString roomid)
+    {
+        roomlistmodel->joinPreview(roomid, filterType == FilterBy::Space ? filterStr : "");
+    }
+    void acceptInvite(QString roomid) { roomlistmodel->acceptInvite(roomid); }
+    void declineInvite(QString roomid) { roomlistmodel->declineInvite(roomid); }
+    void leave(QString roomid) { roomlistmodel->leave(roomid); }
+    void toggleTag(QString roomid, QString tag, bool on);
+
+    TimelineModel *currentRoom() const { return roomlistmodel->currentRoom(); }
+    RoomPreview currentRoomPreview() const { return roomlistmodel->currentRoomPreview(); }
+    void setCurrentRoom(QString roomid) { roomlistmodel->setCurrentRoom(std::move(roomid)); }
+    void resetCurrentRoom() { roomlistmodel->resetCurrentRoom(); }
+
+    void nextRoomWithActivity();
+    void nextRoom();
+    void previousRoom();
+
+    void updateFilterTag(QString tagId)
+    {
+        if (tagId.startsWith("tag:")) {
+            filterType = FilterBy::Tag;
+            filterStr  = tagId.mid(4);
+        } else if (tagId.startsWith("space:")) {
+            filterType = FilterBy::Space;
+            filterStr  = tagId.mid(6);
+        } else {
+            filterType = FilterBy::Nothing;
+            filterStr.clear();
         }
 
-        void updateHiddenTagsAndSpaces();
+        invalidateFilter();
+    }
+
+    void updateHiddenTagsAndSpaces();
 
 signals:
-        void currentRoomChanged();
+    void currentRoomChanged();
 
 private:
-        short int calculateImportance(const QModelIndex &idx) const;
-        RoomlistModel *roomlistmodel;
-        bool sortByImportance = true;
-
-        enum class FilterBy
-        {
-                Tag,
-                Space,
-                Nothing,
-        };
-        QString filterStr   = "";
-        FilterBy filterType = FilterBy::Nothing;
-        QStringList hiddenTags, hiddenSpaces;
+    short int calculateImportance(const QModelIndex &idx) const;
+    RoomlistModel *roomlistmodel;
+    bool sortByImportance = true;
+
+    enum class FilterBy
+    {
+        Tag,
+        Space,
+        Nothing,
+    };
+    QString filterStr   = "";
+    FilterBy filterType = FilterBy::Nothing;
+    QStringList hiddenTags, hiddenSpaces;
 };
diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp
index 00f6d9df..720a78fe 100644
--- a/src/timeline/TimelineModel.cpp
+++ b/src/timeline/TimelineModel.cpp
@@ -38,288 +38,285 @@ namespace std {
 inline uint
 qHash(const std::string &key, uint seed = 0)
 {
-        return qHash(QByteArray::fromRawData(key.data(), (int)key.length()), seed);
+    return qHash(QByteArray::fromRawData(key.data(), (int)key.length()), seed);
 }
 }
 
 namespace {
 struct RoomEventType
 {
-        template<class T>
-        qml_mtx_events::EventType operator()(const mtx::events::Event<T> &e)
-        {
-                using mtx::events::EventType;
-                switch (e.type) {
-                case EventType::RoomKeyRequest:
-                        return qml_mtx_events::EventType::KeyRequest;
-                case EventType::Reaction:
-                        return qml_mtx_events::EventType::Reaction;
-                case EventType::RoomAliases:
-                        return qml_mtx_events::EventType::Aliases;
-                case EventType::RoomAvatar:
-                        return qml_mtx_events::EventType::Avatar;
-                case EventType::RoomCanonicalAlias:
-                        return qml_mtx_events::EventType::CanonicalAlias;
-                case EventType::RoomCreate:
-                        return qml_mtx_events::EventType::RoomCreate;
-                case EventType::RoomEncrypted:
-                        return qml_mtx_events::EventType::Encrypted;
-                case EventType::RoomEncryption:
-                        return qml_mtx_events::EventType::Encryption;
-                case EventType::RoomGuestAccess:
-                        return qml_mtx_events::EventType::RoomGuestAccess;
-                case EventType::RoomHistoryVisibility:
-                        return qml_mtx_events::EventType::RoomHistoryVisibility;
-                case EventType::RoomJoinRules:
-                        return qml_mtx_events::EventType::RoomJoinRules;
-                case EventType::RoomMember:
-                        return qml_mtx_events::EventType::Member;
-                case EventType::RoomMessage:
-                        return qml_mtx_events::EventType::UnknownMessage;
-                case EventType::RoomName:
-                        return qml_mtx_events::EventType::Name;
-                case EventType::RoomPowerLevels:
-                        return qml_mtx_events::EventType::PowerLevels;
-                case EventType::RoomTopic:
-                        return qml_mtx_events::EventType::Topic;
-                case EventType::RoomTombstone:
-                        return qml_mtx_events::EventType::Tombstone;
-                case EventType::RoomRedaction:
-                        return qml_mtx_events::EventType::Redaction;
-                case EventType::RoomPinnedEvents:
-                        return qml_mtx_events::EventType::PinnedEvents;
-                case EventType::Sticker:
-                        return qml_mtx_events::EventType::Sticker;
-                case EventType::Tag:
-                        return qml_mtx_events::EventType::Tag;
-                case EventType::Unsupported:
-                        return qml_mtx_events::EventType::Unsupported;
-                default:
-                        return qml_mtx_events::EventType::UnknownMessage;
-                }
-        }
-        qml_mtx_events::EventType operator()(const mtx::events::Event<mtx::events::msg::Audio> &)
-        {
-                return qml_mtx_events::EventType::AudioMessage;
-        }
-        qml_mtx_events::EventType operator()(const mtx::events::Event<mtx::events::msg::Emote> &)
-        {
-                return qml_mtx_events::EventType::EmoteMessage;
-        }
-        qml_mtx_events::EventType operator()(const mtx::events::Event<mtx::events::msg::File> &)
-        {
-                return qml_mtx_events::EventType::FileMessage;
-        }
-        qml_mtx_events::EventType operator()(const mtx::events::Event<mtx::events::msg::Image> &)
-        {
-                return qml_mtx_events::EventType::ImageMessage;
-        }
-        qml_mtx_events::EventType operator()(const mtx::events::Event<mtx::events::msg::Notice> &)
-        {
-                return qml_mtx_events::EventType::NoticeMessage;
-        }
-        qml_mtx_events::EventType operator()(const mtx::events::Event<mtx::events::msg::Text> &)
-        {
-                return qml_mtx_events::EventType::TextMessage;
-        }
-        qml_mtx_events::EventType operator()(const mtx::events::Event<mtx::events::msg::Video> &)
-        {
-                return qml_mtx_events::EventType::VideoMessage;
-        }
-        qml_mtx_events::EventType operator()(
-          const mtx::events::Event<mtx::events::msg::KeyVerificationRequest> &)
-        {
-                return qml_mtx_events::EventType::KeyVerificationRequest;
-        }
-        qml_mtx_events::EventType operator()(
-          const mtx::events::Event<mtx::events::msg::KeyVerificationStart> &)
-        {
-                return qml_mtx_events::EventType::KeyVerificationStart;
-        }
-        qml_mtx_events::EventType operator()(
-          const mtx::events::Event<mtx::events::msg::KeyVerificationMac> &)
-        {
-                return qml_mtx_events::EventType::KeyVerificationMac;
-        }
-        qml_mtx_events::EventType operator()(
-          const mtx::events::Event<mtx::events::msg::KeyVerificationAccept> &)
-        {
-                return qml_mtx_events::EventType::KeyVerificationAccept;
-        }
-        qml_mtx_events::EventType operator()(
-          const mtx::events::Event<mtx::events::msg::KeyVerificationReady> &)
-        {
-                return qml_mtx_events::EventType::KeyVerificationReady;
-        }
-        qml_mtx_events::EventType operator()(
-          const mtx::events::Event<mtx::events::msg::KeyVerificationCancel> &)
-        {
-                return qml_mtx_events::EventType::KeyVerificationCancel;
-        }
-        qml_mtx_events::EventType operator()(
-          const mtx::events::Event<mtx::events::msg::KeyVerificationKey> &)
-        {
-                return qml_mtx_events::EventType::KeyVerificationKey;
-        }
-        qml_mtx_events::EventType operator()(
-          const mtx::events::Event<mtx::events::msg::KeyVerificationDone> &)
-        {
-                return qml_mtx_events::EventType::KeyVerificationDone;
-        }
-        qml_mtx_events::EventType operator()(const mtx::events::Event<mtx::events::msg::Redacted> &)
-        {
-                return qml_mtx_events::EventType::Redacted;
-        }
-        qml_mtx_events::EventType operator()(
-          const mtx::events::Event<mtx::events::msg::CallInvite> &)
-        {
-                return qml_mtx_events::EventType::CallInvite;
-        }
-        qml_mtx_events::EventType operator()(
-          const mtx::events::Event<mtx::events::msg::CallAnswer> &)
-        {
-                return qml_mtx_events::EventType::CallAnswer;
-        }
-        qml_mtx_events::EventType operator()(
-          const mtx::events::Event<mtx::events::msg::CallHangUp> &)
-        {
-                return qml_mtx_events::EventType::CallHangUp;
-        }
-        qml_mtx_events::EventType operator()(
-          const mtx::events::Event<mtx::events::msg::CallCandidates> &)
-        {
-                return qml_mtx_events::EventType::CallCandidates;
-        }
-        // ::EventType::Type operator()(const Event<mtx::events::msg::Location> &e) { return
-        // ::EventType::LocationMessage; }
+    template<class T>
+    qml_mtx_events::EventType operator()(const mtx::events::Event<T> &e)
+    {
+        using mtx::events::EventType;
+        switch (e.type) {
+        case EventType::RoomKeyRequest:
+            return qml_mtx_events::EventType::KeyRequest;
+        case EventType::Reaction:
+            return qml_mtx_events::EventType::Reaction;
+        case EventType::RoomAliases:
+            return qml_mtx_events::EventType::Aliases;
+        case EventType::RoomAvatar:
+            return qml_mtx_events::EventType::Avatar;
+        case EventType::RoomCanonicalAlias:
+            return qml_mtx_events::EventType::CanonicalAlias;
+        case EventType::RoomCreate:
+            return qml_mtx_events::EventType::RoomCreate;
+        case EventType::RoomEncrypted:
+            return qml_mtx_events::EventType::Encrypted;
+        case EventType::RoomEncryption:
+            return qml_mtx_events::EventType::Encryption;
+        case EventType::RoomGuestAccess:
+            return qml_mtx_events::EventType::RoomGuestAccess;
+        case EventType::RoomHistoryVisibility:
+            return qml_mtx_events::EventType::RoomHistoryVisibility;
+        case EventType::RoomJoinRules:
+            return qml_mtx_events::EventType::RoomJoinRules;
+        case EventType::RoomMember:
+            return qml_mtx_events::EventType::Member;
+        case EventType::RoomMessage:
+            return qml_mtx_events::EventType::UnknownMessage;
+        case EventType::RoomName:
+            return qml_mtx_events::EventType::Name;
+        case EventType::RoomPowerLevels:
+            return qml_mtx_events::EventType::PowerLevels;
+        case EventType::RoomTopic:
+            return qml_mtx_events::EventType::Topic;
+        case EventType::RoomTombstone:
+            return qml_mtx_events::EventType::Tombstone;
+        case EventType::RoomRedaction:
+            return qml_mtx_events::EventType::Redaction;
+        case EventType::RoomPinnedEvents:
+            return qml_mtx_events::EventType::PinnedEvents;
+        case EventType::Sticker:
+            return qml_mtx_events::EventType::Sticker;
+        case EventType::Tag:
+            return qml_mtx_events::EventType::Tag;
+        case EventType::Unsupported:
+            return qml_mtx_events::EventType::Unsupported;
+        default:
+            return qml_mtx_events::EventType::UnknownMessage;
+        }
+    }
+    qml_mtx_events::EventType operator()(const mtx::events::Event<mtx::events::msg::Audio> &)
+    {
+        return qml_mtx_events::EventType::AudioMessage;
+    }
+    qml_mtx_events::EventType operator()(const mtx::events::Event<mtx::events::msg::Emote> &)
+    {
+        return qml_mtx_events::EventType::EmoteMessage;
+    }
+    qml_mtx_events::EventType operator()(const mtx::events::Event<mtx::events::msg::File> &)
+    {
+        return qml_mtx_events::EventType::FileMessage;
+    }
+    qml_mtx_events::EventType operator()(const mtx::events::Event<mtx::events::msg::Image> &)
+    {
+        return qml_mtx_events::EventType::ImageMessage;
+    }
+    qml_mtx_events::EventType operator()(const mtx::events::Event<mtx::events::msg::Notice> &)
+    {
+        return qml_mtx_events::EventType::NoticeMessage;
+    }
+    qml_mtx_events::EventType operator()(const mtx::events::Event<mtx::events::msg::Text> &)
+    {
+        return qml_mtx_events::EventType::TextMessage;
+    }
+    qml_mtx_events::EventType operator()(const mtx::events::Event<mtx::events::msg::Video> &)
+    {
+        return qml_mtx_events::EventType::VideoMessage;
+    }
+    qml_mtx_events::EventType operator()(
+      const mtx::events::Event<mtx::events::msg::KeyVerificationRequest> &)
+    {
+        return qml_mtx_events::EventType::KeyVerificationRequest;
+    }
+    qml_mtx_events::EventType operator()(
+      const mtx::events::Event<mtx::events::msg::KeyVerificationStart> &)
+    {
+        return qml_mtx_events::EventType::KeyVerificationStart;
+    }
+    qml_mtx_events::EventType operator()(
+      const mtx::events::Event<mtx::events::msg::KeyVerificationMac> &)
+    {
+        return qml_mtx_events::EventType::KeyVerificationMac;
+    }
+    qml_mtx_events::EventType operator()(
+      const mtx::events::Event<mtx::events::msg::KeyVerificationAccept> &)
+    {
+        return qml_mtx_events::EventType::KeyVerificationAccept;
+    }
+    qml_mtx_events::EventType operator()(
+      const mtx::events::Event<mtx::events::msg::KeyVerificationReady> &)
+    {
+        return qml_mtx_events::EventType::KeyVerificationReady;
+    }
+    qml_mtx_events::EventType operator()(
+      const mtx::events::Event<mtx::events::msg::KeyVerificationCancel> &)
+    {
+        return qml_mtx_events::EventType::KeyVerificationCancel;
+    }
+    qml_mtx_events::EventType operator()(
+      const mtx::events::Event<mtx::events::msg::KeyVerificationKey> &)
+    {
+        return qml_mtx_events::EventType::KeyVerificationKey;
+    }
+    qml_mtx_events::EventType operator()(
+      const mtx::events::Event<mtx::events::msg::KeyVerificationDone> &)
+    {
+        return qml_mtx_events::EventType::KeyVerificationDone;
+    }
+    qml_mtx_events::EventType operator()(const mtx::events::Event<mtx::events::msg::Redacted> &)
+    {
+        return qml_mtx_events::EventType::Redacted;
+    }
+    qml_mtx_events::EventType operator()(const mtx::events::Event<mtx::events::msg::CallInvite> &)
+    {
+        return qml_mtx_events::EventType::CallInvite;
+    }
+    qml_mtx_events::EventType operator()(const mtx::events::Event<mtx::events::msg::CallAnswer> &)
+    {
+        return qml_mtx_events::EventType::CallAnswer;
+    }
+    qml_mtx_events::EventType operator()(const mtx::events::Event<mtx::events::msg::CallHangUp> &)
+    {
+        return qml_mtx_events::EventType::CallHangUp;
+    }
+    qml_mtx_events::EventType operator()(
+      const mtx::events::Event<mtx::events::msg::CallCandidates> &)
+    {
+        return qml_mtx_events::EventType::CallCandidates;
+    }
+    // ::EventType::Type operator()(const Event<mtx::events::msg::Location> &e) { return
+    // ::EventType::LocationMessage; }
 };
 }
 
 qml_mtx_events::EventType
 toRoomEventType(const mtx::events::collections::TimelineEvents &event)
 {
-        return std::visit(RoomEventType{}, event);
+    return std::visit(RoomEventType{}, event);
 }
 
 QString
 toRoomEventTypeString(const mtx::events::collections::TimelineEvents &event)
 {
-        return std::visit([](const auto &e) { return QString::fromStdString(to_string(e.type)); },
-                          event);
+    return std::visit([](const auto &e) { return QString::fromStdString(to_string(e.type)); },
+                      event);
 }
 
 mtx::events::EventType
 qml_mtx_events::fromRoomEventType(qml_mtx_events::EventType t)
 {
-        switch (t) {
-        // Unsupported event
-        case qml_mtx_events::Unsupported:
-                return mtx::events::EventType::Unsupported;
-
-        /// m.room_key_request
-        case qml_mtx_events::KeyRequest:
-                return mtx::events::EventType::RoomKeyRequest;
-        /// m.reaction:
-        case qml_mtx_events::Reaction:
-                return mtx::events::EventType::Reaction;
-        /// m.room.aliases
-        case qml_mtx_events::Aliases:
-                return mtx::events::EventType::RoomAliases;
-        /// m.room.avatar
-        case qml_mtx_events::Avatar:
-                return mtx::events::EventType::RoomAvatar;
-        /// m.call.invite
-        case qml_mtx_events::CallInvite:
-                return mtx::events::EventType::CallInvite;
-        /// m.call.answer
-        case qml_mtx_events::CallAnswer:
-                return mtx::events::EventType::CallAnswer;
-        /// m.call.hangup
-        case qml_mtx_events::CallHangUp:
-                return mtx::events::EventType::CallHangUp;
-        /// m.call.candidates
-        case qml_mtx_events::CallCandidates:
-                return mtx::events::EventType::CallCandidates;
-        /// m.room.canonical_alias
-        case qml_mtx_events::CanonicalAlias:
-                return mtx::events::EventType::RoomCanonicalAlias;
-        /// m.room.create
-        case qml_mtx_events::RoomCreate:
-                return mtx::events::EventType::RoomCreate;
-        /// m.room.encrypted.
-        case qml_mtx_events::Encrypted:
-                return mtx::events::EventType::RoomEncrypted;
-        /// m.room.encryption.
-        case qml_mtx_events::Encryption:
-                return mtx::events::EventType::RoomEncryption;
-        /// m.room.guest_access
-        case qml_mtx_events::RoomGuestAccess:
-                return mtx::events::EventType::RoomGuestAccess;
-        /// m.room.history_visibility
-        case qml_mtx_events::RoomHistoryVisibility:
-                return mtx::events::EventType::RoomHistoryVisibility;
-        /// m.room.join_rules
-        case qml_mtx_events::RoomJoinRules:
-                return mtx::events::EventType::RoomJoinRules;
-        /// m.room.member
-        case qml_mtx_events::Member:
-                return mtx::events::EventType::RoomMember;
-        /// m.room.name
-        case qml_mtx_events::Name:
-                return mtx::events::EventType::RoomName;
-        /// m.room.power_levels
-        case qml_mtx_events::PowerLevels:
-                return mtx::events::EventType::RoomPowerLevels;
-        /// m.room.tombstone
-        case qml_mtx_events::Tombstone:
-                return mtx::events::EventType::RoomTombstone;
-        /// m.room.topic
-        case qml_mtx_events::Topic:
-                return mtx::events::EventType::RoomTopic;
-        /// m.room.redaction
-        case qml_mtx_events::Redaction:
-                return mtx::events::EventType::RoomRedaction;
-        /// m.room.pinned_events
-        case qml_mtx_events::PinnedEvents:
-                return mtx::events::EventType::RoomPinnedEvents;
-        // m.sticker
-        case qml_mtx_events::Sticker:
-                return mtx::events::EventType::Sticker;
-        // m.tag
-        case qml_mtx_events::Tag:
-                return mtx::events::EventType::Tag;
-        /// m.room.message
-        case qml_mtx_events::AudioMessage:
-        case qml_mtx_events::EmoteMessage:
-        case qml_mtx_events::FileMessage:
-        case qml_mtx_events::ImageMessage:
-        case qml_mtx_events::LocationMessage:
-        case qml_mtx_events::NoticeMessage:
-        case qml_mtx_events::TextMessage:
-        case qml_mtx_events::VideoMessage:
-        case qml_mtx_events::Redacted:
-        case qml_mtx_events::UnknownMessage:
-        case qml_mtx_events::KeyVerificationRequest:
-        case qml_mtx_events::KeyVerificationStart:
-        case qml_mtx_events::KeyVerificationMac:
-        case qml_mtx_events::KeyVerificationAccept:
-        case qml_mtx_events::KeyVerificationCancel:
-        case qml_mtx_events::KeyVerificationKey:
-        case qml_mtx_events::KeyVerificationDone:
-        case qml_mtx_events::KeyVerificationReady:
-                return mtx::events::EventType::RoomMessage;
-                //! m.image_pack, currently im.ponies.room_emotes
-        case qml_mtx_events::ImagePackInRoom:
-                return mtx::events::EventType::ImagePackInRoom;
-        //! m.image_pack, currently im.ponies.user_emotes
-        case qml_mtx_events::ImagePackInAccountData:
-                return mtx::events::EventType::ImagePackInAccountData;
-        //! m.image_pack.rooms, currently im.ponies.emote_rooms
-        case qml_mtx_events::ImagePackRooms:
-                return mtx::events::EventType::ImagePackRooms;
-        default:
-                return mtx::events::EventType::Unsupported;
-        };
+    switch (t) {
+    // Unsupported event
+    case qml_mtx_events::Unsupported:
+        return mtx::events::EventType::Unsupported;
+
+    /// m.room_key_request
+    case qml_mtx_events::KeyRequest:
+        return mtx::events::EventType::RoomKeyRequest;
+    /// m.reaction:
+    case qml_mtx_events::Reaction:
+        return mtx::events::EventType::Reaction;
+    /// m.room.aliases
+    case qml_mtx_events::Aliases:
+        return mtx::events::EventType::RoomAliases;
+    /// m.room.avatar
+    case qml_mtx_events::Avatar:
+        return mtx::events::EventType::RoomAvatar;
+    /// m.call.invite
+    case qml_mtx_events::CallInvite:
+        return mtx::events::EventType::CallInvite;
+    /// m.call.answer
+    case qml_mtx_events::CallAnswer:
+        return mtx::events::EventType::CallAnswer;
+    /// m.call.hangup
+    case qml_mtx_events::CallHangUp:
+        return mtx::events::EventType::CallHangUp;
+    /// m.call.candidates
+    case qml_mtx_events::CallCandidates:
+        return mtx::events::EventType::CallCandidates;
+    /// m.room.canonical_alias
+    case qml_mtx_events::CanonicalAlias:
+        return mtx::events::EventType::RoomCanonicalAlias;
+    /// m.room.create
+    case qml_mtx_events::RoomCreate:
+        return mtx::events::EventType::RoomCreate;
+    /// m.room.encrypted.
+    case qml_mtx_events::Encrypted:
+        return mtx::events::EventType::RoomEncrypted;
+    /// m.room.encryption.
+    case qml_mtx_events::Encryption:
+        return mtx::events::EventType::RoomEncryption;
+    /// m.room.guest_access
+    case qml_mtx_events::RoomGuestAccess:
+        return mtx::events::EventType::RoomGuestAccess;
+    /// m.room.history_visibility
+    case qml_mtx_events::RoomHistoryVisibility:
+        return mtx::events::EventType::RoomHistoryVisibility;
+    /// m.room.join_rules
+    case qml_mtx_events::RoomJoinRules:
+        return mtx::events::EventType::RoomJoinRules;
+    /// m.room.member
+    case qml_mtx_events::Member:
+        return mtx::events::EventType::RoomMember;
+    /// m.room.name
+    case qml_mtx_events::Name:
+        return mtx::events::EventType::RoomName;
+    /// m.room.power_levels
+    case qml_mtx_events::PowerLevels:
+        return mtx::events::EventType::RoomPowerLevels;
+    /// m.room.tombstone
+    case qml_mtx_events::Tombstone:
+        return mtx::events::EventType::RoomTombstone;
+    /// m.room.topic
+    case qml_mtx_events::Topic:
+        return mtx::events::EventType::RoomTopic;
+    /// m.room.redaction
+    case qml_mtx_events::Redaction:
+        return mtx::events::EventType::RoomRedaction;
+    /// m.room.pinned_events
+    case qml_mtx_events::PinnedEvents:
+        return mtx::events::EventType::RoomPinnedEvents;
+    // m.sticker
+    case qml_mtx_events::Sticker:
+        return mtx::events::EventType::Sticker;
+    // m.tag
+    case qml_mtx_events::Tag:
+        return mtx::events::EventType::Tag;
+    /// m.room.message
+    case qml_mtx_events::AudioMessage:
+    case qml_mtx_events::EmoteMessage:
+    case qml_mtx_events::FileMessage:
+    case qml_mtx_events::ImageMessage:
+    case qml_mtx_events::LocationMessage:
+    case qml_mtx_events::NoticeMessage:
+    case qml_mtx_events::TextMessage:
+    case qml_mtx_events::VideoMessage:
+    case qml_mtx_events::Redacted:
+    case qml_mtx_events::UnknownMessage:
+    case qml_mtx_events::KeyVerificationRequest:
+    case qml_mtx_events::KeyVerificationStart:
+    case qml_mtx_events::KeyVerificationMac:
+    case qml_mtx_events::KeyVerificationAccept:
+    case qml_mtx_events::KeyVerificationCancel:
+    case qml_mtx_events::KeyVerificationKey:
+    case qml_mtx_events::KeyVerificationDone:
+    case qml_mtx_events::KeyVerificationReady:
+        return mtx::events::EventType::RoomMessage;
+        //! m.image_pack, currently im.ponies.room_emotes
+    case qml_mtx_events::ImagePackInRoom:
+        return mtx::events::EventType::ImagePackInRoom;
+    //! m.image_pack, currently im.ponies.user_emotes
+    case qml_mtx_events::ImagePackInAccountData:
+        return mtx::events::EventType::ImagePackInAccountData;
+    //! m.image_pack.rooms, currently im.ponies.emote_rooms
+    case qml_mtx_events::ImagePackRooms:
+        return mtx::events::EventType::ImagePackRooms;
+    default:
+        return mtx::events::EventType::Unsupported;
+    };
 }
 
 TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObject *parent)
@@ -329,566 +326,549 @@ TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObj
   , manager_(manager)
   , permissions_{room_id}
 {
-        lastMessage_.timestamp = 0;
-
-        if (auto create =
-              cache::client()->getStateEvent<mtx::events::state::Create>(room_id.toStdString()))
-                this->isSpace_ = create->content.type == mtx::events::state::room_type::space;
-        this->isEncrypted_ = cache::isRoomEncrypted(room_id_.toStdString());
-
-        // this connection will simplify adding the plainRoomNameChanged() signal everywhere that it
-        // needs to be
-        connect(this, &TimelineModel::roomNameChanged, this, &TimelineModel::plainRoomNameChanged);
-
-        connect(
-          this,
-          &TimelineModel::redactionFailed,
-          this,
-          [](const QString &msg) { emit ChatPage::instance()->showNotification(msg); },
-          Qt::QueuedConnection);
-
-        connect(this,
-                &TimelineModel::newMessageToSend,
-                this,
-                &TimelineModel::addPendingMessage,
-                Qt::QueuedConnection);
-        connect(this, &TimelineModel::addPendingMessageToStore, &events, &EventStore::addPending);
-
-        connect(&events, &EventStore::dataChanged, this, [this](int from, int to) {
-                relatedEventCacheBuster++;
-                nhlog::ui()->debug(
-                  "data changed {} to {}", events.size() - to - 1, events.size() - from - 1);
-                emit dataChanged(index(events.size() - to - 1, 0),
-                                 index(events.size() - from - 1, 0));
-        });
-
-        connect(&events, &EventStore::beginInsertRows, this, [this](int from, int to) {
-                int first = events.size() - to;
-                int last  = events.size() - from;
-                if (from >= events.size()) {
-                        int batch_size = to - from;
-                        first += batch_size;
-                        last += batch_size;
-                } else {
-                        first -= 1;
-                        last -= 1;
-                }
-                nhlog::ui()->debug("begin insert from {} to {}", first, last);
-                beginInsertRows(QModelIndex(), first, last);
-        });
-        connect(&events, &EventStore::endInsertRows, this, [this]() { endInsertRows(); });
-        connect(&events, &EventStore::beginResetModel, this, [this]() { beginResetModel(); });
-        connect(&events, &EventStore::endResetModel, this, [this]() { endResetModel(); });
-        connect(&events, &EventStore::newEncryptedImage, this, &TimelineModel::newEncryptedImage);
-        connect(
-          &events, &EventStore::fetchedMore, this, [this]() { setPaginationInProgress(false); });
-        connect(&events,
-                &EventStore::startDMVerification,
-                this,
-                [this](mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest> msg) {
-                        ChatPage::instance()->receivedRoomDeviceVerificationRequest(msg, this);
-                });
-        connect(&events, &EventStore::updateFlowEventId, this, [this](std::string event_id) {
-                this->updateFlowEventId(event_id);
-        });
-
-        // When a message is sent, check if the current edit/reply relates to that message,
-        // and update the event_id so that it points to the sent message and not the pending one.
-        connect(&events,
-                &EventStore::messageSent,
-                this,
-                [this](std::string txn_id, std::string event_id) {
-                        if (edit_.toStdString() == txn_id) {
-                                edit_ = QString::fromStdString(event_id);
-                                emit editChanged(edit_);
-                        }
-                        if (reply_.toStdString() == txn_id) {
-                                reply_ = QString::fromStdString(event_id);
-                                emit replyChanged(reply_);
-                        }
-                });
-
-        connect(manager_,
-                &TimelineViewManager::initialSyncChanged,
-                &events,
-                &EventStore::enableKeyRequests);
-
-        connect(this, &TimelineModel::encryptionChanged, this, &TimelineModel::trustlevelChanged);
-        connect(
-          this, &TimelineModel::roomMemberCountChanged, this, &TimelineModel::trustlevelChanged);
-        connect(cache::client(),
-                &Cache::verificationStatusChanged,
-                this,
-                &TimelineModel::trustlevelChanged);
-
-        showEventTimer.callOnTimeout(this, &TimelineModel::scrollTimerEvent);
+    lastMessage_.timestamp = 0;
+
+    if (auto create =
+          cache::client()->getStateEvent<mtx::events::state::Create>(room_id.toStdString()))
+        this->isSpace_ = create->content.type == mtx::events::state::room_type::space;
+    this->isEncrypted_ = cache::isRoomEncrypted(room_id_.toStdString());
+
+    // this connection will simplify adding the plainRoomNameChanged() signal everywhere that it
+    // needs to be
+    connect(this, &TimelineModel::roomNameChanged, this, &TimelineModel::plainRoomNameChanged);
+
+    connect(
+      this,
+      &TimelineModel::redactionFailed,
+      this,
+      [](const QString &msg) { emit ChatPage::instance()->showNotification(msg); },
+      Qt::QueuedConnection);
+
+    connect(this,
+            &TimelineModel::newMessageToSend,
+            this,
+            &TimelineModel::addPendingMessage,
+            Qt::QueuedConnection);
+    connect(this, &TimelineModel::addPendingMessageToStore, &events, &EventStore::addPending);
+
+    connect(&events, &EventStore::dataChanged, this, [this](int from, int to) {
+        relatedEventCacheBuster++;
+        nhlog::ui()->debug(
+          "data changed {} to {}", events.size() - to - 1, events.size() - from - 1);
+        emit dataChanged(index(events.size() - to - 1, 0), index(events.size() - from - 1, 0));
+    });
+
+    connect(&events, &EventStore::beginInsertRows, this, [this](int from, int to) {
+        int first = events.size() - to;
+        int last  = events.size() - from;
+        if (from >= events.size()) {
+            int batch_size = to - from;
+            first += batch_size;
+            last += batch_size;
+        } else {
+            first -= 1;
+            last -= 1;
+        }
+        nhlog::ui()->debug("begin insert from {} to {}", first, last);
+        beginInsertRows(QModelIndex(), first, last);
+    });
+    connect(&events, &EventStore::endInsertRows, this, [this]() { endInsertRows(); });
+    connect(&events, &EventStore::beginResetModel, this, [this]() { beginResetModel(); });
+    connect(&events, &EventStore::endResetModel, this, [this]() { endResetModel(); });
+    connect(&events, &EventStore::newEncryptedImage, this, &TimelineModel::newEncryptedImage);
+    connect(&events, &EventStore::fetchedMore, this, [this]() { setPaginationInProgress(false); });
+    connect(&events,
+            &EventStore::startDMVerification,
+            this,
+            [this](mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest> msg) {
+                ChatPage::instance()->receivedRoomDeviceVerificationRequest(msg, this);
+            });
+    connect(&events, &EventStore::updateFlowEventId, this, [this](std::string event_id) {
+        this->updateFlowEventId(event_id);
+    });
+
+    // When a message is sent, check if the current edit/reply relates to that message,
+    // and update the event_id so that it points to the sent message and not the pending one.
+    connect(
+      &events, &EventStore::messageSent, this, [this](std::string txn_id, std::string event_id) {
+          if (edit_.toStdString() == txn_id) {
+              edit_ = QString::fromStdString(event_id);
+              emit editChanged(edit_);
+          }
+          if (reply_.toStdString() == txn_id) {
+              reply_ = QString::fromStdString(event_id);
+              emit replyChanged(reply_);
+          }
+      });
+
+    connect(
+      manager_, &TimelineViewManager::initialSyncChanged, &events, &EventStore::enableKeyRequests);
+
+    connect(this, &TimelineModel::encryptionChanged, this, &TimelineModel::trustlevelChanged);
+    connect(this, &TimelineModel::roomMemberCountChanged, this, &TimelineModel::trustlevelChanged);
+    connect(
+      cache::client(), &Cache::verificationStatusChanged, this, &TimelineModel::trustlevelChanged);
+
+    showEventTimer.callOnTimeout(this, &TimelineModel::scrollTimerEvent);
 }
 
 QHash<int, QByteArray>
 TimelineModel::roleNames() const
 {
-        return {
-          {Type, "type"},
-          {TypeString, "typeString"},
-          {IsOnlyEmoji, "isOnlyEmoji"},
-          {Body, "body"},
-          {FormattedBody, "formattedBody"},
-          {PreviousMessageUserId, "previousMessageUserId"},
-          {IsSender, "isSender"},
-          {UserId, "userId"},
-          {UserName, "userName"},
-          {PreviousMessageDay, "previousMessageDay"},
-          {Day, "day"},
-          {Timestamp, "timestamp"},
-          {Url, "url"},
-          {ThumbnailUrl, "thumbnailUrl"},
-          {Blurhash, "blurhash"},
-          {Filename, "filename"},
-          {Filesize, "filesize"},
-          {MimeType, "mimetype"},
-          {OriginalHeight, "originalHeight"},
-          {OriginalWidth, "originalWidth"},
-          {ProportionalHeight, "proportionalHeight"},
-          {EventId, "eventId"},
-          {State, "status"},
-          {IsEdited, "isEdited"},
-          {IsEditable, "isEditable"},
-          {IsEncrypted, "isEncrypted"},
-          {Trustlevel, "trustlevel"},
-          {EncryptionError, "encryptionError"},
-          {ReplyTo, "replyTo"},
-          {Reactions, "reactions"},
-          {RoomId, "roomId"},
-          {RoomName, "roomName"},
-          {RoomTopic, "roomTopic"},
-          {CallType, "callType"},
-          {Dump, "dump"},
-          {RelatedEventCacheBuster, "relatedEventCacheBuster"},
-        };
+    return {
+      {Type, "type"},
+      {TypeString, "typeString"},
+      {IsOnlyEmoji, "isOnlyEmoji"},
+      {Body, "body"},
+      {FormattedBody, "formattedBody"},
+      {PreviousMessageUserId, "previousMessageUserId"},
+      {IsSender, "isSender"},
+      {UserId, "userId"},
+      {UserName, "userName"},
+      {PreviousMessageDay, "previousMessageDay"},
+      {Day, "day"},
+      {Timestamp, "timestamp"},
+      {Url, "url"},
+      {ThumbnailUrl, "thumbnailUrl"},
+      {Blurhash, "blurhash"},
+      {Filename, "filename"},
+      {Filesize, "filesize"},
+      {MimeType, "mimetype"},
+      {OriginalHeight, "originalHeight"},
+      {OriginalWidth, "originalWidth"},
+      {ProportionalHeight, "proportionalHeight"},
+      {EventId, "eventId"},
+      {State, "status"},
+      {IsEdited, "isEdited"},
+      {IsEditable, "isEditable"},
+      {IsEncrypted, "isEncrypted"},
+      {Trustlevel, "trustlevel"},
+      {EncryptionError, "encryptionError"},
+      {ReplyTo, "replyTo"},
+      {Reactions, "reactions"},
+      {RoomId, "roomId"},
+      {RoomName, "roomName"},
+      {RoomTopic, "roomTopic"},
+      {CallType, "callType"},
+      {Dump, "dump"},
+      {RelatedEventCacheBuster, "relatedEventCacheBuster"},
+    };
 }
 int
 TimelineModel::rowCount(const QModelIndex &parent) const
 {
-        Q_UNUSED(parent);
-        return this->events.size();
+    Q_UNUSED(parent);
+    return this->events.size();
 }
 
 QVariantMap
 TimelineModel::getDump(QString eventId, QString relatedTo) const
 {
-        if (auto event = events.get(eventId.toStdString(), relatedTo.toStdString()))
-                return data(*event, Dump).toMap();
-        return {};
+    if (auto event = events.get(eventId.toStdString(), relatedTo.toStdString()))
+        return data(*event, Dump).toMap();
+    return {};
 }
 
 QVariant
 TimelineModel::data(const mtx::events::collections::TimelineEvents &event, int role) const
 {
-        using namespace mtx::accessors;
-        namespace acc = mtx::accessors;
-
-        switch (role) {
-        case IsSender:
-                return QVariant(acc::sender(event) == http::client()->user_id().to_string());
-        case UserId:
-                return QVariant(QString::fromStdString(acc::sender(event)));
-        case UserName:
-                return QVariant(displayName(QString::fromStdString(acc::sender(event))));
-
-        case Day: {
-                QDateTime prevDate = origin_server_ts(event);
-                prevDate.setTime(QTime());
-                return QVariant(prevDate.toMSecsSinceEpoch());
-        }
-        case Timestamp:
-                return QVariant(origin_server_ts(event));
-        case Type:
-                return QVariant(toRoomEventType(event));
-        case TypeString:
-                return QVariant(toRoomEventTypeString(event));
-        case IsOnlyEmoji: {
-                QString qBody = QString::fromStdString(body(event));
-
-                QVector<uint> utf32_string = qBody.toUcs4();
-                int emojiCount             = 0;
-
-                for (auto &code : utf32_string) {
-                        if (utils::codepointIsEmoji(code)) {
-                                emojiCount++;
-                        } else {
-                                return QVariant(0);
-                        }
-                }
-
-                return QVariant(emojiCount);
-        }
-        case Body:
-                return QVariant(
-                  utils::replaceEmoji(QString::fromStdString(body(event)).toHtmlEscaped()));
-        case FormattedBody: {
-                const static QRegularExpression replyFallback(
-                  "<mx-reply>.*</mx-reply>", QRegularExpression::DotMatchesEverythingOption);
-
-                auto ascent = QFontMetrics(UserSettings::instance()->font()).ascent();
-
-                bool isReply = utils::isReply(event);
-
-                auto formattedBody_ = QString::fromStdString(formatted_body(event));
-                if (formattedBody_.isEmpty()) {
-                        auto body_ = QString::fromStdString(body(event));
-
-                        if (isReply) {
-                                while (body_.startsWith("> "))
-                                        body_ = body_.right(body_.size() - body_.indexOf('\n') - 1);
-                                if (body_.startsWith('\n'))
-                                        body_ = body_.right(body_.size() - 1);
-                        }
-                        formattedBody_ = body_.toHtmlEscaped().replace('\n', "<br>");
-                } else {
-                        if (isReply)
-                                formattedBody_ = formattedBody_.remove(replyFallback);
-                }
-
-                // TODO(Nico): Don't parse html with a regex
-                const static QRegularExpression matchImgUri(
-                  "(<img [^>]*)src=\"mxc://([^\"]*)\"([^>]*>)");
-                formattedBody_.replace(matchImgUri, "\\1 src=\"image://mxcImage/\\2\"\\3");
-                // Same regex but for single quotes around the src
-                const static QRegularExpression matchImgUri2(
-                  "(<img [^>]*)src=\'mxc://([^\']*)\'([^>]*>)");
-                formattedBody_.replace(matchImgUri2, "\\1 src=\"image://mxcImage/\\2\"\\3");
-                const static QRegularExpression matchEmoticonHeight(
-                  "(<img data-mx-emoticon [^>]*)height=\"([^\"]*)\"([^>]*>)");
-                formattedBody_.replace(matchEmoticonHeight,
-                                       QString("\\1 height=\"%1\"\\3").arg(ascent));
-
-                return QVariant(utils::replaceEmoji(
-                  utils::linkifyMessage(utils::escapeBlacklistedHtml(formattedBody_))));
-        }
-        case Url:
-                return QVariant(QString::fromStdString(url(event)));
-        case ThumbnailUrl:
-                return QVariant(QString::fromStdString(thumbnail_url(event)));
-        case Blurhash:
-                return QVariant(QString::fromStdString(blurhash(event)));
-        case Filename:
-                return QVariant(QString::fromStdString(filename(event)));
-        case Filesize:
-                return QVariant(utils::humanReadableFileSize(filesize(event)));
-        case MimeType:
-                return QVariant(QString::fromStdString(mimetype(event)));
-        case OriginalHeight:
-                return QVariant(qulonglong{media_height(event)});
-        case OriginalWidth:
-                return QVariant(qulonglong{media_width(event)});
-        case ProportionalHeight: {
-                auto w = media_width(event);
-                if (w == 0)
-                        w = 1;
-
-                double prop = media_height(event) / (double)w;
-
-                return QVariant(prop > 0 ? prop : 1.);
-        }
-        case EventId: {
-                if (auto replaces = relations(event).replaces())
-                        return QVariant(QString::fromStdString(replaces.value()));
-                else
-                        return QVariant(QString::fromStdString(event_id(event)));
-        }
-        case State: {
-                auto id             = QString::fromStdString(event_id(event));
-                auto containsOthers = [](const auto &vec) {
-                        for (const auto &e : vec)
-                                if (e.second != http::client()->user_id().to_string())
-                                        return true;
-                        return false;
-                };
-
-                // only show read receipts for messages not from us
-                if (acc::sender(event) != http::client()->user_id().to_string())
-                        return qml_mtx_events::Empty;
-                else if (!id.isEmpty() && id[0] == "m")
-                        return qml_mtx_events::Sent;
-                else if (read.contains(id) || containsOthers(cache::readReceipts(id, room_id_)))
-                        return qml_mtx_events::Read;
-                else
-                        return qml_mtx_events::Received;
-        }
-        case IsEdited:
-                return QVariant(relations(event).replaces().has_value());
-        case IsEditable:
-                return QVariant(!is_state_event(event) && mtx::accessors::sender(event) ==
-                                                            http::client()->user_id().to_string());
-        case IsEncrypted: {
-                auto id              = event_id(event);
-                auto encrypted_event = events.get(id, "", false);
-                return encrypted_event &&
-                       std::holds_alternative<
-                         mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(
-                         *encrypted_event);
-        }
-
-        case Trustlevel: {
-                auto id              = event_id(event);
-                auto encrypted_event = events.get(id, "", false);
-                if (encrypted_event) {
-                        if (auto encrypted =
-                              std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(
-                                &*encrypted_event)) {
-                                return olm::calculate_trust(
-                                  encrypted->sender,
-                                  MegolmSessionIndex(room_id_.toStdString(), encrypted->content));
-                        }
-                }
-                return crypto::Trust::Unverified;
-        }
-
-        case EncryptionError:
-                return events.decryptionError(event_id(event));
+    using namespace mtx::accessors;
+    namespace acc = mtx::accessors;
+
+    switch (role) {
+    case IsSender:
+        return QVariant(acc::sender(event) == http::client()->user_id().to_string());
+    case UserId:
+        return QVariant(QString::fromStdString(acc::sender(event)));
+    case UserName:
+        return QVariant(displayName(QString::fromStdString(acc::sender(event))));
+
+    case Day: {
+        QDateTime prevDate = origin_server_ts(event);
+        prevDate.setTime(QTime());
+        return QVariant(prevDate.toMSecsSinceEpoch());
+    }
+    case Timestamp:
+        return QVariant(origin_server_ts(event));
+    case Type:
+        return QVariant(toRoomEventType(event));
+    case TypeString:
+        return QVariant(toRoomEventTypeString(event));
+    case IsOnlyEmoji: {
+        QString qBody = QString::fromStdString(body(event));
+
+        QVector<uint> utf32_string = qBody.toUcs4();
+        int emojiCount             = 0;
+
+        for (auto &code : utf32_string) {
+            if (utils::codepointIsEmoji(code)) {
+                emojiCount++;
+            } else {
+                return QVariant(0);
+            }
+        }
+
+        return QVariant(emojiCount);
+    }
+    case Body:
+        return QVariant(utils::replaceEmoji(QString::fromStdString(body(event)).toHtmlEscaped()));
+    case FormattedBody: {
+        const static QRegularExpression replyFallback(
+          "<mx-reply>.*</mx-reply>", QRegularExpression::DotMatchesEverythingOption);
+
+        auto ascent = QFontMetrics(UserSettings::instance()->font()).ascent();
+
+        bool isReply = utils::isReply(event);
+
+        auto formattedBody_ = QString::fromStdString(formatted_body(event));
+        if (formattedBody_.isEmpty()) {
+            auto body_ = QString::fromStdString(body(event));
+
+            if (isReply) {
+                while (body_.startsWith("> "))
+                    body_ = body_.right(body_.size() - body_.indexOf('\n') - 1);
+                if (body_.startsWith('\n'))
+                    body_ = body_.right(body_.size() - 1);
+            }
+            formattedBody_ = body_.toHtmlEscaped().replace('\n', "<br>");
+        } else {
+            if (isReply)
+                formattedBody_ = formattedBody_.remove(replyFallback);
+        }
+
+        // TODO(Nico): Don't parse html with a regex
+        const static QRegularExpression matchImgUri("(<img [^>]*)src=\"mxc://([^\"]*)\"([^>]*>)");
+        formattedBody_.replace(matchImgUri, "\\1 src=\"image://mxcImage/\\2\"\\3");
+        // Same regex but for single quotes around the src
+        const static QRegularExpression matchImgUri2("(<img [^>]*)src=\'mxc://([^\']*)\'([^>]*>)");
+        formattedBody_.replace(matchImgUri2, "\\1 src=\"image://mxcImage/\\2\"\\3");
+        const static QRegularExpression matchEmoticonHeight(
+          "(<img data-mx-emoticon [^>]*)height=\"([^\"]*)\"([^>]*>)");
+        formattedBody_.replace(matchEmoticonHeight, QString("\\1 height=\"%1\"\\3").arg(ascent));
+
+        return QVariant(
+          utils::replaceEmoji(utils::linkifyMessage(utils::escapeBlacklistedHtml(formattedBody_))));
+    }
+    case Url:
+        return QVariant(QString::fromStdString(url(event)));
+    case ThumbnailUrl:
+        return QVariant(QString::fromStdString(thumbnail_url(event)));
+    case Blurhash:
+        return QVariant(QString::fromStdString(blurhash(event)));
+    case Filename:
+        return QVariant(QString::fromStdString(filename(event)));
+    case Filesize:
+        return QVariant(utils::humanReadableFileSize(filesize(event)));
+    case MimeType:
+        return QVariant(QString::fromStdString(mimetype(event)));
+    case OriginalHeight:
+        return QVariant(qulonglong{media_height(event)});
+    case OriginalWidth:
+        return QVariant(qulonglong{media_width(event)});
+    case ProportionalHeight: {
+        auto w = media_width(event);
+        if (w == 0)
+            w = 1;
+
+        double prop = media_height(event) / (double)w;
+
+        return QVariant(prop > 0 ? prop : 1.);
+    }
+    case EventId: {
+        if (auto replaces = relations(event).replaces())
+            return QVariant(QString::fromStdString(replaces.value()));
+        else
+            return QVariant(QString::fromStdString(event_id(event)));
+    }
+    case State: {
+        auto id             = QString::fromStdString(event_id(event));
+        auto containsOthers = [](const auto &vec) {
+            for (const auto &e : vec)
+                if (e.second != http::client()->user_id().to_string())
+                    return true;
+            return false;
+        };
 
-        case ReplyTo:
-                return QVariant(QString::fromStdString(relations(event).reply_to().value_or("")));
-        case Reactions: {
-                auto id = relations(event).replaces().value_or(event_id(event));
-                return QVariant::fromValue(events.reactions(id));
-        }
-        case RoomId:
-                return QVariant(room_id_);
-        case RoomName:
-                return QVariant(
-                  utils::replaceEmoji(QString::fromStdString(room_name(event)).toHtmlEscaped()));
-        case RoomTopic:
-                return QVariant(utils::replaceEmoji(
-                  utils::linkifyMessage(QString::fromStdString(room_topic(event))
-                                          .toHtmlEscaped()
-                                          .replace("\n", "<br>"))));
-        case CallType:
-                return QVariant(QString::fromStdString(call_type(event)));
-        case Dump: {
-                QVariantMap m;
-                auto names = roleNames();
-
-                m.insert(names[Type], data(event, static_cast<int>(Type)));
-                m.insert(names[TypeString], data(event, static_cast<int>(TypeString)));
-                m.insert(names[IsOnlyEmoji], data(event, static_cast<int>(IsOnlyEmoji)));
-                m.insert(names[Body], data(event, static_cast<int>(Body)));
-                m.insert(names[FormattedBody], data(event, static_cast<int>(FormattedBody)));
-                m.insert(names[IsSender], data(event, static_cast<int>(IsSender)));
-                m.insert(names[UserId], data(event, static_cast<int>(UserId)));
-                m.insert(names[UserName], data(event, static_cast<int>(UserName)));
-                m.insert(names[Day], data(event, static_cast<int>(Day)));
-                m.insert(names[Timestamp], data(event, static_cast<int>(Timestamp)));
-                m.insert(names[Url], data(event, static_cast<int>(Url)));
-                m.insert(names[ThumbnailUrl], data(event, static_cast<int>(ThumbnailUrl)));
-                m.insert(names[Blurhash], data(event, static_cast<int>(Blurhash)));
-                m.insert(names[Filename], data(event, static_cast<int>(Filename)));
-                m.insert(names[Filesize], data(event, static_cast<int>(Filesize)));
-                m.insert(names[MimeType], data(event, static_cast<int>(MimeType)));
-                m.insert(names[OriginalHeight], data(event, static_cast<int>(OriginalHeight)));
-                m.insert(names[OriginalWidth], data(event, static_cast<int>(OriginalWidth)));
-                m.insert(names[ProportionalHeight],
-                         data(event, static_cast<int>(ProportionalHeight)));
-                m.insert(names[EventId], data(event, static_cast<int>(EventId)));
-                m.insert(names[State], data(event, static_cast<int>(State)));
-                m.insert(names[IsEdited], data(event, static_cast<int>(IsEdited)));
-                m.insert(names[IsEditable], data(event, static_cast<int>(IsEditable)));
-                m.insert(names[IsEncrypted], data(event, static_cast<int>(IsEncrypted)));
-                m.insert(names[ReplyTo], data(event, static_cast<int>(ReplyTo)));
-                m.insert(names[RoomName], data(event, static_cast<int>(RoomName)));
-                m.insert(names[RoomTopic], data(event, static_cast<int>(RoomTopic)));
-                m.insert(names[CallType], data(event, static_cast<int>(CallType)));
-                m.insert(names[EncryptionError], data(event, static_cast<int>(EncryptionError)));
-
-                return QVariant(m);
-        }
-        case RelatedEventCacheBuster:
-                return relatedEventCacheBuster;
-        default:
-                return QVariant();
-        }
+        // only show read receipts for messages not from us
+        if (acc::sender(event) != http::client()->user_id().to_string())
+            return qml_mtx_events::Empty;
+        else if (!id.isEmpty() && id[0] == "m")
+            return qml_mtx_events::Sent;
+        else if (read.contains(id) || containsOthers(cache::readReceipts(id, room_id_)))
+            return qml_mtx_events::Read;
+        else
+            return qml_mtx_events::Received;
+    }
+    case IsEdited:
+        return QVariant(relations(event).replaces().has_value());
+    case IsEditable:
+        return QVariant(!is_state_event(event) &&
+                        mtx::accessors::sender(event) == http::client()->user_id().to_string());
+    case IsEncrypted: {
+        auto id              = event_id(event);
+        auto encrypted_event = events.get(id, "", false);
+        return encrypted_event &&
+               std::holds_alternative<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(
+                 *encrypted_event);
+    }
+
+    case Trustlevel: {
+        auto id              = event_id(event);
+        auto encrypted_event = events.get(id, "", false);
+        if (encrypted_event) {
+            if (auto encrypted =
+                  std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(
+                    &*encrypted_event)) {
+                return olm::calculate_trust(
+                  encrypted->sender,
+                  MegolmSessionIndex(room_id_.toStdString(), encrypted->content));
+            }
+        }
+        return crypto::Trust::Unverified;
+    }
+
+    case EncryptionError:
+        return events.decryptionError(event_id(event));
+
+    case ReplyTo:
+        return QVariant(QString::fromStdString(relations(event).reply_to().value_or("")));
+    case Reactions: {
+        auto id = relations(event).replaces().value_or(event_id(event));
+        return QVariant::fromValue(events.reactions(id));
+    }
+    case RoomId:
+        return QVariant(room_id_);
+    case RoomName:
+        return QVariant(
+          utils::replaceEmoji(QString::fromStdString(room_name(event)).toHtmlEscaped()));
+    case RoomTopic:
+        return QVariant(utils::replaceEmoji(utils::linkifyMessage(
+          QString::fromStdString(room_topic(event)).toHtmlEscaped().replace("\n", "<br>"))));
+    case CallType:
+        return QVariant(QString::fromStdString(call_type(event)));
+    case Dump: {
+        QVariantMap m;
+        auto names = roleNames();
+
+        m.insert(names[Type], data(event, static_cast<int>(Type)));
+        m.insert(names[TypeString], data(event, static_cast<int>(TypeString)));
+        m.insert(names[IsOnlyEmoji], data(event, static_cast<int>(IsOnlyEmoji)));
+        m.insert(names[Body], data(event, static_cast<int>(Body)));
+        m.insert(names[FormattedBody], data(event, static_cast<int>(FormattedBody)));
+        m.insert(names[IsSender], data(event, static_cast<int>(IsSender)));
+        m.insert(names[UserId], data(event, static_cast<int>(UserId)));
+        m.insert(names[UserName], data(event, static_cast<int>(UserName)));
+        m.insert(names[Day], data(event, static_cast<int>(Day)));
+        m.insert(names[Timestamp], data(event, static_cast<int>(Timestamp)));
+        m.insert(names[Url], data(event, static_cast<int>(Url)));
+        m.insert(names[ThumbnailUrl], data(event, static_cast<int>(ThumbnailUrl)));
+        m.insert(names[Blurhash], data(event, static_cast<int>(Blurhash)));
+        m.insert(names[Filename], data(event, static_cast<int>(Filename)));
+        m.insert(names[Filesize], data(event, static_cast<int>(Filesize)));
+        m.insert(names[MimeType], data(event, static_cast<int>(MimeType)));
+        m.insert(names[OriginalHeight], data(event, static_cast<int>(OriginalHeight)));
+        m.insert(names[OriginalWidth], data(event, static_cast<int>(OriginalWidth)));
+        m.insert(names[ProportionalHeight], data(event, static_cast<int>(ProportionalHeight)));
+        m.insert(names[EventId], data(event, static_cast<int>(EventId)));
+        m.insert(names[State], data(event, static_cast<int>(State)));
+        m.insert(names[IsEdited], data(event, static_cast<int>(IsEdited)));
+        m.insert(names[IsEditable], data(event, static_cast<int>(IsEditable)));
+        m.insert(names[IsEncrypted], data(event, static_cast<int>(IsEncrypted)));
+        m.insert(names[ReplyTo], data(event, static_cast<int>(ReplyTo)));
+        m.insert(names[RoomName], data(event, static_cast<int>(RoomName)));
+        m.insert(names[RoomTopic], data(event, static_cast<int>(RoomTopic)));
+        m.insert(names[CallType], data(event, static_cast<int>(CallType)));
+        m.insert(names[EncryptionError], data(event, static_cast<int>(EncryptionError)));
+
+        return QVariant(m);
+    }
+    case RelatedEventCacheBuster:
+        return relatedEventCacheBuster;
+    default:
+        return QVariant();
+    }
 }
 
 QVariant
 TimelineModel::data(const QModelIndex &index, int role) const
 {
-        using namespace mtx::accessors;
-        namespace acc = mtx::accessors;
-        if (index.row() < 0 && index.row() >= rowCount())
-                return QVariant();
+    using namespace mtx::accessors;
+    namespace acc = mtx::accessors;
+    if (index.row() < 0 && index.row() >= rowCount())
+        return QVariant();
 
-        // HACK(Nico): fetchMore likes to break with dynamically sized delegates and reuseItems
-        if (index.row() + 1 == rowCount() && !m_paginationInProgress)
-                const_cast<TimelineModel *>(this)->fetchMore(index);
+    // HACK(Nico): fetchMore likes to break with dynamically sized delegates and reuseItems
+    if (index.row() + 1 == rowCount() && !m_paginationInProgress)
+        const_cast<TimelineModel *>(this)->fetchMore(index);
 
-        auto event = events.get(rowCount() - index.row() - 1);
+    auto event = events.get(rowCount() - index.row() - 1);
 
-        if (!event)
-                return "";
-
-        if (role == PreviousMessageDay || role == PreviousMessageUserId) {
-                int prevIdx = rowCount() - index.row() - 2;
-                if (prevIdx < 0)
-                        return QVariant();
-                auto tempEv = events.get(prevIdx);
-                if (!tempEv)
-                        return QVariant();
-                if (role == PreviousMessageUserId)
-                        return data(*tempEv, UserId);
-                else
-                        return data(*tempEv, Day);
-        }
+    if (!event)
+        return "";
 
-        return data(*event, role);
+    if (role == PreviousMessageDay || role == PreviousMessageUserId) {
+        int prevIdx = rowCount() - index.row() - 2;
+        if (prevIdx < 0)
+            return QVariant();
+        auto tempEv = events.get(prevIdx);
+        if (!tempEv)
+            return QVariant();
+        if (role == PreviousMessageUserId)
+            return data(*tempEv, UserId);
+        else
+            return data(*tempEv, Day);
+    }
+
+    return data(*event, role);
 }
 
 QVariant
 TimelineModel::dataById(QString id, int role, QString relatedTo)
 {
-        if (auto event = events.get(id.toStdString(), relatedTo.toStdString()))
-                return data(*event, role);
-        return QVariant();
+    if (auto event = events.get(id.toStdString(), relatedTo.toStdString()))
+        return data(*event, role);
+    return QVariant();
 }
 
 bool
 TimelineModel::canFetchMore(const QModelIndex &) const
 {
-        if (!events.size())
-                return true;
-        if (auto first = events.get(0);
-            first &&
-            !std::holds_alternative<mtx::events::StateEvent<mtx::events::state::Create>>(*first))
-                return true;
-        else
+    if (!events.size())
+        return true;
+    if (auto first = events.get(0);
+        first &&
+        !std::holds_alternative<mtx::events::StateEvent<mtx::events::state::Create>>(*first))
+        return true;
+    else
 
-                return false;
+        return false;
 }
 
 void
 TimelineModel::setPaginationInProgress(const bool paginationInProgress)
 {
-        if (m_paginationInProgress == paginationInProgress) {
-                return;
-        }
+    if (m_paginationInProgress == paginationInProgress) {
+        return;
+    }
 
-        m_paginationInProgress = paginationInProgress;
-        emit paginationInProgressChanged(m_paginationInProgress);
+    m_paginationInProgress = paginationInProgress;
+    emit paginationInProgressChanged(m_paginationInProgress);
 }
 
 void
 TimelineModel::fetchMore(const QModelIndex &)
 {
-        if (m_paginationInProgress) {
-                nhlog::ui()->warn("Already loading older messages");
-                return;
-        }
+    if (m_paginationInProgress) {
+        nhlog::ui()->warn("Already loading older messages");
+        return;
+    }
 
-        setPaginationInProgress(true);
+    setPaginationInProgress(true);
 
-        events.fetchMore();
+    events.fetchMore();
 }
 
 void
 TimelineModel::sync(const mtx::responses::JoinedRoom &room)
 {
-        this->syncState(room.state);
-        this->addEvents(room.timeline);
+    this->syncState(room.state);
+    this->addEvents(room.timeline);
 
-        if (room.unread_notifications.highlight_count != highlight_count ||
-            room.unread_notifications.notification_count != notification_count) {
-                notification_count = room.unread_notifications.notification_count;
-                highlight_count    = room.unread_notifications.highlight_count;
-                emit notificationsChanged();
-        }
+    if (room.unread_notifications.highlight_count != highlight_count ||
+        room.unread_notifications.notification_count != notification_count) {
+        notification_count = room.unread_notifications.notification_count;
+        highlight_count    = room.unread_notifications.highlight_count;
+        emit notificationsChanged();
+    }
 }
 
 void
 TimelineModel::syncState(const mtx::responses::State &s)
 {
-        using namespace mtx::events;
-
-        for (const auto &e : s.events) {
-                if (std::holds_alternative<StateEvent<state::Avatar>>(e))
-                        emit roomAvatarUrlChanged();
-                else if (std::holds_alternative<StateEvent<state::Name>>(e))
-                        emit roomNameChanged();
-                else if (std::holds_alternative<StateEvent<state::Topic>>(e))
-                        emit roomTopicChanged();
-                else if (std::holds_alternative<StateEvent<state::Topic>>(e)) {
-                        permissions_.invalidate();
-                        emit permissionsChanged();
-                } else if (std::holds_alternative<StateEvent<state::Member>>(e)) {
-                        emit roomAvatarUrlChanged();
-                        emit roomNameChanged();
-                        emit roomMemberCountChanged();
-
-                        if (roomMemberCount() <= 2) {
-                                emit isDirectChanged();
-                                emit directChatOtherUserIdChanged();
-                        }
-                } else if (std::holds_alternative<StateEvent<state::Encryption>>(e)) {
-                        this->isEncrypted_ = cache::isRoomEncrypted(room_id_.toStdString());
-                        emit encryptionChanged();
-                }
-        }
+    using namespace mtx::events;
+
+    for (const auto &e : s.events) {
+        if (std::holds_alternative<StateEvent<state::Avatar>>(e))
+            emit roomAvatarUrlChanged();
+        else if (std::holds_alternative<StateEvent<state::Name>>(e))
+            emit roomNameChanged();
+        else if (std::holds_alternative<StateEvent<state::Topic>>(e))
+            emit roomTopicChanged();
+        else if (std::holds_alternative<StateEvent<state::Topic>>(e)) {
+            permissions_.invalidate();
+            emit permissionsChanged();
+        } else if (std::holds_alternative<StateEvent<state::Member>>(e)) {
+            emit roomAvatarUrlChanged();
+            emit roomNameChanged();
+            emit roomMemberCountChanged();
+
+            if (roomMemberCount() <= 2) {
+                emit isDirectChanged();
+                emit directChatOtherUserIdChanged();
+            }
+        } else if (std::holds_alternative<StateEvent<state::Encryption>>(e)) {
+            this->isEncrypted_ = cache::isRoomEncrypted(room_id_.toStdString());
+            emit encryptionChanged();
+        }
+    }
 }
 
 void
 TimelineModel::addEvents(const mtx::responses::Timeline &timeline)
 {
-        if (timeline.events.empty())
-                return;
-
-        events.handleSync(timeline);
-
-        using namespace mtx::events;
-
-        for (auto e : timeline.events) {
-                if (auto encryptedEvent = std::get_if<EncryptedEvent<msg::Encrypted>>(&e)) {
-                        MegolmSessionIndex index(room_id_.toStdString(), encryptedEvent->content);
-
-                        auto result = olm::decryptEvent(index, *encryptedEvent);
-                        if (result.event)
-                                e = result.event.value();
-                }
+    if (timeline.events.empty())
+        return;
 
-                if (std::holds_alternative<RoomEvent<msg::CallCandidates>>(e) ||
-                    std::holds_alternative<RoomEvent<msg::CallInvite>>(e) ||
-                    std::holds_alternative<RoomEvent<msg::CallAnswer>>(e) ||
-                    std::holds_alternative<RoomEvent<msg::CallHangUp>>(e))
-                        std::visit(
-                          [this](auto &event) {
-                                  event.room_id = room_id_.toStdString();
-                                  if constexpr (std::is_same_v<std::decay_t<decltype(event)>,
-                                                               RoomEvent<msg::CallAnswer>> ||
-                                                std::is_same_v<std::decay_t<decltype(event)>,
-                                                               RoomEvent<msg::CallHangUp>>)
-                                          emit newCallEvent(event);
-                                  else {
-                                          if (event.sender != http::client()->user_id().to_string())
-                                                  emit newCallEvent(event);
-                                  }
-                          },
-                          e);
-                else if (std::holds_alternative<StateEvent<state::Avatar>>(e))
-                        emit roomAvatarUrlChanged();
-                else if (std::holds_alternative<StateEvent<state::Name>>(e))
-                        emit roomNameChanged();
-                else if (std::holds_alternative<StateEvent<state::Topic>>(e))
-                        emit roomTopicChanged();
-                else if (std::holds_alternative<StateEvent<state::PowerLevels>>(e)) {
-                        permissions_.invalidate();
-                        emit permissionsChanged();
-                } else if (std::holds_alternative<StateEvent<state::Member>>(e)) {
-                        emit roomAvatarUrlChanged();
-                        emit roomNameChanged();
-                        emit roomMemberCountChanged();
-                } else if (std::holds_alternative<StateEvent<state::Encryption>>(e)) {
-                        this->isEncrypted_ = cache::isRoomEncrypted(room_id_.toStdString());
-                        emit encryptionChanged();
-                }
-        }
-        updateLastMessage();
+    events.handleSync(timeline);
+
+    using namespace mtx::events;
+
+    for (auto e : timeline.events) {
+        if (auto encryptedEvent = std::get_if<EncryptedEvent<msg::Encrypted>>(&e)) {
+            MegolmSessionIndex index(room_id_.toStdString(), encryptedEvent->content);
+
+            auto result = olm::decryptEvent(index, *encryptedEvent);
+            if (result.event)
+                e = result.event.value();
+        }
+
+        if (std::holds_alternative<RoomEvent<msg::CallCandidates>>(e) ||
+            std::holds_alternative<RoomEvent<msg::CallInvite>>(e) ||
+            std::holds_alternative<RoomEvent<msg::CallAnswer>>(e) ||
+            std::holds_alternative<RoomEvent<msg::CallHangUp>>(e))
+            std::visit(
+              [this](auto &event) {
+                  event.room_id = room_id_.toStdString();
+                  if constexpr (std::is_same_v<std::decay_t<decltype(event)>,
+                                               RoomEvent<msg::CallAnswer>> ||
+                                std::is_same_v<std::decay_t<decltype(event)>,
+                                               RoomEvent<msg::CallHangUp>>)
+                      emit newCallEvent(event);
+                  else {
+                      if (event.sender != http::client()->user_id().to_string())
+                          emit newCallEvent(event);
+                  }
+              },
+              e);
+        else if (std::holds_alternative<StateEvent<state::Avatar>>(e))
+            emit roomAvatarUrlChanged();
+        else if (std::holds_alternative<StateEvent<state::Name>>(e))
+            emit roomNameChanged();
+        else if (std::holds_alternative<StateEvent<state::Topic>>(e))
+            emit roomTopicChanged();
+        else if (std::holds_alternative<StateEvent<state::PowerLevels>>(e)) {
+            permissions_.invalidate();
+            emit permissionsChanged();
+        } else if (std::holds_alternative<StateEvent<state::Member>>(e)) {
+            emit roomAvatarUrlChanged();
+            emit roomNameChanged();
+            emit roomMemberCountChanged();
+        } else if (std::holds_alternative<StateEvent<state::Encryption>>(e)) {
+            this->isEncrypted_ = cache::isRoomEncrypted(room_id_.toStdString());
+            emit encryptionChanged();
+        }
+    }
+    updateLastMessage();
 }
 
 template<typename T>
@@ -896,1216 +876,1191 @@ auto
 isMessage(const mtx::events::RoomEvent<T> &e)
   -> std::enable_if_t<std::is_same<decltype(e.content.msgtype), std::string>::value, bool>
 {
-        return true;
+    return true;
 }
 
 template<typename T>
 auto
 isMessage(const mtx::events::Event<T> &)
 {
-        return false;
+    return false;
 }
 
 template<typename T>
 auto
 isMessage(const mtx::events::EncryptedEvent<T> &)
 {
-        return true;
+    return true;
 }
 
 auto
 isMessage(const mtx::events::RoomEvent<mtx::events::msg::CallInvite> &)
 {
-        return true;
+    return true;
 }
 
 auto
 isMessage(const mtx::events::RoomEvent<mtx::events::msg::CallAnswer> &)
 {
-        return true;
+    return true;
 }
 auto
 isMessage(const mtx::events::RoomEvent<mtx::events::msg::CallHangUp> &)
 {
-        return true;
+    return true;
 }
 
 // Workaround. We also want to see a room at the top, if we just joined it
 auto
 isYourJoin(const mtx::events::StateEvent<mtx::events::state::Member> &e)
 {
-        return e.content.membership == mtx::events::state::Membership::Join &&
-               e.state_key == http::client()->user_id().to_string();
+    return e.content.membership == mtx::events::state::Membership::Join &&
+           e.state_key == http::client()->user_id().to_string();
 }
 template<typename T>
 auto
 isYourJoin(const mtx::events::Event<T> &)
 {
-        return false;
+    return false;
 }
 
 void
 TimelineModel::updateLastMessage()
 {
-        for (auto it = events.size() - 1; it >= 0; --it) {
-                auto event = events.get(it, decryptDescription);
-                if (!event)
-                        continue;
-
-                if (std::visit([](const auto &e) -> bool { return isYourJoin(e); }, *event)) {
-                        auto time   = mtx::accessors::origin_server_ts(*event);
-                        uint64_t ts = time.toMSecsSinceEpoch();
-                        auto description =
-                          DescInfo{QString::fromStdString(mtx::accessors::event_id(*event)),
-                                   QString::fromStdString(http::client()->user_id().to_string()),
-                                   tr("You joined this room."),
-                                   utils::descriptiveTime(time),
-                                   ts,
-                                   time};
-                        if (description != lastMessage_) {
-                                lastMessage_ = description;
-                                emit lastMessageChanged();
-                        }
-                        return;
-                }
-                if (!std::visit([](const auto &e) -> bool { return isMessage(e); }, *event))
-                        continue;
-
-                auto description = utils::getMessageDescription(
-                  *event,
-                  QString::fromStdString(http::client()->user_id().to_string()),
-                  cache::displayName(room_id_,
-                                     QString::fromStdString(mtx::accessors::sender(*event))));
-                if (description != lastMessage_) {
-                        lastMessage_ = description;
-                        emit lastMessageChanged();
-                }
-                return;
+    for (auto it = events.size() - 1; it >= 0; --it) {
+        auto event = events.get(it, decryptDescription);
+        if (!event)
+            continue;
+
+        if (std::visit([](const auto &e) -> bool { return isYourJoin(e); }, *event)) {
+            auto time   = mtx::accessors::origin_server_ts(*event);
+            uint64_t ts = time.toMSecsSinceEpoch();
+            auto description =
+              DescInfo{QString::fromStdString(mtx::accessors::event_id(*event)),
+                       QString::fromStdString(http::client()->user_id().to_string()),
+                       tr("You joined this room."),
+                       utils::descriptiveTime(time),
+                       ts,
+                       time};
+            if (description != lastMessage_) {
+                lastMessage_ = description;
+                emit lastMessageChanged();
+            }
+            return;
+        }
+        if (!std::visit([](const auto &e) -> bool { return isMessage(e); }, *event))
+            continue;
+
+        auto description = utils::getMessageDescription(
+          *event,
+          QString::fromStdString(http::client()->user_id().to_string()),
+          cache::displayName(room_id_, QString::fromStdString(mtx::accessors::sender(*event))));
+        if (description != lastMessage_) {
+            lastMessage_ = description;
+            emit lastMessageChanged();
         }
+        return;
+    }
 }
 
 void
 TimelineModel::setCurrentIndex(int index)
 {
-        auto oldIndex = idToIndex(currentId);
-        currentId     = indexToId(index);
-        if (index != oldIndex)
-                emit currentIndexChanged(index);
+    auto oldIndex = idToIndex(currentId);
+    currentId     = indexToId(index);
+    if (index != oldIndex)
+        emit currentIndexChanged(index);
 
-        if (!ChatPage::instance()->isActiveWindow())
-                return;
+    if (!ChatPage::instance()->isActiveWindow())
+        return;
 
-        if (!currentId.startsWith("m")) {
-                auto oldReadIndex =
-                  cache::getEventIndex(roomId().toStdString(), currentReadId.toStdString());
-                auto nextEventIndexAndId =
-                  cache::lastInvisibleEventAfter(roomId().toStdString(), currentId.toStdString());
+    if (!currentId.startsWith("m")) {
+        auto oldReadIndex =
+          cache::getEventIndex(roomId().toStdString(), currentReadId.toStdString());
+        auto nextEventIndexAndId =
+          cache::lastInvisibleEventAfter(roomId().toStdString(), currentId.toStdString());
 
-                if (nextEventIndexAndId &&
-                    (!oldReadIndex || *oldReadIndex < nextEventIndexAndId->first)) {
-                        readEvent(nextEventIndexAndId->second);
-                        currentReadId = QString::fromStdString(nextEventIndexAndId->second);
-                }
+        if (nextEventIndexAndId && (!oldReadIndex || *oldReadIndex < nextEventIndexAndId->first)) {
+            readEvent(nextEventIndexAndId->second);
+            currentReadId = QString::fromStdString(nextEventIndexAndId->second);
         }
+    }
 }
 
 void
 TimelineModel::readEvent(const std::string &id)
 {
-        http::client()->read_event(room_id_.toStdString(), id, [this](mtx::http::RequestErr err) {
-                if (err) {
-                        nhlog::net()->warn("failed to read_event ({}, {})",
-                                           room_id_.toStdString(),
-                                           currentId.toStdString());
-                }
-        });
+    http::client()->read_event(room_id_.toStdString(), id, [this](mtx::http::RequestErr err) {
+        if (err) {
+            nhlog::net()->warn(
+              "failed to read_event ({}, {})", room_id_.toStdString(), currentId.toStdString());
+        }
+    });
 }
 
 QString
 TimelineModel::displayName(QString id) const
 {
-        return cache::displayName(room_id_, id).toHtmlEscaped();
+    return cache::displayName(room_id_, id).toHtmlEscaped();
 }
 
 QString
 TimelineModel::avatarUrl(QString id) const
 {
-        return cache::avatarUrl(room_id_, id);
+    return cache::avatarUrl(room_id_, id);
 }
 
 QString
 TimelineModel::formatDateSeparator(QDate date) const
 {
-        auto now = QDateTime::currentDateTime();
+    auto now = QDateTime::currentDateTime();
 
-        QString fmt = QLocale::system().dateFormat(QLocale::LongFormat);
+    QString fmt = QLocale::system().dateFormat(QLocale::LongFormat);
 
-        if (now.date().year() == date.year()) {
-                QRegularExpression rx("[^a-zA-Z]*y+[^a-zA-Z]*");
-                fmt = fmt.remove(rx);
-        }
+    if (now.date().year() == date.year()) {
+        QRegularExpression rx("[^a-zA-Z]*y+[^a-zA-Z]*");
+        fmt = fmt.remove(rx);
+    }
 
-        return date.toString(fmt);
+    return date.toString(fmt);
 }
 
 void
 TimelineModel::viewRawMessage(QString id)
 {
-        auto e = events.get(id.toStdString(), "", false);
-        if (!e)
-                return;
-        std::string ev = mtx::accessors::serialize_event(*e).dump(4);
-        emit showRawMessageDialog(QString::fromStdString(ev));
+    auto e = events.get(id.toStdString(), "", false);
+    if (!e)
+        return;
+    std::string ev = mtx::accessors::serialize_event(*e).dump(4);
+    emit showRawMessageDialog(QString::fromStdString(ev));
 }
 
 void
 TimelineModel::forwardMessage(QString eventId, QString roomId)
 {
-        auto e = events.get(eventId.toStdString(), "");
-        if (!e)
-                return;
+    auto e = events.get(eventId.toStdString(), "");
+    if (!e)
+        return;
 
-        emit forwardToRoom(e, roomId);
+    emit forwardToRoom(e, roomId);
 }
 
 void
 TimelineModel::viewDecryptedRawMessage(QString id)
 {
-        auto e = events.get(id.toStdString(), "");
-        if (!e)
-                return;
+    auto e = events.get(id.toStdString(), "");
+    if (!e)
+        return;
 
-        std::string ev = mtx::accessors::serialize_event(*e).dump(4);
-        emit showRawMessageDialog(QString::fromStdString(ev));
+    std::string ev = mtx::accessors::serialize_event(*e).dump(4);
+    emit showRawMessageDialog(QString::fromStdString(ev));
 }
 
 void
 TimelineModel::openUserProfile(QString userid)
 {
-        UserProfile *userProfile = new UserProfile(room_id_, userid, manager_, this);
-        connect(
-          this, &TimelineModel::roomAvatarUrlChanged, userProfile, &UserProfile::updateAvatarUrl);
-        emit manager_->openProfile(userProfile);
+    UserProfile *userProfile = new UserProfile(room_id_, userid, manager_, this);
+    connect(this, &TimelineModel::roomAvatarUrlChanged, userProfile, &UserProfile::updateAvatarUrl);
+    emit manager_->openProfile(userProfile);
 }
 
 void
 TimelineModel::replyAction(QString id)
 {
-        setReply(id);
+    setReply(id);
 }
 
 void
 TimelineModel::editAction(QString id)
 {
-        setEdit(id);
+    setEdit(id);
 }
 
 RelatedInfo
 TimelineModel::relatedInfo(QString id)
 {
-        auto event = events.get(id.toStdString(), "");
-        if (!event)
-                return {};
+    auto event = events.get(id.toStdString(), "");
+    if (!event)
+        return {};
 
-        return utils::stripReplyFallbacks(*event, id.toStdString(), room_id_);
+    return utils::stripReplyFallbacks(*event, id.toStdString(), room_id_);
 }
 
 void
 TimelineModel::showReadReceipts(QString id)
 {
-        emit openReadReceiptsDialog(new ReadReceiptsProxy{id, roomId(), this});
+    emit openReadReceiptsDialog(new ReadReceiptsProxy{id, roomId(), this});
 }
 
 void
 TimelineModel::redactEvent(QString id)
 {
-        if (!id.isEmpty())
-                http::client()->redact_event(
-                  room_id_.toStdString(),
-                  id.toStdString(),
-                  [this, id](const mtx::responses::EventId &, mtx::http::RequestErr err) {
-                          if (err) {
-                                  emit redactionFailed(
-                                    tr("Message redaction failed: %1")
-                                      .arg(QString::fromStdString(err->matrix_error.error)));
-                                  return;
-                          }
-
-                          emit eventRedacted(id);
-                  });
+    if (!id.isEmpty())
+        http::client()->redact_event(
+          room_id_.toStdString(),
+          id.toStdString(),
+          [this, id](const mtx::responses::EventId &, mtx::http::RequestErr err) {
+              if (err) {
+                  emit redactionFailed(tr("Message redaction failed: %1")
+                                         .arg(QString::fromStdString(err->matrix_error.error)));
+                  return;
+              }
+
+              emit eventRedacted(id);
+          });
 }
 
 int
 TimelineModel::idToIndex(QString id) const
 {
-        if (id.isEmpty())
-                return -1;
+    if (id.isEmpty())
+        return -1;
 
-        auto idx = events.idToIndex(id.toStdString());
-        if (idx)
-                return events.size() - *idx - 1;
-        else
-                return -1;
+    auto idx = events.idToIndex(id.toStdString());
+    if (idx)
+        return events.size() - *idx - 1;
+    else
+        return -1;
 }
 
 QString
 TimelineModel::indexToId(int index) const
 {
-        auto id = events.indexToId(events.size() - index - 1);
-        return id ? QString::fromStdString(*id) : "";
+    auto id = events.indexToId(events.size() - index - 1);
+    return id ? QString::fromStdString(*id) : "";
 }
 
 // Note: this will only be called for our messages
 void
 TimelineModel::markEventsAsRead(const std::vector<QString> &event_ids)
 {
-        for (const auto &id : event_ids) {
-                read.insert(id);
-                int idx = idToIndex(id);
-                if (idx < 0) {
-                        return;
-                }
-                emit dataChanged(index(idx, 0), index(idx, 0));
+    for (const auto &id : event_ids) {
+        read.insert(id);
+        int idx = idToIndex(id);
+        if (idx < 0) {
+            return;
         }
+        emit dataChanged(index(idx, 0), index(idx, 0));
+    }
 }
 
 template<typename T>
 void
 TimelineModel::sendEncryptedMessage(mtx::events::RoomEvent<T> msg, mtx::events::EventType eventType)
 {
-        const auto room_id = room_id_.toStdString();
-
-        using namespace mtx::events;
-        using namespace mtx::identifiers;
-
-        json doc = {{"type", mtx::events::to_string(eventType)},
-                    {"content", json(msg.content)},
-                    {"room_id", room_id}};
-
-        try {
-                mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> event;
-                event.content =
-                  olm::encrypt_group_message(room_id, http::client()->device_id(), doc);
-                event.event_id         = msg.event_id;
-                event.room_id          = room_id;
-                event.sender           = http::client()->user_id().to_string();
-                event.type             = mtx::events::EventType::RoomEncrypted;
-                event.origin_server_ts = QDateTime::currentMSecsSinceEpoch();
-
-                emit this->addPendingMessageToStore(event);
-
-                // TODO: Let the user know about the errors.
-        } catch (const lmdb::error &e) {
-                nhlog::db()->critical(
-                  "failed to open outbound megolm session ({}): {}", room_id, e.what());
-                emit ChatPage::instance()->showNotification(
-                  tr("Failed to encrypt event, sending aborted!"));
-        } catch (const mtx::crypto::olm_exception &e) {
-                nhlog::crypto()->critical(
-                  "failed to open outbound megolm session ({}): {}", room_id, e.what());
-                emit ChatPage::instance()->showNotification(
-                  tr("Failed to encrypt event, sending aborted!"));
-        }
-}
-
-struct SendMessageVisitor
-{
-        explicit SendMessageVisitor(TimelineModel *model)
-          : model_(model)
-        {}
-
-        template<typename T, mtx::events::EventType Event>
-        void sendRoomEvent(mtx::events::RoomEvent<T> msg)
-        {
-                if (cache::isRoomEncrypted(model_->room_id_.toStdString())) {
-                        auto encInfo = mtx::accessors::file(msg);
-                        if (encInfo)
-                                emit model_->newEncryptedImage(encInfo.value());
-
-                        model_->sendEncryptedMessage(msg, Event);
-                } else {
-                        msg.type = Event;
-                        emit model_->addPendingMessageToStore(msg);
-                }
-        }
-
-        // Do-nothing operator for all unhandled events
-        template<typename T>
-        void operator()(const mtx::events::Event<T> &)
-        {}
-
-        // Operator for m.room.message events that contain a msgtype in their content
-        template<typename T,
-                 std::enable_if_t<std::is_same<decltype(T::msgtype), std::string>::value, int> = 0>
-        void operator()(mtx::events::RoomEvent<T> msg)
-        {
-                sendRoomEvent<T, mtx::events::EventType::RoomMessage>(msg);
-        }
+    const auto room_id = room_id_.toStdString();
 
-        // Special operator for reactions, which are a type of m.room.message, but need to be
-        // handled distinctly for their differences from normal room messages.  Specifically,
-        // reactions need to have the relation outside of ciphertext, or synapse / the homeserver
-        // cannot handle it correctly.  See the MSC for more details:
-        // https://github.com/matrix-org/matrix-doc/blob/matthew/msc1849/proposals/1849-aggregations.md#end-to-end-encryption
-        void operator()(mtx::events::RoomEvent<mtx::events::msg::Reaction> msg)
-        {
-                msg.type = mtx::events::EventType::Reaction;
-                emit model_->addPendingMessageToStore(msg);
-        }
-
-        void operator()(const mtx::events::RoomEvent<mtx::events::msg::CallInvite> &event)
-        {
-                sendRoomEvent<mtx::events::msg::CallInvite, mtx::events::EventType::CallInvite>(
-                  event);
-        }
-
-        void operator()(const mtx::events::RoomEvent<mtx::events::msg::CallCandidates> &event)
-        {
-                sendRoomEvent<mtx::events::msg::CallCandidates,
-                              mtx::events::EventType::CallCandidates>(event);
-        }
+    using namespace mtx::events;
+    using namespace mtx::identifiers;
 
-        void operator()(const mtx::events::RoomEvent<mtx::events::msg::CallAnswer> &event)
-        {
-                sendRoomEvent<mtx::events::msg::CallAnswer, mtx::events::EventType::CallAnswer>(
-                  event);
-        }
+    json doc = {{"type", mtx::events::to_string(eventType)},
+                {"content", json(msg.content)},
+                {"room_id", room_id}};
 
-        void operator()(const mtx::events::RoomEvent<mtx::events::msg::CallHangUp> &event)
-        {
-                sendRoomEvent<mtx::events::msg::CallHangUp, mtx::events::EventType::CallHangUp>(
-                  event);
-        }
+    try {
+        mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> event;
+        event.content  = olm::encrypt_group_message(room_id, http::client()->device_id(), doc);
+        event.event_id = msg.event_id;
+        event.room_id  = room_id;
+        event.sender   = http::client()->user_id().to_string();
+        event.type     = mtx::events::EventType::RoomEncrypted;
+        event.origin_server_ts = QDateTime::currentMSecsSinceEpoch();
 
-        void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest> &msg)
-        {
-                sendRoomEvent<mtx::events::msg::KeyVerificationRequest,
-                              mtx::events::EventType::RoomMessage>(msg);
-        }
+        emit this->addPendingMessageToStore(event);
 
-        void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationReady> &msg)
-        {
-                sendRoomEvent<mtx::events::msg::KeyVerificationReady,
-                              mtx::events::EventType::KeyVerificationReady>(msg);
-        }
-
-        void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationStart> &msg)
-        {
-                sendRoomEvent<mtx::events::msg::KeyVerificationStart,
-                              mtx::events::EventType::KeyVerificationStart>(msg);
-        }
-
-        void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationAccept> &msg)
-        {
-                sendRoomEvent<mtx::events::msg::KeyVerificationAccept,
-                              mtx::events::EventType::KeyVerificationAccept>(msg);
-        }
-
-        void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationMac> &msg)
-        {
-                sendRoomEvent<mtx::events::msg::KeyVerificationMac,
-                              mtx::events::EventType::KeyVerificationMac>(msg);
-        }
+        // TODO: Let the user know about the errors.
+    } catch (const lmdb::error &e) {
+        nhlog::db()->critical("failed to open outbound megolm session ({}): {}", room_id, e.what());
+        emit ChatPage::instance()->showNotification(
+          tr("Failed to encrypt event, sending aborted!"));
+    } catch (const mtx::crypto::olm_exception &e) {
+        nhlog::crypto()->critical(
+          "failed to open outbound megolm session ({}): {}", room_id, e.what());
+        emit ChatPage::instance()->showNotification(
+          tr("Failed to encrypt event, sending aborted!"));
+    }
+}
 
-        void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationKey> &msg)
-        {
-                sendRoomEvent<mtx::events::msg::KeyVerificationKey,
-                              mtx::events::EventType::KeyVerificationKey>(msg);
-        }
+struct SendMessageVisitor
+{
+    explicit SendMessageVisitor(TimelineModel *model)
+      : model_(model)
+    {}
 
-        void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationDone> &msg)
-        {
-                sendRoomEvent<mtx::events::msg::KeyVerificationDone,
-                              mtx::events::EventType::KeyVerificationDone>(msg);
-        }
+    template<typename T, mtx::events::EventType Event>
+    void sendRoomEvent(mtx::events::RoomEvent<T> msg)
+    {
+        if (cache::isRoomEncrypted(model_->room_id_.toStdString())) {
+            auto encInfo = mtx::accessors::file(msg);
+            if (encInfo)
+                emit model_->newEncryptedImage(encInfo.value());
 
-        void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationCancel> &msg)
-        {
-                sendRoomEvent<mtx::events::msg::KeyVerificationCancel,
-                              mtx::events::EventType::KeyVerificationCancel>(msg);
-        }
-        void operator()(mtx::events::Sticker msg)
-        {
-                msg.type = mtx::events::EventType::Sticker;
-                if (cache::isRoomEncrypted(model_->room_id_.toStdString())) {
-                        model_->sendEncryptedMessage(msg, mtx::events::EventType::Sticker);
-                } else
-                        emit model_->addPendingMessageToStore(msg);
-        }
+            model_->sendEncryptedMessage(msg, Event);
+        } else {
+            msg.type = Event;
+            emit model_->addPendingMessageToStore(msg);
+        }
+    }
+
+    // Do-nothing operator for all unhandled events
+    template<typename T>
+    void operator()(const mtx::events::Event<T> &)
+    {}
+
+    // Operator for m.room.message events that contain a msgtype in their content
+    template<typename T,
+             std::enable_if_t<std::is_same<decltype(T::msgtype), std::string>::value, int> = 0>
+    void operator()(mtx::events::RoomEvent<T> msg)
+    {
+        sendRoomEvent<T, mtx::events::EventType::RoomMessage>(msg);
+    }
+
+    // Special operator for reactions, which are a type of m.room.message, but need to be
+    // handled distinctly for their differences from normal room messages.  Specifically,
+    // reactions need to have the relation outside of ciphertext, or synapse / the homeserver
+    // cannot handle it correctly.  See the MSC for more details:
+    // https://github.com/matrix-org/matrix-doc/blob/matthew/msc1849/proposals/1849-aggregations.md#end-to-end-encryption
+    void operator()(mtx::events::RoomEvent<mtx::events::msg::Reaction> msg)
+    {
+        msg.type = mtx::events::EventType::Reaction;
+        emit model_->addPendingMessageToStore(msg);
+    }
+
+    void operator()(const mtx::events::RoomEvent<mtx::events::msg::CallInvite> &event)
+    {
+        sendRoomEvent<mtx::events::msg::CallInvite, mtx::events::EventType::CallInvite>(event);
+    }
+
+    void operator()(const mtx::events::RoomEvent<mtx::events::msg::CallCandidates> &event)
+    {
+        sendRoomEvent<mtx::events::msg::CallCandidates, mtx::events::EventType::CallCandidates>(
+          event);
+    }
+
+    void operator()(const mtx::events::RoomEvent<mtx::events::msg::CallAnswer> &event)
+    {
+        sendRoomEvent<mtx::events::msg::CallAnswer, mtx::events::EventType::CallAnswer>(event);
+    }
+
+    void operator()(const mtx::events::RoomEvent<mtx::events::msg::CallHangUp> &event)
+    {
+        sendRoomEvent<mtx::events::msg::CallHangUp, mtx::events::EventType::CallHangUp>(event);
+    }
+
+    void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest> &msg)
+    {
+        sendRoomEvent<mtx::events::msg::KeyVerificationRequest,
+                      mtx::events::EventType::RoomMessage>(msg);
+    }
+
+    void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationReady> &msg)
+    {
+        sendRoomEvent<mtx::events::msg::KeyVerificationReady,
+                      mtx::events::EventType::KeyVerificationReady>(msg);
+    }
+
+    void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationStart> &msg)
+    {
+        sendRoomEvent<mtx::events::msg::KeyVerificationStart,
+                      mtx::events::EventType::KeyVerificationStart>(msg);
+    }
+
+    void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationAccept> &msg)
+    {
+        sendRoomEvent<mtx::events::msg::KeyVerificationAccept,
+                      mtx::events::EventType::KeyVerificationAccept>(msg);
+    }
+
+    void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationMac> &msg)
+    {
+        sendRoomEvent<mtx::events::msg::KeyVerificationMac,
+                      mtx::events::EventType::KeyVerificationMac>(msg);
+    }
+
+    void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationKey> &msg)
+    {
+        sendRoomEvent<mtx::events::msg::KeyVerificationKey,
+                      mtx::events::EventType::KeyVerificationKey>(msg);
+    }
+
+    void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationDone> &msg)
+    {
+        sendRoomEvent<mtx::events::msg::KeyVerificationDone,
+                      mtx::events::EventType::KeyVerificationDone>(msg);
+    }
+
+    void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationCancel> &msg)
+    {
+        sendRoomEvent<mtx::events::msg::KeyVerificationCancel,
+                      mtx::events::EventType::KeyVerificationCancel>(msg);
+    }
+    void operator()(mtx::events::Sticker msg)
+    {
+        msg.type = mtx::events::EventType::Sticker;
+        if (cache::isRoomEncrypted(model_->room_id_.toStdString())) {
+            model_->sendEncryptedMessage(msg, mtx::events::EventType::Sticker);
+        } else
+            emit model_->addPendingMessageToStore(msg);
+    }
 
-        TimelineModel *model_;
+    TimelineModel *model_;
 };
 
 void
 TimelineModel::addPendingMessage(mtx::events::collections::TimelineEvents event)
 {
-        std::visit(
-          [](auto &msg) {
-                  // gets overwritten for reactions and stickers in SendMessageVisitor
-                  msg.type             = mtx::events::EventType::RoomMessage;
-                  msg.event_id         = "m" + http::client()->generate_txn_id();
-                  msg.sender           = http::client()->user_id().to_string();
-                  msg.origin_server_ts = QDateTime::currentMSecsSinceEpoch();
-          },
-          event);
+    std::visit(
+      [](auto &msg) {
+          // gets overwritten for reactions and stickers in SendMessageVisitor
+          msg.type             = mtx::events::EventType::RoomMessage;
+          msg.event_id         = "m" + http::client()->generate_txn_id();
+          msg.sender           = http::client()->user_id().to_string();
+          msg.origin_server_ts = QDateTime::currentMSecsSinceEpoch();
+      },
+      event);
 
-        std::visit(SendMessageVisitor{this}, event);
+    std::visit(SendMessageVisitor{this}, event);
 }
 
 void
 TimelineModel::openMedia(QString eventId)
 {
-        cacheMedia(eventId, [](QString filename) {
-                QDesktopServices::openUrl(QUrl::fromLocalFile(filename));
-        });
+    cacheMedia(eventId,
+               [](QString filename) { QDesktopServices::openUrl(QUrl::fromLocalFile(filename)); });
 }
 
 bool
 TimelineModel::saveMedia(QString eventId) const
 {
-        mtx::events::collections::TimelineEvents *event = events.get(eventId.toStdString(), "");
-        if (!event)
-                return false;
+    mtx::events::collections::TimelineEvents *event = events.get(eventId.toStdString(), "");
+    if (!event)
+        return false;
 
-        QString mxcUrl           = QString::fromStdString(mtx::accessors::url(*event));
-        QString originalFilename = QString::fromStdString(mtx::accessors::filename(*event));
-        QString mimeType         = QString::fromStdString(mtx::accessors::mimetype(*event));
+    QString mxcUrl           = QString::fromStdString(mtx::accessors::url(*event));
+    QString originalFilename = QString::fromStdString(mtx::accessors::filename(*event));
+    QString mimeType         = QString::fromStdString(mtx::accessors::mimetype(*event));
 
-        auto encryptionInfo = mtx::accessors::file(*event);
+    auto encryptionInfo = mtx::accessors::file(*event);
 
-        qml_mtx_events::EventType eventType = toRoomEventType(*event);
+    qml_mtx_events::EventType eventType = toRoomEventType(*event);
 
-        QString dialogTitle;
-        if (eventType == qml_mtx_events::EventType::ImageMessage) {
-                dialogTitle = tr("Save image");
-        } else if (eventType == qml_mtx_events::EventType::VideoMessage) {
-                dialogTitle = tr("Save video");
-        } else if (eventType == qml_mtx_events::EventType::AudioMessage) {
-                dialogTitle = tr("Save audio");
-        } else {
-                dialogTitle = tr("Save file");
-        }
+    QString dialogTitle;
+    if (eventType == qml_mtx_events::EventType::ImageMessage) {
+        dialogTitle = tr("Save image");
+    } else if (eventType == qml_mtx_events::EventType::VideoMessage) {
+        dialogTitle = tr("Save video");
+    } else if (eventType == qml_mtx_events::EventType::AudioMessage) {
+        dialogTitle = tr("Save audio");
+    } else {
+        dialogTitle = tr("Save file");
+    }
 
-        const QString filterString = QMimeDatabase().mimeTypeForName(mimeType).filterString();
-        const QString downloadsFolder =
-          QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
-        const QString openLocation = downloadsFolder + "/" + originalFilename;
-
-        const QString filename = QFileDialog::getSaveFileName(
-          manager_->getWidget(), dialogTitle, openLocation, filterString);
-
-        if (filename.isEmpty())
-                return false;
-
-        const auto url = mxcUrl.toStdString();
-
-        http::client()->download(
-          url,
-          [filename, url, encryptionInfo](const std::string &data,
-                                          const std::string &,
-                                          const std::string &,
-                                          mtx::http::RequestErr err) {
-                  if (err) {
-                          nhlog::net()->warn("failed to retrieve image {}: {} {}",
-                                             url,
-                                             err->matrix_error.error,
-                                             static_cast<int>(err->status_code));
-                          return;
-                  }
+    const QString filterString = QMimeDatabase().mimeTypeForName(mimeType).filterString();
+    const QString downloadsFolder =
+      QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
+    const QString openLocation = downloadsFolder + "/" + originalFilename;
 
-                  try {
-                          auto temp = data;
-                          if (encryptionInfo)
-                                  temp = mtx::crypto::to_string(
-                                    mtx::crypto::decrypt_file(temp, encryptionInfo.value()));
+    const QString filename =
+      QFileDialog::getSaveFileName(manager_->getWidget(), dialogTitle, openLocation, filterString);
 
-                          QFile file(filename);
+    if (filename.isEmpty())
+        return false;
 
-                          if (!file.open(QIODevice::WriteOnly))
-                                  return;
+    const auto url = mxcUrl.toStdString();
 
-                          file.write(QByteArray(temp.data(), (int)temp.size()));
-                          file.close();
+    http::client()->download(url,
+                             [filename, url, encryptionInfo](const std::string &data,
+                                                             const std::string &,
+                                                             const std::string &,
+                                                             mtx::http::RequestErr err) {
+                                 if (err) {
+                                     nhlog::net()->warn("failed to retrieve image {}: {} {}",
+                                                        url,
+                                                        err->matrix_error.error,
+                                                        static_cast<int>(err->status_code));
+                                     return;
+                                 }
 
-                          return;
-                  } catch (const std::exception &e) {
-                          nhlog::ui()->warn("Error while saving file to: {}", e.what());
-                  }
-          });
-        return true;
+                                 try {
+                                     auto temp = data;
+                                     if (encryptionInfo)
+                                         temp = mtx::crypto::to_string(
+                                           mtx::crypto::decrypt_file(temp, encryptionInfo.value()));
+
+                                     QFile file(filename);
+
+                                     if (!file.open(QIODevice::WriteOnly))
+                                         return;
+
+                                     file.write(QByteArray(temp.data(), (int)temp.size()));
+                                     file.close();
+
+                                     return;
+                                 } catch (const std::exception &e) {
+                                     nhlog::ui()->warn("Error while saving file to: {}", e.what());
+                                 }
+                             });
+    return true;
 }
 
 void
 TimelineModel::cacheMedia(QString eventId, std::function<void(const QString)> callback)
 {
-        mtx::events::collections::TimelineEvents *event = events.get(eventId.toStdString(), "");
-        if (!event)
-                return;
+    mtx::events::collections::TimelineEvents *event = events.get(eventId.toStdString(), "");
+    if (!event)
+        return;
 
-        QString mxcUrl           = QString::fromStdString(mtx::accessors::url(*event));
-        QString originalFilename = QString::fromStdString(mtx::accessors::filename(*event));
-        QString mimeType         = QString::fromStdString(mtx::accessors::mimetype(*event));
+    QString mxcUrl           = QString::fromStdString(mtx::accessors::url(*event));
+    QString originalFilename = QString::fromStdString(mtx::accessors::filename(*event));
+    QString mimeType         = QString::fromStdString(mtx::accessors::mimetype(*event));
 
-        auto encryptionInfo = mtx::accessors::file(*event);
+    auto encryptionInfo = mtx::accessors::file(*event);
 
-        // If the message is a link to a non mxcUrl, don't download it
-        if (!mxcUrl.startsWith("mxc://")) {
-                emit mediaCached(mxcUrl, mxcUrl);
-                return;
-        }
-
-        QString suffix = QMimeDatabase().mimeTypeForName(mimeType).preferredSuffix();
-
-        const auto url  = mxcUrl.toStdString();
-        const auto name = QString(mxcUrl).remove("mxc://");
-        QFileInfo filename(QString("%1/media_cache/%2.%3")
-                             .arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))
-                             .arg(name)
-                             .arg(suffix));
-        if (QDir::cleanPath(name) != name) {
-                nhlog::net()->warn("mxcUrl '{}' is not safe, not downloading file", url);
-                return;
-        }
+    // If the message is a link to a non mxcUrl, don't download it
+    if (!mxcUrl.startsWith("mxc://")) {
+        emit mediaCached(mxcUrl, mxcUrl);
+        return;
+    }
+
+    QString suffix = QMimeDatabase().mimeTypeForName(mimeType).preferredSuffix();
+
+    const auto url  = mxcUrl.toStdString();
+    const auto name = QString(mxcUrl).remove("mxc://");
+    QFileInfo filename(QString("%1/media_cache/%2.%3")
+                         .arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))
+                         .arg(name)
+                         .arg(suffix));
+    if (QDir::cleanPath(name) != name) {
+        nhlog::net()->warn("mxcUrl '{}' is not safe, not downloading file", url);
+        return;
+    }
 
-        QDir().mkpath(filename.path());
+    QDir().mkpath(filename.path());
 
-        if (filename.isReadable()) {
+    if (filename.isReadable()) {
 #if defined(Q_OS_WIN)
-                emit mediaCached(mxcUrl, filename.filePath());
+        emit mediaCached(mxcUrl, filename.filePath());
 #else
-                emit mediaCached(mxcUrl, "file://" + filename.filePath());
+        emit mediaCached(mxcUrl, "file://" + filename.filePath());
 #endif
-                if (callback) {
-                        callback(filename.filePath());
-                }
-                return;
+        if (callback) {
+            callback(filename.filePath());
         }
-
-        http::client()->download(
-          url,
-          [this, callback, mxcUrl, filename, url, encryptionInfo](const std::string &data,
-                                                                  const std::string &,
-                                                                  const std::string &,
-                                                                  mtx::http::RequestErr err) {
-                  if (err) {
-                          nhlog::net()->warn("failed to retrieve image {}: {} {}",
-                                             url,
-                                             err->matrix_error.error,
-                                             static_cast<int>(err->status_code));
-                          return;
-                  }
-
-                  try {
-                          auto temp = data;
-                          if (encryptionInfo)
-                                  temp = mtx::crypto::to_string(
-                                    mtx::crypto::decrypt_file(temp, encryptionInfo.value()));
-
-                          QFile file(filename.filePath());
-
-                          if (!file.open(QIODevice::WriteOnly))
-                                  return;
-
-                          file.write(QByteArray(temp.data(), (int)temp.size()));
-                          file.close();
-
-                          if (callback) {
-                                  callback(filename.filePath());
-                          }
-                  } catch (const std::exception &e) {
-                          nhlog::ui()->warn("Error while saving file to: {}", e.what());
-                  }
+        return;
+    }
+
+    http::client()->download(
+      url,
+      [this, callback, mxcUrl, filename, url, encryptionInfo](const std::string &data,
+                                                              const std::string &,
+                                                              const std::string &,
+                                                              mtx::http::RequestErr err) {
+          if (err) {
+              nhlog::net()->warn("failed to retrieve image {}: {} {}",
+                                 url,
+                                 err->matrix_error.error,
+                                 static_cast<int>(err->status_code));
+              return;
+          }
+
+          try {
+              auto temp = data;
+              if (encryptionInfo)
+                  temp =
+                    mtx::crypto::to_string(mtx::crypto::decrypt_file(temp, encryptionInfo.value()));
+
+              QFile file(filename.filePath());
+
+              if (!file.open(QIODevice::WriteOnly))
+                  return;
+
+              file.write(QByteArray(temp.data(), (int)temp.size()));
+              file.close();
+
+              if (callback) {
+                  callback(filename.filePath());
+              }
+          } catch (const std::exception &e) {
+              nhlog::ui()->warn("Error while saving file to: {}", e.what());
+          }
 
 #if defined(Q_OS_WIN)
-                  emit mediaCached(mxcUrl, filename.filePath());
+          emit mediaCached(mxcUrl, filename.filePath());
 #else
-                  emit mediaCached(mxcUrl, "file://" + filename.filePath());
+          emit mediaCached(mxcUrl, "file://" + filename.filePath());
 #endif
-          });
+      });
 }
 
 void
 TimelineModel::cacheMedia(QString eventId)
 {
-        cacheMedia(eventId, NULL);
+    cacheMedia(eventId, NULL);
 }
 
 void
 TimelineModel::showEvent(QString eventId)
 {
-        using namespace std::chrono_literals;
-        // Direct to eventId
-        if (eventId[0] == '$') {
-                int idx = idToIndex(eventId);
-                if (idx == -1) {
-                        nhlog::ui()->warn("Scrolling to event id {}, failed - no known index",
-                                          eventId.toStdString());
-                        return;
-                }
-                eventIdToShow = eventId;
-                emit scrollTargetChanged();
-                showEventTimer.start(50ms);
-                return;
+    using namespace std::chrono_literals;
+    // Direct to eventId
+    if (eventId[0] == '$') {
+        int idx = idToIndex(eventId);
+        if (idx == -1) {
+            nhlog::ui()->warn("Scrolling to event id {}, failed - no known index",
+                              eventId.toStdString());
+            return;
         }
-        // to message index
-        eventId       = indexToId(eventId.toInt());
         eventIdToShow = eventId;
         emit scrollTargetChanged();
         showEventTimer.start(50ms);
         return;
+    }
+    // to message index
+    eventId       = indexToId(eventId.toInt());
+    eventIdToShow = eventId;
+    emit scrollTargetChanged();
+    showEventTimer.start(50ms);
+    return;
 }
 
 void
 TimelineModel::eventShown()
 {
-        eventIdToShow.clear();
-        emit scrollTargetChanged();
+    eventIdToShow.clear();
+    emit scrollTargetChanged();
 }
 
 QString
 TimelineModel::scrollTarget() const
 {
-        return eventIdToShow;
+    return eventIdToShow;
 }
 
 void
 TimelineModel::scrollTimerEvent()
 {
-        if (eventIdToShow.isEmpty() || showEventTimerCounter > 3) {
-                showEventTimer.stop();
-                showEventTimerCounter = 0;
-        } else {
-                emit scrollToIndex(idToIndex(eventIdToShow));
-                showEventTimerCounter++;
-        }
+    if (eventIdToShow.isEmpty() || showEventTimerCounter > 3) {
+        showEventTimer.stop();
+        showEventTimerCounter = 0;
+    } else {
+        emit scrollToIndex(idToIndex(eventIdToShow));
+        showEventTimerCounter++;
+    }
 }
 
 void
 TimelineModel::requestKeyForEvent(QString id)
 {
-        auto encrypted_event = events.get(id.toStdString(), "", false);
-        if (encrypted_event) {
-                if (auto ev = std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(
-                      encrypted_event))
-                        events.requestSession(*ev, true);
-        }
+    auto encrypted_event = events.get(id.toStdString(), "", false);
+    if (encrypted_event) {
+        if (auto ev = std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(
+              encrypted_event))
+            events.requestSession(*ev, true);
+    }
 }
 
 void
 TimelineModel::copyLinkToEvent(QString eventId) const
 {
-        QStringList vias;
+    QStringList vias;
 
-        auto alias = cache::client()->getRoomAliases(room_id_.toStdString());
-        QString room;
-        if (alias) {
-                room = QString::fromStdString(alias->alias);
-                if (room.isEmpty() && !alias->alt_aliases.empty()) {
-                        room = QString::fromStdString(alias->alt_aliases.front());
-                }
+    auto alias = cache::client()->getRoomAliases(room_id_.toStdString());
+    QString room;
+    if (alias) {
+        room = QString::fromStdString(alias->alias);
+        if (room.isEmpty() && !alias->alt_aliases.empty()) {
+            room = QString::fromStdString(alias->alt_aliases.front());
         }
+    }
 
-        if (room.isEmpty())
-                room = room_id_;
+    if (room.isEmpty())
+        room = room_id_;
 
-        vias.push_back(QString("via=%1").arg(QString(
-          QUrl::toPercentEncoding(QString::fromStdString(http::client()->user_id().hostname())))));
-        auto members = cache::getMembers(room_id_.toStdString(), 0, 100);
-        for (const auto &m : members) {
-                if (vias.size() >= 4)
-                        break;
+    vias.push_back(QString("via=%1").arg(QString(
+      QUrl::toPercentEncoding(QString::fromStdString(http::client()->user_id().hostname())))));
+    auto members = cache::getMembers(room_id_.toStdString(), 0, 100);
+    for (const auto &m : members) {
+        if (vias.size() >= 4)
+            break;
 
-                auto user_id =
-                  mtx::identifiers::parse<mtx::identifiers::User>(m.user_id.toStdString());
-                QString server = QString("via=%1").arg(
-                  QString(QUrl::toPercentEncoding(QString::fromStdString(user_id.hostname()))));
+        auto user_id   = mtx::identifiers::parse<mtx::identifiers::User>(m.user_id.toStdString());
+        QString server = QString("via=%1").arg(
+          QString(QUrl::toPercentEncoding(QString::fromStdString(user_id.hostname()))));
 
-                if (!vias.contains(server))
-                        vias.push_back(server);
-        }
+        if (!vias.contains(server))
+            vias.push_back(server);
+    }
 
-        auto link = QString("https://matrix.to/#/%1/%2?%3")
-                      .arg(QString(QUrl::toPercentEncoding(room)),
-                           QString(QUrl::toPercentEncoding(eventId)),
-                           vias.join('&'));
+    auto link = QString("https://matrix.to/#/%1/%2?%3")
+                  .arg(QString(QUrl::toPercentEncoding(room)),
+                       QString(QUrl::toPercentEncoding(eventId)),
+                       vias.join('&'));
 
-        QGuiApplication::clipboard()->setText(link);
+    QGuiApplication::clipboard()->setText(link);
 }
 
 QString
 TimelineModel::formatTypingUsers(const std::vector<QString> &users, QColor bg)
 {
-        QString temp =
-          tr("%1 and %2 are typing.",
-             "Multiple users are typing. First argument is a comma separated list of potentially "
-             "multiple users. Second argument is the last user of that list. (If only one user is "
-             "typing, %1 is empty. You should still use it in your string though to silence Qt "
-             "warnings.)",
-             (int)users.size());
+    QString temp =
+      tr("%1 and %2 are typing.",
+         "Multiple users are typing. First argument is a comma separated list of potentially "
+         "multiple users. Second argument is the last user of that list. (If only one user is "
+         "typing, %1 is empty. You should still use it in your string though to silence Qt "
+         "warnings.)",
+         (int)users.size());
 
-        if (users.empty()) {
-                return "";
-        }
+    if (users.empty()) {
+        return "";
+    }
 
-        QStringList uidWithoutLast;
+    QStringList uidWithoutLast;
 
-        auto formatUser = [this, bg](const QString &user_id) -> QString {
-                auto uncoloredUsername = utils::replaceEmoji(displayName(user_id));
-                QString prefix =
-                  QString("<font color=\"%1\">").arg(manager_->userColor(user_id, bg).name());
+    auto formatUser = [this, bg](const QString &user_id) -> QString {
+        auto uncoloredUsername = utils::replaceEmoji(displayName(user_id));
+        QString prefix =
+          QString("<font color=\"%1\">").arg(manager_->userColor(user_id, bg).name());
 
-                // color only parts that don't have a font already specified
-                QString coloredUsername;
-                int index = 0;
-                do {
-                        auto startIndex = uncoloredUsername.indexOf("<font", index);
+        // color only parts that don't have a font already specified
+        QString coloredUsername;
+        int index = 0;
+        do {
+            auto startIndex = uncoloredUsername.indexOf("<font", index);
 
-                        if (startIndex - index != 0)
-                                coloredUsername +=
-                                  prefix +
-                                  uncoloredUsername.midRef(
-                                    index, startIndex > 0 ? startIndex - index : -1) +
-                                  "</font>";
+            if (startIndex - index != 0)
+                coloredUsername +=
+                  prefix +
+                  uncoloredUsername.midRef(index, startIndex > 0 ? startIndex - index : -1) +
+                  "</font>";
 
-                        auto endIndex = uncoloredUsername.indexOf("</font>", startIndex);
-                        if (endIndex > 0)
-                                endIndex += sizeof("</font>") - 1;
+            auto endIndex = uncoloredUsername.indexOf("</font>", startIndex);
+            if (endIndex > 0)
+                endIndex += sizeof("</font>") - 1;
 
-                        if (endIndex - startIndex != 0)
-                                coloredUsername +=
-                                  uncoloredUsername.midRef(startIndex, endIndex - startIndex);
+            if (endIndex - startIndex != 0)
+                coloredUsername += uncoloredUsername.midRef(startIndex, endIndex - startIndex);
 
-                        index = endIndex;
-                } while (index > 0 && index < uncoloredUsername.size());
+            index = endIndex;
+        } while (index > 0 && index < uncoloredUsername.size());
 
-                return coloredUsername;
-        };
+        return coloredUsername;
+    };
 
-        for (size_t i = 0; i + 1 < users.size(); i++) {
-                uidWithoutLast.append(formatUser(users[i]));
-        }
+    for (size_t i = 0; i + 1 < users.size(); i++) {
+        uidWithoutLast.append(formatUser(users[i]));
+    }
 
-        return temp.arg(uidWithoutLast.join(", ")).arg(formatUser(users.back()));
+    return temp.arg(uidWithoutLast.join(", ")).arg(formatUser(users.back()));
 }
 
 QString
 TimelineModel::formatJoinRuleEvent(QString id)
 {
-        mtx::events::collections::TimelineEvents *e = events.get(id.toStdString(), "");
-        if (!e)
-                return "";
-
-        auto event = std::get_if<mtx::events::StateEvent<mtx::events::state::JoinRules>>(e);
-        if (!event)
-                return "";
-
-        QString user = QString::fromStdString(event->sender);
-        QString name = utils::replaceEmoji(displayName(user));
-
-        switch (event->content.join_rule) {
-        case mtx::events::state::JoinRule::Public:
-                return tr("%1 opened the room to the public.").arg(name);
-        case mtx::events::state::JoinRule::Invite:
-                return tr("%1 made this room require and invitation to join.").arg(name);
-        case mtx::events::state::JoinRule::Knock:
-                return tr("%1 allowed to join this room by knocking.").arg(name);
-        case mtx::events::state::JoinRule::Restricted: {
-                QStringList rooms;
-                for (const auto &r : event->content.allow) {
-                        if (r.type == mtx::events::state::JoinAllowanceType::RoomMembership)
-                                rooms.push_back(QString::fromStdString(r.room_id));
-                }
-                return tr("%1 allowed members of the following rooms to automatically join this "
-                          "room: %2")
-                  .arg(name)
-                  .arg(rooms.join(", "));
-        }
-        default:
-                // Currently, knock and private are reserved keywords and not implemented in Matrix.
-                return "";
-        }
+    mtx::events::collections::TimelineEvents *e = events.get(id.toStdString(), "");
+    if (!e)
+        return "";
+
+    auto event = std::get_if<mtx::events::StateEvent<mtx::events::state::JoinRules>>(e);
+    if (!event)
+        return "";
+
+    QString user = QString::fromStdString(event->sender);
+    QString name = utils::replaceEmoji(displayName(user));
+
+    switch (event->content.join_rule) {
+    case mtx::events::state::JoinRule::Public:
+        return tr("%1 opened the room to the public.").arg(name);
+    case mtx::events::state::JoinRule::Invite:
+        return tr("%1 made this room require and invitation to join.").arg(name);
+    case mtx::events::state::JoinRule::Knock:
+        return tr("%1 allowed to join this room by knocking.").arg(name);
+    case mtx::events::state::JoinRule::Restricted: {
+        QStringList rooms;
+        for (const auto &r : event->content.allow) {
+            if (r.type == mtx::events::state::JoinAllowanceType::RoomMembership)
+                rooms.push_back(QString::fromStdString(r.room_id));
+        }
+        return tr("%1 allowed members of the following rooms to automatically join this "
+                  "room: %2")
+          .arg(name)
+          .arg(rooms.join(", "));
+    }
+    default:
+        // Currently, knock and private are reserved keywords and not implemented in Matrix.
+        return "";
+    }
 }
 
 QString
 TimelineModel::formatGuestAccessEvent(QString id)
 {
-        mtx::events::collections::TimelineEvents *e = events.get(id.toStdString(), "");
-        if (!e)
-                return "";
+    mtx::events::collections::TimelineEvents *e = events.get(id.toStdString(), "");
+    if (!e)
+        return "";
 
-        auto event = std::get_if<mtx::events::StateEvent<mtx::events::state::GuestAccess>>(e);
-        if (!event)
-                return "";
+    auto event = std::get_if<mtx::events::StateEvent<mtx::events::state::GuestAccess>>(e);
+    if (!event)
+        return "";
 
-        QString user = QString::fromStdString(event->sender);
-        QString name = utils::replaceEmoji(displayName(user));
+    QString user = QString::fromStdString(event->sender);
+    QString name = utils::replaceEmoji(displayName(user));
 
-        switch (event->content.guest_access) {
-        case mtx::events::state::AccessState::CanJoin:
-                return tr("%1 made the room open to guests.").arg(name);
-        case mtx::events::state::AccessState::Forbidden:
-                return tr("%1 has closed the room to guest access.").arg(name);
-        default:
-                return "";
-        }
+    switch (event->content.guest_access) {
+    case mtx::events::state::AccessState::CanJoin:
+        return tr("%1 made the room open to guests.").arg(name);
+    case mtx::events::state::AccessState::Forbidden:
+        return tr("%1 has closed the room to guest access.").arg(name);
+    default:
+        return "";
+    }
 }
 
 QString
 TimelineModel::formatHistoryVisibilityEvent(QString id)
 {
-        mtx::events::collections::TimelineEvents *e = events.get(id.toStdString(), "");
-        if (!e)
-                return "";
+    mtx::events::collections::TimelineEvents *e = events.get(id.toStdString(), "");
+    if (!e)
+        return "";
 
-        auto event = std::get_if<mtx::events::StateEvent<mtx::events::state::HistoryVisibility>>(e);
+    auto event = std::get_if<mtx::events::StateEvent<mtx::events::state::HistoryVisibility>>(e);
 
-        if (!event)
-                return "";
-
-        QString user = QString::fromStdString(event->sender);
-        QString name = utils::replaceEmoji(displayName(user));
-
-        switch (event->content.history_visibility) {
-        case mtx::events::state::Visibility::WorldReadable:
-                return tr("%1 made the room history world readable. Events may be now read by "
-                          "non-joined people.")
-                  .arg(name);
-        case mtx::events::state::Visibility::Shared:
-                return tr("%1 set the room history visible to members from this point on.")
-                  .arg(name);
-        case mtx::events::state::Visibility::Invited:
-                return tr("%1 set the room history visible to members since they were invited.")
-                  .arg(name);
-        case mtx::events::state::Visibility::Joined:
-                return tr("%1 set the room history visible to members since they joined the room.")
-                  .arg(name);
-        default:
-                return "";
-        }
+    if (!event)
+        return "";
+
+    QString user = QString::fromStdString(event->sender);
+    QString name = utils::replaceEmoji(displayName(user));
+
+    switch (event->content.history_visibility) {
+    case mtx::events::state::Visibility::WorldReadable:
+        return tr("%1 made the room history world readable. Events may be now read by "
+                  "non-joined people.")
+          .arg(name);
+    case mtx::events::state::Visibility::Shared:
+        return tr("%1 set the room history visible to members from this point on.").arg(name);
+    case mtx::events::state::Visibility::Invited:
+        return tr("%1 set the room history visible to members since they were invited.").arg(name);
+    case mtx::events::state::Visibility::Joined:
+        return tr("%1 set the room history visible to members since they joined the room.")
+          .arg(name);
+    default:
+        return "";
+    }
 }
 
 QString
 TimelineModel::formatPowerLevelEvent(QString id)
 {
-        mtx::events::collections::TimelineEvents *e = events.get(id.toStdString(), "");
-        if (!e)
-                return "";
+    mtx::events::collections::TimelineEvents *e = events.get(id.toStdString(), "");
+    if (!e)
+        return "";
 
-        auto event = std::get_if<mtx::events::StateEvent<mtx::events::state::PowerLevels>>(e);
-        if (!event)
-                return "";
+    auto event = std::get_if<mtx::events::StateEvent<mtx::events::state::PowerLevels>>(e);
+    if (!event)
+        return "";
 
-        QString user = QString::fromStdString(event->sender);
-        QString name = utils::replaceEmoji(displayName(user));
+    QString user = QString::fromStdString(event->sender);
+    QString name = utils::replaceEmoji(displayName(user));
 
-        // TODO: power levels rendering is actually a bit complex. work on this later.
-        return tr("%1 has changed the room's permissions.").arg(name);
+    // TODO: power levels rendering is actually a bit complex. work on this later.
+    return tr("%1 has changed the room's permissions.").arg(name);
 }
 
 void
 TimelineModel::acceptKnock(QString id)
 {
-        mtx::events::collections::TimelineEvents *e = events.get(id.toStdString(), "");
-        if (!e)
-                return;
+    mtx::events::collections::TimelineEvents *e = events.get(id.toStdString(), "");
+    if (!e)
+        return;
 
-        auto event = std::get_if<mtx::events::StateEvent<mtx::events::state::Member>>(e);
-        if (!event)
-                return;
+    auto event = std::get_if<mtx::events::StateEvent<mtx::events::state::Member>>(e);
+    if (!event)
+        return;
 
-        if (!permissions_.canInvite())
-                return;
+    if (!permissions_.canInvite())
+        return;
 
-        if (cache::isRoomMember(event->state_key, room_id_.toStdString()))
-                return;
+    if (cache::isRoomMember(event->state_key, room_id_.toStdString()))
+        return;
 
-        using namespace mtx::events::state;
-        if (event->content.membership != Membership::Knock)
-                return;
+    using namespace mtx::events::state;
+    if (event->content.membership != Membership::Knock)
+        return;
 
-        ChatPage::instance()->inviteUser(QString::fromStdString(event->state_key), "");
+    ChatPage::instance()->inviteUser(QString::fromStdString(event->state_key), "");
 }
 
 bool
 TimelineModel::showAcceptKnockButton(QString id)
 {
-        mtx::events::collections::TimelineEvents *e = events.get(id.toStdString(), "");
-        if (!e)
-                return false;
+    mtx::events::collections::TimelineEvents *e = events.get(id.toStdString(), "");
+    if (!e)
+        return false;
 
-        auto event = std::get_if<mtx::events::StateEvent<mtx::events::state::Member>>(e);
-        if (!event)
-                return false;
+    auto event = std::get_if<mtx::events::StateEvent<mtx::events::state::Member>>(e);
+    if (!event)
+        return false;
 
-        if (!permissions_.canInvite())
-                return false;
+    if (!permissions_.canInvite())
+        return false;
 
-        if (cache::isRoomMember(event->state_key, room_id_.toStdString()))
-                return false;
+    if (cache::isRoomMember(event->state_key, room_id_.toStdString()))
+        return false;
 
-        using namespace mtx::events::state;
-        return event->content.membership == Membership::Knock;
+    using namespace mtx::events::state;
+    return event->content.membership == Membership::Knock;
 }
 
 QString
 TimelineModel::formatMemberEvent(QString id)
 {
-        mtx::events::collections::TimelineEvents *e = events.get(id.toStdString(), "");
-        if (!e)
-                return "";
-
-        auto event = std::get_if<mtx::events::StateEvent<mtx::events::state::Member>>(e);
-        if (!event)
-                return "";
-
-        mtx::events::StateEvent<mtx::events::state::Member> *prevEvent = nullptr;
-        if (!event->unsigned_data.replaces_state.empty()) {
-                auto tempPrevEvent =
-                  events.get(event->unsigned_data.replaces_state, event->event_id);
-                if (tempPrevEvent) {
-                        prevEvent =
-                          std::get_if<mtx::events::StateEvent<mtx::events::state::Member>>(
-                            tempPrevEvent);
-                }
-        }
+    mtx::events::collections::TimelineEvents *e = events.get(id.toStdString(), "");
+    if (!e)
+        return "";
+
+    auto event = std::get_if<mtx::events::StateEvent<mtx::events::state::Member>>(e);
+    if (!event)
+        return "";
+
+    mtx::events::StateEvent<mtx::events::state::Member> *prevEvent = nullptr;
+    if (!event->unsigned_data.replaces_state.empty()) {
+        auto tempPrevEvent = events.get(event->unsigned_data.replaces_state, event->event_id);
+        if (tempPrevEvent) {
+            prevEvent =
+              std::get_if<mtx::events::StateEvent<mtx::events::state::Member>>(tempPrevEvent);
+        }
+    }
+
+    QString user = QString::fromStdString(event->state_key);
+    QString name = utils::replaceEmoji(displayName(user));
+    QString rendered;
+
+    // see table https://matrix.org/docs/spec/client_server/latest#m-room-member
+    using namespace mtx::events::state;
+    switch (event->content.membership) {
+    case Membership::Invite:
+        rendered = tr("%1 was invited.").arg(name);
+        break;
+    case Membership::Join:
+        if (prevEvent && prevEvent->content.membership == Membership::Join) {
+            QString oldName = utils::replaceEmoji(
+              QString::fromStdString(prevEvent->content.display_name).toHtmlEscaped());
+
+            bool displayNameChanged =
+              prevEvent->content.display_name != event->content.display_name;
+            bool avatarChanged = prevEvent->content.avatar_url != event->content.avatar_url;
+
+            if (displayNameChanged && avatarChanged)
+                rendered = tr("%1 has changed their avatar and changed their "
+                              "display name to %2.")
+                             .arg(oldName, name);
+            else if (displayNameChanged)
+                rendered = tr("%1 has changed their display name to %2.").arg(oldName, name);
+            else if (avatarChanged)
+                rendered = tr("%1 changed their avatar.").arg(name);
+            else
+                rendered = tr("%1 changed some profile info.").arg(name);
+            // the case of nothing changed but join follows join shouldn't happen, so
+            // just show it as join
+        } else {
+            if (event->content.join_authorised_via_users_server.empty())
+                rendered = tr("%1 joined.").arg(name);
+            else
+                rendered =
+                  tr("%1 joined via authorisation from %2's server.")
+                    .arg(name)
+                    .arg(QString::fromStdString(event->content.join_authorised_via_users_server));
+        }
+        break;
+    case Membership::Leave:
+        if (!prevEvent) // Should only ever happen temporarily
+            return "";
+
+        if (prevEvent->content.membership == Membership::Invite) {
+            if (event->state_key == event->sender)
+                rendered = tr("%1 rejected their invite.").arg(name);
+            else
+                rendered = tr("Revoked the invite to %1.").arg(name);
+        } else if (prevEvent->content.membership == Membership::Join) {
+            if (event->state_key == event->sender)
+                rendered = tr("%1 left the room.").arg(name);
+            else
+                rendered = tr("Kicked %1.").arg(name);
+        } else if (prevEvent->content.membership == Membership::Ban) {
+            rendered = tr("Unbanned %1.").arg(name);
+        } else if (prevEvent->content.membership == Membership::Knock) {
+            if (event->state_key == event->sender)
+                rendered = tr("%1 redacted their knock.").arg(name);
+            else
+                rendered = tr("Rejected the knock from %1.").arg(name);
+        } else
+            return tr("%1 left after having already left!",
+                      "This is a leave event after the user already left and shouldn't "
+                      "happen apart from state resets")
+              .arg(name);
+        break;
 
-        QString user = QString::fromStdString(event->state_key);
-        QString name = utils::replaceEmoji(displayName(user));
-        QString rendered;
-
-        // see table https://matrix.org/docs/spec/client_server/latest#m-room-member
-        using namespace mtx::events::state;
-        switch (event->content.membership) {
-        case Membership::Invite:
-                rendered = tr("%1 was invited.").arg(name);
-                break;
-        case Membership::Join:
-                if (prevEvent && prevEvent->content.membership == Membership::Join) {
-                        QString oldName = utils::replaceEmoji(
-                          QString::fromStdString(prevEvent->content.display_name).toHtmlEscaped());
-
-                        bool displayNameChanged =
-                          prevEvent->content.display_name != event->content.display_name;
-                        bool avatarChanged =
-                          prevEvent->content.avatar_url != event->content.avatar_url;
-
-                        if (displayNameChanged && avatarChanged)
-                                rendered = tr("%1 has changed their avatar and changed their "
-                                              "display name to %2.")
-                                             .arg(oldName, name);
-                        else if (displayNameChanged)
-                                rendered =
-                                  tr("%1 has changed their display name to %2.").arg(oldName, name);
-                        else if (avatarChanged)
-                                rendered = tr("%1 changed their avatar.").arg(name);
-                        else
-                                rendered = tr("%1 changed some profile info.").arg(name);
-                        // the case of nothing changed but join follows join shouldn't happen, so
-                        // just show it as join
-                } else {
-                        if (event->content.join_authorised_via_users_server.empty())
-                                rendered = tr("%1 joined.").arg(name);
-                        else
-                                rendered = tr("%1 joined via authorisation from %2's server.")
-                                             .arg(name)
-                                             .arg(QString::fromStdString(
-                                               event->content.join_authorised_via_users_server));
-                }
-                break;
-        case Membership::Leave:
-                if (!prevEvent) // Should only ever happen temporarily
-                        return "";
-
-                if (prevEvent->content.membership == Membership::Invite) {
-                        if (event->state_key == event->sender)
-                                rendered = tr("%1 rejected their invite.").arg(name);
-                        else
-                                rendered = tr("Revoked the invite to %1.").arg(name);
-                } else if (prevEvent->content.membership == Membership::Join) {
-                        if (event->state_key == event->sender)
-                                rendered = tr("%1 left the room.").arg(name);
-                        else
-                                rendered = tr("Kicked %1.").arg(name);
-                } else if (prevEvent->content.membership == Membership::Ban) {
-                        rendered = tr("Unbanned %1.").arg(name);
-                } else if (prevEvent->content.membership == Membership::Knock) {
-                        if (event->state_key == event->sender)
-                                rendered = tr("%1 redacted their knock.").arg(name);
-                        else
-                                rendered = tr("Rejected the knock from %1.").arg(name);
-                } else
-                        return tr("%1 left after having already left!",
-                                  "This is a leave event after the user already left and shouldn't "
-                                  "happen apart from state resets")
-                          .arg(name);
-                break;
-
-        case Membership::Ban:
-                rendered = tr("%1 was banned.").arg(name);
-                break;
-        case Membership::Knock:
-                rendered = tr("%1 knocked.").arg(name);
-                break;
-        }
+    case Membership::Ban:
+        rendered = tr("%1 was banned.").arg(name);
+        break;
+    case Membership::Knock:
+        rendered = tr("%1 knocked.").arg(name);
+        break;
+    }
 
-        if (event->content.reason != "") {
-                rendered +=
-                  " " + tr("Reason: %1").arg(QString::fromStdString(event->content.reason));
-        }
+    if (event->content.reason != "") {
+        rendered += " " + tr("Reason: %1").arg(QString::fromStdString(event->content.reason));
+    }
 
-        return rendered;
+    return rendered;
 }
 
 void
 TimelineModel::setEdit(QString newEdit)
 {
-        if (newEdit.isEmpty()) {
-                resetEdit();
-                return;
-        }
+    if (newEdit.isEmpty()) {
+        resetEdit();
+        return;
+    }
+
+    if (edit_.isEmpty()) {
+        this->textBeforeEdit  = input()->text();
+        this->replyBeforeEdit = reply_;
+        nhlog::ui()->debug("Stored: {}", textBeforeEdit.toStdString());
+    }
+
+    if (edit_ != newEdit) {
+        auto ev = events.get(newEdit.toStdString(), "");
+        if (ev && mtx::accessors::sender(*ev) == http::client()->user_id().to_string()) {
+            auto e = *ev;
+            setReply(QString::fromStdString(mtx::accessors::relations(e).reply_to().value_or("")));
+
+            auto msgType = mtx::accessors::msg_type(e);
+            if (msgType == mtx::events::MessageType::Text ||
+                msgType == mtx::events::MessageType::Notice ||
+                msgType == mtx::events::MessageType::Emote) {
+                auto relInfo  = relatedInfo(newEdit);
+                auto editText = relInfo.quoted_body;
+
+                if (!relInfo.quoted_formatted_body.isEmpty()) {
+                    auto matches =
+                      conf::strings::matrixToLink.globalMatch(relInfo.quoted_formatted_body);
+                    std::map<QString, QString> reverseNameMapping;
+                    while (matches.hasNext()) {
+                        auto m                            = matches.next();
+                        reverseNameMapping[m.captured(2)] = m.captured(1);
+                    }
+
+                    for (const auto &[user, link] : reverseNameMapping) {
+                        // TODO(Nico): html unescape the user name
+                        editText.replace(user, QStringLiteral("[%1](%2)").arg(user, link));
+                    }
+                }
 
-        if (edit_.isEmpty()) {
-                this->textBeforeEdit  = input()->text();
-                this->replyBeforeEdit = reply_;
-                nhlog::ui()->debug("Stored: {}", textBeforeEdit.toStdString());
-        }
+                if (msgType == mtx::events::MessageType::Emote)
+                    input()->setText("/me " + editText);
+                else
+                    input()->setText(editText);
+            } else {
+                input()->setText("");
+            }
 
-        if (edit_ != newEdit) {
-                auto ev = events.get(newEdit.toStdString(), "");
-                if (ev && mtx::accessors::sender(*ev) == http::client()->user_id().to_string()) {
-                        auto e = *ev;
-                        setReply(QString::fromStdString(
-                          mtx::accessors::relations(e).reply_to().value_or("")));
-
-                        auto msgType = mtx::accessors::msg_type(e);
-                        if (msgType == mtx::events::MessageType::Text ||
-                            msgType == mtx::events::MessageType::Notice ||
-                            msgType == mtx::events::MessageType::Emote) {
-                                auto relInfo  = relatedInfo(newEdit);
-                                auto editText = relInfo.quoted_body;
-
-                                if (!relInfo.quoted_formatted_body.isEmpty()) {
-                                        auto matches = conf::strings::matrixToLink.globalMatch(
-                                          relInfo.quoted_formatted_body);
-                                        std::map<QString, QString> reverseNameMapping;
-                                        while (matches.hasNext()) {
-                                                auto m                            = matches.next();
-                                                reverseNameMapping[m.captured(2)] = m.captured(1);
-                                        }
-
-                                        for (const auto &[user, link] : reverseNameMapping) {
-                                                // TODO(Nico): html unescape the user name
-                                                editText.replace(
-                                                  user, QStringLiteral("[%1](%2)").arg(user, link));
-                                        }
-                                }
-
-                                if (msgType == mtx::events::MessageType::Emote)
-                                        input()->setText("/me " + editText);
-                                else
-                                        input()->setText(editText);
-                        } else {
-                                input()->setText("");
-                        }
-
-                        edit_ = newEdit;
-                } else {
-                        resetReply();
-
-                        input()->setText("");
-                        edit_ = "";
-                }
-                emit editChanged(edit_);
+            edit_ = newEdit;
+        } else {
+            resetReply();
+
+            input()->setText("");
+            edit_ = "";
         }
+        emit editChanged(edit_);
+    }
 }
 
 void
 TimelineModel::resetEdit()
 {
-        if (!edit_.isEmpty()) {
-                edit_ = "";
-                emit editChanged(edit_);
-                nhlog::ui()->debug("Restoring: {}", textBeforeEdit.toStdString());
-                input()->setText(textBeforeEdit);
-                textBeforeEdit.clear();
-                if (replyBeforeEdit.isEmpty())
-                        resetReply();
-                else
-                        setReply(replyBeforeEdit);
-                replyBeforeEdit.clear();
-        }
+    if (!edit_.isEmpty()) {
+        edit_ = "";
+        emit editChanged(edit_);
+        nhlog::ui()->debug("Restoring: {}", textBeforeEdit.toStdString());
+        input()->setText(textBeforeEdit);
+        textBeforeEdit.clear();
+        if (replyBeforeEdit.isEmpty())
+            resetReply();
+        else
+            setReply(replyBeforeEdit);
+        replyBeforeEdit.clear();
+    }
 }
 
 QString
 TimelineModel::roomName() const
 {
-        auto info = cache::getRoomInfo({room_id_.toStdString()});
+    auto info = cache::getRoomInfo({room_id_.toStdString()});
 
-        if (!info.count(room_id_))
-                return "";
-        else
-                return utils::replaceEmoji(
-                  QString::fromStdString(info[room_id_].name).toHtmlEscaped());
+    if (!info.count(room_id_))
+        return "";
+    else
+        return utils::replaceEmoji(QString::fromStdString(info[room_id_].name).toHtmlEscaped());
 }
 
 QString
 TimelineModel::plainRoomName() const
 {
-        auto info = cache::getRoomInfo({room_id_.toStdString()});
+    auto info = cache::getRoomInfo({room_id_.toStdString()});
 
-        if (!info.count(room_id_))
-                return "";
-        else
-                return QString::fromStdString(info[room_id_].name);
+    if (!info.count(room_id_))
+        return "";
+    else
+        return QString::fromStdString(info[room_id_].name);
 }
 
 QString
 TimelineModel::roomAvatarUrl() const
 {
-        auto info = cache::getRoomInfo({room_id_.toStdString()});
+    auto info = cache::getRoomInfo({room_id_.toStdString()});
 
-        if (!info.count(room_id_))
-                return "";
-        else
-                return QString::fromStdString(info[room_id_].avatar_url);
+    if (!info.count(room_id_))
+        return "";
+    else
+        return QString::fromStdString(info[room_id_].avatar_url);
 }
 
 QString
 TimelineModel::roomTopic() const
 {
-        auto info = cache::getRoomInfo({room_id_.toStdString()});
+    auto info = cache::getRoomInfo({room_id_.toStdString()});
 
-        if (!info.count(room_id_))
-                return "";
-        else
-                return utils::replaceEmoji(utils::linkifyMessage(
-                  QString::fromStdString(info[room_id_].topic).toHtmlEscaped()));
+    if (!info.count(room_id_))
+        return "";
+    else
+        return utils::replaceEmoji(
+          utils::linkifyMessage(QString::fromStdString(info[room_id_].topic).toHtmlEscaped()));
 }
 
 crypto::Trust
 TimelineModel::trustlevel() const
 {
-        if (!isEncrypted_)
-                return crypto::Trust::Unverified;
+    if (!isEncrypted_)
+        return crypto::Trust::Unverified;
 
-        return cache::client()->roomVerificationStatus(room_id_.toStdString());
+    return cache::client()->roomVerificationStatus(room_id_.toStdString());
 }
 
 int
 TimelineModel::roomMemberCount() const
 {
-        return (int)cache::client()->memberCount(room_id_.toStdString());
+    return (int)cache::client()->memberCount(room_id_.toStdString());
 }
 
 QString
 TimelineModel::directChatOtherUserId() const
 {
-        if (roomMemberCount() < 3) {
-                QString id;
-                for (auto member : cache::getMembers(room_id_.toStdString()))
-                        if (member.user_id != UserSettings::instance()->userId())
-                                id = member.user_id;
-                return id;
-        } else
-                return "";
+    if (roomMemberCount() < 3) {
+        QString id;
+        for (auto member : cache::getMembers(room_id_.toStdString()))
+            if (member.user_id != UserSettings::instance()->userId())
+                id = member.user_id;
+        return id;
+    } else
+        return "";
 }
diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h
index 66e0622e..f16529e2 100644
--- a/src/timeline/TimelineModel.h
+++ b/src/timeline/TimelineModel.h
@@ -39,95 +39,95 @@ Q_NAMESPACE
 
 enum EventType
 {
-        // Unsupported event
-        Unsupported,
-        /// m.room_key_request
-        KeyRequest,
-        /// m.reaction,
-        Reaction,
-        /// m.room.aliases
-        Aliases,
-        /// m.room.avatar
-        Avatar,
-        /// m.call.invite
-        CallInvite,
-        /// m.call.answer
-        CallAnswer,
-        /// m.call.hangup
-        CallHangUp,
-        /// m.call.candidates
-        CallCandidates,
-        /// m.room.canonical_alias
-        CanonicalAlias,
-        /// m.room.create
-        RoomCreate,
-        /// m.room.encrypted.
-        Encrypted,
-        /// m.room.encryption.
-        Encryption,
-        /// m.room.guest_access
-        RoomGuestAccess,
-        /// m.room.history_visibility
-        RoomHistoryVisibility,
-        /// m.room.join_rules
-        RoomJoinRules,
-        /// m.room.member
-        Member,
-        /// m.room.name
-        Name,
-        /// m.room.power_levels
-        PowerLevels,
-        /// m.room.tombstone
-        Tombstone,
-        /// m.room.topic
-        Topic,
-        /// m.room.redaction
-        Redaction,
-        /// m.room.pinned_events
-        PinnedEvents,
-        // m.sticker
-        Sticker,
-        // m.tag
-        Tag,
-        /// m.room.message
-        AudioMessage,
-        EmoteMessage,
-        FileMessage,
-        ImageMessage,
-        LocationMessage,
-        NoticeMessage,
-        TextMessage,
-        VideoMessage,
-        Redacted,
-        UnknownMessage,
-        KeyVerificationRequest,
-        KeyVerificationStart,
-        KeyVerificationMac,
-        KeyVerificationAccept,
-        KeyVerificationCancel,
-        KeyVerificationKey,
-        KeyVerificationDone,
-        KeyVerificationReady,
-        //! m.image_pack, currently im.ponies.room_emotes
-        ImagePackInRoom,
-        //! m.image_pack, currently im.ponies.user_emotes
-        ImagePackInAccountData,
-        //! m.image_pack.rooms, currently im.ponies.emote_rooms
-        ImagePackRooms,
+    // Unsupported event
+    Unsupported,
+    /// m.room_key_request
+    KeyRequest,
+    /// m.reaction,
+    Reaction,
+    /// m.room.aliases
+    Aliases,
+    /// m.room.avatar
+    Avatar,
+    /// m.call.invite
+    CallInvite,
+    /// m.call.answer
+    CallAnswer,
+    /// m.call.hangup
+    CallHangUp,
+    /// m.call.candidates
+    CallCandidates,
+    /// m.room.canonical_alias
+    CanonicalAlias,
+    /// m.room.create
+    RoomCreate,
+    /// m.room.encrypted.
+    Encrypted,
+    /// m.room.encryption.
+    Encryption,
+    /// m.room.guest_access
+    RoomGuestAccess,
+    /// m.room.history_visibility
+    RoomHistoryVisibility,
+    /// m.room.join_rules
+    RoomJoinRules,
+    /// m.room.member
+    Member,
+    /// m.room.name
+    Name,
+    /// m.room.power_levels
+    PowerLevels,
+    /// m.room.tombstone
+    Tombstone,
+    /// m.room.topic
+    Topic,
+    /// m.room.redaction
+    Redaction,
+    /// m.room.pinned_events
+    PinnedEvents,
+    // m.sticker
+    Sticker,
+    // m.tag
+    Tag,
+    /// m.room.message
+    AudioMessage,
+    EmoteMessage,
+    FileMessage,
+    ImageMessage,
+    LocationMessage,
+    NoticeMessage,
+    TextMessage,
+    VideoMessage,
+    Redacted,
+    UnknownMessage,
+    KeyVerificationRequest,
+    KeyVerificationStart,
+    KeyVerificationMac,
+    KeyVerificationAccept,
+    KeyVerificationCancel,
+    KeyVerificationKey,
+    KeyVerificationDone,
+    KeyVerificationReady,
+    //! m.image_pack, currently im.ponies.room_emotes
+    ImagePackInRoom,
+    //! m.image_pack, currently im.ponies.user_emotes
+    ImagePackInAccountData,
+    //! m.image_pack.rooms, currently im.ponies.emote_rooms
+    ImagePackRooms,
 };
 Q_ENUM_NS(EventType)
 mtx::events::EventType fromRoomEventType(qml_mtx_events::EventType);
 
 enum EventState
 {
-        //! The plaintext message was received by the server.
-        Received,
-        //! At least one of the participants has read the message.
-        Read,
-        //! The client sent the message. Not yet received.
-        Sent,
-        //! When the message is loaded from cache or backfill.
-        Empty,
+    //! The plaintext message was received by the server.
+    Received,
+    //! At least one of the participants has read the message.
+    Read,
+    //! The client sent the message. Not yet received.
+    Sent,
+    //! When the message is loaded from cache or backfill.
+    Empty,
 };
 Q_ENUM_NS(EventState)
 }
@@ -135,330 +135,329 @@ Q_ENUM_NS(EventState)
 class StateKeeper
 {
 public:
-        StateKeeper(std::function<void()> &&fn)
-          : fn_(std::move(fn))
-        {}
+    StateKeeper(std::function<void()> &&fn)
+      : fn_(std::move(fn))
+    {}
 
-        ~StateKeeper() { fn_(); }
+    ~StateKeeper() { fn_(); }
 
 private:
-        std::function<void()> fn_;
+    std::function<void()> fn_;
 };
 
 struct DecryptionResult
 {
-        //! The decrypted content as a normal plaintext event.
-        mtx::events::collections::TimelineEvents event;
-        //! Whether or not the decryption was successful.
-        bool isDecrypted = false;
+    //! The decrypted content as a normal plaintext event.
+    mtx::events::collections::TimelineEvents event;
+    //! Whether or not the decryption was successful.
+    bool isDecrypted = false;
 };
 
 class TimelineViewManager;
 
 class TimelineModel : public QAbstractListModel
 {
-        Q_OBJECT
-        Q_PROPERTY(
-          int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
-        Q_PROPERTY(std::vector<QString> typingUsers READ typingUsers WRITE updateTypingUsers NOTIFY
-                     typingUsersChanged)
-        Q_PROPERTY(QString scrollTarget READ scrollTarget NOTIFY scrollTargetChanged)
-        Q_PROPERTY(QString reply READ reply WRITE setReply NOTIFY replyChanged RESET resetReply)
-        Q_PROPERTY(QString edit READ edit WRITE setEdit NOTIFY editChanged RESET resetEdit)
-        Q_PROPERTY(
-          bool paginationInProgress READ paginationInProgress NOTIFY paginationInProgressChanged)
-        Q_PROPERTY(QString roomId READ roomId CONSTANT)
-        Q_PROPERTY(QString roomName READ roomName NOTIFY roomNameChanged)
-        Q_PROPERTY(QString plainRoomName READ plainRoomName NOTIFY plainRoomNameChanged)
-        Q_PROPERTY(QString roomAvatarUrl READ roomAvatarUrl NOTIFY roomAvatarUrlChanged)
-        Q_PROPERTY(QString roomTopic READ roomTopic NOTIFY roomTopicChanged)
-        Q_PROPERTY(int roomMemberCount READ roomMemberCount NOTIFY roomMemberCountChanged)
-        Q_PROPERTY(bool isEncrypted READ isEncrypted NOTIFY encryptionChanged)
-        Q_PROPERTY(bool isSpace READ isSpace CONSTANT)
-        Q_PROPERTY(int trustlevel READ trustlevel NOTIFY trustlevelChanged)
-        Q_PROPERTY(bool isDirect READ isDirect NOTIFY isDirectChanged)
-        Q_PROPERTY(QString directChatOtherUserId READ directChatOtherUserId NOTIFY
-                     directChatOtherUserIdChanged)
-        Q_PROPERTY(InputBar *input READ input CONSTANT)
-        Q_PROPERTY(Permissions *permissions READ permissions NOTIFY permissionsChanged)
+    Q_OBJECT
+    Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
+    Q_PROPERTY(std::vector<QString> typingUsers READ typingUsers WRITE updateTypingUsers NOTIFY
+                 typingUsersChanged)
+    Q_PROPERTY(QString scrollTarget READ scrollTarget NOTIFY scrollTargetChanged)
+    Q_PROPERTY(QString reply READ reply WRITE setReply NOTIFY replyChanged RESET resetReply)
+    Q_PROPERTY(QString edit READ edit WRITE setEdit NOTIFY editChanged RESET resetEdit)
+    Q_PROPERTY(
+      bool paginationInProgress READ paginationInProgress NOTIFY paginationInProgressChanged)
+    Q_PROPERTY(QString roomId READ roomId CONSTANT)
+    Q_PROPERTY(QString roomName READ roomName NOTIFY roomNameChanged)
+    Q_PROPERTY(QString plainRoomName READ plainRoomName NOTIFY plainRoomNameChanged)
+    Q_PROPERTY(QString roomAvatarUrl READ roomAvatarUrl NOTIFY roomAvatarUrlChanged)
+    Q_PROPERTY(QString roomTopic READ roomTopic NOTIFY roomTopicChanged)
+    Q_PROPERTY(int roomMemberCount READ roomMemberCount NOTIFY roomMemberCountChanged)
+    Q_PROPERTY(bool isEncrypted READ isEncrypted NOTIFY encryptionChanged)
+    Q_PROPERTY(bool isSpace READ isSpace CONSTANT)
+    Q_PROPERTY(int trustlevel READ trustlevel NOTIFY trustlevelChanged)
+    Q_PROPERTY(bool isDirect READ isDirect NOTIFY isDirectChanged)
+    Q_PROPERTY(
+      QString directChatOtherUserId READ directChatOtherUserId NOTIFY directChatOtherUserIdChanged)
+    Q_PROPERTY(InputBar *input READ input CONSTANT)
+    Q_PROPERTY(Permissions *permissions READ permissions NOTIFY permissionsChanged)
 
 public:
-        explicit TimelineModel(TimelineViewManager *manager,
-                               QString room_id,
-                               QObject *parent = nullptr);
-
-        enum Roles
-        {
-                Type,
-                TypeString,
-                IsOnlyEmoji,
-                Body,
-                FormattedBody,
-                PreviousMessageUserId,
-                IsSender,
-                UserId,
-                UserName,
-                PreviousMessageDay,
-                Day,
-                Timestamp,
-                Url,
-                ThumbnailUrl,
-                Blurhash,
-                Filename,
-                Filesize,
-                MimeType,
-                OriginalHeight,
-                OriginalWidth,
-                ProportionalHeight,
-                EventId,
-                State,
-                IsEdited,
-                IsEditable,
-                IsEncrypted,
-                Trustlevel,
-                EncryptionError,
-                ReplyTo,
-                Reactions,
-                RoomId,
-                RoomName,
-                RoomTopic,
-                CallType,
-                Dump,
-                RelatedEventCacheBuster,
-        };
-        Q_ENUM(Roles);
-
-        QHash<int, QByteArray> roleNames() const override;
-        int rowCount(const QModelIndex &parent = QModelIndex()) const override;
-        QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
-        QVariant data(const mtx::events::collections::TimelineEvents &event, int role) const;
-        Q_INVOKABLE QVariant dataById(QString id, int role, QString relatedTo);
-
-        bool canFetchMore(const QModelIndex &) const override;
-        void fetchMore(const QModelIndex &) override;
-
-        Q_INVOKABLE QString displayName(QString id) const;
-        Q_INVOKABLE QString avatarUrl(QString id) const;
-        Q_INVOKABLE QString formatDateSeparator(QDate date) const;
-        Q_INVOKABLE QString formatTypingUsers(const std::vector<QString> &users, QColor bg);
-        Q_INVOKABLE bool showAcceptKnockButton(QString id);
-        Q_INVOKABLE void acceptKnock(QString id);
-        Q_INVOKABLE QString formatMemberEvent(QString id);
-        Q_INVOKABLE QString formatJoinRuleEvent(QString id);
-        Q_INVOKABLE QString formatHistoryVisibilityEvent(QString id);
-        Q_INVOKABLE QString formatGuestAccessEvent(QString id);
-        Q_INVOKABLE QString formatPowerLevelEvent(QString id);
-
-        Q_INVOKABLE void viewRawMessage(QString id);
-        Q_INVOKABLE void forwardMessage(QString eventId, QString roomId);
-        Q_INVOKABLE void viewDecryptedRawMessage(QString id);
-        Q_INVOKABLE void openUserProfile(QString userid);
-        Q_INVOKABLE void editAction(QString id);
-        Q_INVOKABLE void replyAction(QString id);
-        Q_INVOKABLE void showReadReceipts(QString id);
-        Q_INVOKABLE void redactEvent(QString id);
-        Q_INVOKABLE int idToIndex(QString id) const;
-        Q_INVOKABLE QString indexToId(int index) const;
-        Q_INVOKABLE void openMedia(QString eventId);
-        Q_INVOKABLE void cacheMedia(QString eventId);
-        Q_INVOKABLE bool saveMedia(QString eventId) const;
-        Q_INVOKABLE void showEvent(QString eventId);
-        Q_INVOKABLE void copyLinkToEvent(QString eventId) const;
-        void cacheMedia(QString eventId, std::function<void(const QString filename)> callback);
-        Q_INVOKABLE void sendReset()
-        {
-                beginResetModel();
-                endResetModel();
-        }
-
-        Q_INVOKABLE void requestKeyForEvent(QString id);
-
-        std::vector<::Reaction> reactions(const std::string &event_id)
-        {
-                auto list = events.reactions(event_id);
-                std::vector<::Reaction> vec;
-                for (const auto &r : list)
-                        vec.push_back(r.value<Reaction>());
-                return vec;
-        }
-
-        void updateLastMessage();
-        void sync(const mtx::responses::JoinedRoom &room);
-        void addEvents(const mtx::responses::Timeline &events);
-        void syncState(const mtx::responses::State &state);
-        template<class T>
-        void sendMessageEvent(const T &content, mtx::events::EventType eventType);
-        RelatedInfo relatedInfo(QString id);
-
-        DescInfo lastMessage() const { return lastMessage_; }
-        bool isSpace() const { return isSpace_; }
-        bool isEncrypted() const { return isEncrypted_; }
-        crypto::Trust trustlevel() const;
-        int roomMemberCount() const;
-        bool isDirect() const { return roomMemberCount() <= 2; }
-        QString directChatOtherUserId() const;
-
-        std::optional<mtx::events::collections::TimelineEvents> eventById(const QString &id)
-        {
-                auto e = events.get(id.toStdString(), "");
-                if (e)
-                        return *e;
-                else
-                        return std::nullopt;
-        }
+    explicit TimelineModel(TimelineViewManager *manager,
+                           QString room_id,
+                           QObject *parent = nullptr);
+
+    enum Roles
+    {
+        Type,
+        TypeString,
+        IsOnlyEmoji,
+        Body,
+        FormattedBody,
+        PreviousMessageUserId,
+        IsSender,
+        UserId,
+        UserName,
+        PreviousMessageDay,
+        Day,
+        Timestamp,
+        Url,
+        ThumbnailUrl,
+        Blurhash,
+        Filename,
+        Filesize,
+        MimeType,
+        OriginalHeight,
+        OriginalWidth,
+        ProportionalHeight,
+        EventId,
+        State,
+        IsEdited,
+        IsEditable,
+        IsEncrypted,
+        Trustlevel,
+        EncryptionError,
+        ReplyTo,
+        Reactions,
+        RoomId,
+        RoomName,
+        RoomTopic,
+        CallType,
+        Dump,
+        RelatedEventCacheBuster,
+    };
+    Q_ENUM(Roles);
+
+    QHash<int, QByteArray> roleNames() const override;
+    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+    QVariant data(const mtx::events::collections::TimelineEvents &event, int role) const;
+    Q_INVOKABLE QVariant dataById(QString id, int role, QString relatedTo);
+
+    bool canFetchMore(const QModelIndex &) const override;
+    void fetchMore(const QModelIndex &) override;
+
+    Q_INVOKABLE QString displayName(QString id) const;
+    Q_INVOKABLE QString avatarUrl(QString id) const;
+    Q_INVOKABLE QString formatDateSeparator(QDate date) const;
+    Q_INVOKABLE QString formatTypingUsers(const std::vector<QString> &users, QColor bg);
+    Q_INVOKABLE bool showAcceptKnockButton(QString id);
+    Q_INVOKABLE void acceptKnock(QString id);
+    Q_INVOKABLE QString formatMemberEvent(QString id);
+    Q_INVOKABLE QString formatJoinRuleEvent(QString id);
+    Q_INVOKABLE QString formatHistoryVisibilityEvent(QString id);
+    Q_INVOKABLE QString formatGuestAccessEvent(QString id);
+    Q_INVOKABLE QString formatPowerLevelEvent(QString id);
+
+    Q_INVOKABLE void viewRawMessage(QString id);
+    Q_INVOKABLE void forwardMessage(QString eventId, QString roomId);
+    Q_INVOKABLE void viewDecryptedRawMessage(QString id);
+    Q_INVOKABLE void openUserProfile(QString userid);
+    Q_INVOKABLE void editAction(QString id);
+    Q_INVOKABLE void replyAction(QString id);
+    Q_INVOKABLE void showReadReceipts(QString id);
+    Q_INVOKABLE void redactEvent(QString id);
+    Q_INVOKABLE int idToIndex(QString id) const;
+    Q_INVOKABLE QString indexToId(int index) const;
+    Q_INVOKABLE void openMedia(QString eventId);
+    Q_INVOKABLE void cacheMedia(QString eventId);
+    Q_INVOKABLE bool saveMedia(QString eventId) const;
+    Q_INVOKABLE void showEvent(QString eventId);
+    Q_INVOKABLE void copyLinkToEvent(QString eventId) const;
+    void cacheMedia(QString eventId, std::function<void(const QString filename)> callback);
+    Q_INVOKABLE void sendReset()
+    {
+        beginResetModel();
+        endResetModel();
+    }
+
+    Q_INVOKABLE void requestKeyForEvent(QString id);
+
+    std::vector<::Reaction> reactions(const std::string &event_id)
+    {
+        auto list = events.reactions(event_id);
+        std::vector<::Reaction> vec;
+        for (const auto &r : list)
+            vec.push_back(r.value<Reaction>());
+        return vec;
+    }
+
+    void updateLastMessage();
+    void sync(const mtx::responses::JoinedRoom &room);
+    void addEvents(const mtx::responses::Timeline &events);
+    void syncState(const mtx::responses::State &state);
+    template<class T>
+    void sendMessageEvent(const T &content, mtx::events::EventType eventType);
+    RelatedInfo relatedInfo(QString id);
+
+    DescInfo lastMessage() const { return lastMessage_; }
+    bool isSpace() const { return isSpace_; }
+    bool isEncrypted() const { return isEncrypted_; }
+    crypto::Trust trustlevel() const;
+    int roomMemberCount() const;
+    bool isDirect() const { return roomMemberCount() <= 2; }
+    QString directChatOtherUserId() const;
+
+    std::optional<mtx::events::collections::TimelineEvents> eventById(const QString &id)
+    {
+        auto e = events.get(id.toStdString(), "");
+        if (e)
+            return *e;
+        else
+            return std::nullopt;
+    }
 
 public slots:
-        void setCurrentIndex(int index);
-        int currentIndex() const { return idToIndex(currentId); }
-        void eventShown();
-        void markEventsAsRead(const std::vector<QString> &event_ids);
-        QVariantMap getDump(QString eventId, QString relatedTo) const;
-        void updateTypingUsers(const std::vector<QString> &users)
-        {
-                if (this->typingUsers_ != users) {
-                        this->typingUsers_ = users;
-                        emit typingUsersChanged(typingUsers_);
-                }
+    void setCurrentIndex(int index);
+    int currentIndex() const { return idToIndex(currentId); }
+    void eventShown();
+    void markEventsAsRead(const std::vector<QString> &event_ids);
+    QVariantMap getDump(QString eventId, QString relatedTo) const;
+    void updateTypingUsers(const std::vector<QString> &users)
+    {
+        if (this->typingUsers_ != users) {
+            this->typingUsers_ = users;
+            emit typingUsersChanged(typingUsers_);
         }
-        std::vector<QString> typingUsers() const { return typingUsers_; }
-        bool paginationInProgress() const { return m_paginationInProgress; }
-        QString reply() const { return reply_; }
-        void setReply(QString newReply)
-        {
-                if (edit_.startsWith('m'))
-                        return;
-
-                if (reply_ != newReply) {
-                        reply_ = newReply;
-                        emit replyChanged(reply_);
-                }
+    }
+    std::vector<QString> typingUsers() const { return typingUsers_; }
+    bool paginationInProgress() const { return m_paginationInProgress; }
+    QString reply() const { return reply_; }
+    void setReply(QString newReply)
+    {
+        if (edit_.startsWith('m'))
+            return;
+
+        if (reply_ != newReply) {
+            reply_ = newReply;
+            emit replyChanged(reply_);
         }
-        void resetReply()
-        {
-                if (!reply_.isEmpty()) {
-                        reply_ = "";
-                        emit replyChanged(reply_);
-                }
+    }
+    void resetReply()
+    {
+        if (!reply_.isEmpty()) {
+            reply_ = "";
+            emit replyChanged(reply_);
         }
-        QString edit() const { return edit_; }
-        void setEdit(QString newEdit);
-        void resetEdit();
-        void setDecryptDescription(bool decrypt) { decryptDescription = decrypt; }
-        void clearTimeline() { events.clearTimeline(); }
-        void receivedSessionKey(const std::string &session_key)
-        {
-                events.receivedSessionKey(session_key);
-        }
-
-        QString roomName() const;
-        QString plainRoomName() const;
-        QString roomTopic() const;
-        InputBar *input() { return &input_; }
-        Permissions *permissions() { return &permissions_; }
-        QString roomAvatarUrl() const;
-        QString roomId() const { return room_id_; }
-
-        bool hasMentions() { return highlight_count > 0; }
-        int notificationCount() { return notification_count; }
-
-        QString scrollTarget() const;
+    }
+    QString edit() const { return edit_; }
+    void setEdit(QString newEdit);
+    void resetEdit();
+    void setDecryptDescription(bool decrypt) { decryptDescription = decrypt; }
+    void clearTimeline() { events.clearTimeline(); }
+    void receivedSessionKey(const std::string &session_key)
+    {
+        events.receivedSessionKey(session_key);
+    }
+
+    QString roomName() const;
+    QString plainRoomName() const;
+    QString roomTopic() const;
+    InputBar *input() { return &input_; }
+    Permissions *permissions() { return &permissions_; }
+    QString roomAvatarUrl() const;
+    QString roomId() const { return room_id_; }
+
+    bool hasMentions() { return highlight_count > 0; }
+    int notificationCount() { return notification_count; }
+
+    QString scrollTarget() const;
 
 private slots:
-        void addPendingMessage(mtx::events::collections::TimelineEvents event);
-        void scrollTimerEvent();
+    void addPendingMessage(mtx::events::collections::TimelineEvents event);
+    void scrollTimerEvent();
 
 signals:
-        void currentIndexChanged(int index);
-        void redactionFailed(QString id);
-        void eventRedacted(QString id);
-        void mediaCached(QString mxcUrl, QString cacheUrl);
-        void newEncryptedImage(mtx::crypto::EncryptedFile encryptionInfo);
-        void typingUsersChanged(std::vector<QString> users);
-        void replyChanged(QString reply);
-        void editChanged(QString reply);
-        void openReadReceiptsDialog(ReadReceiptsProxy *rr);
-        void showRawMessageDialog(QString rawMessage);
-        void paginationInProgressChanged(const bool);
-        void newCallEvent(const mtx::events::collections::TimelineEvents &event);
-        void scrollToIndex(int index);
-
-        void lastMessageChanged();
-        void notificationsChanged();
-
-        void newMessageToSend(mtx::events::collections::TimelineEvents event);
-        void addPendingMessageToStore(mtx::events::collections::TimelineEvents event);
-        void updateFlowEventId(std::string event_id);
-
-        void encryptionChanged();
-        void trustlevelChanged();
-        void roomNameChanged();
-        void plainRoomNameChanged();
-        void roomTopicChanged();
-        void roomAvatarUrlChanged();
-        void roomMemberCountChanged();
-        void isDirectChanged();
-        void directChatOtherUserIdChanged();
-        void permissionsChanged();
-        void forwardToRoom(mtx::events::collections::TimelineEvents *e, QString roomId);
-
-        void scrollTargetChanged();
+    void currentIndexChanged(int index);
+    void redactionFailed(QString id);
+    void eventRedacted(QString id);
+    void mediaCached(QString mxcUrl, QString cacheUrl);
+    void newEncryptedImage(mtx::crypto::EncryptedFile encryptionInfo);
+    void typingUsersChanged(std::vector<QString> users);
+    void replyChanged(QString reply);
+    void editChanged(QString reply);
+    void openReadReceiptsDialog(ReadReceiptsProxy *rr);
+    void showRawMessageDialog(QString rawMessage);
+    void paginationInProgressChanged(const bool);
+    void newCallEvent(const mtx::events::collections::TimelineEvents &event);
+    void scrollToIndex(int index);
+
+    void lastMessageChanged();
+    void notificationsChanged();
+
+    void newMessageToSend(mtx::events::collections::TimelineEvents event);
+    void addPendingMessageToStore(mtx::events::collections::TimelineEvents event);
+    void updateFlowEventId(std::string event_id);
+
+    void encryptionChanged();
+    void trustlevelChanged();
+    void roomNameChanged();
+    void plainRoomNameChanged();
+    void roomTopicChanged();
+    void roomAvatarUrlChanged();
+    void roomMemberCountChanged();
+    void isDirectChanged();
+    void directChatOtherUserIdChanged();
+    void permissionsChanged();
+    void forwardToRoom(mtx::events::collections::TimelineEvents *e, QString roomId);
+
+    void scrollTargetChanged();
 
 private:
-        template<typename T>
-        void sendEncryptedMessage(mtx::events::RoomEvent<T> msg, mtx::events::EventType eventType);
-        void readEvent(const std::string &id);
+    template<typename T>
+    void sendEncryptedMessage(mtx::events::RoomEvent<T> msg, mtx::events::EventType eventType);
+    void readEvent(const std::string &id);
 
-        void setPaginationInProgress(const bool paginationInProgress);
+    void setPaginationInProgress(const bool paginationInProgress);
 
-        QSet<QString> read;
+    QSet<QString> read;
 
-        mutable EventStore events;
+    mutable EventStore events;
 
-        QString room_id_;
+    QString room_id_;
 
-        QString currentId, currentReadId;
-        QString reply_, edit_;
-        QString textBeforeEdit, replyBeforeEdit;
-        std::vector<QString> typingUsers_;
+    QString currentId, currentReadId;
+    QString reply_, edit_;
+    QString textBeforeEdit, replyBeforeEdit;
+    std::vector<QString> typingUsers_;
 
-        TimelineViewManager *manager_;
+    TimelineViewManager *manager_;
 
-        InputBar input_{this};
-        Permissions permissions_;
+    InputBar input_{this};
+    Permissions permissions_;
 
-        QTimer showEventTimer{this};
-        QString eventIdToShow;
-        int showEventTimerCounter = 0;
+    QTimer showEventTimer{this};
+    QString eventIdToShow;
+    int showEventTimerCounter = 0;
 
-        DescInfo lastMessage_{};
+    DescInfo lastMessage_{};
 
-        friend struct SendMessageVisitor;
+    friend struct SendMessageVisitor;
 
-        int notification_count = 0, highlight_count = 0;
+    int notification_count = 0, highlight_count = 0;
 
-        unsigned int relatedEventCacheBuster = 0;
+    unsigned int relatedEventCacheBuster = 0;
 
-        bool decryptDescription     = true;
-        bool m_paginationInProgress = false;
-        bool isSpace_               = false;
-        bool isEncrypted_           = false;
+    bool decryptDescription     = true;
+    bool m_paginationInProgress = false;
+    bool isSpace_               = false;
+    bool isEncrypted_           = false;
 };
 
 template<class T>
 void
 TimelineModel::sendMessageEvent(const T &content, mtx::events::EventType eventType)
 {
-        if constexpr (std::is_same_v<T, mtx::events::msg::StickerImage>) {
-                mtx::events::Sticker msgCopy = {};
-                msgCopy.content              = content;
-                msgCopy.type                 = eventType;
-                emit newMessageToSend(msgCopy);
-        } else {
-                mtx::events::RoomEvent<T> msgCopy = {};
-                msgCopy.content                   = content;
-                msgCopy.type                      = eventType;
-                emit newMessageToSend(msgCopy);
-        }
-        resetReply();
-        resetEdit();
+    if constexpr (std::is_same_v<T, mtx::events::msg::StickerImage>) {
+        mtx::events::Sticker msgCopy = {};
+        msgCopy.content              = content;
+        msgCopy.type                 = eventType;
+        emit newMessageToSend(msgCopy);
+    } else {
+        mtx::events::RoomEvent<T> msgCopy = {};
+        msgCopy.content                   = content;
+        msgCopy.type                      = eventType;
+        emit newMessageToSend(msgCopy);
+    }
+    resetReply();
+    resetEdit();
 }
diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp
index ea231b03..8a33dc2b 100644
--- a/src/timeline/TimelineViewManager.cpp
+++ b/src/timeline/TimelineViewManager.cpp
@@ -67,73 +67,72 @@ 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;
+    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<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);
-                }
+    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);
         }
+    }
 }
 }
 
 void
 TimelineViewManager::updateColorPalette()
 {
-        userColors.clear();
+    userColors.clear();
 
-        if (ChatPage::instance()->userSettings()->theme() == "light") {
-                view->rootContext()->setContextProperty("currentActivePalette", QPalette());
-                view->rootContext()->setContextProperty("currentInactivePalette", QPalette());
-        } else if (ChatPage::instance()->userSettings()->theme() == "dark") {
-                view->rootContext()->setContextProperty("currentActivePalette", QPalette());
-                view->rootContext()->setContextProperty("currentInactivePalette", QPalette());
-        } else {
-                view->rootContext()->setContextProperty("currentActivePalette", QPalette());
-                view->rootContext()->setContextProperty("currentInactivePalette", nullptr);
-        }
+    if (ChatPage::instance()->userSettings()->theme() == "light") {
+        view->rootContext()->setContextProperty("currentActivePalette", QPalette());
+        view->rootContext()->setContextProperty("currentInactivePalette", QPalette());
+    } else if (ChatPage::instance()->userSettings()->theme() == "dark") {
+        view->rootContext()->setContextProperty("currentActivePalette", QPalette());
+        view->rootContext()->setContextProperty("currentInactivePalette", QPalette());
+    } else {
+        view->rootContext()->setContextProperty("currentActivePalette", QPalette());
+        view->rootContext()->setContextProperty("currentInactivePalette", nullptr);
+    }
 }
 
 QColor
 TimelineViewManager::userColor(QString id, QColor background)
 {
-        if (!userColors.contains(id))
-                userColors.insert(id, QColor(utils::generateContrastingHexColor(id, background)));
-        return userColors.value(id);
+    if (!userColors.contains(id))
+        userColors.insert(id, QColor(utils::generateContrastingHexColor(id, background)));
+    return userColors.value(id);
 }
 
 QString
 TimelineViewManager::userPresence(QString id) const
 {
-        if (id.isEmpty())
-                return "";
-        else
-                return QString::fromStdString(
-                  mtx::presence::to_string(cache::presenceState(id.toStdString())));
+    if (id.isEmpty())
+        return "";
+    else
+        return QString::fromStdString(
+          mtx::presence::to_string(cache::presenceState(id.toStdString())));
 }
 
 QString
 TimelineViewManager::userStatus(QString id) const
 {
-        return QString::fromStdString(cache::statusMessage(id.toStdString()));
+    return QString::fromStdString(cache::statusMessage(id.toStdString()));
 }
 
 TimelineViewManager::TimelineViewManager(CallManager *callManager, ChatPage *parent)
@@ -146,453 +145,432 @@ TimelineViewManager::TimelineViewManager(CallManager *callManager, ChatPage *par
   , rooms_(new RoomlistModel(this))
   , communities_(new CommunitiesModel(this))
 {
-        qRegisterMetaType<mtx::events::msg::KeyVerificationAccept>();
-        qRegisterMetaType<mtx::events::msg::KeyVerificationCancel>();
-        qRegisterMetaType<mtx::events::msg::KeyVerificationDone>();
-        qRegisterMetaType<mtx::events::msg::KeyVerificationKey>();
-        qRegisterMetaType<mtx::events::msg::KeyVerificationMac>();
-        qRegisterMetaType<mtx::events::msg::KeyVerificationReady>();
-        qRegisterMetaType<mtx::events::msg::KeyVerificationRequest>();
-        qRegisterMetaType<mtx::events::msg::KeyVerificationStart>();
-        qRegisterMetaType<CombinedImagePackModel *>();
-
-        qRegisterMetaType<std::vector<mtx::responses::PublicRoomsChunk>>();
-
-        qmlRegisterUncreatableMetaObject(qml_mtx_events::staticMetaObject,
-                                         "im.nheko",
-                                         1,
-                                         0,
-                                         "MtxEvent",
-                                         "Can't instantiate enum!");
-        qmlRegisterUncreatableMetaObject(
-          olm::staticMetaObject, "im.nheko", 1, 0, "Olm", "Can't instantiate enum!");
-        qmlRegisterUncreatableMetaObject(
-          crypto::staticMetaObject, "im.nheko", 1, 0, "Crypto", "Can't instantiate enum!");
-        qmlRegisterUncreatableMetaObject(verification::staticMetaObject,
-                                         "im.nheko",
-                                         1,
-                                         0,
-                                         "VerificationStatus",
-                                         "Can't instantiate enum!");
-
-        qmlRegisterType<DelegateChoice>("im.nheko", 1, 0, "DelegateChoice");
-        qmlRegisterType<DelegateChooser>("im.nheko", 1, 0, "DelegateChooser");
-        qmlRegisterType<NhekoDropArea>("im.nheko", 1, 0, "NhekoDropArea");
-        qmlRegisterType<NhekoCursorShape>("im.nheko", 1, 0, "CursorShape");
-        qmlRegisterType<MxcAnimatedImage>("im.nheko", 1, 0, "MxcAnimatedImage");
-        qmlRegisterType<MxcMediaProxy>("im.nheko", 1, 0, "MxcMedia");
-        qmlRegisterUncreatableType<DeviceVerificationFlow>(
-          "im.nheko", 1, 0, "DeviceVerificationFlow", "Can't create verification flow from QML!");
-        qmlRegisterUncreatableType<UserProfile>(
-          "im.nheko",
-          1,
-          0,
-          "UserProfileModel",
-          "UserProfile needs to be instantiated on the C++ side");
-        qmlRegisterUncreatableType<MemberList>(
-          "im.nheko", 1, 0, "MemberList", "MemberList needs to be instantiated on the C++ side");
-        qmlRegisterUncreatableType<RoomSettings>(
-          "im.nheko",
-          1,
-          0,
-          "RoomSettingsModel",
-          "Room Settings needs to be instantiated on the C++ side");
-        qmlRegisterUncreatableType<TimelineModel>(
-          "im.nheko", 1, 0, "Room", "Room needs to be instantiated on the C++ side");
-        qmlRegisterUncreatableType<ImagePackListModel>(
-          "im.nheko",
-          1,
-          0,
-          "ImagePackListModel",
-          "ImagePackListModel needs to be instantiated on the C++ side");
-        qmlRegisterUncreatableType<SingleImagePackModel>(
-          "im.nheko",
-          1,
-          0,
-          "SingleImagePackModel",
-          "SingleImagePackModel needs to be instantiated on the C++ side");
-        qmlRegisterUncreatableType<InviteesModel>(
-          "im.nheko",
-          1,
-          0,
-          "InviteesModel",
-          "InviteesModel needs to be instantiated on the C++ side");
-        qmlRegisterUncreatableType<ReadReceiptsProxy>(
-          "im.nheko",
-          1,
-          0,
-          "ReadReceiptsProxy",
-          "ReadReceiptsProxy needs to be instantiated on the C++ side");
-
-        static auto self = this;
-        qmlRegisterSingletonType<MainWindow>(
-          "im.nheko", 1, 0, "MainWindow", [](QQmlEngine *, QJSEngine *) -> QObject * {
-                  auto ptr = MainWindow::instance();
-                  QQmlEngine::setObjectOwnership(ptr, QQmlEngine::CppOwnership);
-                  return ptr;
-          });
-        qmlRegisterSingletonType<TimelineViewManager>(
-          "im.nheko", 1, 0, "TimelineManager", [](QQmlEngine *, QJSEngine *) -> QObject * {
-                  auto ptr = self;
-                  QQmlEngine::setObjectOwnership(ptr, QQmlEngine::CppOwnership);
-                  return ptr;
-          });
-        qmlRegisterSingletonType<RoomlistModel>(
-          "im.nheko", 1, 0, "Rooms", [](QQmlEngine *, QJSEngine *) -> QObject * {
-                  auto ptr = new FilteredRoomlistModel(self->rooms_);
-
-                  connect(self->communities_,
-                          &CommunitiesModel::currentTagIdChanged,
-                          ptr,
-                          &FilteredRoomlistModel::updateFilterTag);
-                  connect(self->communities_,
-                          &CommunitiesModel::hiddenTagsChanged,
-                          ptr,
-                          &FilteredRoomlistModel::updateHiddenTagsAndSpaces);
-                  return ptr;
-          });
-        qmlRegisterSingletonType<RoomlistModel>(
-          "im.nheko", 1, 0, "Communities", [](QQmlEngine *, QJSEngine *) -> QObject * {
-                  auto ptr = self->communities_;
-                  QQmlEngine::setObjectOwnership(ptr, QQmlEngine::CppOwnership);
-                  return ptr;
-          });
-        qmlRegisterSingletonType<UserSettings>(
-          "im.nheko", 1, 0, "Settings", [](QQmlEngine *, QJSEngine *) -> QObject * {
-                  auto ptr = ChatPage::instance()->userSettings().data();
-                  QQmlEngine::setObjectOwnership(ptr, QQmlEngine::CppOwnership);
-                  return ptr;
-          });
-        qmlRegisterSingletonType<CallManager>(
-          "im.nheko", 1, 0, "CallManager", [](QQmlEngine *, QJSEngine *) -> QObject * {
-                  auto ptr = ChatPage::instance()->callManager();
-                  QQmlEngine::setObjectOwnership(ptr, QQmlEngine::CppOwnership);
-                  return ptr;
-          });
-        qmlRegisterSingletonType<Clipboard>(
-          "im.nheko", 1, 0, "Clipboard", [](QQmlEngine *, QJSEngine *) -> QObject * {
-                  return new Clipboard();
-          });
-        qmlRegisterSingletonType<Nheko>(
-          "im.nheko", 1, 0, "Nheko", [](QQmlEngine *, QJSEngine *) -> QObject * {
-                  return new Nheko();
-          });
-
-        qRegisterMetaType<mtx::events::collections::TimelineEvents>();
-        qRegisterMetaType<std::vector<DeviceInfo>>();
-
-        qmlRegisterType<emoji::EmojiModel>("im.nheko.EmojiModel", 1, 0, "EmojiModel");
-        qmlRegisterUncreatableType<emoji::Emoji>(
-          "im.nheko.EmojiModel", 1, 0, "Emoji", "Used by emoji models");
-        qmlRegisterUncreatableMetaObject(emoji::staticMetaObject,
-                                         "im.nheko.EmojiModel",
-                                         1,
-                                         0,
-                                         "EmojiCategory",
-                                         "Error: Only enums");
-
-        qmlRegisterType<RoomDirectoryModel>("im.nheko", 1, 0, "RoomDirectoryModel");
+    qRegisterMetaType<mtx::events::msg::KeyVerificationAccept>();
+    qRegisterMetaType<mtx::events::msg::KeyVerificationCancel>();
+    qRegisterMetaType<mtx::events::msg::KeyVerificationDone>();
+    qRegisterMetaType<mtx::events::msg::KeyVerificationKey>();
+    qRegisterMetaType<mtx::events::msg::KeyVerificationMac>();
+    qRegisterMetaType<mtx::events::msg::KeyVerificationReady>();
+    qRegisterMetaType<mtx::events::msg::KeyVerificationRequest>();
+    qRegisterMetaType<mtx::events::msg::KeyVerificationStart>();
+    qRegisterMetaType<CombinedImagePackModel *>();
+
+    qRegisterMetaType<std::vector<mtx::responses::PublicRoomsChunk>>();
+
+    qmlRegisterUncreatableMetaObject(
+      qml_mtx_events::staticMetaObject, "im.nheko", 1, 0, "MtxEvent", "Can't instantiate enum!");
+    qmlRegisterUncreatableMetaObject(
+      olm::staticMetaObject, "im.nheko", 1, 0, "Olm", "Can't instantiate enum!");
+    qmlRegisterUncreatableMetaObject(
+      crypto::staticMetaObject, "im.nheko", 1, 0, "Crypto", "Can't instantiate enum!");
+    qmlRegisterUncreatableMetaObject(verification::staticMetaObject,
+                                     "im.nheko",
+                                     1,
+                                     0,
+                                     "VerificationStatus",
+                                     "Can't instantiate enum!");
+
+    qmlRegisterType<DelegateChoice>("im.nheko", 1, 0, "DelegateChoice");
+    qmlRegisterType<DelegateChooser>("im.nheko", 1, 0, "DelegateChooser");
+    qmlRegisterType<NhekoDropArea>("im.nheko", 1, 0, "NhekoDropArea");
+    qmlRegisterType<NhekoCursorShape>("im.nheko", 1, 0, "CursorShape");
+    qmlRegisterType<MxcAnimatedImage>("im.nheko", 1, 0, "MxcAnimatedImage");
+    qmlRegisterType<MxcMediaProxy>("im.nheko", 1, 0, "MxcMedia");
+    qmlRegisterUncreatableType<DeviceVerificationFlow>(
+      "im.nheko", 1, 0, "DeviceVerificationFlow", "Can't create verification flow from QML!");
+    qmlRegisterUncreatableType<UserProfile>(
+      "im.nheko", 1, 0, "UserProfileModel", "UserProfile needs to be instantiated on the C++ side");
+    qmlRegisterUncreatableType<MemberList>(
+      "im.nheko", 1, 0, "MemberList", "MemberList needs to be instantiated on the C++ side");
+    qmlRegisterUncreatableType<RoomSettings>(
+      "im.nheko",
+      1,
+      0,
+      "RoomSettingsModel",
+      "Room Settings needs to be instantiated on the C++ side");
+    qmlRegisterUncreatableType<TimelineModel>(
+      "im.nheko", 1, 0, "Room", "Room needs to be instantiated on the C++ side");
+    qmlRegisterUncreatableType<ImagePackListModel>(
+      "im.nheko",
+      1,
+      0,
+      "ImagePackListModel",
+      "ImagePackListModel needs to be instantiated on the C++ side");
+    qmlRegisterUncreatableType<SingleImagePackModel>(
+      "im.nheko",
+      1,
+      0,
+      "SingleImagePackModel",
+      "SingleImagePackModel needs to be instantiated on the C++ side");
+    qmlRegisterUncreatableType<InviteesModel>(
+      "im.nheko", 1, 0, "InviteesModel", "InviteesModel needs to be instantiated on the C++ side");
+    qmlRegisterUncreatableType<ReadReceiptsProxy>(
+      "im.nheko",
+      1,
+      0,
+      "ReadReceiptsProxy",
+      "ReadReceiptsProxy needs to be instantiated on the C++ side");
+
+    static auto self = this;
+    qmlRegisterSingletonType<MainWindow>(
+      "im.nheko", 1, 0, "MainWindow", [](QQmlEngine *, QJSEngine *) -> QObject * {
+          auto ptr = MainWindow::instance();
+          QQmlEngine::setObjectOwnership(ptr, QQmlEngine::CppOwnership);
+          return ptr;
+      });
+    qmlRegisterSingletonType<TimelineViewManager>(
+      "im.nheko", 1, 0, "TimelineManager", [](QQmlEngine *, QJSEngine *) -> QObject * {
+          auto ptr = self;
+          QQmlEngine::setObjectOwnership(ptr, QQmlEngine::CppOwnership);
+          return ptr;
+      });
+    qmlRegisterSingletonType<RoomlistModel>(
+      "im.nheko", 1, 0, "Rooms", [](QQmlEngine *, QJSEngine *) -> QObject * {
+          auto ptr = new FilteredRoomlistModel(self->rooms_);
+
+          connect(self->communities_,
+                  &CommunitiesModel::currentTagIdChanged,
+                  ptr,
+                  &FilteredRoomlistModel::updateFilterTag);
+          connect(self->communities_,
+                  &CommunitiesModel::hiddenTagsChanged,
+                  ptr,
+                  &FilteredRoomlistModel::updateHiddenTagsAndSpaces);
+          return ptr;
+      });
+    qmlRegisterSingletonType<RoomlistModel>(
+      "im.nheko", 1, 0, "Communities", [](QQmlEngine *, QJSEngine *) -> QObject * {
+          auto ptr = self->communities_;
+          QQmlEngine::setObjectOwnership(ptr, QQmlEngine::CppOwnership);
+          return ptr;
+      });
+    qmlRegisterSingletonType<UserSettings>(
+      "im.nheko", 1, 0, "Settings", [](QQmlEngine *, QJSEngine *) -> QObject * {
+          auto ptr = ChatPage::instance()->userSettings().data();
+          QQmlEngine::setObjectOwnership(ptr, QQmlEngine::CppOwnership);
+          return ptr;
+      });
+    qmlRegisterSingletonType<CallManager>(
+      "im.nheko", 1, 0, "CallManager", [](QQmlEngine *, QJSEngine *) -> QObject * {
+          auto ptr = ChatPage::instance()->callManager();
+          QQmlEngine::setObjectOwnership(ptr, QQmlEngine::CppOwnership);
+          return ptr;
+      });
+    qmlRegisterSingletonType<Clipboard>(
+      "im.nheko", 1, 0, "Clipboard", [](QQmlEngine *, QJSEngine *) -> QObject * {
+          return new Clipboard();
+      });
+    qmlRegisterSingletonType<Nheko>(
+      "im.nheko", 1, 0, "Nheko", [](QQmlEngine *, QJSEngine *) -> QObject * {
+          return new Nheko();
+      });
+
+    qRegisterMetaType<mtx::events::collections::TimelineEvents>();
+    qRegisterMetaType<std::vector<DeviceInfo>>();
+
+    qmlRegisterType<emoji::EmojiModel>("im.nheko.EmojiModel", 1, 0, "EmojiModel");
+    qmlRegisterUncreatableType<emoji::Emoji>(
+      "im.nheko.EmojiModel", 1, 0, "Emoji", "Used by emoji models");
+    qmlRegisterUncreatableMetaObject(
+      emoji::staticMetaObject, "im.nheko.EmojiModel", 1, 0, "EmojiCategory", "Error: Only enums");
+
+    qmlRegisterType<RoomDirectoryModel>("im.nheko", 1, 0, "RoomDirectoryModel");
 
 #ifdef USE_QUICK_VIEW
-        view      = new QQuickView(parent);
-        container = QWidget::createWindowContainer(view, parent);
+    view      = new QQuickView(parent);
+    container = QWidget::createWindowContainer(view, parent);
 #else
-        view      = new QQuickWidget(parent);
-        container = view;
-        view->setResizeMode(QQuickWidget::SizeRootObjectToView);
-        container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
-
-        connect(view, &QQuickWidget::statusChanged, this, [](QQuickWidget::Status status) {
-                nhlog::ui()->debug("Status changed to {}", status);
-        });
+    view      = new QQuickWidget(parent);
+    container = view;
+    view->setResizeMode(QQuickWidget::SizeRootObjectToView);
+    container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+
+    connect(view, &QQuickWidget::statusChanged, this, [](QQuickWidget::Status status) {
+        nhlog::ui()->debug("Status changed to {}", status);
+    });
 #endif
-        container->setMinimumSize(200, 200);
-        updateColorPalette();
-        view->engine()->addImageProvider("MxcImage", imgProvider);
-        view->engine()->addImageProvider("colorimage", colorImgProvider);
-        view->engine()->addImageProvider("blurhash", blurhashProvider);
-        if (JdenticonProvider::isAvailable())
-                view->engine()->addImageProvider("jdenticon", jdenticonProvider);
-        view->setSource(QUrl("qrc:///qml/Root.qml"));
-
-        connect(parent, &ChatPage::themeChanged, this, &TimelineViewManager::updateColorPalette);
-        connect(
-          dynamic_cast<ChatPage *>(parent),
-          &ChatPage::receivedRoomDeviceVerificationRequest,
-          this,
-          [this](const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest> &message,
-                 TimelineModel *model) {
-                  if (this->isInitialSync_)
-                          return;
-
-                  auto event_id = QString::fromStdString(message.event_id);
-                  if (!this->dvList.contains(event_id)) {
-                          if (auto flow = DeviceVerificationFlow::NewInRoomVerification(
-                                this,
-                                model,
-                                message.content,
-                                QString::fromStdString(message.sender),
-                                event_id)) {
-                                  dvList[event_id] = flow;
-                                  emit newDeviceVerificationRequest(flow.data());
-                          }
-                  }
-          });
-        connect(dynamic_cast<ChatPage *>(parent),
-                &ChatPage::receivedDeviceVerificationRequest,
-                this,
-                [this](const mtx::events::msg::KeyVerificationRequest &msg, std::string sender) {
-                        if (this->isInitialSync_)
-                                return;
-
-                        if (!msg.transaction_id)
-                                return;
-
-                        auto txnid = QString::fromStdString(msg.transaction_id.value());
-                        if (!this->dvList.contains(txnid)) {
-                                if (auto flow = DeviceVerificationFlow::NewToDeviceVerification(
-                                      this, msg, QString::fromStdString(sender), txnid)) {
-                                        dvList[txnid] = flow;
-                                        emit newDeviceVerificationRequest(flow.data());
-                                }
-                        }
-                });
-        connect(dynamic_cast<ChatPage *>(parent),
-                &ChatPage::receivedDeviceVerificationStart,
-                this,
-                [this](const mtx::events::msg::KeyVerificationStart &msg, std::string sender) {
-                        if (this->isInitialSync_)
-                                return;
-
-                        if (!msg.transaction_id)
-                                return;
-
-                        auto txnid = QString::fromStdString(msg.transaction_id.value());
-                        if (!this->dvList.contains(txnid)) {
-                                if (auto flow = DeviceVerificationFlow::NewToDeviceVerification(
-                                      this, msg, QString::fromStdString(sender), txnid)) {
-                                        dvList[txnid] = flow;
-                                        emit newDeviceVerificationRequest(flow.data());
-                                }
-                        }
-                });
-        connect(parent, &ChatPage::loggedOut, this, [this]() {
-                isInitialSync_ = true;
-                emit initialSyncChanged(true);
-        });
+    container->setMinimumSize(200, 200);
+    updateColorPalette();
+    view->engine()->addImageProvider("MxcImage", imgProvider);
+    view->engine()->addImageProvider("colorimage", colorImgProvider);
+    view->engine()->addImageProvider("blurhash", blurhashProvider);
+    if (JdenticonProvider::isAvailable())
+        view->engine()->addImageProvider("jdenticon", jdenticonProvider);
+    view->setSource(QUrl("qrc:///qml/Root.qml"));
+
+    connect(parent, &ChatPage::themeChanged, this, &TimelineViewManager::updateColorPalette);
+    connect(dynamic_cast<ChatPage *>(parent),
+            &ChatPage::receivedRoomDeviceVerificationRequest,
+            this,
+            [this](const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest> &message,
+                   TimelineModel *model) {
+                if (this->isInitialSync_)
+                    return;
+
+                auto event_id = QString::fromStdString(message.event_id);
+                if (!this->dvList.contains(event_id)) {
+                    if (auto flow = DeviceVerificationFlow::NewInRoomVerification(
+                          this,
+                          model,
+                          message.content,
+                          QString::fromStdString(message.sender),
+                          event_id)) {
+                        dvList[event_id] = flow;
+                        emit newDeviceVerificationRequest(flow.data());
+                    }
+                }
+            });
+    connect(dynamic_cast<ChatPage *>(parent),
+            &ChatPage::receivedDeviceVerificationRequest,
+            this,
+            [this](const mtx::events::msg::KeyVerificationRequest &msg, std::string sender) {
+                if (this->isInitialSync_)
+                    return;
+
+                if (!msg.transaction_id)
+                    return;
+
+                auto txnid = QString::fromStdString(msg.transaction_id.value());
+                if (!this->dvList.contains(txnid)) {
+                    if (auto flow = DeviceVerificationFlow::NewToDeviceVerification(
+                          this, msg, QString::fromStdString(sender), txnid)) {
+                        dvList[txnid] = flow;
+                        emit newDeviceVerificationRequest(flow.data());
+                    }
+                }
+            });
+    connect(dynamic_cast<ChatPage *>(parent),
+            &ChatPage::receivedDeviceVerificationStart,
+            this,
+            [this](const mtx::events::msg::KeyVerificationStart &msg, std::string sender) {
+                if (this->isInitialSync_)
+                    return;
+
+                if (!msg.transaction_id)
+                    return;
+
+                auto txnid = QString::fromStdString(msg.transaction_id.value());
+                if (!this->dvList.contains(txnid)) {
+                    if (auto flow = DeviceVerificationFlow::NewToDeviceVerification(
+                          this, msg, QString::fromStdString(sender), txnid)) {
+                        dvList[txnid] = flow;
+                        emit newDeviceVerificationRequest(flow.data());
+                    }
+                }
+            });
+    connect(parent, &ChatPage::loggedOut, this, [this]() {
+        isInitialSync_ = true;
+        emit initialSyncChanged(true);
+    });
 
-        connect(this,
-                &TimelineViewManager::openImageOverlayInternalCb,
-                this,
-                &TimelineViewManager::openImageOverlayInternal);
+    connect(this,
+            &TimelineViewManager::openImageOverlayInternalCb,
+            this,
+            &TimelineViewManager::openImageOverlayInternal);
 }
 
 void
 TimelineViewManager::openRoomMembers(TimelineModel *room)
 {
-        if (!room)
-                return;
-        MemberList *memberList = new MemberList(room->roomId(), this);
-        emit openRoomMembersDialog(memberList, room);
+    if (!room)
+        return;
+    MemberList *memberList = new MemberList(room->roomId(), this);
+    emit openRoomMembersDialog(memberList, room);
 }
 
 void
 TimelineViewManager::openRoomSettings(QString room_id)
 {
-        RoomSettings *settings = new RoomSettings(room_id, this);
-        connect(rooms_->getRoomById(room_id).data(),
-                &TimelineModel::roomAvatarUrlChanged,
-                settings,
-                &RoomSettings::avatarChanged);
-        emit openRoomSettingsDialog(settings);
+    RoomSettings *settings = new RoomSettings(room_id, this);
+    connect(rooms_->getRoomById(room_id).data(),
+            &TimelineModel::roomAvatarUrlChanged,
+            settings,
+            &RoomSettings::avatarChanged);
+    emit openRoomSettingsDialog(settings);
 }
 
 void
 TimelineViewManager::openInviteUsers(QString roomId)
 {
-        InviteesModel *model = new InviteesModel{this};
-        connect(model, &InviteesModel::accept, this, [this, model, roomId]() {
-                emit inviteUsers(roomId, model->mxids());
-        });
-        emit openInviteUsersDialog(model);
+    InviteesModel *model = new InviteesModel{this};
+    connect(model, &InviteesModel::accept, this, [this, model, roomId]() {
+        emit inviteUsers(roomId, model->mxids());
+    });
+    emit openInviteUsersDialog(model);
 }
 
 void
 TimelineViewManager::openGlobalUserProfile(QString userId)
 {
-        UserProfile *profile = new UserProfile{QString{}, userId, this};
-        emit openProfile(profile);
+    UserProfile *profile = new UserProfile{QString{}, userId, this};
+    emit openProfile(profile);
 }
 
 void
 TimelineViewManager::setVideoCallItem()
 {
-        WebRTCSession::instance().setVideoItem(
-          view->rootObject()->findChild<QQuickItem *>("videoCallItem"));
+    WebRTCSession::instance().setVideoItem(
+      view->rootObject()->findChild<QQuickItem *>("videoCallItem"));
 }
 
 void
 TimelineViewManager::sync(const mtx::responses::Rooms &rooms_res)
 {
-        this->rooms_->sync(rooms_res);
-        this->communities_->sync(rooms_res);
+    this->rooms_->sync(rooms_res);
+    this->communities_->sync(rooms_res);
 
-        if (isInitialSync_) {
-                this->isInitialSync_ = false;
-                emit initialSyncChanged(false);
-        }
+    if (isInitialSync_) {
+        this->isInitialSync_ = false;
+        emit initialSyncChanged(false);
+    }
 }
 
 void
 TimelineViewManager::showEvent(const QString &room_id, const QString &event_id)
 {
-        if (auto room = rooms_->getRoomById(room_id)) {
-                if (rooms_->currentRoom() != room) {
-                        rooms_->setCurrentRoom(room_id);
-                        container->setFocus();
-                        nhlog::ui()->info("Activated room {}", room_id.toStdString());
-                }
-
-                room->showEvent(event_id);
+    if (auto room = rooms_->getRoomById(room_id)) {
+        if (rooms_->currentRoom() != room) {
+            rooms_->setCurrentRoom(room_id);
+            container->setFocus();
+            nhlog::ui()->info("Activated room {}", room_id.toStdString());
         }
+
+        room->showEvent(event_id);
+    }
 }
 
 QString
 TimelineViewManager::escapeEmoji(QString str) const
 {
-        return utils::replaceEmoji(str);
+    return utils::replaceEmoji(str);
 }
 
 void
 TimelineViewManager::openImageOverlay(QString mxcUrl, QString eventId)
 {
-        if (mxcUrl.isEmpty()) {
-                return;
-        }
+    if (mxcUrl.isEmpty()) {
+        return;
+    }
 
-        MxcImageProvider::download(
-          mxcUrl.remove("mxc://"), QSize(), [this, eventId](QString, QSize, QImage img, QString) {
-                  if (img.isNull()) {
-                          nhlog::ui()->error("Error when retrieving image for overlay.");
-                          return;
-                  }
+    MxcImageProvider::download(
+      mxcUrl.remove("mxc://"), QSize(), [this, eventId](QString, QSize, QImage img, QString) {
+          if (img.isNull()) {
+              nhlog::ui()->error("Error when retrieving image for overlay.");
+              return;
+          }
 
-                  emit openImageOverlayInternalCb(eventId, std::move(img));
-          });
+          emit openImageOverlayInternalCb(eventId, std::move(img));
+      });
 }
 
 void
 TimelineViewManager::openImagePackSettings(QString roomid)
 {
-        emit showImagePackSettings(new ImagePackListModel(roomid.toStdString(), this));
+    emit showImagePackSettings(new ImagePackListModel(roomid.toStdString(), this));
 }
 
 void
 TimelineViewManager::openImageOverlayInternal(QString eventId, QImage img)
 {
-        auto pixmap = QPixmap::fromImage(img);
+    auto pixmap = QPixmap::fromImage(img);
 
-        auto imgDialog = new dialogs::ImageOverlay(pixmap);
-        imgDialog->showFullScreen();
+    auto imgDialog = new dialogs::ImageOverlay(pixmap);
+    imgDialog->showFullScreen();
 
-        auto room = rooms_->currentRoom();
-        connect(imgDialog, &dialogs::ImageOverlay::saving, room, [eventId, imgDialog, room]() {
-                // hide the overlay while presenting the save dialog for better
-                // cross platform support.
-                imgDialog->hide();
+    auto room = rooms_->currentRoom();
+    connect(imgDialog, &dialogs::ImageOverlay::saving, room, [eventId, imgDialog, room]() {
+        // hide the overlay while presenting the save dialog for better
+        // cross platform support.
+        imgDialog->hide();
 
-                if (!room->saveMedia(eventId)) {
-                        imgDialog->show();
-                } else {
-                        imgDialog->close();
-                }
-        });
+        if (!room->saveMedia(eventId)) {
+            imgDialog->show();
+        } else {
+            imgDialog->close();
+        }
+    });
 }
 
 void
 TimelineViewManager::openLeaveRoomDialog(QString roomid) const
 {
-        MainWindow::instance()->openLeaveRoomDialog(roomid);
+    MainWindow::instance()->openLeaveRoomDialog(roomid);
 }
 
 void
 TimelineViewManager::verifyUser(QString userid)
 {
-        auto joined_rooms = cache::joinedRooms();
-        auto room_infos   = cache::getRoomInfo(joined_rooms);
-
-        for (std::string room_id : joined_rooms) {
-                if ((room_infos[QString::fromStdString(room_id)].member_count == 2) &&
-                    cache::isRoomEncrypted(room_id)) {
-                        auto room_members = cache::roomMembers(room_id);
-                        if (std::find(room_members.begin(),
-                                      room_members.end(),
-                                      (userid).toStdString()) != room_members.end()) {
-                                if (auto model =
-                                      rooms_->getRoomById(QString::fromStdString(room_id))) {
-                                        auto flow =
-                                          DeviceVerificationFlow::InitiateUserVerification(
-                                            this, model.data(), userid);
-                                        connect(model.data(),
-                                                &TimelineModel::updateFlowEventId,
-                                                this,
-                                                [this, flow](std::string eventId) {
-                                                        dvList[QString::fromStdString(eventId)] =
-                                                          flow;
-                                                });
-                                        emit newDeviceVerificationRequest(flow.data());
-                                        return;
-                                }
-                        }
+    auto joined_rooms = cache::joinedRooms();
+    auto room_infos   = cache::getRoomInfo(joined_rooms);
+
+    for (std::string room_id : joined_rooms) {
+        if ((room_infos[QString::fromStdString(room_id)].member_count == 2) &&
+            cache::isRoomEncrypted(room_id)) {
+            auto room_members = cache::roomMembers(room_id);
+            if (std::find(room_members.begin(), room_members.end(), (userid).toStdString()) !=
+                room_members.end()) {
+                if (auto model = rooms_->getRoomById(QString::fromStdString(room_id))) {
+                    auto flow =
+                      DeviceVerificationFlow::InitiateUserVerification(this, model.data(), userid);
+                    connect(model.data(),
+                            &TimelineModel::updateFlowEventId,
+                            this,
+                            [this, flow](std::string eventId) {
+                                dvList[QString::fromStdString(eventId)] = flow;
+                            });
+                    emit newDeviceVerificationRequest(flow.data());
+                    return;
                 }
+            }
         }
+    }
 
-        emit ChatPage::instance()->showNotification(
-          tr("No encrypted private chat found with this user. Create an "
-             "encrypted private chat with this user and try again."));
+    emit ChatPage::instance()->showNotification(
+      tr("No encrypted private chat found with this user. Create an "
+         "encrypted private chat with this user and try again."));
 }
 
 void
 TimelineViewManager::removeVerificationFlow(DeviceVerificationFlow *flow)
 {
-        for (auto it = dvList.keyValueBegin(); it != dvList.keyValueEnd(); ++it) {
-                if ((*it).second == flow) {
-                        dvList.remove((*it).first);
-                        return;
-                }
+    for (auto it = dvList.keyValueBegin(); it != dvList.keyValueEnd(); ++it) {
+        if ((*it).second == flow) {
+            dvList.remove((*it).first);
+            return;
         }
+    }
 }
 
 void
 TimelineViewManager::verifyDevice(QString userid, QString deviceid)
 {
-        auto flow = DeviceVerificationFlow::InitiateDeviceVerification(this, userid, deviceid);
-        this->dvList[flow->transactionId()] = flow;
-        emit newDeviceVerificationRequest(flow.data());
+    auto flow = DeviceVerificationFlow::InitiateDeviceVerification(this, userid, deviceid);
+    this->dvList[flow->transactionId()] = flow;
+    emit newDeviceVerificationRequest(flow.data());
 }
 
 void
 TimelineViewManager::updateReadReceipts(const QString &room_id,
                                         const std::vector<QString> &event_ids)
 {
-        if (auto room = rooms_->getRoomById(room_id)) {
-                room->markEventsAsRead(event_ids);
-        }
+    if (auto room = rooms_->getRoomById(room_id)) {
+        room->markEventsAsRead(event_ids);
+    }
 }
 
 void
 TimelineViewManager::receivedSessionKey(const std::string &room_id, const std::string &session_id)
 {
-        if (auto room = rooms_->getRoomById(QString::fromStdString(room_id))) {
-                room->receivedSessionKey(session_id);
-        }
+    if (auto room = rooms_->getRoomById(QString::fromStdString(room_id))) {
+        room->receivedSessionKey(session_id);
+    }
 }
 
 void
 TimelineViewManager::initializeRoomlist()
 {
-        rooms_->initializeRooms();
-        communities_->initializeSidebar();
+    rooms_->initializeRooms();
+    communities_->initializeSidebar();
 }
 
 void
@@ -600,178 +578,175 @@ TimelineViewManager::queueReply(const QString &roomid,
                                 const QString &repliedToEvent,
                                 const QString &replyBody)
 {
-        if (auto room = rooms_->getRoomById(roomid)) {
-                room->setReply(repliedToEvent);
-                room->input()->message(replyBody);
-        }
+    if (auto room = rooms_->getRoomById(roomid)) {
+        room->setReply(repliedToEvent);
+        room->input()->message(replyBody);
+    }
 }
 
 void
 TimelineViewManager::queueCallMessage(const QString &roomid,
                                       const mtx::events::msg::CallInvite &callInvite)
 {
-        if (auto room = rooms_->getRoomById(roomid))
-                room->sendMessageEvent(callInvite, mtx::events::EventType::CallInvite);
+    if (auto room = rooms_->getRoomById(roomid))
+        room->sendMessageEvent(callInvite, mtx::events::EventType::CallInvite);
 }
 
 void
 TimelineViewManager::queueCallMessage(const QString &roomid,
                                       const mtx::events::msg::CallCandidates &callCandidates)
 {
-        if (auto room = rooms_->getRoomById(roomid))
-                room->sendMessageEvent(callCandidates, mtx::events::EventType::CallCandidates);
+    if (auto room = rooms_->getRoomById(roomid))
+        room->sendMessageEvent(callCandidates, mtx::events::EventType::CallCandidates);
 }
 
 void
 TimelineViewManager::queueCallMessage(const QString &roomid,
                                       const mtx::events::msg::CallAnswer &callAnswer)
 {
-        if (auto room = rooms_->getRoomById(roomid))
-                room->sendMessageEvent(callAnswer, mtx::events::EventType::CallAnswer);
+    if (auto room = rooms_->getRoomById(roomid))
+        room->sendMessageEvent(callAnswer, mtx::events::EventType::CallAnswer);
 }
 
 void
 TimelineViewManager::queueCallMessage(const QString &roomid,
                                       const mtx::events::msg::CallHangUp &callHangUp)
 {
-        if (auto room = rooms_->getRoomById(roomid))
-                room->sendMessageEvent(callHangUp, mtx::events::EventType::CallHangUp);
+    if (auto room = rooms_->getRoomById(roomid))
+        room->sendMessageEvent(callHangUp, mtx::events::EventType::CallHangUp);
 }
 
 void
 TimelineViewManager::focusMessageInput()
 {
-        emit focusInput();
+    emit focusInput();
 }
 
 QObject *
 TimelineViewManager::completerFor(QString completerName, QString roomId)
 {
-        if (completerName == "user") {
-                auto userModel = new UsersModel(roomId.toStdString());
-                auto proxy     = new CompletionProxyModel(userModel);
-                userModel->setParent(proxy);
-                return proxy;
-        } else if (completerName == "emoji") {
-                auto emojiModel = new emoji::EmojiModel();
-                auto proxy      = new CompletionProxyModel(emojiModel);
-                emojiModel->setParent(proxy);
-                return proxy;
-        } else if (completerName == "allemoji") {
-                auto emojiModel = new emoji::EmojiModel();
-                auto proxy = new CompletionProxyModel(emojiModel, 1, static_cast<size_t>(-1) / 4);
-                emojiModel->setParent(proxy);
-                return proxy;
-        } else if (completerName == "room") {
-                auto roomModel = new RoomsModel(false);
-                auto proxy     = new CompletionProxyModel(roomModel, 4);
-                roomModel->setParent(proxy);
-                return proxy;
-        } else if (completerName == "roomAliases") {
-                auto roomModel = new RoomsModel(true);
-                auto proxy     = new CompletionProxyModel(roomModel);
-                roomModel->setParent(proxy);
-                return proxy;
-        } else if (completerName == "stickers") {
-                auto stickerModel = new CombinedImagePackModel(roomId.toStdString(), true);
-                auto proxy = new CompletionProxyModel(stickerModel, 1, static_cast<size_t>(-1) / 4);
-                stickerModel->setParent(proxy);
-                return proxy;
-        }
-        return nullptr;
+    if (completerName == "user") {
+        auto userModel = new UsersModel(roomId.toStdString());
+        auto proxy     = new CompletionProxyModel(userModel);
+        userModel->setParent(proxy);
+        return proxy;
+    } else if (completerName == "emoji") {
+        auto emojiModel = new emoji::EmojiModel();
+        auto proxy      = new CompletionProxyModel(emojiModel);
+        emojiModel->setParent(proxy);
+        return proxy;
+    } else if (completerName == "allemoji") {
+        auto emojiModel = new emoji::EmojiModel();
+        auto proxy      = new CompletionProxyModel(emojiModel, 1, static_cast<size_t>(-1) / 4);
+        emojiModel->setParent(proxy);
+        return proxy;
+    } else if (completerName == "room") {
+        auto roomModel = new RoomsModel(false);
+        auto proxy     = new CompletionProxyModel(roomModel, 4);
+        roomModel->setParent(proxy);
+        return proxy;
+    } else if (completerName == "roomAliases") {
+        auto roomModel = new RoomsModel(true);
+        auto proxy     = new CompletionProxyModel(roomModel);
+        roomModel->setParent(proxy);
+        return proxy;
+    } else if (completerName == "stickers") {
+        auto stickerModel = new CombinedImagePackModel(roomId.toStdString(), true);
+        auto proxy        = new CompletionProxyModel(stickerModel, 1, static_cast<size_t>(-1) / 4);
+        stickerModel->setParent(proxy);
+        return proxy;
+    }
+    return nullptr;
 }
 
 void
 TimelineViewManager::focusTimeline()
 {
-        getWidget()->setFocus();
+    getWidget()->setFocus();
 }
 
 void
 TimelineViewManager::forwardMessageToRoom(mtx::events::collections::TimelineEvents *e,
                                           QString roomId)
 {
-        auto room                                                = rooms_->getRoomById(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;
-                                                      }
-
-                                                      if (auto room = rooms_->getRoomById(roomId)) {
-                                                              removeReplyFallback(ev);
-                                                              ev.content.relations.relations
-                                                                .clear();
-                                                              room->sendMessageEvent(
-                                                                ev.content,
-                                                                mtx::events::EventType::
-                                                                  RoomMessage);
-                                                      }
-                                              }
-                                      },
-                                      *e);
-                            });
+    auto room                                                = rooms_->getRoomById(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) {
+                          using namespace mtx::events;
+                          if constexpr (EventType::RoomMessage ==
+                                          message_content_to_type<decltype(ev.content)> ||
+                                        EventType::Sticker ==
+                                          message_content_to_type<decltype(ev.content)>) {
+                              if constexpr (messageWithFileAndUrl(ev)) {
+                                  ev.content.relations.relations.clear();
+                                  ev.content.file.reset();
+                                  ev.content.url = url;
+                              }
+
+                              if (auto room = rooms_->getRoomById(roomId)) {
+                                  removeReplyFallback(ev);
+                                  ev.content.relations.relations.clear();
+                                  room->sendMessageEvent(ev.content,
+                                                         mtx::events::EventType::RoomMessage);
+                              }
+                          }
+                      },
+                      *e);
+                });
 
-                          return;
-                  });
+              return;
+          });
 
-                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->sendMessageEvent(e.content, mtx::events::EventType::RoomMessage);
-                  }
-          },
-          *e);
+    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->sendMessageEvent(e.content, mtx::events::EventType::RoomMessage);
+          }
+      },
+      *e);
 }
 
 //! WORKAROUND(Nico): for https://bugreports.qt.io/browse/QTBUG-93281
 void
 TimelineViewManager::fixImageRendering(QQuickTextDocument *t, QQuickItem *i)
 {
-        if (t) {
-                QObject::connect(
-                  t->textDocument(), SIGNAL(imagesLoaded()), i, SLOT(updateWholeDocument()));
-        }
+    if (t) {
+        QObject::connect(t->textDocument(), SIGNAL(imagesLoaded()), i, SLOT(updateWholeDocument()));
+    }
 }
diff --git a/src/timeline/TimelineViewManager.h b/src/timeline/TimelineViewManager.h
index 8991de55..f7b01315 100644
--- a/src/timeline/TimelineViewManager.h
+++ b/src/timeline/TimelineViewManager.h
@@ -38,123 +38,121 @@ class ImagePackListModel;
 
 class TimelineViewManager : public QObject
 {
-        Q_OBJECT
+    Q_OBJECT
 
-        Q_PROPERTY(
-          bool isInitialSync MEMBER isInitialSync_ READ isInitialSync NOTIFY initialSyncChanged)
-        Q_PROPERTY(
-          bool isWindowFocused MEMBER isWindowFocused_ READ isWindowFocused NOTIFY focusChanged)
+    Q_PROPERTY(
+      bool isInitialSync MEMBER isInitialSync_ READ isInitialSync NOTIFY initialSyncChanged)
+    Q_PROPERTY(
+      bool isWindowFocused MEMBER isWindowFocused_ READ isWindowFocused NOTIFY focusChanged)
 
 public:
-        TimelineViewManager(CallManager *callManager, ChatPage *parent = nullptr);
-        QWidget *getWidget() const { return container; }
+    TimelineViewManager(CallManager *callManager, ChatPage *parent = nullptr);
+    QWidget *getWidget() const { return container; }
 
-        void sync(const mtx::responses::Rooms &rooms);
+    void sync(const mtx::responses::Rooms &rooms);
 
-        MxcImageProvider *imageProvider() { return imgProvider; }
-        CallManager *callManager() { return callManager_; }
+    MxcImageProvider *imageProvider() { return imgProvider; }
+    CallManager *callManager() { return callManager_; }
 
-        void clearAll() { rooms_->clear(); }
+    void clearAll() { rooms_->clear(); }
 
-        Q_INVOKABLE bool isInitialSync() const { return isInitialSync_; }
-        bool isWindowFocused() const { return isWindowFocused_; }
-        Q_INVOKABLE void openImageOverlay(QString mxcUrl, QString eventId);
-        Q_INVOKABLE void openImagePackSettings(QString roomid);
-        Q_INVOKABLE QColor userColor(QString id, QColor background);
-        Q_INVOKABLE QString escapeEmoji(QString str) const;
-        Q_INVOKABLE QString htmlEscape(QString str) const { return str.toHtmlEscaped(); }
+    Q_INVOKABLE bool isInitialSync() const { return isInitialSync_; }
+    bool isWindowFocused() const { return isWindowFocused_; }
+    Q_INVOKABLE void openImageOverlay(QString mxcUrl, QString eventId);
+    Q_INVOKABLE void openImagePackSettings(QString roomid);
+    Q_INVOKABLE QColor userColor(QString id, QColor background);
+    Q_INVOKABLE QString escapeEmoji(QString str) const;
+    Q_INVOKABLE QString htmlEscape(QString str) const { return str.toHtmlEscaped(); }
 
-        Q_INVOKABLE QString userPresence(QString id) const;
-        Q_INVOKABLE QString userStatus(QString id) const;
+    Q_INVOKABLE QString userPresence(QString id) const;
+    Q_INVOKABLE QString userStatus(QString id) const;
 
-        Q_INVOKABLE void openRoomMembers(TimelineModel *room);
-        Q_INVOKABLE void openRoomSettings(QString room_id);
-        Q_INVOKABLE void openInviteUsers(QString roomId);
-        Q_INVOKABLE void openGlobalUserProfile(QString userId);
+    Q_INVOKABLE void openRoomMembers(TimelineModel *room);
+    Q_INVOKABLE void openRoomSettings(QString room_id);
+    Q_INVOKABLE void openInviteUsers(QString roomId);
+    Q_INVOKABLE void openGlobalUserProfile(QString userId);
 
-        Q_INVOKABLE void focusMessageInput();
-        Q_INVOKABLE void openLeaveRoomDialog(QString roomid) const;
-        Q_INVOKABLE void removeVerificationFlow(DeviceVerificationFlow *flow);
+    Q_INVOKABLE void focusMessageInput();
+    Q_INVOKABLE void openLeaveRoomDialog(QString roomid) const;
+    Q_INVOKABLE void removeVerificationFlow(DeviceVerificationFlow *flow);
 
-        Q_INVOKABLE void fixImageRendering(QQuickTextDocument *t, QQuickItem *i);
+    Q_INVOKABLE void fixImageRendering(QQuickTextDocument *t, QQuickItem *i);
 
-        void verifyUser(QString userid);
-        void verifyDevice(QString userid, QString deviceid);
+    void verifyUser(QString userid);
+    void verifyDevice(QString userid, QString deviceid);
 
 signals:
-        void activeTimelineChanged(TimelineModel *timeline);
-        void initialSyncChanged(bool isInitialSync);
-        void replyingEventChanged(QString replyingEvent);
-        void replyClosed();
-        void newDeviceVerificationRequest(DeviceVerificationFlow *flow);
-        void inviteUsers(QString roomId, QStringList users);
-        void showRoomList();
-        void narrowViewChanged();
-        void focusChanged();
-        void focusInput();
-        void openImageOverlayInternalCb(QString eventId, QImage img);
-        void openRoomMembersDialog(MemberList *members, TimelineModel *room);
-        void openRoomSettingsDialog(RoomSettings *settings);
-        void openInviteUsersDialog(InviteesModel *invitees);
-        void openProfile(UserProfile *profile);
-        void showImagePackSettings(ImagePackListModel *packlist);
+    void activeTimelineChanged(TimelineModel *timeline);
+    void initialSyncChanged(bool isInitialSync);
+    void replyingEventChanged(QString replyingEvent);
+    void replyClosed();
+    void newDeviceVerificationRequest(DeviceVerificationFlow *flow);
+    void inviteUsers(QString roomId, QStringList users);
+    void showRoomList();
+    void narrowViewChanged();
+    void focusChanged();
+    void focusInput();
+    void openImageOverlayInternalCb(QString eventId, QImage img);
+    void openRoomMembersDialog(MemberList *members, TimelineModel *room);
+    void openRoomSettingsDialog(RoomSettings *settings);
+    void openInviteUsersDialog(InviteesModel *invitees);
+    void openProfile(UserProfile *profile);
+    void showImagePackSettings(ImagePackListModel *packlist);
 
 public slots:
-        void updateReadReceipts(const QString &room_id, const std::vector<QString> &event_ids);
-        void receivedSessionKey(const std::string &room_id, const std::string &session_id);
-        void initializeRoomlist();
-        void chatFocusChanged(bool focused)
-        {
-                isWindowFocused_ = focused;
-                emit focusChanged();
-        }
-
-        void showEvent(const QString &room_id, const QString &event_id);
-        void focusTimeline();
-
-        void updateColorPalette();
-        void queueReply(const QString &roomid,
-                        const QString &repliedToEvent,
-                        const QString &replyBody);
-        void queueCallMessage(const QString &roomid, const mtx::events::msg::CallInvite &);
-        void queueCallMessage(const QString &roomid, const mtx::events::msg::CallCandidates &);
-        void queueCallMessage(const QString &roomid, const mtx::events::msg::CallAnswer &);
-        void queueCallMessage(const QString &roomid, const mtx::events::msg::CallHangUp &);
-
-        void setVideoCallItem();
-
-        QObject *completerFor(QString completerName, QString roomId = "");
-        void forwardMessageToRoom(mtx::events::collections::TimelineEvents *e, QString roomId);
-
-        RoomlistModel *rooms() { return rooms_; }
+    void updateReadReceipts(const QString &room_id, const std::vector<QString> &event_ids);
+    void receivedSessionKey(const std::string &room_id, const std::string &session_id);
+    void initializeRoomlist();
+    void chatFocusChanged(bool focused)
+    {
+        isWindowFocused_ = focused;
+        emit focusChanged();
+    }
+
+    void showEvent(const QString &room_id, const QString &event_id);
+    void focusTimeline();
+
+    void updateColorPalette();
+    void queueReply(const QString &roomid, const QString &repliedToEvent, const QString &replyBody);
+    void queueCallMessage(const QString &roomid, const mtx::events::msg::CallInvite &);
+    void queueCallMessage(const QString &roomid, const mtx::events::msg::CallCandidates &);
+    void queueCallMessage(const QString &roomid, const mtx::events::msg::CallAnswer &);
+    void queueCallMessage(const QString &roomid, const mtx::events::msg::CallHangUp &);
+
+    void setVideoCallItem();
+
+    QObject *completerFor(QString completerName, QString roomId = "");
+    void forwardMessageToRoom(mtx::events::collections::TimelineEvents *e, QString roomId);
+
+    RoomlistModel *rooms() { return rooms_; }
 
 private slots:
-        void openImageOverlayInternal(QString eventId, QImage img);
+    void openImageOverlayInternal(QString eventId, QImage img);
 
 private:
 #ifdef USE_QUICK_VIEW
-        QQuickView *view;
+    QQuickView *view;
 #else
-        QQuickWidget *view;
+    QQuickWidget *view;
 #endif
-        QWidget *container;
+    QWidget *container;
 
-        MxcImageProvider *imgProvider;
-        ColorImageProvider *colorImgProvider;
-        BlurhashProvider *blurhashProvider;
-        JdenticonProvider *jdenticonProvider;
+    MxcImageProvider *imgProvider;
+    ColorImageProvider *colorImgProvider;
+    BlurhashProvider *blurhashProvider;
+    JdenticonProvider *jdenticonProvider;
 
-        CallManager *callManager_ = nullptr;
+    CallManager *callManager_ = nullptr;
 
-        bool isInitialSync_   = true;
-        bool isWindowFocused_ = false;
+    bool isInitialSync_   = true;
+    bool isWindowFocused_ = false;
 
-        RoomlistModel *rooms_          = nullptr;
-        CommunitiesModel *communities_ = nullptr;
+    RoomlistModel *rooms_          = nullptr;
+    CommunitiesModel *communities_ = nullptr;
 
-        QHash<QString, QColor> userColors;
+    QHash<QString, QColor> userColors;
 
-        QHash<QString, QSharedPointer<DeviceVerificationFlow>> dvList;
+    QHash<QString, QSharedPointer<DeviceVerificationFlow>> dvList;
 };
 Q_DECLARE_METATYPE(mtx::events::msg::KeyVerificationAccept)
 Q_DECLARE_METATYPE(mtx::events::msg::KeyVerificationCancel)
diff --git a/src/ui/Badge.cpp b/src/ui/Badge.cpp
index 66210d06..1b5aba2f 100644
--- a/src/ui/Badge.cpp
+++ b/src/ui/Badge.cpp
@@ -9,214 +9,214 @@
 Badge::Badge(QWidget *parent)
   : OverlayWidget(parent)
 {
-        init();
+    init();
 }
 
 Badge::Badge(const QIcon &icon, QWidget *parent)
   : OverlayWidget(parent)
 {
-        init();
-        setIcon(icon);
+    init();
+    setIcon(icon);
 }
 
 Badge::Badge(const QString &text, QWidget *parent)
   : OverlayWidget(parent)
 {
-        init();
-        setText(text);
+    init();
+    setText(text);
 }
 
 void
 Badge::init()
 {
-        x_ = 0;
-        y_ = 0;
-        // TODO: Make padding configurable.
-        padding_  = 5;
-        diameter_ = 24;
+    x_ = 0;
+    y_ = 0;
+    // TODO: Make padding configurable.
+    padding_  = 5;
+    diameter_ = 24;
 
-        setAttribute(Qt::WA_TransparentForMouseEvents);
+    setAttribute(Qt::WA_TransparentForMouseEvents);
 
-        QFont _font(font());
-        _font.setPointSizeF(7.5);
-        _font.setStyleName("Bold");
+    QFont _font(font());
+    _font.setPointSizeF(7.5);
+    _font.setStyleName("Bold");
 
-        setFont(_font);
-        setText("");
+    setFont(_font);
+    setText("");
 }
 
 QString
 Badge::text() const
 {
-        return text_;
+    return text_;
 }
 
 QIcon
 Badge::icon() const
 {
-        return icon_;
+    return icon_;
 }
 
 QSize
 Badge::sizeHint() const
 {
-        const int d = diameter();
-        return QSize(d + 4, d + 4);
+    const int d = diameter();
+    return QSize(d + 4, d + 4);
 }
 
 qreal
 Badge::relativeYPosition() const
 {
-        return y_;
+    return y_;
 }
 
 qreal
 Badge::relativeXPosition() const
 {
-        return x_;
+    return x_;
 }
 
 QPointF
 Badge::relativePosition() const
 {
-        return QPointF(x_, y_);
+    return QPointF(x_, y_);
 }
 
 QColor
 Badge::backgroundColor() const
 {
-        if (!background_color_.isValid())
-                return QColor("black");
+    if (!background_color_.isValid())
+        return QColor("black");
 
-        return background_color_;
+    return background_color_;
 }
 
 QColor
 Badge::textColor() const
 {
-        if (!text_color_.isValid())
-                return QColor("white");
+    if (!text_color_.isValid())
+        return QColor("white");
 
-        return text_color_;
+    return text_color_;
 }
 
 void
 Badge::setTextColor(const QColor &color)
 {
-        text_color_ = color;
+    text_color_ = color;
 }
 
 void
 Badge::setBackgroundColor(const QColor &color)
 {
-        background_color_ = color;
+    background_color_ = color;
 }
 
 void
 Badge::setRelativePosition(const QPointF &pos)
 {
-        setRelativePosition(pos.x(), pos.y());
+    setRelativePosition(pos.x(), pos.y());
 }
 
 void
 Badge::setRelativePosition(qreal x, qreal y)
 {
-        x_ = x;
-        y_ = y;
-        update();
+    x_ = x;
+    y_ = y;
+    update();
 }
 
 void
 Badge::setRelativeXPosition(qreal x)
 {
-        x_ = x;
-        update();
+    x_ = x;
+    update();
 }
 
 void
 Badge::setRelativeYPosition(qreal y)
 {
-        y_ = y;
-        update();
+    y_ = y;
+    update();
 }
 
 void
 Badge::setIcon(const QIcon &icon)
 {
-        icon_ = icon;
-        update();
+    icon_ = icon;
+    update();
 }
 
 void
 Badge::setText(const QString &text)
 {
-        text_ = text;
+    text_ = text;
 
-        if (!icon_.isNull())
-                icon_ = QIcon();
+    if (!icon_.isNull())
+        icon_ = QIcon();
 
-        size_ = fontMetrics().size(Qt::TextShowMnemonic, text);
+    size_ = fontMetrics().size(Qt::TextShowMnemonic, text);
 
-        update();
+    update();
 }
 
 void
 Badge::setDiameter(int diameter)
 {
-        if (diameter > 0) {
-                diameter_ = diameter;
-                update();
-        }
+    if (diameter > 0) {
+        diameter_ = diameter;
+        update();
+    }
 }
 
 void
 Badge::paintEvent(QPaintEvent *)
 {
-        QPainter painter(this);
-        painter.setRenderHint(QPainter::Antialiasing);
-        painter.translate(x_, y_);
+    QPainter painter(this);
+    painter.setRenderHint(QPainter::Antialiasing);
+    painter.translate(x_, y_);
 
-        QBrush brush;
-        brush.setStyle(Qt::SolidPattern);
+    QBrush brush;
+    brush.setStyle(Qt::SolidPattern);
 
-        painter.setBrush(brush);
-        painter.setPen(Qt::NoPen);
+    painter.setBrush(brush);
+    painter.setPen(Qt::NoPen);
 
-        const int d = diameter();
+    const int d = diameter();
 
-        QRectF r(0, 0, d, d);
-        r.translate(QPointF((width() - d), (height() - d)) / 2);
+    QRectF r(0, 0, d, d);
+    r.translate(QPointF((width() - d), (height() - d)) / 2);
 
-        if (icon_.isNull()) {
-                QPen pen;
-                // TODO: Make badge width configurable.
-                pen.setWidth(1);
-                pen.setColor(textColor());
+    if (icon_.isNull()) {
+        QPen pen;
+        // TODO: Make badge width configurable.
+        pen.setWidth(1);
+        pen.setColor(textColor());
 
-                painter.setPen(pen);
-                painter.drawEllipse(r);
+        painter.setPen(pen);
+        painter.drawEllipse(r);
 
-                painter.setPen(textColor());
-                painter.setBrush(Qt::NoBrush);
-                painter.drawText(r.translated(0, -0.5), Qt::AlignCenter, text_);
-        } else {
-                painter.drawEllipse(r);
-                QRectF q(0, 0, 16, 16);
-                q.moveCenter(r.center());
-                QPixmap pixmap = icon().pixmap(16, 16);
-                QPainter icon(&pixmap);
-                icon.setCompositionMode(QPainter::CompositionMode_SourceIn);
-                icon.fillRect(pixmap.rect(), textColor());
-                painter.drawPixmap(q.toRect(), pixmap);
-        }
+        painter.setPen(textColor());
+        painter.setBrush(Qt::NoBrush);
+        painter.drawText(r.translated(0, -0.5), Qt::AlignCenter, text_);
+    } else {
+        painter.drawEllipse(r);
+        QRectF q(0, 0, 16, 16);
+        q.moveCenter(r.center());
+        QPixmap pixmap = icon().pixmap(16, 16);
+        QPainter icon(&pixmap);
+        icon.setCompositionMode(QPainter::CompositionMode_SourceIn);
+        icon.fillRect(pixmap.rect(), textColor());
+        painter.drawPixmap(q.toRect(), pixmap);
+    }
 }
 
 int
 Badge::diameter() const
 {
-        if (icon_.isNull()) {
-                return qMax(size_.width(), size_.height()) + padding_;
-        }
+    if (icon_.isNull()) {
+        return qMax(size_.width(), size_.height()) + padding_;
+    }
 
-        return diameter_;
+    return diameter_;
 }
diff --git a/src/ui/Badge.h b/src/ui/Badge.h
index 98e16873..15b69b58 100644
--- a/src/ui/Badge.h
+++ b/src/ui/Badge.h
@@ -13,54 +13,54 @@
 
 class Badge : public OverlayWidget
 {
-        Q_OBJECT
+    Q_OBJECT
 
-        Q_PROPERTY(QColor textColor WRITE setTextColor READ textColor)
-        Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor)
-        Q_PROPERTY(QPointF relativePosition WRITE setRelativePosition READ relativePosition)
+    Q_PROPERTY(QColor textColor WRITE setTextColor READ textColor)
+    Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor)
+    Q_PROPERTY(QPointF relativePosition WRITE setRelativePosition READ relativePosition)
 
 public:
-        explicit Badge(QWidget *parent = nullptr);
-        explicit Badge(const QIcon &icon, QWidget *parent = nullptr);
-        explicit Badge(const QString &text, QWidget *parent = nullptr);
+    explicit Badge(QWidget *parent = nullptr);
+    explicit Badge(const QIcon &icon, QWidget *parent = nullptr);
+    explicit Badge(const QString &text, QWidget *parent = nullptr);
 
-        void setBackgroundColor(const QColor &color);
-        void setTextColor(const QColor &color);
-        void setIcon(const QIcon &icon);
-        void setRelativePosition(const QPointF &pos);
-        void setRelativePosition(qreal x, qreal y);
-        void setRelativeXPosition(qreal x);
-        void setRelativeYPosition(qreal y);
-        void setText(const QString &text);
-        void setDiameter(int diameter);
+    void setBackgroundColor(const QColor &color);
+    void setTextColor(const QColor &color);
+    void setIcon(const QIcon &icon);
+    void setRelativePosition(const QPointF &pos);
+    void setRelativePosition(qreal x, qreal y);
+    void setRelativeXPosition(qreal x);
+    void setRelativeYPosition(qreal y);
+    void setText(const QString &text);
+    void setDiameter(int diameter);
 
-        QIcon icon() const;
-        QString text() const;
-        QColor backgroundColor() const;
-        QColor textColor() const;
-        QPointF relativePosition() const;
-        QSize sizeHint() const override;
-        qreal relativeXPosition() const;
-        qreal relativeYPosition() const;
+    QIcon icon() const;
+    QString text() const;
+    QColor backgroundColor() const;
+    QColor textColor() const;
+    QPointF relativePosition() const;
+    QSize sizeHint() const override;
+    qreal relativeXPosition() const;
+    qreal relativeYPosition() const;
 
-        int diameter() const;
+    int diameter() const;
 
 protected:
-        void paintEvent(QPaintEvent *event) override;
+    void paintEvent(QPaintEvent *event) override;
 
 private:
-        void init();
+    void init();
 
-        QColor background_color_;
-        QColor text_color_;
+    QColor background_color_;
+    QColor text_color_;
 
-        QIcon icon_;
-        QSize size_;
-        QString text_;
+    QIcon icon_;
+    QSize size_;
+    QString text_;
 
-        int padding_;
-        int diameter_;
+    int padding_;
+    int diameter_;
 
-        qreal x_;
-        qreal y_;
+    qreal x_;
+    qreal y_;
 };
diff --git a/src/ui/DropShadow.cpp b/src/ui/DropShadow.cpp
index a413e3f7..31d13b93 100644
--- a/src/ui/DropShadow.cpp
+++ b/src/ui/DropShadow.cpp
@@ -19,94 +19,89 @@ DropShadow::draw(QPainter &painter,
                  qreal width,
                  qreal height)
 {
-        painter.setPen(Qt::NoPen);
+    painter.setPen(Qt::NoPen);
 
-        QLinearGradient gradient;
-        gradient.setColorAt(startPosition, start);
-        gradient.setColorAt(endPosition0, end);
+    QLinearGradient gradient;
+    gradient.setColorAt(startPosition, start);
+    gradient.setColorAt(endPosition0, end);
 
-        // Right
-        QPointF right0(width - margin, height / 2);
-        QPointF right1(width, height / 2);
-        gradient.setStart(right0);
-        gradient.setFinalStop(right1);
-        painter.setBrush(QBrush(gradient));
-        // Deprecated in 5.13: painter.drawRoundRect(
-        //  QRectF(QPointF(width - margin * radius, margin), QPointF(width, height -
-        //  margin)), 0.0, 0.0);
-        painter.drawRoundedRect(
-          QRectF(QPointF(width - margin * radius, margin), QPointF(width, height - margin)),
-          0.0,
-          0.0);
+    // Right
+    QPointF right0(width - margin, height / 2);
+    QPointF right1(width, height / 2);
+    gradient.setStart(right0);
+    gradient.setFinalStop(right1);
+    painter.setBrush(QBrush(gradient));
+    // Deprecated in 5.13: painter.drawRoundRect(
+    //  QRectF(QPointF(width - margin * radius, margin), QPointF(width, height -
+    //  margin)), 0.0, 0.0);
+    painter.drawRoundedRect(
+      QRectF(QPointF(width - margin * radius, margin), QPointF(width, height - margin)), 0.0, 0.0);
 
-        // Left
-        QPointF left0(margin, height / 2);
-        QPointF left1(0, height / 2);
-        gradient.setStart(left0);
-        gradient.setFinalStop(left1);
-        painter.setBrush(QBrush(gradient));
-        painter.drawRoundedRect(
-          QRectF(QPointF(margin * radius, margin), QPointF(0, height - margin)), 0.0, 0.0);
+    // Left
+    QPointF left0(margin, height / 2);
+    QPointF left1(0, height / 2);
+    gradient.setStart(left0);
+    gradient.setFinalStop(left1);
+    painter.setBrush(QBrush(gradient));
+    painter.drawRoundedRect(
+      QRectF(QPointF(margin * radius, margin), QPointF(0, height - margin)), 0.0, 0.0);
 
-        // Top
-        QPointF top0(width / 2, margin);
-        QPointF top1(width / 2, 0);
-        gradient.setStart(top0);
-        gradient.setFinalStop(top1);
-        painter.setBrush(QBrush(gradient));
-        painter.drawRoundedRect(
-          QRectF(QPointF(width - margin, 0), QPointF(margin, margin)), 0.0, 0.0);
+    // Top
+    QPointF top0(width / 2, margin);
+    QPointF top1(width / 2, 0);
+    gradient.setStart(top0);
+    gradient.setFinalStop(top1);
+    painter.setBrush(QBrush(gradient));
+    painter.drawRoundedRect(QRectF(QPointF(width - margin, 0), QPointF(margin, margin)), 0.0, 0.0);
 
-        // Bottom
-        QPointF bottom0(width / 2, height - margin);
-        QPointF bottom1(width / 2, height);
-        gradient.setStart(bottom0);
-        gradient.setFinalStop(bottom1);
-        painter.setBrush(QBrush(gradient));
-        painter.drawRoundedRect(
-          QRectF(QPointF(margin, height - margin), QPointF(width - margin, height)), 0.0, 0.0);
+    // Bottom
+    QPointF bottom0(width / 2, height - margin);
+    QPointF bottom1(width / 2, height);
+    gradient.setStart(bottom0);
+    gradient.setFinalStop(bottom1);
+    painter.setBrush(QBrush(gradient));
+    painter.drawRoundedRect(
+      QRectF(QPointF(margin, height - margin), QPointF(width - margin, height)), 0.0, 0.0);
 
-        // BottomRight
-        QPointF bottomright0(width - margin, height - margin);
-        QPointF bottomright1(width, height);
-        gradient.setStart(bottomright0);
-        gradient.setFinalStop(bottomright1);
-        gradient.setColorAt(endPosition1, end);
-        painter.setBrush(QBrush(gradient));
-        painter.drawRoundedRect(QRectF(bottomright0, bottomright1), 0.0, 0.0);
+    // BottomRight
+    QPointF bottomright0(width - margin, height - margin);
+    QPointF bottomright1(width, height);
+    gradient.setStart(bottomright0);
+    gradient.setFinalStop(bottomright1);
+    gradient.setColorAt(endPosition1, end);
+    painter.setBrush(QBrush(gradient));
+    painter.drawRoundedRect(QRectF(bottomright0, bottomright1), 0.0, 0.0);
 
-        // BottomLeft
-        QPointF bottomleft0(margin, height - margin);
-        QPointF bottomleft1(0, height);
-        gradient.setStart(bottomleft0);
-        gradient.setFinalStop(bottomleft1);
-        gradient.setColorAt(endPosition1, end);
-        painter.setBrush(QBrush(gradient));
-        painter.drawRoundedRect(QRectF(bottomleft0, bottomleft1), 0.0, 0.0);
+    // BottomLeft
+    QPointF bottomleft0(margin, height - margin);
+    QPointF bottomleft1(0, height);
+    gradient.setStart(bottomleft0);
+    gradient.setFinalStop(bottomleft1);
+    gradient.setColorAt(endPosition1, end);
+    painter.setBrush(QBrush(gradient));
+    painter.drawRoundedRect(QRectF(bottomleft0, bottomleft1), 0.0, 0.0);
 
-        // TopLeft
-        QPointF topleft0(margin, margin);
-        QPointF topleft1(0, 0);
-        gradient.setStart(topleft0);
-        gradient.setFinalStop(topleft1);
-        gradient.setColorAt(endPosition1, end);
-        painter.setBrush(QBrush(gradient));
-        painter.drawRoundedRect(QRectF(topleft0, topleft1), 0.0, 0.0);
+    // TopLeft
+    QPointF topleft0(margin, margin);
+    QPointF topleft1(0, 0);
+    gradient.setStart(topleft0);
+    gradient.setFinalStop(topleft1);
+    gradient.setColorAt(endPosition1, end);
+    painter.setBrush(QBrush(gradient));
+    painter.drawRoundedRect(QRectF(topleft0, topleft1), 0.0, 0.0);
 
-        // TopRight
-        QPointF topright0(width - margin, margin);
-        QPointF topright1(width, 0);
-        gradient.setStart(topright0);
-        gradient.setFinalStop(topright1);
-        gradient.setColorAt(endPosition1, end);
-        painter.setBrush(QBrush(gradient));
-        painter.drawRoundedRect(QRectF(topright0, topright1), 0.0, 0.0);
+    // TopRight
+    QPointF topright0(width - margin, margin);
+    QPointF topright1(width, 0);
+    gradient.setStart(topright0);
+    gradient.setFinalStop(topright1);
+    gradient.setColorAt(endPosition1, end);
+    painter.setBrush(QBrush(gradient));
+    painter.drawRoundedRect(QRectF(topright0, topright1), 0.0, 0.0);
 
-        // Widget
-        painter.setBrush(QBrush("#FFFFFF"));
-        painter.setRenderHint(QPainter::Antialiasing);
-        painter.drawRoundedRect(
-          QRectF(QPointF(margin, margin), QPointF(width - margin, height - margin)),
-          radius,
-          radius);
+    // Widget
+    painter.setBrush(QBrush("#FFFFFF"));
+    painter.setRenderHint(QPainter::Antialiasing);
+    painter.drawRoundedRect(
+      QRectF(QPointF(margin, margin), QPointF(width - margin, height - margin)), radius, radius);
 }
diff --git a/src/ui/DropShadow.h b/src/ui/DropShadow.h
index 4ace4731..f089d0b3 100644
--- a/src/ui/DropShadow.h
+++ b/src/ui/DropShadow.h
@@ -11,14 +11,14 @@ class QPainter;
 class DropShadow
 {
 public:
-        static void draw(QPainter &painter,
-                         qint16 margin,
-                         qreal radius,
-                         QColor start,
-                         QColor end,
-                         qreal startPosition,
-                         qreal endPosition0,
-                         qreal endPosition1,
-                         qreal width,
-                         qreal height);
+    static void draw(QPainter &painter,
+                     qint16 margin,
+                     qreal radius,
+                     QColor start,
+                     QColor end,
+                     qreal startPosition,
+                     qreal endPosition0,
+                     qreal endPosition1,
+                     qreal width,
+                     qreal height);
 };
diff --git a/src/ui/FlatButton.cpp b/src/ui/FlatButton.cpp
index c036401b..4d19c8bb 100644
--- a/src/ui/FlatButton.cpp
+++ b/src/ui/FlatButton.cpp
@@ -30,60 +30,60 @@
 static QString
 removeKDEAccelerators(QString text)
 {
-        return text.remove(QChar('&'));
+    return text.remove(QChar('&'));
 }
 
 void
 FlatButton::init()
 {
-        ripple_overlay_          = new RippleOverlay(this);
-        state_machine_           = new FlatButtonStateMachine(this);
-        role_                    = ui::Role::Default;
-        ripple_style_            = ui::RippleStyle::PositionedRipple;
-        icon_placement_          = ui::ButtonIconPlacement::LeftIcon;
-        overlay_style_           = ui::OverlayStyle::GrayOverlay;
-        bg_mode_                 = Qt::TransparentMode;
-        fixed_ripple_radius_     = 64;
-        corner_radius_           = 3;
-        base_opacity_            = 0.13;
-        font_size_               = 10; // 10.5;
-        use_fixed_ripple_radius_ = false;
-
-        setStyle(&ThemeManager::instance());
-        setAttribute(Qt::WA_Hover);
-        setMouseTracking(true);
-        setCursor(QCursor(Qt::PointingHandCursor));
+    ripple_overlay_          = new RippleOverlay(this);
+    state_machine_           = new FlatButtonStateMachine(this);
+    role_                    = ui::Role::Default;
+    ripple_style_            = ui::RippleStyle::PositionedRipple;
+    icon_placement_          = ui::ButtonIconPlacement::LeftIcon;
+    overlay_style_           = ui::OverlayStyle::GrayOverlay;
+    bg_mode_                 = Qt::TransparentMode;
+    fixed_ripple_radius_     = 64;
+    corner_radius_           = 3;
+    base_opacity_            = 0.13;
+    font_size_               = 10; // 10.5;
+    use_fixed_ripple_radius_ = false;
 
-        QPainterPath path;
-        path.addRoundedRect(rect(), corner_radius_, corner_radius_);
+    setStyle(&ThemeManager::instance());
+    setAttribute(Qt::WA_Hover);
+    setMouseTracking(true);
+    setCursor(QCursor(Qt::PointingHandCursor));
+
+    QPainterPath path;
+    path.addRoundedRect(rect(), corner_radius_, corner_radius_);
 
-        ripple_overlay_->setClipPath(path);
-        ripple_overlay_->setClipping(true);
+    ripple_overlay_->setClipPath(path);
+    ripple_overlay_->setClipping(true);
 
-        state_machine_->setupProperties();
-        state_machine_->startAnimations();
+    state_machine_->setupProperties();
+    state_machine_->startAnimations();
 }
 
 FlatButton::FlatButton(QWidget *parent, ui::ButtonPreset preset)
   : QPushButton(parent)
 {
-        init();
-        applyPreset(preset);
+    init();
+    applyPreset(preset);
 }
 
 FlatButton::FlatButton(const QString &text, QWidget *parent, ui::ButtonPreset preset)
   : QPushButton(text, parent)
 {
-        init();
-        applyPreset(preset);
+    init();
+    applyPreset(preset);
 }
 
 FlatButton::FlatButton(const QString &text, ui::Role role, QWidget *parent, ui::ButtonPreset preset)
   : QPushButton(text, parent)
 {
-        init();
-        applyPreset(preset);
-        setRole(role);
+    init();
+    applyPreset(preset);
+    setRole(role);
 }
 
 FlatButton::~FlatButton() {}
@@ -91,406 +91,406 @@ FlatButton::~FlatButton() {}
 void
 FlatButton::applyPreset(ui::ButtonPreset preset)
 {
-        switch (preset) {
-        case ui::ButtonPreset::FlatPreset:
-                setOverlayStyle(ui::OverlayStyle::NoOverlay);
-                break;
-        case ui::ButtonPreset::CheckablePreset:
-                setOverlayStyle(ui::OverlayStyle::NoOverlay);
-                setCheckable(true);
-                break;
-        default:
-                break;
-        }
+    switch (preset) {
+    case ui::ButtonPreset::FlatPreset:
+        setOverlayStyle(ui::OverlayStyle::NoOverlay);
+        break;
+    case ui::ButtonPreset::CheckablePreset:
+        setOverlayStyle(ui::OverlayStyle::NoOverlay);
+        setCheckable(true);
+        break;
+    default:
+        break;
+    }
 }
 
 void
 FlatButton::setRole(ui::Role role)
 {
-        role_ = role;
-        state_machine_->setupProperties();
+    role_ = role;
+    state_machine_->setupProperties();
 }
 
 ui::Role
 FlatButton::role() const
 {
-        return role_;
+    return role_;
 }
 
 void
 FlatButton::setForegroundColor(const QColor &color)
 {
-        foreground_color_ = color;
+    foreground_color_ = color;
 }
 
 QColor
 FlatButton::foregroundColor() const
 {
-        if (!foreground_color_.isValid()) {
-                if (bg_mode_ == Qt::OpaqueMode) {
-                        return ThemeManager::instance().themeColor("BrightWhite");
-                }
-
-                switch (role_) {
-                case ui::Role::Primary:
-                        return ThemeManager::instance().themeColor("Blue");
-                case ui::Role::Secondary:
-                        return ThemeManager::instance().themeColor("Gray");
-                case ui::Role::Default:
-                default:
-                        return ThemeManager::instance().themeColor("Black");
-                }
+    if (!foreground_color_.isValid()) {
+        if (bg_mode_ == Qt::OpaqueMode) {
+            return ThemeManager::instance().themeColor("BrightWhite");
+        }
+
+        switch (role_) {
+        case ui::Role::Primary:
+            return ThemeManager::instance().themeColor("Blue");
+        case ui::Role::Secondary:
+            return ThemeManager::instance().themeColor("Gray");
+        case ui::Role::Default:
+        default:
+            return ThemeManager::instance().themeColor("Black");
         }
+    }
 
-        return foreground_color_;
+    return foreground_color_;
 }
 
 void
 FlatButton::setBackgroundColor(const QColor &color)
 {
-        background_color_ = color;
+    background_color_ = color;
 }
 
 QColor
 FlatButton::backgroundColor() const
 {
-        if (!background_color_.isValid()) {
-                switch (role_) {
-                case ui::Role::Primary:
-                        return ThemeManager::instance().themeColor("Blue");
-                case ui::Role::Secondary:
-                        return ThemeManager::instance().themeColor("Gray");
-                case ui::Role::Default:
-                default:
-                        return ThemeManager::instance().themeColor("Black");
-                }
+    if (!background_color_.isValid()) {
+        switch (role_) {
+        case ui::Role::Primary:
+            return ThemeManager::instance().themeColor("Blue");
+        case ui::Role::Secondary:
+            return ThemeManager::instance().themeColor("Gray");
+        case ui::Role::Default:
+        default:
+            return ThemeManager::instance().themeColor("Black");
         }
+    }
 
-        return background_color_;
+    return background_color_;
 }
 
 void
 FlatButton::setOverlayColor(const QColor &color)
 {
-        overlay_color_ = color;
-        setOverlayStyle(ui::OverlayStyle::TintedOverlay);
+    overlay_color_ = color;
+    setOverlayStyle(ui::OverlayStyle::TintedOverlay);
 }
 
 QColor
 FlatButton::overlayColor() const
 {
-        if (!overlay_color_.isValid()) {
-                return foregroundColor();
-        }
+    if (!overlay_color_.isValid()) {
+        return foregroundColor();
+    }
 
-        return overlay_color_;
+    return overlay_color_;
 }
 
 void
 FlatButton::setDisabledForegroundColor(const QColor &color)
 {
-        disabled_color_ = color;
+    disabled_color_ = color;
 }
 
 QColor
 FlatButton::disabledForegroundColor() const
 {
-        if (!disabled_color_.isValid()) {
-                return ThemeManager::instance().themeColor("FadedWhite");
-        }
+    if (!disabled_color_.isValid()) {
+        return ThemeManager::instance().themeColor("FadedWhite");
+    }
 
-        return disabled_color_;
+    return disabled_color_;
 }
 
 void
 FlatButton::setDisabledBackgroundColor(const QColor &color)
 {
-        disabled_background_color_ = color;
+    disabled_background_color_ = color;
 }
 
 QColor
 FlatButton::disabledBackgroundColor() const
 {
-        if (!disabled_background_color_.isValid()) {
-                return ThemeManager::instance().themeColor("FadedWhite");
-        }
+    if (!disabled_background_color_.isValid()) {
+        return ThemeManager::instance().themeColor("FadedWhite");
+    }
 
-        return disabled_background_color_;
+    return disabled_background_color_;
 }
 
 void
 FlatButton::setFontSize(qreal size)
 {
-        font_size_ = size;
+    font_size_ = size;
 
-        QFont f(font());
-        f.setPointSizeF(size);
-        setFont(f);
+    QFont f(font());
+    f.setPointSizeF(size);
+    setFont(f);
 
-        update();
+    update();
 }
 
 qreal
 FlatButton::fontSize() const
 {
-        return font_size_;
+    return font_size_;
 }
 
 void
 FlatButton::setOverlayStyle(ui::OverlayStyle style)
 {
-        overlay_style_ = style;
-        update();
+    overlay_style_ = style;
+    update();
 }
 
 ui::OverlayStyle
 FlatButton::overlayStyle() const
 {
-        return overlay_style_;
+    return overlay_style_;
 }
 
 void
 FlatButton::setRippleStyle(ui::RippleStyle style)
 {
-        ripple_style_ = style;
+    ripple_style_ = style;
 }
 
 ui::RippleStyle
 FlatButton::rippleStyle() const
 {
-        return ripple_style_;
+    return ripple_style_;
 }
 
 void
 FlatButton::setIconPlacement(ui::ButtonIconPlacement placement)
 {
-        icon_placement_ = placement;
-        update();
+    icon_placement_ = placement;
+    update();
 }
 
 ui::ButtonIconPlacement
 FlatButton::iconPlacement() const
 {
-        return icon_placement_;
+    return icon_placement_;
 }
 
 void
 FlatButton::setCornerRadius(qreal radius)
 {
-        corner_radius_ = radius;
-        updateClipPath();
-        update();
+    corner_radius_ = radius;
+    updateClipPath();
+    update();
 }
 
 qreal
 FlatButton::cornerRadius() const
 {
-        return corner_radius_;
+    return corner_radius_;
 }
 
 void
 FlatButton::setBackgroundMode(Qt::BGMode mode)
 {
-        bg_mode_ = mode;
-        state_machine_->setupProperties();
+    bg_mode_ = mode;
+    state_machine_->setupProperties();
 }
 
 Qt::BGMode
 FlatButton::backgroundMode() const
 {
-        return bg_mode_;
+    return bg_mode_;
 }
 
 void
 FlatButton::setBaseOpacity(qreal opacity)
 {
-        base_opacity_ = opacity;
-        state_machine_->setupProperties();
+    base_opacity_ = opacity;
+    state_machine_->setupProperties();
 }
 
 qreal
 FlatButton::baseOpacity() const
 {
-        return base_opacity_;
+    return base_opacity_;
 }
 
 void
 FlatButton::setCheckable(bool value)
 {
-        state_machine_->updateCheckedStatus();
-        state_machine_->setCheckedOverlayProgress(0);
+    state_machine_->updateCheckedStatus();
+    state_machine_->setCheckedOverlayProgress(0);
 
-        QPushButton::setCheckable(value);
+    QPushButton::setCheckable(value);
 }
 
 void
 FlatButton::setHasFixedRippleRadius(bool value)
 {
-        use_fixed_ripple_radius_ = value;
+    use_fixed_ripple_radius_ = value;
 }
 
 bool
 FlatButton::hasFixedRippleRadius() const
 {
-        return use_fixed_ripple_radius_;
+    return use_fixed_ripple_radius_;
 }
 
 void
 FlatButton::setFixedRippleRadius(qreal radius)
 {
-        fixed_ripple_radius_ = radius;
-        setHasFixedRippleRadius(true);
+    fixed_ripple_radius_ = radius;
+    setHasFixedRippleRadius(true);
 }
 
 QSize
 FlatButton::sizeHint() const
 {
-        ensurePolished();
+    ensurePolished();
 
-        QSize label(fontMetrics().size(Qt::TextSingleLine, removeKDEAccelerators(text())));
+    QSize label(fontMetrics().size(Qt::TextSingleLine, removeKDEAccelerators(text())));
 
-        int w = 20 + label.width();
-        int h = label.height();
+    int w = 20 + label.width();
+    int h = label.height();
 
-        if (!icon().isNull()) {
-                w += iconSize().width() + FlatButton::IconPadding;
-                h = qMax(h, iconSize().height());
-        }
+    if (!icon().isNull()) {
+        w += iconSize().width() + FlatButton::IconPadding;
+        h = qMax(h, iconSize().height());
+    }
 
-        return QSize(w, 20 + h);
+    return QSize(w, 20 + h);
 }
 
 void
 FlatButton::checkStateSet()
 {
-        state_machine_->updateCheckedStatus();
-        QPushButton::checkStateSet();
+    state_machine_->updateCheckedStatus();
+    QPushButton::checkStateSet();
 }
 
 void
 FlatButton::mousePressEvent(QMouseEvent *event)
 {
-        if (ui::RippleStyle::NoRipple != ripple_style_) {
-                QPoint pos;
-                qreal radiusEndValue;
+    if (ui::RippleStyle::NoRipple != ripple_style_) {
+        QPoint pos;
+        qreal radiusEndValue;
 
-                if (ui::RippleStyle::CenteredRipple == ripple_style_) {
-                        pos = rect().center();
-                } else {
-                        pos = event->pos();
-                }
+        if (ui::RippleStyle::CenteredRipple == ripple_style_) {
+            pos = rect().center();
+        } else {
+            pos = event->pos();
+        }
 
-                if (use_fixed_ripple_radius_) {
-                        radiusEndValue = fixed_ripple_radius_;
-                } else {
-                        radiusEndValue = static_cast<qreal>(width()) / 2;
-                }
+        if (use_fixed_ripple_radius_) {
+            radiusEndValue = fixed_ripple_radius_;
+        } else {
+            radiusEndValue = static_cast<qreal>(width()) / 2;
+        }
 
-                Ripple *ripple = new Ripple(pos);
+        Ripple *ripple = new Ripple(pos);
 
-                ripple->setRadiusEndValue(radiusEndValue);
-                ripple->setOpacityStartValue(0.35);
-                ripple->setColor(foregroundColor());
-                ripple->radiusAnimation()->setDuration(250);
-                ripple->opacityAnimation()->setDuration(250);
+        ripple->setRadiusEndValue(radiusEndValue);
+        ripple->setOpacityStartValue(0.35);
+        ripple->setColor(foregroundColor());
+        ripple->radiusAnimation()->setDuration(250);
+        ripple->opacityAnimation()->setDuration(250);
 
-                ripple_overlay_->addRipple(ripple);
-        }
+        ripple_overlay_->addRipple(ripple);
+    }
 
-        QPushButton::mousePressEvent(event);
+    QPushButton::mousePressEvent(event);
 }
 
 void
 FlatButton::mouseReleaseEvent(QMouseEvent *event)
 {
-        QPushButton::mouseReleaseEvent(event);
-        state_machine_->updateCheckedStatus();
+    QPushButton::mouseReleaseEvent(event);
+    state_machine_->updateCheckedStatus();
 }
 
 void
 FlatButton::resizeEvent(QResizeEvent *event)
 {
-        QPushButton::resizeEvent(event);
-        updateClipPath();
+    QPushButton::resizeEvent(event);
+    updateClipPath();
 }
 
 void
 FlatButton::paintEvent(QPaintEvent *event)
 {
-        Q_UNUSED(event)
+    Q_UNUSED(event)
 
-        QPainter painter(this);
-        painter.setRenderHint(QPainter::Antialiasing);
+    QPainter painter(this);
+    painter.setRenderHint(QPainter::Antialiasing);
 
-        const qreal cr = corner_radius_;
+    const qreal cr = corner_radius_;
 
-        if (cr > 0) {
-                QPainterPath path;
-                path.addRoundedRect(rect(), cr, cr);
+    if (cr > 0) {
+        QPainterPath path;
+        path.addRoundedRect(rect(), cr, cr);
 
-                painter.setClipPath(path);
-                painter.setClipping(true);
-        }
+        painter.setClipPath(path);
+        painter.setClipping(true);
+    }
 
-        paintBackground(&painter);
+    paintBackground(&painter);
 
-        painter.setOpacity(1);
-        painter.setClipping(false);
+    painter.setOpacity(1);
+    painter.setClipping(false);
 
-        paintForeground(&painter);
+    paintForeground(&painter);
 }
 
 void
 FlatButton::paintBackground(QPainter *painter)
 {
-        const qreal overlayOpacity  = state_machine_->overlayOpacity();
-        const qreal checkedProgress = state_machine_->checkedOverlayProgress();
+    const qreal overlayOpacity  = state_machine_->overlayOpacity();
+    const qreal checkedProgress = state_machine_->checkedOverlayProgress();
 
-        if (Qt::OpaqueMode == bg_mode_) {
-                QBrush brush;
-                brush.setStyle(Qt::SolidPattern);
-
-                if (isEnabled()) {
-                        brush.setColor(backgroundColor());
-                } else {
-                        brush.setColor(disabledBackgroundColor());
-                }
+    if (Qt::OpaqueMode == bg_mode_) {
+        QBrush brush;
+        brush.setStyle(Qt::SolidPattern);
 
-                painter->setOpacity(1);
-                painter->setBrush(brush);
-                painter->setPen(Qt::NoPen);
-                painter->drawRect(rect());
+        if (isEnabled()) {
+            brush.setColor(backgroundColor());
+        } else {
+            brush.setColor(disabledBackgroundColor());
         }
 
-        QBrush brush;
-        brush.setStyle(Qt::SolidPattern);
+        painter->setOpacity(1);
+        painter->setBrush(brush);
         painter->setPen(Qt::NoPen);
+        painter->drawRect(rect());
+    }
 
-        if (!isEnabled()) {
-                return;
-        }
+    QBrush brush;
+    brush.setStyle(Qt::SolidPattern);
+    painter->setPen(Qt::NoPen);
 
-        if ((ui::OverlayStyle::NoOverlay != overlay_style_) && (overlayOpacity > 0)) {
-                if (ui::OverlayStyle::TintedOverlay == overlay_style_) {
-                        brush.setColor(overlayColor());
-                } else {
-                        brush.setColor(Qt::gray);
-                }
+    if (!isEnabled()) {
+        return;
+    }
 
-                painter->setOpacity(overlayOpacity);
-                painter->setBrush(brush);
-                painter->drawRect(rect());
+    if ((ui::OverlayStyle::NoOverlay != overlay_style_) && (overlayOpacity > 0)) {
+        if (ui::OverlayStyle::TintedOverlay == overlay_style_) {
+            brush.setColor(overlayColor());
+        } else {
+            brush.setColor(Qt::gray);
         }
 
-        if (isCheckable() && checkedProgress > 0) {
-                const qreal q = Qt::TransparentMode == bg_mode_ ? 0.45 : 0.7;
-                brush.setColor(foregroundColor());
-                painter->setOpacity(q * checkedProgress);
-                painter->setBrush(brush);
-                QRect r(rect());
-                r.setHeight(static_cast<qreal>(r.height()) * checkedProgress);
-                painter->drawRect(r);
-        }
+        painter->setOpacity(overlayOpacity);
+        painter->setBrush(brush);
+        painter->drawRect(rect());
+    }
+
+    if (isCheckable() && checkedProgress > 0) {
+        const qreal q = Qt::TransparentMode == bg_mode_ ? 0.45 : 0.7;
+        brush.setColor(foregroundColor());
+        painter->setOpacity(q * checkedProgress);
+        painter->setBrush(brush);
+        QRect r(rect());
+        r.setHeight(static_cast<qreal>(r.height()) * checkedProgress);
+        painter->drawRect(r);
+    }
 }
 
 #define COLOR_INTERPOLATE(CH) (1 - progress) * source.CH() + progress *dest.CH()
@@ -498,64 +498,63 @@ FlatButton::paintBackground(QPainter *painter)
 void
 FlatButton::paintForeground(QPainter *painter)
 {
-        if (isEnabled()) {
-                painter->setPen(foregroundColor());
-                const qreal progress = state_machine_->checkedOverlayProgress();
-
-                if (isCheckable() && progress > 0) {
-                        QColor source = foregroundColor();
-                        QColor dest =
-                          Qt::TransparentMode == bg_mode_ ? Qt::white : backgroundColor();
-                        if (qFuzzyCompare(1, progress)) {
-                                painter->setPen(dest);
-                        } else {
-                                painter->setPen(QColor(COLOR_INTERPOLATE(red),
-                                                       COLOR_INTERPOLATE(green),
-                                                       COLOR_INTERPOLATE(blue),
-                                                       COLOR_INTERPOLATE(alpha)));
-                        }
-                }
-        } else {
-                painter->setPen(disabledForegroundColor());
+    if (isEnabled()) {
+        painter->setPen(foregroundColor());
+        const qreal progress = state_machine_->checkedOverlayProgress();
+
+        if (isCheckable() && progress > 0) {
+            QColor source = foregroundColor();
+            QColor dest   = Qt::TransparentMode == bg_mode_ ? Qt::white : backgroundColor();
+            if (qFuzzyCompare(1, progress)) {
+                painter->setPen(dest);
+            } else {
+                painter->setPen(QColor(COLOR_INTERPOLATE(red),
+                                       COLOR_INTERPOLATE(green),
+                                       COLOR_INTERPOLATE(blue),
+                                       COLOR_INTERPOLATE(alpha)));
+            }
         }
+    } else {
+        painter->setPen(disabledForegroundColor());
+    }
 
-        if (icon().isNull()) {
-                painter->drawText(rect(), Qt::AlignCenter, removeKDEAccelerators(text()));
-                return;
-        }
+    if (icon().isNull()) {
+        painter->drawText(rect(), Qt::AlignCenter, removeKDEAccelerators(text()));
+        return;
+    }
 
-        QSize textSize(fontMetrics().size(Qt::TextSingleLine, removeKDEAccelerators(text())));
-        QSize base(size() - textSize);
+    QSize textSize(fontMetrics().size(Qt::TextSingleLine, removeKDEAccelerators(text())));
+    QSize base(size() - textSize);
 
-        const int iw = iconSize().width() + IconPadding;
-        QPoint pos((base.width() - iw) / 2, 0);
+    const int iw = iconSize().width() + IconPadding;
+    QPoint pos((base.width() - iw) / 2, 0);
 
-        QRect textGeometry(pos + QPoint(0, base.height() / 2), textSize);
-        QRect iconGeometry(pos + QPoint(0, (height() - iconSize().height()) / 2), iconSize());
+    QRect textGeometry(pos + QPoint(0, base.height() / 2), textSize);
+    QRect iconGeometry(pos + QPoint(0, (height() - iconSize().height()) / 2), iconSize());
 
-        /* if (ui::LeftIcon == icon_placement_) { */
-        /* 	textGeometry.translate(iw, 0); */
-        /* } else { */
-        /* 	iconGeometry.translate(textSize.width() + IconPadding, 0); */
-        /* } */
+    /* if (ui::LeftIcon == icon_placement_) { */
+    /* 	textGeometry.translate(iw, 0); */
+    /* } else { */
+    /* 	iconGeometry.translate(textSize.width() + IconPadding, 0); */
+    /* } */
 
-        painter->drawText(textGeometry, Qt::AlignCenter, removeKDEAccelerators(text()));
+    painter->drawText(textGeometry, Qt::AlignCenter, removeKDEAccelerators(text()));
 
-        QPixmap pixmap = icon().pixmap(iconSize());
-        QPainter icon(&pixmap);
-        icon.setCompositionMode(QPainter::CompositionMode_SourceIn);
-        icon.fillRect(pixmap.rect(), painter->pen().color());
-        painter->drawPixmap(iconGeometry, pixmap);
+    QPixmap pixmap = icon().pixmap(iconSize());
+    QPainter icon(&pixmap);
+    icon.setCompositionMode(QPainter::CompositionMode_SourceIn);
+    icon.fillRect(pixmap.rect(), painter->pen().color());
+    painter->drawPixmap(iconGeometry, pixmap);
 }
 
 void
 FlatButton::updateClipPath()
 {
-        const qreal radius = corner_radius_;
+    const qreal radius = corner_radius_;
 
-        QPainterPath path;
-        path.addRoundedRect(rect(), radius, radius);
-        ripple_overlay_->setClipPath(path);
+    QPainterPath path;
+    path.addRoundedRect(rect(), radius, radius);
+    ripple_overlay_->setClipPath(path);
 }
 
 FlatButtonStateMachine::FlatButtonStateMachine(FlatButton *parent)
@@ -575,45 +574,45 @@ FlatButtonStateMachine::FlatButtonStateMachine(FlatButton *parent)
   , checked_overlay_progress_(parent->isChecked() ? 1 : 0)
   , was_checked_(false)
 {
-        Q_ASSERT(parent);
+    Q_ASSERT(parent);
 
-        parent->installEventFilter(this);
+    parent->installEventFilter(this);
 
-        config_state_->setInitialState(neutral_state_);
-        addState(top_level_state_);
-        setInitialState(top_level_state_);
+    config_state_->setInitialState(neutral_state_);
+    addState(top_level_state_);
+    setInitialState(top_level_state_);
 
-        checkable_state_->setInitialState(parent->isChecked() ? checked_state_ : unchecked_state_);
-        QSignalTransition *transition;
-        QPropertyAnimation *animation;
+    checkable_state_->setInitialState(parent->isChecked() ? checked_state_ : unchecked_state_);
+    QSignalTransition *transition;
+    QPropertyAnimation *animation;
 
-        transition = new QSignalTransition(this, SIGNAL(buttonChecked()));
-        transition->setTargetState(checked_state_);
-        unchecked_state_->addTransition(transition);
+    transition = new QSignalTransition(this, SIGNAL(buttonChecked()));
+    transition->setTargetState(checked_state_);
+    unchecked_state_->addTransition(transition);
 
-        animation = new QPropertyAnimation(this, "checkedOverlayProgress", this);
-        animation->setDuration(200);
-        transition->addAnimation(animation);
+    animation = new QPropertyAnimation(this, "checkedOverlayProgress", this);
+    animation->setDuration(200);
+    transition->addAnimation(animation);
 
-        transition = new QSignalTransition(this, SIGNAL(buttonUnchecked()));
-        transition->setTargetState(unchecked_state_);
-        checked_state_->addTransition(transition);
+    transition = new QSignalTransition(this, SIGNAL(buttonUnchecked()));
+    transition->setTargetState(unchecked_state_);
+    checked_state_->addTransition(transition);
 
-        animation = new QPropertyAnimation(this, "checkedOverlayProgress", this);
-        animation->setDuration(200);
-        transition->addAnimation(animation);
+    animation = new QPropertyAnimation(this, "checkedOverlayProgress", this);
+    animation->setDuration(200);
+    transition->addAnimation(animation);
 
-        addTransition(button_, QEvent::FocusIn, neutral_state_, neutral_focused_state_);
-        addTransition(button_, QEvent::FocusOut, neutral_focused_state_, neutral_state_);
-        addTransition(button_, QEvent::Enter, neutral_state_, hovered_state_);
-        addTransition(button_, QEvent::Leave, hovered_state_, neutral_state_);
-        addTransition(button_, QEvent::Enter, neutral_focused_state_, hovered_focused_state_);
-        addTransition(button_, QEvent::Leave, hovered_focused_state_, neutral_focused_state_);
-        addTransition(button_, QEvent::FocusIn, hovered_state_, hovered_focused_state_);
-        addTransition(button_, QEvent::FocusOut, hovered_focused_state_, hovered_state_);
-        addTransition(this, SIGNAL(buttonPressed()), hovered_state_, pressed_state_);
-        addTransition(button_, QEvent::Leave, pressed_state_, neutral_focused_state_);
-        addTransition(button_, QEvent::FocusOut, pressed_state_, hovered_state_);
+    addTransition(button_, QEvent::FocusIn, neutral_state_, neutral_focused_state_);
+    addTransition(button_, QEvent::FocusOut, neutral_focused_state_, neutral_state_);
+    addTransition(button_, QEvent::Enter, neutral_state_, hovered_state_);
+    addTransition(button_, QEvent::Leave, hovered_state_, neutral_state_);
+    addTransition(button_, QEvent::Enter, neutral_focused_state_, hovered_focused_state_);
+    addTransition(button_, QEvent::Leave, hovered_focused_state_, neutral_focused_state_);
+    addTransition(button_, QEvent::FocusIn, hovered_state_, hovered_focused_state_);
+    addTransition(button_, QEvent::FocusOut, hovered_focused_state_, hovered_state_);
+    addTransition(this, SIGNAL(buttonPressed()), hovered_state_, pressed_state_);
+    addTransition(button_, QEvent::Leave, pressed_state_, neutral_focused_state_);
+    addTransition(button_, QEvent::FocusOut, pressed_state_, hovered_state_);
 }
 
 FlatButtonStateMachine::~FlatButtonStateMachine() {}
@@ -621,73 +620,73 @@ FlatButtonStateMachine::~FlatButtonStateMachine() {}
 void
 FlatButtonStateMachine::setOverlayOpacity(qreal opacity)
 {
-        overlay_opacity_ = opacity;
-        button_->update();
+    overlay_opacity_ = opacity;
+    button_->update();
 }
 
 void
 FlatButtonStateMachine::setCheckedOverlayProgress(qreal opacity)
 {
-        checked_overlay_progress_ = opacity;
-        button_->update();
+    checked_overlay_progress_ = opacity;
+    button_->update();
 }
 
 void
 FlatButtonStateMachine::startAnimations()
 {
-        start();
+    start();
 }
 
 void
 FlatButtonStateMachine::setupProperties()
 {
-        QColor overlayColor;
+    QColor overlayColor;
 
-        if (Qt::TransparentMode == button_->backgroundMode()) {
-                overlayColor = button_->backgroundColor();
-        } else {
-                overlayColor = button_->foregroundColor();
-        }
+    if (Qt::TransparentMode == button_->backgroundMode()) {
+        overlayColor = button_->backgroundColor();
+    } else {
+        overlayColor = button_->foregroundColor();
+    }
 
-        const qreal baseOpacity = button_->baseOpacity();
+    const qreal baseOpacity = button_->baseOpacity();
 
-        neutral_state_->assignProperty(this, "overlayOpacity", 0);
-        neutral_focused_state_->assignProperty(this, "overlayOpacity", 0);
-        hovered_state_->assignProperty(this, "overlayOpacity", baseOpacity);
-        hovered_focused_state_->assignProperty(this, "overlayOpacity", baseOpacity);
-        pressed_state_->assignProperty(this, "overlayOpacity", baseOpacity);
-        checked_state_->assignProperty(this, "checkedOverlayProgress", 1);
-        unchecked_state_->assignProperty(this, "checkedOverlayProgress", 0);
+    neutral_state_->assignProperty(this, "overlayOpacity", 0);
+    neutral_focused_state_->assignProperty(this, "overlayOpacity", 0);
+    hovered_state_->assignProperty(this, "overlayOpacity", baseOpacity);
+    hovered_focused_state_->assignProperty(this, "overlayOpacity", baseOpacity);
+    pressed_state_->assignProperty(this, "overlayOpacity", baseOpacity);
+    checked_state_->assignProperty(this, "checkedOverlayProgress", 1);
+    unchecked_state_->assignProperty(this, "checkedOverlayProgress", 0);
 
-        button_->update();
+    button_->update();
 }
 
 void
 FlatButtonStateMachine::updateCheckedStatus()
 {
-        const bool checked = button_->isChecked();
-        if (was_checked_ != checked) {
-                was_checked_ = checked;
-                if (checked) {
-                        emit buttonChecked();
-                } else {
-                        emit buttonUnchecked();
-                }
+    const bool checked = button_->isChecked();
+    if (was_checked_ != checked) {
+        was_checked_ = checked;
+        if (checked) {
+            emit buttonChecked();
+        } else {
+            emit buttonUnchecked();
         }
+    }
 }
 
 bool
 FlatButtonStateMachine::eventFilter(QObject *watched, QEvent *event)
 {
-        if (QEvent::FocusIn == event->type()) {
-                QFocusEvent *focusEvent = static_cast<QFocusEvent *>(event);
-                if (focusEvent && Qt::MouseFocusReason == focusEvent->reason()) {
-                        emit buttonPressed();
-                        return true;
-                }
+    if (QEvent::FocusIn == event->type()) {
+        QFocusEvent *focusEvent = static_cast<QFocusEvent *>(event);
+        if (focusEvent && Qt::MouseFocusReason == focusEvent->reason()) {
+            emit buttonPressed();
+            return true;
         }
+    }
 
-        return QStateMachine::eventFilter(watched, event);
+    return QStateMachine::eventFilter(watched, event);
 }
 
 void
@@ -696,7 +695,7 @@ FlatButtonStateMachine::addTransition(QObject *object,
                                       QState *fromState,
                                       QState *toState)
 {
-        addTransition(new QSignalTransition(object, signal), fromState, toState);
+    addTransition(new QSignalTransition(object, signal), fromState, toState);
 }
 
 void
@@ -705,7 +704,7 @@ FlatButtonStateMachine::addTransition(QObject *object,
                                       QState *fromState,
                                       QState *toState)
 {
-        addTransition(new QEventTransition(object, eventType), fromState, toState);
+    addTransition(new QEventTransition(object, eventType), fromState, toState);
 }
 
 void
@@ -713,13 +712,13 @@ FlatButtonStateMachine::addTransition(QAbstractTransition *transition,
                                       QState *fromState,
                                       QState *toState)
 {
-        transition->setTargetState(toState);
+    transition->setTargetState(toState);
 
-        QPropertyAnimation *animation;
+    QPropertyAnimation *animation;
 
-        animation = new QPropertyAnimation(this, "overlayOpacity", this);
-        animation->setDuration(150);
-        transition->addAnimation(animation);
+    animation = new QPropertyAnimation(this, "overlayOpacity", this);
+    animation->setDuration(150);
+    transition->addAnimation(animation);
 
-        fromState->addTransition(transition);
+    fromState->addTransition(transition);
 }
diff --git a/src/ui/FlatButton.h b/src/ui/FlatButton.h
index c79945b7..b39c94ac 100644
--- a/src/ui/FlatButton.h
+++ b/src/ui/FlatButton.h
@@ -14,174 +14,171 @@ class FlatButton;
 
 class FlatButtonStateMachine : public QStateMachine
 {
-        Q_OBJECT
+    Q_OBJECT
 
-        Q_PROPERTY(qreal overlayOpacity WRITE setOverlayOpacity READ overlayOpacity)
-        Q_PROPERTY(
-          qreal checkedOverlayProgress WRITE setCheckedOverlayProgress READ checkedOverlayProgress)
+    Q_PROPERTY(qreal overlayOpacity WRITE setOverlayOpacity READ overlayOpacity)
+    Q_PROPERTY(
+      qreal checkedOverlayProgress WRITE setCheckedOverlayProgress READ checkedOverlayProgress)
 
 public:
-        explicit FlatButtonStateMachine(FlatButton *parent);
-        ~FlatButtonStateMachine() override;
+    explicit FlatButtonStateMachine(FlatButton *parent);
+    ~FlatButtonStateMachine() override;
 
-        void setOverlayOpacity(qreal opacity);
-        void setCheckedOverlayProgress(qreal opacity);
+    void setOverlayOpacity(qreal opacity);
+    void setCheckedOverlayProgress(qreal opacity);
 
-        inline qreal overlayOpacity() const;
-        inline qreal checkedOverlayProgress() const;
+    inline qreal overlayOpacity() const;
+    inline qreal checkedOverlayProgress() const;
 
-        void startAnimations();
-        void setupProperties();
-        void updateCheckedStatus();
+    void startAnimations();
+    void setupProperties();
+    void updateCheckedStatus();
 
 signals:
-        void buttonPressed();
-        void buttonChecked();
-        void buttonUnchecked();
+    void buttonPressed();
+    void buttonChecked();
+    void buttonUnchecked();
 
 protected:
-        bool eventFilter(QObject *watched, QEvent *event) override;
+    bool eventFilter(QObject *watched, QEvent *event) override;
 
 private:
-        void addTransition(QObject *object, const char *signal, QState *fromState, QState *toState);
-        void addTransition(QObject *object,
-                           QEvent::Type eventType,
-                           QState *fromState,
-                           QState *toState);
-        void addTransition(QAbstractTransition *transition, QState *fromState, QState *toState);
-
-        FlatButton *const button_;
-
-        QState *const top_level_state_;
-        QState *const config_state_;
-        QState *const checkable_state_;
-        QState *const checked_state_;
-        QState *const unchecked_state_;
-        QState *const neutral_state_;
-        QState *const neutral_focused_state_;
-        QState *const hovered_state_;
-        QState *const hovered_focused_state_;
-        QState *const pressed_state_;
-
-        qreal overlay_opacity_;
-        qreal checked_overlay_progress_;
-
-        bool was_checked_;
+    void addTransition(QObject *object, const char *signal, QState *fromState, QState *toState);
+    void addTransition(QObject *object, QEvent::Type eventType, QState *fromState, QState *toState);
+    void addTransition(QAbstractTransition *transition, QState *fromState, QState *toState);
+
+    FlatButton *const button_;
+
+    QState *const top_level_state_;
+    QState *const config_state_;
+    QState *const checkable_state_;
+    QState *const checked_state_;
+    QState *const unchecked_state_;
+    QState *const neutral_state_;
+    QState *const neutral_focused_state_;
+    QState *const hovered_state_;
+    QState *const hovered_focused_state_;
+    QState *const pressed_state_;
+
+    qreal overlay_opacity_;
+    qreal checked_overlay_progress_;
+
+    bool was_checked_;
 };
 
 inline qreal
 FlatButtonStateMachine::overlayOpacity() const
 {
-        return overlay_opacity_;
+    return overlay_opacity_;
 }
 
 inline qreal
 FlatButtonStateMachine::checkedOverlayProgress() const
 {
-        return checked_overlay_progress_;
+    return checked_overlay_progress_;
 }
 
 class FlatButton : public QPushButton
 {
-        Q_OBJECT
+    Q_OBJECT
 
-        Q_PROPERTY(QColor foregroundColor WRITE setForegroundColor READ foregroundColor)
-        Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor)
-        Q_PROPERTY(QColor overlayColor WRITE setOverlayColor READ overlayColor)
-        Q_PROPERTY(QColor disabledForegroundColor WRITE setDisabledForegroundColor READ
-                     disabledForegroundColor)
-        Q_PROPERTY(QColor disabledBackgroundColor WRITE setDisabledBackgroundColor READ
-                     disabledBackgroundColor)
-        Q_PROPERTY(qreal fontSize WRITE setFontSize READ fontSize)
+    Q_PROPERTY(QColor foregroundColor WRITE setForegroundColor READ foregroundColor)
+    Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor)
+    Q_PROPERTY(QColor overlayColor WRITE setOverlayColor READ overlayColor)
+    Q_PROPERTY(
+      QColor disabledForegroundColor WRITE setDisabledForegroundColor READ disabledForegroundColor)
+    Q_PROPERTY(
+      QColor disabledBackgroundColor WRITE setDisabledBackgroundColor READ disabledBackgroundColor)
+    Q_PROPERTY(qreal fontSize WRITE setFontSize READ fontSize)
 
 public:
-        explicit FlatButton(QWidget *parent         = nullptr,
-                            ui::ButtonPreset preset = ui::ButtonPreset::FlatPreset);
-        explicit FlatButton(const QString &text,
-                            QWidget *parent         = nullptr,
-                            ui::ButtonPreset preset = ui::ButtonPreset::FlatPreset);
-        FlatButton(const QString &text,
-                   ui::Role role,
-                   QWidget *parent         = nullptr,
-                   ui::ButtonPreset preset = ui::ButtonPreset::FlatPreset);
-        ~FlatButton() override;
-
-        void applyPreset(ui::ButtonPreset preset);
-
-        void setBackgroundColor(const QColor &color);
-        void setBackgroundMode(Qt::BGMode mode);
-        void setBaseOpacity(qreal opacity);
-        void setCheckable(bool value);
-        void setCornerRadius(qreal radius);
-        void setDisabledBackgroundColor(const QColor &color);
-        void setDisabledForegroundColor(const QColor &color);
-        void setFixedRippleRadius(qreal radius);
-        void setFontSize(qreal size);
-        void setForegroundColor(const QColor &color);
-        void setHasFixedRippleRadius(bool value);
-        void setIconPlacement(ui::ButtonIconPlacement placement);
-        void setOverlayColor(const QColor &color);
-        void setOverlayStyle(ui::OverlayStyle style);
-        void setRippleStyle(ui::RippleStyle style);
-        void setRole(ui::Role role);
-
-        QColor foregroundColor() const;
-        QColor backgroundColor() const;
-        QColor overlayColor() const;
-        QColor disabledForegroundColor() const;
-        QColor disabledBackgroundColor() const;
-
-        qreal fontSize() const;
-        qreal cornerRadius() const;
-        qreal baseOpacity() const;
-
-        bool hasFixedRippleRadius() const;
-
-        ui::Role role() const;
-        ui::OverlayStyle overlayStyle() const;
-        ui::RippleStyle rippleStyle() const;
-        ui::ButtonIconPlacement iconPlacement() const;
-
-        Qt::BGMode backgroundMode() const;
-
-        QSize sizeHint() const override;
+    explicit FlatButton(QWidget *parent         = nullptr,
+                        ui::ButtonPreset preset = ui::ButtonPreset::FlatPreset);
+    explicit FlatButton(const QString &text,
+                        QWidget *parent         = nullptr,
+                        ui::ButtonPreset preset = ui::ButtonPreset::FlatPreset);
+    FlatButton(const QString &text,
+               ui::Role role,
+               QWidget *parent         = nullptr,
+               ui::ButtonPreset preset = ui::ButtonPreset::FlatPreset);
+    ~FlatButton() override;
+
+    void applyPreset(ui::ButtonPreset preset);
+
+    void setBackgroundColor(const QColor &color);
+    void setBackgroundMode(Qt::BGMode mode);
+    void setBaseOpacity(qreal opacity);
+    void setCheckable(bool value);
+    void setCornerRadius(qreal radius);
+    void setDisabledBackgroundColor(const QColor &color);
+    void setDisabledForegroundColor(const QColor &color);
+    void setFixedRippleRadius(qreal radius);
+    void setFontSize(qreal size);
+    void setForegroundColor(const QColor &color);
+    void setHasFixedRippleRadius(bool value);
+    void setIconPlacement(ui::ButtonIconPlacement placement);
+    void setOverlayColor(const QColor &color);
+    void setOverlayStyle(ui::OverlayStyle style);
+    void setRippleStyle(ui::RippleStyle style);
+    void setRole(ui::Role role);
+
+    QColor foregroundColor() const;
+    QColor backgroundColor() const;
+    QColor overlayColor() const;
+    QColor disabledForegroundColor() const;
+    QColor disabledBackgroundColor() const;
+
+    qreal fontSize() const;
+    qreal cornerRadius() const;
+    qreal baseOpacity() const;
+
+    bool hasFixedRippleRadius() const;
+
+    ui::Role role() const;
+    ui::OverlayStyle overlayStyle() const;
+    ui::RippleStyle rippleStyle() const;
+    ui::ButtonIconPlacement iconPlacement() const;
+
+    Qt::BGMode backgroundMode() const;
+
+    QSize sizeHint() const override;
 
 protected:
-        int IconPadding = 0;
+    int IconPadding = 0;
 
-        void checkStateSet() override;
-        void mousePressEvent(QMouseEvent *event) override;
-        void mouseReleaseEvent(QMouseEvent *event) override;
-        void resizeEvent(QResizeEvent *event) override;
-        void paintEvent(QPaintEvent *event) override;
+    void checkStateSet() override;
+    void mousePressEvent(QMouseEvent *event) override;
+    void mouseReleaseEvent(QMouseEvent *event) override;
+    void resizeEvent(QResizeEvent *event) override;
+    void paintEvent(QPaintEvent *event) override;
 
-        virtual void paintBackground(QPainter *painter);
-        virtual void paintForeground(QPainter *painter);
-        virtual void updateClipPath();
+    virtual void paintBackground(QPainter *painter);
+    virtual void paintForeground(QPainter *painter);
+    virtual void updateClipPath();
 
-        void init();
+    void init();
 
 private:
-        RippleOverlay *ripple_overlay_;
-        FlatButtonStateMachine *state_machine_;
+    RippleOverlay *ripple_overlay_;
+    FlatButtonStateMachine *state_machine_;
 
-        ui::Role role_;
-        ui::RippleStyle ripple_style_;
-        ui::ButtonIconPlacement icon_placement_;
-        ui::OverlayStyle overlay_style_;
+    ui::Role role_;
+    ui::RippleStyle ripple_style_;
+    ui::ButtonIconPlacement icon_placement_;
+    ui::OverlayStyle overlay_style_;
 
-        Qt::BGMode bg_mode_;
+    Qt::BGMode bg_mode_;
 
-        QColor background_color_;
-        QColor foreground_color_;
-        QColor overlay_color_;
-        QColor disabled_color_;
-        QColor disabled_background_color_;
+    QColor background_color_;
+    QColor foreground_color_;
+    QColor overlay_color_;
+    QColor disabled_color_;
+    QColor disabled_background_color_;
 
-        qreal fixed_ripple_radius_;
-        qreal corner_radius_;
-        qreal base_opacity_;
-        qreal font_size_;
+    qreal fixed_ripple_radius_;
+    qreal corner_radius_;
+    qreal base_opacity_;
+    qreal font_size_;
 
-        bool use_fixed_ripple_radius_;
+    bool use_fixed_ripple_radius_;
 };
diff --git a/src/ui/FloatingButton.cpp b/src/ui/FloatingButton.cpp
index 95b6ae1d..3f88e313 100644
--- a/src/ui/FloatingButton.cpp
+++ b/src/ui/FloatingButton.cpp
@@ -10,91 +10,91 @@
 FloatingButton::FloatingButton(const QIcon &icon, QWidget *parent)
   : RaisedButton(parent)
 {
-        setFixedSize(DIAMETER, DIAMETER);
-        setGeometry(buttonGeometry());
+    setFixedSize(DIAMETER, DIAMETER);
+    setGeometry(buttonGeometry());
 
-        if (parentWidget())
-                parentWidget()->installEventFilter(this);
+    if (parentWidget())
+        parentWidget()->installEventFilter(this);
 
-        setFixedRippleRadius(50);
-        setIcon(icon);
-        raise();
+    setFixedRippleRadius(50);
+    setIcon(icon);
+    raise();
 }
 
 QRect
 FloatingButton::buttonGeometry() const
 {
-        QWidget *parent = parentWidget();
+    QWidget *parent = parentWidget();
 
-        if (!parent)
-                return QRect();
+    if (!parent)
+        return QRect();
 
-        return QRect(parent->width() - (OFFSET_X + DIAMETER),
-                     parent->height() - (OFFSET_Y + DIAMETER),
-                     DIAMETER,
-                     DIAMETER);
+    return QRect(parent->width() - (OFFSET_X + DIAMETER),
+                 parent->height() - (OFFSET_Y + DIAMETER),
+                 DIAMETER,
+                 DIAMETER);
 }
 
 bool
 FloatingButton::event(QEvent *event)
 {
-        if (!parent())
-                return RaisedButton::event(event);
-
-        switch (event->type()) {
-        case QEvent::ParentChange: {
-                parent()->installEventFilter(this);
-                setGeometry(buttonGeometry());
-                break;
-        }
-        case QEvent::ParentAboutToChange: {
-                parent()->installEventFilter(this);
-                break;
-        }
-        default:
-                break;
-        }
-
+    if (!parent())
         return RaisedButton::event(event);
+
+    switch (event->type()) {
+    case QEvent::ParentChange: {
+        parent()->installEventFilter(this);
+        setGeometry(buttonGeometry());
+        break;
+    }
+    case QEvent::ParentAboutToChange: {
+        parent()->installEventFilter(this);
+        break;
+    }
+    default:
+        break;
+    }
+
+    return RaisedButton::event(event);
 }
 
 bool
 FloatingButton::eventFilter(QObject *obj, QEvent *event)
 {
-        const QEvent::Type type = event->type();
+    const QEvent::Type type = event->type();
 
-        if (QEvent::Move == type || QEvent::Resize == type)
-                setGeometry(buttonGeometry());
+    if (QEvent::Move == type || QEvent::Resize == type)
+        setGeometry(buttonGeometry());
 
-        return RaisedButton::eventFilter(obj, event);
+    return RaisedButton::eventFilter(obj, event);
 }
 
 void
 FloatingButton::paintEvent(QPaintEvent *event)
 {
-        Q_UNUSED(event);
+    Q_UNUSED(event);
 
-        QRect square = QRect(0, 0, DIAMETER, DIAMETER);
-        square.moveCenter(rect().center());
+    QRect square = QRect(0, 0, DIAMETER, DIAMETER);
+    square.moveCenter(rect().center());
 
-        QPainter p(this);
-        p.setRenderHints(QPainter::Antialiasing);
+    QPainter p(this);
+    p.setRenderHints(QPainter::Antialiasing);
 
-        QBrush brush;
-        brush.setStyle(Qt::SolidPattern);
-        brush.setColor(backgroundColor());
+    QBrush brush;
+    brush.setStyle(Qt::SolidPattern);
+    brush.setColor(backgroundColor());
 
-        p.setBrush(brush);
-        p.setPen(Qt::NoPen);
-        p.drawEllipse(square);
+    p.setBrush(brush);
+    p.setPen(Qt::NoPen);
+    p.drawEllipse(square);
 
-        QRect iconGeometry(0, 0, ICON_SIZE, ICON_SIZE);
-        iconGeometry.moveCenter(square.center());
+    QRect iconGeometry(0, 0, ICON_SIZE, ICON_SIZE);
+    iconGeometry.moveCenter(square.center());
 
-        QPixmap pixmap = icon().pixmap(QSize(ICON_SIZE, ICON_SIZE));
-        QPainter icon(&pixmap);
-        icon.setCompositionMode(QPainter::CompositionMode_SourceIn);
-        icon.fillRect(pixmap.rect(), foregroundColor());
+    QPixmap pixmap = icon().pixmap(QSize(ICON_SIZE, ICON_SIZE));
+    QPainter icon(&pixmap);
+    icon.setCompositionMode(QPainter::CompositionMode_SourceIn);
+    icon.fillRect(pixmap.rect(), foregroundColor());
 
-        p.drawPixmap(iconGeometry, pixmap);
+    p.drawPixmap(iconGeometry, pixmap);
 }
diff --git a/src/ui/FloatingButton.h b/src/ui/FloatingButton.h
index b59b3854..df14dd2c 100644
--- a/src/ui/FloatingButton.h
+++ b/src/ui/FloatingButton.h
@@ -14,17 +14,17 @@ constexpr int OFFSET_Y = 20;
 
 class FloatingButton : public RaisedButton
 {
-        Q_OBJECT
+    Q_OBJECT
 
 public:
-        FloatingButton(const QIcon &icon, QWidget *parent = nullptr);
+    FloatingButton(const QIcon &icon, QWidget *parent = nullptr);
 
-        QSize sizeHint() const override { return QSize(DIAMETER, DIAMETER); };
-        QRect buttonGeometry() const;
+    QSize sizeHint() const override { return QSize(DIAMETER, DIAMETER); };
+    QRect buttonGeometry() const;
 
 protected:
-        bool event(QEvent *event) override;
-        bool eventFilter(QObject *obj, QEvent *event) override;
+    bool event(QEvent *event) override;
+    bool eventFilter(QObject *obj, QEvent *event) override;
 
-        void paintEvent(QPaintEvent *event) override;
+    void paintEvent(QPaintEvent *event) override;
 };
diff --git a/src/ui/InfoMessage.cpp b/src/ui/InfoMessage.cpp
index ebe0e63f..e238a4d2 100644
--- a/src/ui/InfoMessage.cpp
+++ b/src/ui/InfoMessage.cpp
@@ -19,60 +19,60 @@ constexpr int HMargin  = 20;
 InfoMessage::InfoMessage(QWidget *parent)
   : QWidget{parent}
 {
-        initFont();
+    initFont();
 }
 
 InfoMessage::InfoMessage(QString msg, QWidget *parent)
   : QWidget{parent}
   , msg_{msg}
 {
-        initFont();
+    initFont();
 
-        QFontMetrics fm{font()};
-        width_  = fm.horizontalAdvance(msg_) + HPadding * 2;
-        height_ = fm.ascent() + 2 * VPadding;
+    QFontMetrics fm{font()};
+    width_  = fm.horizontalAdvance(msg_) + HPadding * 2;
+    height_ = fm.ascent() + 2 * VPadding;
 
-        setFixedHeight(height_ + 2 * HMargin);
+    setFixedHeight(height_ + 2 * HMargin);
 }
 
 void
 InfoMessage::paintEvent(QPaintEvent *)
 {
-        QPainter p(this);
-        p.setRenderHint(QPainter::Antialiasing);
-        p.setFont(font());
+    QPainter p(this);
+    p.setRenderHint(QPainter::Antialiasing);
+    p.setFont(font());
 
-        // Center the box horizontally & vertically.
-        auto textRegion = QRectF(width() / 2 - width_ / 2, HMargin, width_, height_);
+    // Center the box horizontally & vertically.
+    auto textRegion = QRectF(width() / 2 - width_ / 2, HMargin, width_, height_);
 
-        QPainterPath ppath;
-        ppath.addRoundedRect(textRegion, height_ / 2, height_ / 2);
+    QPainterPath ppath;
+    ppath.addRoundedRect(textRegion, height_ / 2, height_ / 2);
 
-        p.setPen(Qt::NoPen);
-        p.fillPath(ppath, boxColor());
-        p.drawPath(ppath);
+    p.setPen(Qt::NoPen);
+    p.fillPath(ppath, boxColor());
+    p.drawPath(ppath);
 
-        p.setPen(QPen(textColor()));
-        p.drawText(textRegion, Qt::AlignCenter, msg_);
+    p.setPen(QPen(textColor()));
+    p.drawText(textRegion, Qt::AlignCenter, msg_);
 }
 
 DateSeparator::DateSeparator(QDateTime datetime, QWidget *parent)
   : InfoMessage{parent}
 {
-        auto now = QDateTime::currentDateTime();
+    auto now = QDateTime::currentDateTime();
 
-        QString fmt = QLocale::system().dateFormat(QLocale::LongFormat);
+    QString fmt = QLocale::system().dateFormat(QLocale::LongFormat);
 
-        if (now.date().year() == datetime.date().year()) {
-                QRegularExpression rx("[^a-zA-Z]*y+[^a-zA-Z]*");
-                fmt = fmt.remove(rx);
-        }
+    if (now.date().year() == datetime.date().year()) {
+        QRegularExpression rx("[^a-zA-Z]*y+[^a-zA-Z]*");
+        fmt = fmt.remove(rx);
+    }
 
-        msg_ = datetime.date().toString(fmt);
+    msg_ = datetime.date().toString(fmt);
 
-        QFontMetrics fm{font()};
-        width_  = fm.horizontalAdvance(msg_) + HPadding * 2;
-        height_ = fm.ascent() + 2 * VPadding;
+    QFontMetrics fm{font()};
+    width_  = fm.horizontalAdvance(msg_) + HPadding * 2;
+    height_ = fm.ascent() + 2 * VPadding;
 
-        setFixedHeight(height_ + 2 * HMargin);
+    setFixedHeight(height_ + 2 * HMargin);
 }
diff --git a/src/ui/InfoMessage.h b/src/ui/InfoMessage.h
index cc0c57dc..486812a2 100644
--- a/src/ui/InfoMessage.h
+++ b/src/ui/InfoMessage.h
@@ -10,47 +10,47 @@
 
 class InfoMessage : public QWidget
 {
-        Q_OBJECT
+    Q_OBJECT
 
-        Q_PROPERTY(QColor textColor WRITE setTextColor READ textColor)
-        Q_PROPERTY(QColor boxColor WRITE setBoxColor READ boxColor)
+    Q_PROPERTY(QColor textColor WRITE setTextColor READ textColor)
+    Q_PROPERTY(QColor boxColor WRITE setBoxColor READ boxColor)
 
 public:
-        explicit InfoMessage(QWidget *parent = nullptr);
-        InfoMessage(QString msg, QWidget *parent = nullptr);
+    explicit InfoMessage(QWidget *parent = nullptr);
+    InfoMessage(QString msg, QWidget *parent = nullptr);
 
-        void setTextColor(QColor color) { textColor_ = color; }
-        void setBoxColor(QColor color) { boxColor_ = color; }
-        void saveDatetime(QDateTime datetime) { datetime_ = datetime; }
+    void setTextColor(QColor color) { textColor_ = color; }
+    void setBoxColor(QColor color) { boxColor_ = color; }
+    void saveDatetime(QDateTime datetime) { datetime_ = datetime; }
 
-        QColor textColor() const { return textColor_; }
-        QColor boxColor() const { return boxColor_; }
-        QDateTime datetime() const { return datetime_; }
+    QColor textColor() const { return textColor_; }
+    QColor boxColor() const { return boxColor_; }
+    QDateTime datetime() const { return datetime_; }
 
 protected:
-        void paintEvent(QPaintEvent *event) override;
-        void initFont()
-        {
-                QFont f;
-                f.setWeight(QFont::Medium);
-                setFont(f);
-        }
+    void paintEvent(QPaintEvent *event) override;
+    void initFont()
+    {
+        QFont f;
+        f.setWeight(QFont::Medium);
+        setFont(f);
+    }
 
-        int width_;
-        int height_;
+    int width_;
+    int height_;
 
-        QString msg_;
+    QString msg_;
 
-        QDateTime datetime_;
+    QDateTime datetime_;
 
-        QColor textColor_ = QColor("black");
-        QColor boxColor_  = QColor("white");
+    QColor textColor_ = QColor("black");
+    QColor boxColor_  = QColor("white");
 };
 
 class DateSeparator : public InfoMessage
 {
-        Q_OBJECT
+    Q_OBJECT
 
 public:
-        DateSeparator(QDateTime datetime, QWidget *parent = nullptr);
+    DateSeparator(QDateTime datetime, QWidget *parent = nullptr);
 };
diff --git a/src/ui/Label.cpp b/src/ui/Label.cpp
index 2e8f8e1d..220fe2f0 100644
--- a/src/ui/Label.cpp
+++ b/src/ui/Label.cpp
@@ -17,16 +17,16 @@ Label::Label(const QString &text, QWidget *parent, Qt::WindowFlags f)
 void
 Label::mousePressEvent(QMouseEvent *e)
 {
-        pressPosition_ = e->pos();
-        emit pressed(e);
-        QLabel::mousePressEvent(e);
+    pressPosition_ = e->pos();
+    emit pressed(e);
+    QLabel::mousePressEvent(e);
 }
 
 void
 Label::mouseReleaseEvent(QMouseEvent *e)
 {
-        emit released(e);
-        if (pressPosition_ == e->pos())
-                emit clicked(e);
-        QLabel::mouseReleaseEvent(e);
+    emit released(e);
+    if (pressPosition_ == e->pos())
+        emit clicked(e);
+    QLabel::mouseReleaseEvent(e);
 }
diff --git a/src/ui/Label.h b/src/ui/Label.h
index a3eb511b..b6e76b77 100644
--- a/src/ui/Label.h
+++ b/src/ui/Label.h
@@ -8,22 +8,22 @@
 
 class Label : public QLabel
 {
-        Q_OBJECT
+    Q_OBJECT
 
 public:
-        explicit Label(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags());
-        explicit Label(const QString &text,
-                       QWidget *parent   = Q_NULLPTR,
-                       Qt::WindowFlags f = Qt::WindowFlags());
+    explicit Label(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags());
+    explicit Label(const QString &text,
+                   QWidget *parent   = Q_NULLPTR,
+                   Qt::WindowFlags f = Qt::WindowFlags());
 
 signals:
-        void clicked(QMouseEvent *e);
-        void pressed(QMouseEvent *e);
-        void released(QMouseEvent *e);
+    void clicked(QMouseEvent *e);
+    void pressed(QMouseEvent *e);
+    void released(QMouseEvent *e);
 
 protected:
-        void mousePressEvent(QMouseEvent *e) override;
-        void mouseReleaseEvent(QMouseEvent *e) override;
+    void mousePressEvent(QMouseEvent *e) override;
+    void mouseReleaseEvent(QMouseEvent *e) override;
 
-        QPoint pressPosition_;
+    QPoint pressPosition_;
 };
diff --git a/src/ui/LoadingIndicator.cpp b/src/ui/LoadingIndicator.cpp
index fb3c761c..7581ec83 100644
--- a/src/ui/LoadingIndicator.cpp
+++ b/src/ui/LoadingIndicator.cpp
@@ -14,70 +14,70 @@ LoadingIndicator::LoadingIndicator(QWidget *parent)
   , angle_(0)
   , color_(Qt::black)
 {
-        setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
-        setFocusPolicy(Qt::NoFocus);
+    setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+    setFocusPolicy(Qt::NoFocus);
 
-        timer_ = new QTimer(this);
-        connect(timer_, SIGNAL(timeout()), this, SLOT(onTimeout()));
+    timer_ = new QTimer(this);
+    connect(timer_, SIGNAL(timeout()), this, SLOT(onTimeout()));
 }
 
 void
 LoadingIndicator::paintEvent(QPaintEvent *e)
 {
-        Q_UNUSED(e)
+    Q_UNUSED(e)
 
-        if (!timer_->isActive())
-                return;
+    if (!timer_->isActive())
+        return;
 
-        QPainter painter(this);
-        painter.setRenderHint(QPainter::Antialiasing);
+    QPainter painter(this);
+    painter.setRenderHint(QPainter::Antialiasing);
 
-        int width = qMin(this->width(), this->height());
+    int width = qMin(this->width(), this->height());
 
-        int outerRadius = (width - 4) * 0.5f;
-        int innerRadius = outerRadius * 0.78f;
+    int outerRadius = (width - 4) * 0.5f;
+    int innerRadius = outerRadius * 0.78f;
 
-        int capsuleRadius = (outerRadius - innerRadius) / 2;
+    int capsuleRadius = (outerRadius - innerRadius) / 2;
 
-        for (int i = 0; i < 8; ++i) {
-                QColor color = color_;
+    for (int i = 0; i < 8; ++i) {
+        QColor color = color_;
 
-                color.setAlphaF(1.0f - (i / 8.0f));
+        color.setAlphaF(1.0f - (i / 8.0f));
 
-                painter.setPen(Qt::NoPen);
-                painter.setBrush(color);
+        painter.setPen(Qt::NoPen);
+        painter.setBrush(color);
 
-                qreal radius = capsuleRadius * (1.0f - (i / 16.0f));
+        qreal radius = capsuleRadius * (1.0f - (i / 16.0f));
 
-                painter.save();
+        painter.save();
 
-                painter.translate(rect().center());
-                painter.rotate(angle_ - i * 45.0f);
+        painter.translate(rect().center());
+        painter.rotate(angle_ - i * 45.0f);
 
-                QPointF center = QPointF(-capsuleRadius, -innerRadius);
-                painter.drawEllipse(center, radius * 2, radius * 2);
+        QPointF center = QPointF(-capsuleRadius, -innerRadius);
+        painter.drawEllipse(center, radius * 2, radius * 2);
 
-                painter.restore();
-        }
+        painter.restore();
+    }
 }
 
 void
 LoadingIndicator::start()
 {
-        timer_->start(interval_);
-        show();
+    timer_->start(interval_);
+    show();
 }
 
 void
 LoadingIndicator::stop()
 {
-        timer_->stop();
-        hide();
+    timer_->stop();
+    hide();
 }
 
 void
 LoadingIndicator::onTimeout()
 {
-        angle_ = (angle_ + 45) % 360;
-        repaint();
+    angle_ = (angle_ + 45) % 360;
+    repaint();
 }
diff --git a/src/ui/LoadingIndicator.h b/src/ui/LoadingIndicator.h
index ba56b449..458ecd40 100644
--- a/src/ui/LoadingIndicator.h
+++ b/src/ui/LoadingIndicator.h
@@ -12,30 +12,30 @@ class QTimer;
 class QPaintEvent;
 class LoadingIndicator : public QWidget
 {
-        Q_OBJECT
-        Q_PROPERTY(QColor color READ color WRITE setColor)
+    Q_OBJECT
+    Q_PROPERTY(QColor color READ color WRITE setColor)
 
 public:
-        LoadingIndicator(QWidget *parent = nullptr);
+    LoadingIndicator(QWidget *parent = nullptr);
 
-        void paintEvent(QPaintEvent *e) override;
+    void paintEvent(QPaintEvent *e) override;
 
-        void start();
-        void stop();
+    void start();
+    void stop();
 
-        QColor color() { return color_; }
-        void setColor(QColor color) { color_ = color; }
+    QColor color() { return color_; }
+    void setColor(QColor color) { color_ = color; }
 
-        int interval() { return interval_; }
-        void setInterval(int interval) { interval_ = interval; }
+    int interval() { return interval_; }
+    void setInterval(int interval) { interval_ = interval; }
 
 private slots:
-        void onTimeout();
+    void onTimeout();
 
 private:
-        int interval_;
-        int angle_;
+    int interval_;
+    int angle_;
 
-        QColor color_;
-        QTimer *timer_;
+    QColor color_;
+    QTimer *timer_;
 };
diff --git a/src/ui/Menu.h b/src/ui/Menu.h
index fd2946dd..d1ac2b80 100644
--- a/src/ui/Menu.h
+++ b/src/ui/Menu.h
@@ -10,16 +10,16 @@
 
 class Menu : public QMenu
 {
-        Q_OBJECT
+    Q_OBJECT
 public:
-        Menu(QWidget *parent = nullptr)
-          : QMenu(parent){};
+    Menu(QWidget *parent = nullptr)
+      : QMenu(parent){};
 
 protected:
-        void leaveEvent(QEvent *e) override
-        {
-                hide();
+    void leaveEvent(QEvent *e) override
+    {
+        hide();
 
-                QMenu::leaveEvent(e);
-        }
+        QMenu::leaveEvent(e);
+    }
 };
diff --git a/src/ui/MxcAnimatedImage.cpp b/src/ui/MxcAnimatedImage.cpp
index c691bab0..72758653 100644
--- a/src/ui/MxcAnimatedImage.cpp
+++ b/src/ui/MxcAnimatedImage.cpp
@@ -19,160 +19,157 @@
 void
 MxcAnimatedImage::startDownload()
 {
-        if (!room_)
-                return;
-        if (eventId_.isEmpty())
-                return;
-
-        auto event = room_->eventById(eventId_);
-        if (!event) {
-                nhlog::ui()->error("Failed to load media for event {}, event not found.",
-                                   eventId_.toStdString());
-                return;
-        }
+    if (!room_)
+        return;
+    if (eventId_.isEmpty())
+        return;
 
-        QByteArray mimeType = QString::fromStdString(mtx::accessors::mimetype(*event)).toUtf8();
+    auto event = room_->eventById(eventId_);
+    if (!event) {
+        nhlog::ui()->error("Failed to load media for event {}, event not found.",
+                           eventId_.toStdString());
+        return;
+    }
 
-        animatable_ = QMovie::supportedFormats().contains(mimeType.split('/').back());
-        animatableChanged();
+    QByteArray mimeType = QString::fromStdString(mtx::accessors::mimetype(*event)).toUtf8();
 
-        if (!animatable_)
-                return;
+    animatable_ = QMovie::supportedFormats().contains(mimeType.split('/').back());
+    animatableChanged();
 
-        QString mxcUrl           = QString::fromStdString(mtx::accessors::url(*event));
-        QString originalFilename = QString::fromStdString(mtx::accessors::filename(*event));
+    if (!animatable_)
+        return;
 
-        auto encryptionInfo = mtx::accessors::file(*event);
+    QString mxcUrl           = QString::fromStdString(mtx::accessors::url(*event));
+    QString originalFilename = QString::fromStdString(mtx::accessors::filename(*event));
 
-        // If the message is a link to a non mxcUrl, don't download it
-        if (!mxcUrl.startsWith("mxc://")) {
-                return;
-        }
+    auto encryptionInfo = mtx::accessors::file(*event);
 
-        QString suffix = QMimeDatabase().mimeTypeForName(mimeType).preferredSuffix();
-
-        const auto url  = mxcUrl.toStdString();
-        const auto name = QString(mxcUrl).remove("mxc://");
-        QFileInfo filename(QString("%1/media_cache/media/%2.%3")
-                             .arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))
-                             .arg(name)
-                             .arg(suffix));
-        if (QDir::cleanPath(name) != name) {
-                nhlog::net()->warn("mxcUrl '{}' is not safe, not downloading file", url);
-                return;
-        }
+    // If the message is a link to a non mxcUrl, don't download it
+    if (!mxcUrl.startsWith("mxc://")) {
+        return;
+    }
+
+    QString suffix = QMimeDatabase().mimeTypeForName(mimeType).preferredSuffix();
+
+    const auto url  = mxcUrl.toStdString();
+    const auto name = QString(mxcUrl).remove("mxc://");
+    QFileInfo filename(QString("%1/media_cache/media/%2.%3")
+                         .arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))
+                         .arg(name)
+                         .arg(suffix));
+    if (QDir::cleanPath(name) != name) {
+        nhlog::net()->warn("mxcUrl '{}' is not safe, not downloading file", url);
+        return;
+    }
+
+    QDir().mkpath(filename.path());
+
+    QPointer<MxcAnimatedImage> self = this;
+
+    auto processBuffer = [this, mimeType, encryptionInfo, self](QIODevice &device) {
+        if (!self)
+            return;
 
-        QDir().mkpath(filename.path());
-
-        QPointer<MxcAnimatedImage> self = this;
-
-        auto processBuffer = [this, mimeType, encryptionInfo, self](QIODevice &device) {
-                if (!self)
-                        return;
-
-                if (buffer.isOpen()) {
-                        movie.stop();
-                        movie.setDevice(nullptr);
-                        buffer.close();
-                }
-
-                if (encryptionInfo) {
-                        QByteArray ba = device.readAll();
-                        std::string temp(ba.constData(), ba.size());
-                        temp = mtx::crypto::to_string(
-                          mtx::crypto::decrypt_file(temp, encryptionInfo.value()));
-                        buffer.setData(temp.data(), temp.size());
-                } else {
-                        buffer.setData(device.readAll());
-                }
-                buffer.open(QIODevice::ReadOnly);
-                buffer.reset();
-
-                QTimer::singleShot(0, this, [this, mimeType] {
-                        nhlog::ui()->info("Playing movie with size: {}, {}",
-                                          buffer.bytesAvailable(),
-                                          buffer.isOpen());
-                        movie.setFormat(mimeType);
-                        movie.setDevice(&buffer);
-                        if (play_)
-                                movie.start();
-                        else
-                                movie.jumpToFrame(0);
-                        emit loadedChanged();
-                        update();
-                });
-        };
-
-        if (filename.isReadable()) {
-                QFile f(filename.filePath());
-                if (f.open(QIODevice::ReadOnly)) {
-                        processBuffer(f);
-                        return;
-                }
+        if (buffer.isOpen()) {
+            movie.stop();
+            movie.setDevice(nullptr);
+            buffer.close();
         }
 
-        http::client()->download(
-          url,
-          [filename, url, processBuffer](const std::string &data,
-                                         const std::string &,
-                                         const std::string &,
-                                         mtx::http::RequestErr err) {
-                  if (err) {
-                          nhlog::net()->warn("failed to retrieve media {}: {} {}",
-                                             url,
-                                             err->matrix_error.error,
-                                             static_cast<int>(err->status_code));
-                          return;
-                  }
-
-                  try {
-                          QFile file(filename.filePath());
-
-                          if (!file.open(QIODevice::WriteOnly))
-                                  return;
-
-                          QByteArray ba(data.data(), (int)data.size());
-                          file.write(ba);
-                          file.close();
-
-                          QBuffer buf(&ba);
-                          buf.open(QBuffer::ReadOnly);
-                          processBuffer(buf);
-                  } catch (const std::exception &e) {
-                          nhlog::ui()->warn("Error while saving file to: {}", e.what());
-                  }
-          });
+        if (encryptionInfo) {
+            QByteArray ba = device.readAll();
+            std::string temp(ba.constData(), ba.size());
+            temp = mtx::crypto::to_string(mtx::crypto::decrypt_file(temp, encryptionInfo.value()));
+            buffer.setData(temp.data(), temp.size());
+        } else {
+            buffer.setData(device.readAll());
+        }
+        buffer.open(QIODevice::ReadOnly);
+        buffer.reset();
+
+        QTimer::singleShot(0, this, [this, mimeType] {
+            nhlog::ui()->info(
+              "Playing movie with size: {}, {}", buffer.bytesAvailable(), buffer.isOpen());
+            movie.setFormat(mimeType);
+            movie.setDevice(&buffer);
+            if (play_)
+                movie.start();
+            else
+                movie.jumpToFrame(0);
+            emit loadedChanged();
+            update();
+        });
+    };
+
+    if (filename.isReadable()) {
+        QFile f(filename.filePath());
+        if (f.open(QIODevice::ReadOnly)) {
+            processBuffer(f);
+            return;
+        }
+    }
+
+    http::client()->download(url,
+                             [filename, url, processBuffer](const std::string &data,
+                                                            const std::string &,
+                                                            const std::string &,
+                                                            mtx::http::RequestErr err) {
+                                 if (err) {
+                                     nhlog::net()->warn("failed to retrieve media {}: {} {}",
+                                                        url,
+                                                        err->matrix_error.error,
+                                                        static_cast<int>(err->status_code));
+                                     return;
+                                 }
+
+                                 try {
+                                     QFile file(filename.filePath());
+
+                                     if (!file.open(QIODevice::WriteOnly))
+                                         return;
+
+                                     QByteArray ba(data.data(), (int)data.size());
+                                     file.write(ba);
+                                     file.close();
+
+                                     QBuffer buf(&ba);
+                                     buf.open(QBuffer::ReadOnly);
+                                     processBuffer(buf);
+                                 } catch (const std::exception &e) {
+                                     nhlog::ui()->warn("Error while saving file to: {}", e.what());
+                                 }
+                             });
 }
 
 QSGNode *
 MxcAnimatedImage::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
 {
-        if (!imageDirty)
-                return oldNode;
-
-        imageDirty      = false;
-        QSGImageNode *n = static_cast<QSGImageNode *>(oldNode);
-        if (!n) {
-                n = window()->createImageNode();
-                n->setOwnsTexture(true);
-                // n->setFlags(QSGNode::OwnedByParent | QSGNode::OwnsGeometry |
-                // GSGNode::OwnsMaterial);
-                n->setFlags(QSGNode::OwnedByParent);
-        }
-
-        // n->setTexture(nullptr);
-        auto img = movie.currentImage();
-        if (!img.isNull())
-                n->setTexture(window()->createTextureFromImage(img));
-        else {
-                delete n;
-                return nullptr;
-        }
-
-        n->setSourceRect(img.rect());
-        n->setRect(QRect(0, 0, width(), height()));
-        n->setFiltering(QSGTexture::Linear);
-        n->setMipmapFiltering(QSGTexture::Linear);
-
-        return n;
+    if (!imageDirty)
+        return oldNode;
+
+    imageDirty      = false;
+    QSGImageNode *n = static_cast<QSGImageNode *>(oldNode);
+    if (!n) {
+        n = window()->createImageNode();
+        n->setOwnsTexture(true);
+        // n->setFlags(QSGNode::OwnedByParent | QSGNode::OwnsGeometry |
+        // GSGNode::OwnsMaterial);
+        n->setFlags(QSGNode::OwnedByParent);
+    }
+
+    // n->setTexture(nullptr);
+    auto img = movie.currentImage();
+    if (!img.isNull())
+        n->setTexture(window()->createTextureFromImage(img));
+    else {
+        delete n;
+        return nullptr;
+    }
+
+    n->setSourceRect(img.rect());
+    n->setRect(QRect(0, 0, width(), height()));
+    n->setFiltering(QSGTexture::Linear);
+    n->setMipmapFiltering(QSGTexture::Linear);
+
+    return n;
 }
diff --git a/src/ui/MxcAnimatedImage.h b/src/ui/MxcAnimatedImage.h
index 2e0489ad..c3ca24d1 100644
--- a/src/ui/MxcAnimatedImage.h
+++ b/src/ui/MxcAnimatedImage.h
@@ -14,78 +14,78 @@ class TimelineModel;
 // This is an AnimatedImage, that can draw encrypted images
 class MxcAnimatedImage : public QQuickItem
 {
-        Q_OBJECT
-        Q_PROPERTY(TimelineModel *roomm READ room WRITE setRoom NOTIFY roomChanged REQUIRED)
-        Q_PROPERTY(QString eventId READ eventId WRITE setEventId NOTIFY eventIdChanged)
-        Q_PROPERTY(bool animatable READ animatable NOTIFY animatableChanged)
-        Q_PROPERTY(bool loaded READ loaded NOTIFY loadedChanged)
-        Q_PROPERTY(bool play READ play WRITE setPlay NOTIFY playChanged)
+    Q_OBJECT
+    Q_PROPERTY(TimelineModel *roomm READ room WRITE setRoom NOTIFY roomChanged REQUIRED)
+    Q_PROPERTY(QString eventId READ eventId WRITE setEventId NOTIFY eventIdChanged)
+    Q_PROPERTY(bool animatable READ animatable NOTIFY animatableChanged)
+    Q_PROPERTY(bool loaded READ loaded NOTIFY loadedChanged)
+    Q_PROPERTY(bool play READ play WRITE setPlay NOTIFY playChanged)
 public:
-        MxcAnimatedImage(QQuickItem *parent = nullptr)
-          : QQuickItem(parent)
-        {
-                connect(this, &MxcAnimatedImage::eventIdChanged, &MxcAnimatedImage::startDownload);
-                connect(this, &MxcAnimatedImage::roomChanged, &MxcAnimatedImage::startDownload);
-                connect(&movie, &QMovie::frameChanged, this, &MxcAnimatedImage::newFrame);
-                setFlag(QQuickItem::ItemHasContents);
-                // setAcceptHoverEvents(true);
-        }
+    MxcAnimatedImage(QQuickItem *parent = nullptr)
+      : QQuickItem(parent)
+    {
+        connect(this, &MxcAnimatedImage::eventIdChanged, &MxcAnimatedImage::startDownload);
+        connect(this, &MxcAnimatedImage::roomChanged, &MxcAnimatedImage::startDownload);
+        connect(&movie, &QMovie::frameChanged, this, &MxcAnimatedImage::newFrame);
+        setFlag(QQuickItem::ItemHasContents);
+        // setAcceptHoverEvents(true);
+    }
 
-        bool animatable() const { return animatable_; }
-        bool loaded() const { return buffer.size() > 0; }
-        bool play() const { return play_; }
-        QString eventId() const { return eventId_; }
-        TimelineModel *room() const { return room_; }
-        void setEventId(QString newEventId)
-        {
-                if (eventId_ != newEventId) {
-                        eventId_ = newEventId;
-                        emit eventIdChanged();
-                }
+    bool animatable() const { return animatable_; }
+    bool loaded() const { return buffer.size() > 0; }
+    bool play() const { return play_; }
+    QString eventId() const { return eventId_; }
+    TimelineModel *room() const { return room_; }
+    void setEventId(QString newEventId)
+    {
+        if (eventId_ != newEventId) {
+            eventId_ = newEventId;
+            emit eventIdChanged();
         }
-        void setRoom(TimelineModel *room)
-        {
-                if (room_ != room) {
-                        room_ = room;
-                        emit roomChanged();
-                }
+    }
+    void setRoom(TimelineModel *room)
+    {
+        if (room_ != room) {
+            room_ = room;
+            emit roomChanged();
         }
-        void setPlay(bool newPlay)
-        {
-                if (play_ != newPlay) {
-                        play_ = newPlay;
-                        movie.setPaused(!play_);
-                        emit playChanged();
-                }
+    }
+    void setPlay(bool newPlay)
+    {
+        if (play_ != newPlay) {
+            play_ = newPlay;
+            movie.setPaused(!play_);
+            emit playChanged();
         }
+    }
 
-        QSGNode *updatePaintNode(QSGNode *oldNode,
-                                 QQuickItem::UpdatePaintNodeData *updatePaintNodeData) override;
+    QSGNode *updatePaintNode(QSGNode *oldNode,
+                             QQuickItem::UpdatePaintNodeData *updatePaintNodeData) override;
 
 signals:
-        void roomChanged();
-        void eventIdChanged();
-        void animatableChanged();
-        void loadedChanged();
-        void playChanged();
+    void roomChanged();
+    void eventIdChanged();
+    void animatableChanged();
+    void loadedChanged();
+    void playChanged();
 
 private slots:
-        void startDownload();
-        void newFrame(int frame)
-        {
-                currentFrame = frame;
-                imageDirty   = true;
-                update();
-        }
+    void startDownload();
+    void newFrame(int frame)
+    {
+        currentFrame = frame;
+        imageDirty   = true;
+        update();
+    }
 
 private:
-        TimelineModel *room_ = nullptr;
-        QString eventId_;
-        QString filename_;
-        bool animatable_ = false;
-        QBuffer buffer;
-        QMovie movie;
-        int currentFrame = 0;
-        bool imageDirty  = true;
-        bool play_       = true;
+    TimelineModel *room_ = nullptr;
+    QString eventId_;
+    QString filename_;
+    bool animatable_ = false;
+    QBuffer buffer;
+    QMovie movie;
+    int currentFrame = 0;
+    bool imageDirty  = true;
+    bool play_       = true;
 };
diff --git a/src/ui/MxcMediaProxy.cpp b/src/ui/MxcMediaProxy.cpp
index dc65de7c..db8c0f1f 100644
--- a/src/ui/MxcMediaProxy.cpp
+++ b/src/ui/MxcMediaProxy.cpp
@@ -21,122 +21,119 @@
 void
 MxcMediaProxy::setVideoSurface(QAbstractVideoSurface *surface)
 {
-        qDebug() << "Changing surface";
-        m_surface = surface;
-        setVideoOutput(m_surface);
+    qDebug() << "Changing surface";
+    m_surface = surface;
+    setVideoOutput(m_surface);
 }
 
 QAbstractVideoSurface *
 MxcMediaProxy::getVideoSurface()
 {
-        return m_surface;
+    return m_surface;
 }
 
 void
 MxcMediaProxy::startDownload()
 {
-        if (!room_)
-                return;
-        if (eventId_.isEmpty())
-                return;
-
-        auto event = room_->eventById(eventId_);
-        if (!event) {
-                nhlog::ui()->error("Failed to load media for event {}, event not found.",
-                                   eventId_.toStdString());
-                return;
+    if (!room_)
+        return;
+    if (eventId_.isEmpty())
+        return;
+
+    auto event = room_->eventById(eventId_);
+    if (!event) {
+        nhlog::ui()->error("Failed to load media for event {}, event not found.",
+                           eventId_.toStdString());
+        return;
+    }
+
+    QString mxcUrl           = QString::fromStdString(mtx::accessors::url(*event));
+    QString originalFilename = QString::fromStdString(mtx::accessors::filename(*event));
+    QString mimeType         = QString::fromStdString(mtx::accessors::mimetype(*event));
+
+    auto encryptionInfo = mtx::accessors::file(*event);
+
+    // If the message is a link to a non mxcUrl, don't download it
+    if (!mxcUrl.startsWith("mxc://")) {
+        return;
+    }
+
+    QString suffix = QMimeDatabase().mimeTypeForName(mimeType).preferredSuffix();
+
+    const auto url  = mxcUrl.toStdString();
+    const auto name = QString(mxcUrl).remove("mxc://");
+    QFileInfo filename(QString("%1/media_cache/media/%2.%3")
+                         .arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))
+                         .arg(name)
+                         .arg(suffix));
+    if (QDir::cleanPath(name) != name) {
+        nhlog::net()->warn("mxcUrl '{}' is not safe, not downloading file", url);
+        return;
+    }
+
+    QDir().mkpath(filename.path());
+
+    QPointer<MxcMediaProxy> self = this;
+
+    auto processBuffer = [this, encryptionInfo, filename, self](QIODevice &device) {
+        if (!self)
+            return;
+
+        if (encryptionInfo) {
+            QByteArray ba = device.readAll();
+            std::string temp(ba.constData(), ba.size());
+            temp = mtx::crypto::to_string(mtx::crypto::decrypt_file(temp, encryptionInfo.value()));
+            buffer.setData(temp.data(), temp.size());
+        } else {
+            buffer.setData(device.readAll());
         }
-
-        QString mxcUrl           = QString::fromStdString(mtx::accessors::url(*event));
-        QString originalFilename = QString::fromStdString(mtx::accessors::filename(*event));
-        QString mimeType         = QString::fromStdString(mtx::accessors::mimetype(*event));
-
-        auto encryptionInfo = mtx::accessors::file(*event);
-
-        // If the message is a link to a non mxcUrl, don't download it
-        if (!mxcUrl.startsWith("mxc://")) {
-                return;
-        }
-
-        QString suffix = QMimeDatabase().mimeTypeForName(mimeType).preferredSuffix();
-
-        const auto url  = mxcUrl.toStdString();
-        const auto name = QString(mxcUrl).remove("mxc://");
-        QFileInfo filename(QString("%1/media_cache/media/%2.%3")
-                             .arg(QStandardPaths::writableLocation(QStandardPaths::CacheLocation))
-                             .arg(name)
-                             .arg(suffix));
-        if (QDir::cleanPath(name) != name) {
-                nhlog::net()->warn("mxcUrl '{}' is not safe, not downloading file", url);
-                return;
-        }
-
-        QDir().mkpath(filename.path());
-
-        QPointer<MxcMediaProxy> self = this;
-
-        auto processBuffer = [this, encryptionInfo, filename, self](QIODevice &device) {
-                if (!self)
-                        return;
-
-                if (encryptionInfo) {
-                        QByteArray ba = device.readAll();
-                        std::string temp(ba.constData(), ba.size());
-                        temp = mtx::crypto::to_string(
-                          mtx::crypto::decrypt_file(temp, encryptionInfo.value()));
-                        buffer.setData(temp.data(), temp.size());
-                } else {
-                        buffer.setData(device.readAll());
-                }
-                buffer.open(QIODevice::ReadOnly);
-                buffer.reset();
-
-                QTimer::singleShot(0, this, [this, filename] {
-                        nhlog::ui()->info("Playing buffer with size: {}, {}",
-                                          buffer.bytesAvailable(),
-                                          buffer.isOpen());
-                        this->setMedia(QMediaContent(filename.fileName()), &buffer);
-                        emit loadedChanged();
-                });
-        };
-
-        if (filename.isReadable()) {
-                QFile f(filename.filePath());
-                if (f.open(QIODevice::ReadOnly)) {
-                        processBuffer(f);
-                        return;
-                }
+        buffer.open(QIODevice::ReadOnly);
+        buffer.reset();
+
+        QTimer::singleShot(0, this, [this, filename] {
+            nhlog::ui()->info(
+              "Playing buffer with size: {}, {}", buffer.bytesAvailable(), buffer.isOpen());
+            this->setMedia(QMediaContent(filename.fileName()), &buffer);
+            emit loadedChanged();
+        });
+    };
+
+    if (filename.isReadable()) {
+        QFile f(filename.filePath());
+        if (f.open(QIODevice::ReadOnly)) {
+            processBuffer(f);
+            return;
         }
-
-        http::client()->download(
-          url,
-          [filename, url, processBuffer](const std::string &data,
-                                         const std::string &,
-                                         const std::string &,
-                                         mtx::http::RequestErr err) {
-                  if (err) {
-                          nhlog::net()->warn("failed to retrieve media {}: {} {}",
-                                             url,
-                                             err->matrix_error.error,
-                                             static_cast<int>(err->status_code));
-                          return;
-                  }
-
-                  try {
-                          QFile file(filename.filePath());
-
-                          if (!file.open(QIODevice::WriteOnly))
-                                  return;
-
-                          QByteArray ba(data.data(), (int)data.size());
-                          file.write(ba);
-                          file.close();
-
-                          QBuffer buf(&ba);
-                          buf.open(QBuffer::ReadOnly);
-                          processBuffer(buf);
-                  } catch (const std::exception &e) {
-                          nhlog::ui()->warn("Error while saving file to: {}", e.what());
-                  }
-          });
+    }
+
+    http::client()->download(url,
+                             [filename, url, processBuffer](const std::string &data,
+                                                            const std::string &,
+                                                            const std::string &,
+                                                            mtx::http::RequestErr err) {
+                                 if (err) {
+                                     nhlog::net()->warn("failed to retrieve media {}: {} {}",
+                                                        url,
+                                                        err->matrix_error.error,
+                                                        static_cast<int>(err->status_code));
+                                     return;
+                                 }
+
+                                 try {
+                                     QFile file(filename.filePath());
+
+                                     if (!file.open(QIODevice::WriteOnly))
+                                         return;
+
+                                     QByteArray ba(data.data(), (int)data.size());
+                                     file.write(ba);
+                                     file.close();
+
+                                     QBuffer buf(&ba);
+                                     buf.open(QBuffer::ReadOnly);
+                                     processBuffer(buf);
+                                 } catch (const std::exception &e) {
+                                     nhlog::ui()->warn("Error while saving file to: {}", e.what());
+                                 }
+                             });
 }
diff --git a/src/ui/MxcMediaProxy.h b/src/ui/MxcMediaProxy.h
index 14541815..18152c75 100644
--- a/src/ui/MxcMediaProxy.h
+++ b/src/ui/MxcMediaProxy.h
@@ -20,61 +20,58 @@ class TimelineModel;
 // need the videoSurface property, so that part is really easy!
 class MxcMediaProxy : public QMediaPlayer
 {
-        Q_OBJECT
-        Q_PROPERTY(TimelineModel *roomm READ room WRITE setRoom NOTIFY roomChanged REQUIRED)
-        Q_PROPERTY(QString eventId READ eventId WRITE setEventId NOTIFY eventIdChanged)
-        Q_PROPERTY(QAbstractVideoSurface *videoSurface READ getVideoSurface WRITE setVideoSurface)
-        Q_PROPERTY(bool loaded READ loaded NOTIFY loadedChanged)
+    Q_OBJECT
+    Q_PROPERTY(TimelineModel *roomm READ room WRITE setRoom NOTIFY roomChanged REQUIRED)
+    Q_PROPERTY(QString eventId READ eventId WRITE setEventId NOTIFY eventIdChanged)
+    Q_PROPERTY(QAbstractVideoSurface *videoSurface READ getVideoSurface WRITE setVideoSurface)
+    Q_PROPERTY(bool loaded READ loaded NOTIFY loadedChanged)
 public:
-        MxcMediaProxy(QObject *parent = nullptr)
-          : QMediaPlayer(parent)
-        {
-                connect(this, &MxcMediaProxy::eventIdChanged, &MxcMediaProxy::startDownload);
-                connect(this, &MxcMediaProxy::roomChanged, &MxcMediaProxy::startDownload);
-                connect(this,
-                        qOverload<QMediaPlayer::Error>(&MxcMediaProxy::error),
-                        [this](QMediaPlayer::Error error) {
-                                nhlog::ui()->info("Media player error {} and errorStr {}",
-                                                  error,
-                                                  this->errorString().toStdString());
-                        });
-                connect(this,
-                        &MxcMediaProxy::mediaStatusChanged,
-                        [this](QMediaPlayer::MediaStatus status) {
-                                nhlog::ui()->info(
-                                  "Media player status {} and error {}", status, this->error());
-                        });
-        }
+    MxcMediaProxy(QObject *parent = nullptr)
+      : QMediaPlayer(parent)
+    {
+        connect(this, &MxcMediaProxy::eventIdChanged, &MxcMediaProxy::startDownload);
+        connect(this, &MxcMediaProxy::roomChanged, &MxcMediaProxy::startDownload);
+        connect(this,
+                qOverload<QMediaPlayer::Error>(&MxcMediaProxy::error),
+                [this](QMediaPlayer::Error error) {
+                    nhlog::ui()->info("Media player error {} and errorStr {}",
+                                      error,
+                                      this->errorString().toStdString());
+                });
+        connect(this, &MxcMediaProxy::mediaStatusChanged, [this](QMediaPlayer::MediaStatus status) {
+            nhlog::ui()->info("Media player status {} and error {}", status, this->error());
+        });
+    }
 
-        bool loaded() const { return buffer.size() > 0; }
-        QString eventId() const { return eventId_; }
-        TimelineModel *room() const { return room_; }
-        void setEventId(QString newEventId)
-        {
-                eventId_ = newEventId;
-                emit eventIdChanged();
-        }
-        void setRoom(TimelineModel *room)
-        {
-                room_ = room;
-                emit roomChanged();
-        }
-        void setVideoSurface(QAbstractVideoSurface *surface);
-        QAbstractVideoSurface *getVideoSurface();
+    bool loaded() const { return buffer.size() > 0; }
+    QString eventId() const { return eventId_; }
+    TimelineModel *room() const { return room_; }
+    void setEventId(QString newEventId)
+    {
+        eventId_ = newEventId;
+        emit eventIdChanged();
+    }
+    void setRoom(TimelineModel *room)
+    {
+        room_ = room;
+        emit roomChanged();
+    }
+    void setVideoSurface(QAbstractVideoSurface *surface);
+    QAbstractVideoSurface *getVideoSurface();
 
 signals:
-        void roomChanged();
-        void eventIdChanged();
-        void loadedChanged();
-        void newBuffer(QMediaContent, QIODevice *buf);
+    void roomChanged();
+    void eventIdChanged();
+    void loadedChanged();
+    void newBuffer(QMediaContent, QIODevice *buf);
 
 private slots:
-        void startDownload();
+    void startDownload();
 
 private:
-        TimelineModel *room_ = nullptr;
-        QString eventId_;
-        QString filename_;
-        QBuffer buffer;
-        QAbstractVideoSurface *m_surface = nullptr;
+    TimelineModel *room_ = nullptr;
+    QString eventId_;
+    QString filename_;
+    QBuffer buffer;
+    QAbstractVideoSurface *m_surface = nullptr;
 };
diff --git a/src/ui/NhekoCursorShape.cpp b/src/ui/NhekoCursorShape.cpp
index b36eedbd..70991757 100644
--- a/src/ui/NhekoCursorShape.cpp
+++ b/src/ui/NhekoCursorShape.cpp
@@ -14,16 +14,16 @@ NhekoCursorShape::NhekoCursorShape(QQuickItem *parent)
 Qt::CursorShape
 NhekoCursorShape::cursorShape() const
 {
-        return cursor().shape();
+    return cursor().shape();
 }
 
 void
 NhekoCursorShape::setCursorShape(Qt::CursorShape cursorShape)
 {
-        if (currentShape_ == cursorShape)
-                return;
+    if (currentShape_ == cursorShape)
+        return;
 
-        currentShape_ = cursorShape;
-        setCursor(cursorShape);
-        emit cursorShapeChanged();
+    currentShape_ = cursorShape;
+    setCursor(cursorShape);
+    emit cursorShapeChanged();
 }
diff --git a/src/ui/NhekoCursorShape.h b/src/ui/NhekoCursorShape.h
index 6f6a2b82..b3a0a1ba 100644
--- a/src/ui/NhekoCursorShape.h
+++ b/src/ui/NhekoCursorShape.h
@@ -11,20 +11,20 @@
 
 class NhekoCursorShape : public QQuickItem
 {
-        Q_OBJECT
+    Q_OBJECT
 
-        Q_PROPERTY(Qt::CursorShape cursorShape READ cursorShape WRITE setCursorShape NOTIFY
-                     cursorShapeChanged)
+    Q_PROPERTY(
+      Qt::CursorShape cursorShape READ cursorShape WRITE setCursorShape NOTIFY cursorShapeChanged)
 
 public:
-        explicit NhekoCursorShape(QQuickItem *parent = 0);
+    explicit NhekoCursorShape(QQuickItem *parent = 0);
 
 private:
-        Qt::CursorShape cursorShape() const;
-        void setCursorShape(Qt::CursorShape cursorShape);
+    Qt::CursorShape cursorShape() const;
+    void setCursorShape(Qt::CursorShape cursorShape);
 
-        Qt::CursorShape currentShape_;
+    Qt::CursorShape currentShape_;
 
 signals:
-        void cursorShapeChanged();
+    void cursorShapeChanged();
 };
diff --git a/src/ui/NhekoDropArea.cpp b/src/ui/NhekoDropArea.cpp
index bbcedd7e..b1b53c3d 100644
--- a/src/ui/NhekoDropArea.cpp
+++ b/src/ui/NhekoDropArea.cpp
@@ -16,28 +16,28 @@
 NhekoDropArea::NhekoDropArea(QQuickItem *parent)
   : QQuickItem(parent)
 {
-        setFlags(ItemAcceptsDrops);
+    setFlags(ItemAcceptsDrops);
 }
 
 void
 NhekoDropArea::dragEnterEvent(QDragEnterEvent *event)
 {
-        event->acceptProposedAction();
+    event->acceptProposedAction();
 }
 
 void
 NhekoDropArea::dragMoveEvent(QDragMoveEvent *event)
 {
-        event->acceptProposedAction();
+    event->acceptProposedAction();
 }
 
 void
 NhekoDropArea::dropEvent(QDropEvent *event)
 {
-        if (event) {
-                auto model = ChatPage::instance()->timelineManager()->rooms()->getRoomById(roomid_);
-                if (model) {
-                        model->input()->insertMimeData(event->mimeData());
-                }
+    if (event) {
+        auto model = ChatPage::instance()->timelineManager()->rooms()->getRoomById(roomid_);
+        if (model) {
+            model->input()->insertMimeData(event->mimeData());
         }
+    }
 }
diff --git a/src/ui/NhekoDropArea.h b/src/ui/NhekoDropArea.h
index 9fbf1737..7b3de5c9 100644
--- a/src/ui/NhekoDropArea.h
+++ b/src/ui/NhekoDropArea.h
@@ -6,29 +6,29 @@
 
 class NhekoDropArea : public QQuickItem
 {
-        Q_OBJECT
-        Q_PROPERTY(QString roomid READ roomid WRITE setRoomid NOTIFY roomidChanged)
+    Q_OBJECT
+    Q_PROPERTY(QString roomid READ roomid WRITE setRoomid NOTIFY roomidChanged)
 public:
-        NhekoDropArea(QQuickItem *parent = nullptr);
+    NhekoDropArea(QQuickItem *parent = nullptr);
 
 signals:
-        void roomidChanged(QString roomid);
+    void roomidChanged(QString roomid);
 
 public slots:
-        void setRoomid(QString roomid)
-        {
-                if (roomid_ != roomid) {
-                        roomid_ = roomid;
-                        emit roomidChanged(roomid);
-                }
+    void setRoomid(QString roomid)
+    {
+        if (roomid_ != roomid) {
+            roomid_ = roomid;
+            emit roomidChanged(roomid);
         }
-        QString roomid() const { return roomid_; }
+    }
+    QString roomid() const { return roomid_; }
 
 protected:
-        void dragEnterEvent(QDragEnterEvent *event) override;
-        void dragMoveEvent(QDragMoveEvent *event) override;
-        void dropEvent(QDropEvent *event) override;
+    void dragEnterEvent(QDragEnterEvent *event) override;
+    void dragMoveEvent(QDragMoveEvent *event) override;
+    void dropEvent(QDropEvent *event) override;
 
 private:
-        QString roomid_;
+    QString roomid_;
 };
diff --git a/src/ui/NhekoGlobalObject.cpp b/src/ui/NhekoGlobalObject.cpp
index 355f187b..d6824996 100644
--- a/src/ui/NhekoGlobalObject.cpp
+++ b/src/ui/NhekoGlobalObject.cpp
@@ -17,93 +17,93 @@
 
 Nheko::Nheko()
 {
-        connect(
-          UserSettings::instance().get(), &UserSettings::themeChanged, this, &Nheko::colorsChanged);
-        connect(ChatPage::instance(), &ChatPage::contentLoaded, this, &Nheko::updateUserProfile);
+    connect(
+      UserSettings::instance().get(), &UserSettings::themeChanged, this, &Nheko::colorsChanged);
+    connect(ChatPage::instance(), &ChatPage::contentLoaded, this, &Nheko::updateUserProfile);
 }
 
 void
 Nheko::updateUserProfile()
 {
-        if (cache::client() && cache::client()->isInitialized())
-                currentUser_.reset(
-                  new UserProfile("", utils::localUser(), ChatPage::instance()->timelineManager()));
-        else
-                currentUser_.reset();
-        emit profileChanged();
+    if (cache::client() && cache::client()->isInitialized())
+        currentUser_.reset(
+          new UserProfile("", utils::localUser(), ChatPage::instance()->timelineManager()));
+    else
+        currentUser_.reset();
+    emit profileChanged();
 }
 
 QPalette
 Nheko::colors() const
 {
-        return Theme::paletteFromTheme(UserSettings::instance()->theme().toStdString());
+    return Theme::paletteFromTheme(UserSettings::instance()->theme().toStdString());
 }
 
 QPalette
 Nheko::inactiveColors() const
 {
-        auto p = colors();
-        p.setCurrentColorGroup(QPalette::ColorGroup::Inactive);
-        return p;
+    auto p = colors();
+    p.setCurrentColorGroup(QPalette::ColorGroup::Inactive);
+    return p;
 }
 
 Theme
 Nheko::theme() const
 {
-        return Theme(UserSettings::instance()->theme().toStdString());
+    return Theme(UserSettings::instance()->theme().toStdString());
 }
 
 void
 Nheko::openLink(QString link) const
 {
-        QUrl url(link);
-        // Open externally if we couldn't handle it internally
-        if (!ChatPage::instance()->handleMatrixUri(url)) {
-                QDesktopServices::openUrl(url);
-        }
+    QUrl url(link);
+    // Open externally if we couldn't handle it internally
+    if (!ChatPage::instance()->handleMatrixUri(url)) {
+        QDesktopServices::openUrl(url);
+    }
 }
 void
 Nheko::setStatusMessage(QString msg) const
 {
-        ChatPage::instance()->setStatus(msg);
+    ChatPage::instance()->setStatus(msg);
 }
 
 UserProfile *
 Nheko::currentUser() const
 {
-        nhlog::ui()->debug("Profile requested");
+    nhlog::ui()->debug("Profile requested");
 
-        return currentUser_.get();
+    return currentUser_.get();
 }
 
 void
 Nheko::showUserSettingsPage() const
 {
-        ChatPage::instance()->showUserSettingsPage();
+    ChatPage::instance()->showUserSettingsPage();
 }
 
 void
 Nheko::openLogoutDialog() const
 {
-        MainWindow::instance()->openLogoutDialog();
+    MainWindow::instance()->openLogoutDialog();
 }
 
 void
 Nheko::openCreateRoomDialog() const
 {
-        MainWindow::instance()->openCreateRoomDialog(
-          [](const mtx::requests::CreateRoom &req) { ChatPage::instance()->createRoom(req); });
+    MainWindow::instance()->openCreateRoomDialog(
+      [](const mtx::requests::CreateRoom &req) { ChatPage::instance()->createRoom(req); });
 }
 
 void
 Nheko::openJoinRoomDialog() const
 {
-        MainWindow::instance()->openJoinRoomDialog(
-          [](const QString &room_id) { ChatPage::instance()->joinRoom(room_id); });
+    MainWindow::instance()->openJoinRoomDialog(
+      [](const QString &room_id) { ChatPage::instance()->joinRoom(room_id); });
 }
 
 void
 Nheko::reparent(QWindow *win) const
 {
-        win->setTransientParent(MainWindow::instance()->windowHandle());
+    win->setTransientParent(MainWindow::instance()->windowHandle());
 }
diff --git a/src/ui/NhekoGlobalObject.h b/src/ui/NhekoGlobalObject.h
index d4d119dc..aa8435d1 100644
--- a/src/ui/NhekoGlobalObject.h
+++ b/src/ui/NhekoGlobalObject.h
@@ -15,51 +15,51 @@ class QWindow;
 
 class Nheko : public QObject
 {
-        Q_OBJECT
+    Q_OBJECT
 
-        Q_PROPERTY(QPalette colors READ colors NOTIFY colorsChanged)
-        Q_PROPERTY(QPalette inactiveColors READ inactiveColors NOTIFY colorsChanged)
-        Q_PROPERTY(Theme theme READ theme NOTIFY colorsChanged)
-        Q_PROPERTY(int avatarSize READ avatarSize CONSTANT)
-        Q_PROPERTY(int paddingSmall READ paddingSmall CONSTANT)
-        Q_PROPERTY(int paddingMedium READ paddingMedium CONSTANT)
-        Q_PROPERTY(int paddingLarge READ paddingLarge CONSTANT)
+    Q_PROPERTY(QPalette colors READ colors NOTIFY colorsChanged)
+    Q_PROPERTY(QPalette inactiveColors READ inactiveColors NOTIFY colorsChanged)
+    Q_PROPERTY(Theme theme READ theme NOTIFY colorsChanged)
+    Q_PROPERTY(int avatarSize READ avatarSize CONSTANT)
+    Q_PROPERTY(int paddingSmall READ paddingSmall CONSTANT)
+    Q_PROPERTY(int paddingMedium READ paddingMedium CONSTANT)
+    Q_PROPERTY(int paddingLarge READ paddingLarge CONSTANT)
 
-        Q_PROPERTY(UserProfile *currentUser READ currentUser NOTIFY profileChanged)
+    Q_PROPERTY(UserProfile *currentUser READ currentUser NOTIFY profileChanged)
 
 public:
-        Nheko();
+    Nheko();
 
-        QPalette colors() const;
-        QPalette inactiveColors() const;
-        Theme theme() const;
+    QPalette colors() const;
+    QPalette inactiveColors() const;
+    Theme theme() const;
 
-        int avatarSize() const { return 40; }
+    int avatarSize() const { return 40; }
 
-        int paddingSmall() const { return 4; }
-        int paddingMedium() const { return 8; }
-        int paddingLarge() const { return 20; }
-        UserProfile *currentUser() const;
+    int paddingSmall() const { return 4; }
+    int paddingMedium() const { return 8; }
+    int paddingLarge() const { return 20; }
+    UserProfile *currentUser() const;
 
-        Q_INVOKABLE QFont monospaceFont() const
-        {
-                return QFontDatabase::systemFont(QFontDatabase::FixedFont);
-        }
-        Q_INVOKABLE void openLink(QString link) const;
-        Q_INVOKABLE void setStatusMessage(QString msg) const;
-        Q_INVOKABLE void showUserSettingsPage() const;
-        Q_INVOKABLE void openLogoutDialog() const;
-        Q_INVOKABLE void openCreateRoomDialog() const;
-        Q_INVOKABLE void openJoinRoomDialog() const;
-        Q_INVOKABLE void reparent(QWindow *win) const;
+    Q_INVOKABLE QFont monospaceFont() const
+    {
+        return QFontDatabase::systemFont(QFontDatabase::FixedFont);
+    }
+    Q_INVOKABLE void openLink(QString link) const;
+    Q_INVOKABLE void setStatusMessage(QString msg) const;
+    Q_INVOKABLE void showUserSettingsPage() const;
+    Q_INVOKABLE void openLogoutDialog() const;
+    Q_INVOKABLE void openCreateRoomDialog() const;
+    Q_INVOKABLE void openJoinRoomDialog() const;
+    Q_INVOKABLE void reparent(QWindow *win) const;
 
 public slots:
-        void updateUserProfile();
+    void updateUserProfile();
 
 signals:
-        void colorsChanged();
-        void profileChanged();
+    void colorsChanged();
+    void profileChanged();
 
 private:
-        QScopedPointer<UserProfile> currentUser_;
+    QScopedPointer<UserProfile> currentUser_;
 };
diff --git a/src/ui/OverlayModal.cpp b/src/ui/OverlayModal.cpp
index f5f28732..6534c4bc 100644
--- a/src/ui/OverlayModal.cpp
+++ b/src/ui/OverlayModal.cpp
@@ -12,50 +12,50 @@ OverlayModal::OverlayModal(QWidget *parent)
   : OverlayWidget(parent)
   , color_{QColor(30, 30, 30, 170)}
 {
-        layout_ = new QVBoxLayout(this);
-        layout_->setSpacing(0);
-        layout_->setContentsMargins(10, 40, 10, 20);
-        setContentAlignment(Qt::AlignCenter);
+    layout_ = new QVBoxLayout(this);
+    layout_->setSpacing(0);
+    layout_->setContentsMargins(10, 40, 10, 20);
+    setContentAlignment(Qt::AlignCenter);
 }
 
 void
 OverlayModal::setWidget(QWidget *widget)
 {
-        // Delete the previous widget
-        if (layout_->count() > 0) {
-                QLayoutItem *item;
-                while ((item = layout_->takeAt(0)) != nullptr) {
-                        delete item->widget();
-                        delete item;
-                }
+    // Delete the previous widget
+    if (layout_->count() > 0) {
+        QLayoutItem *item;
+        while ((item = layout_->takeAt(0)) != nullptr) {
+            delete item->widget();
+            delete item;
         }
+    }
 
-        layout_->addWidget(widget);
-        content_ = widget;
-        content_->setFocus();
+    layout_->addWidget(widget);
+    content_ = widget;
+    content_->setFocus();
 }
 
 void
 OverlayModal::paintEvent(QPaintEvent *event)
 {
-        Q_UNUSED(event);
+    Q_UNUSED(event);
 
-        QPainter painter(this);
-        painter.fillRect(rect(), color_);
+    QPainter painter(this);
+    painter.fillRect(rect(), color_);
 }
 
 void
 OverlayModal::mousePressEvent(QMouseEvent *e)
 {
-        if (isDismissible_ && content_ && !content_->geometry().contains(e->pos()))
-                hide();
+    if (isDismissible_ && content_ && !content_->geometry().contains(e->pos()))
+        hide();
 }
 
 void
 OverlayModal::keyPressEvent(QKeyEvent *event)
 {
-        if (event->key() == Qt::Key_Escape) {
-                event->accept();
-                hide();
-        }
+    if (event->key() == Qt::Key_Escape) {
+        event->accept();
+        hide();
+    }
 }
diff --git a/src/ui/OverlayModal.h b/src/ui/OverlayModal.h
index 005614fa..5c15f17f 100644
--- a/src/ui/OverlayModal.h
+++ b/src/ui/OverlayModal.h
@@ -15,25 +15,25 @@
 class OverlayModal : public OverlayWidget
 {
 public:
-        OverlayModal(QWidget *parent);
+    OverlayModal(QWidget *parent);
 
-        void setColor(QColor color) { color_ = color; }
-        void setDismissible(bool state) { isDismissible_ = state; }
+    void setColor(QColor color) { color_ = color; }
+    void setDismissible(bool state) { isDismissible_ = state; }
 
-        void setContentAlignment(QFlags<Qt::AlignmentFlag> flag) { layout_->setAlignment(flag); }
-        void setWidget(QWidget *widget);
+    void setContentAlignment(QFlags<Qt::AlignmentFlag> flag) { layout_->setAlignment(flag); }
+    void setWidget(QWidget *widget);
 
 protected:
-        void paintEvent(QPaintEvent *event) override;
-        void keyPressEvent(QKeyEvent *event) override;
-        void mousePressEvent(QMouseEvent *event) override;
+    void paintEvent(QPaintEvent *event) override;
+    void keyPressEvent(QKeyEvent *event) override;
+    void mousePressEvent(QMouseEvent *event) override;
 
 private:
-        QWidget *content_;
-        QVBoxLayout *layout_;
+    QWidget *content_;
+    QVBoxLayout *layout_;
 
-        QColor color_;
+    QColor color_;
 
-        //! Decides whether or not the modal can be removed by clicking into it.
-        bool isDismissible_ = true;
+    //! Decides whether or not the modal can be removed by clicking into it.
+    bool isDismissible_ = true;
 };
diff --git a/src/ui/OverlayWidget.cpp b/src/ui/OverlayWidget.cpp
index c8c95581..4e338753 100644
--- a/src/ui/OverlayWidget.cpp
+++ b/src/ui/OverlayWidget.cpp
@@ -10,69 +10,69 @@
 OverlayWidget::OverlayWidget(QWidget *parent)
   : QWidget(parent)
 {
-        if (parent) {
-                parent->installEventFilter(this);
-                setGeometry(overlayGeometry());
-                raise();
-        }
+    if (parent) {
+        parent->installEventFilter(this);
+        setGeometry(overlayGeometry());
+        raise();
+    }
 }
 
 bool
 OverlayWidget::event(QEvent *event)
 {
-        if (!parent())
-                return QWidget::event(event);
+    if (!parent())
+        return QWidget::event(event);
 
-        switch (event->type()) {
-        case QEvent::ParentChange: {
-                parent()->installEventFilter(this);
-                setGeometry(overlayGeometry());
-                break;
-        }
-        case QEvent::ParentAboutToChange: {
-                parent()->removeEventFilter(this);
-                break;
-        }
-        default:
-                break;
-        }
+    switch (event->type()) {
+    case QEvent::ParentChange: {
+        parent()->installEventFilter(this);
+        setGeometry(overlayGeometry());
+        break;
+    }
+    case QEvent::ParentAboutToChange: {
+        parent()->removeEventFilter(this);
+        break;
+    }
+    default:
+        break;
+    }
 
-        return QWidget::event(event);
+    return QWidget::event(event);
 }
 
 bool
 OverlayWidget::eventFilter(QObject *obj, QEvent *event)
 {
-        switch (event->type()) {
-        case QEvent::Move:
-        case QEvent::Resize:
-                setGeometry(overlayGeometry());
-                break;
-        default:
-                break;
-        }
+    switch (event->type()) {
+    case QEvent::Move:
+    case QEvent::Resize:
+        setGeometry(overlayGeometry());
+        break;
+    default:
+        break;
+    }
 
-        return QWidget::eventFilter(obj, event);
+    return QWidget::eventFilter(obj, event);
 }
 
 QRect
 OverlayWidget::overlayGeometry() const
 {
-        QWidget *widget = parentWidget();
+    QWidget *widget = parentWidget();
 
-        if (!widget)
-                return QRect();
+    if (!widget)
+        return QRect();
 
-        return widget->rect();
+    return widget->rect();
 }
 
 void
 OverlayWidget::paintEvent(QPaintEvent *event)
 {
-        Q_UNUSED(event);
+    Q_UNUSED(event);
 
-        QStyleOption opt;
-        opt.init(this);
-        QPainter p(this);
-        style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
+    QStyleOption opt;
+    opt.init(this);
+    QPainter p(this);
+    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
 }
diff --git a/src/ui/OverlayWidget.h b/src/ui/OverlayWidget.h
index 05bb8696..5f023e35 100644
--- a/src/ui/OverlayWidget.h
+++ b/src/ui/OverlayWidget.h
@@ -11,15 +11,15 @@ class QPainter;
 
 class OverlayWidget : public QWidget
 {
-        Q_OBJECT
+    Q_OBJECT
 
 public:
-        explicit OverlayWidget(QWidget *parent = nullptr);
+    explicit OverlayWidget(QWidget *parent = nullptr);
 
 protected:
-        bool event(QEvent *event) override;
-        bool eventFilter(QObject *obj, QEvent *event) override;
+    bool event(QEvent *event) override;
+    bool eventFilter(QObject *obj, QEvent *event) override;
 
-        QRect overlayGeometry() const;
-        void paintEvent(QPaintEvent *event) override;
+    QRect overlayGeometry() const;
+    void paintEvent(QPaintEvent *event) override;
 };
diff --git a/src/ui/Painter.h b/src/ui/Painter.h
index 9f974116..f78b55e5 100644
--- a/src/ui/Painter.h
+++ b/src/ui/Painter.h
@@ -13,147 +13,141 @@
 class Painter : public QPainter
 {
 public:
-        explicit Painter(QPaintDevice *device)
-          : QPainter(device)
-        {}
-
-        void drawTextLeft(int x, int y, const QString &text)
-        {
-                QFontMetrics m(fontMetrics());
-                drawText(x, y + m.ascent(), text);
-        }
-
-        void drawTextRight(int x, int y, int outerw, const QString &text, int textWidth = -1)
-        {
-                QFontMetrics m(fontMetrics());
-                if (textWidth < 0) {
-                        textWidth = m.horizontalAdvance(text);
-                }
-                drawText((outerw - x - textWidth), y + m.ascent(), text);
-        }
-
-        void drawPixmapLeft(int x, int y, const QPixmap &pix, const QRect &from)
-        {
-                drawPixmap(QPoint(x, y), pix, from);
-        }
-
-        void drawPixmapLeft(const QPoint &p, const QPixmap &pix, const QRect &from)
-        {
-                return drawPixmapLeft(p.x(), p.y(), pix, from);
-        }
-
-        void drawPixmapLeft(int x, int y, int w, int h, const QPixmap &pix, const QRect &from)
-        {
-                drawPixmap(QRect(x, y, w, h), pix, from);
-        }
-
-        void drawPixmapLeft(const QRect &r, const QPixmap &pix, const QRect &from)
-        {
-                return drawPixmapLeft(r.x(), r.y(), r.width(), r.height(), pix, from);
-        }
-
-        void drawPixmapLeft(int x, int y, int outerw, const QPixmap &pix)
-        {
-                Q_UNUSED(outerw);
-                drawPixmap(QPoint(x, y), pix);
-        }
-
-        void drawPixmapLeft(const QPoint &p, int outerw, const QPixmap &pix)
-        {
-                return drawPixmapLeft(p.x(), p.y(), outerw, pix);
-        }
-
-        void drawPixmapRight(int x, int y, int outerw, const QPixmap &pix, const QRect &from)
-        {
-                drawPixmap(
-                  QPoint((outerw - x - (from.width() / pix.devicePixelRatio())), y), pix, from);
-        }
-
-        void drawPixmapRight(const QPoint &p, int outerw, const QPixmap &pix, const QRect &from)
-        {
-                return drawPixmapRight(p.x(), p.y(), outerw, pix, from);
-        }
-        void drawPixmapRight(int x,
-                             int y,
-                             int w,
-                             int h,
-                             int outerw,
-                             const QPixmap &pix,
-                             const QRect &from)
-        {
-                drawPixmap(QRect((outerw - x - w), y, w, h), pix, from);
-        }
-
-        void drawPixmapRight(const QRect &r, int outerw, const QPixmap &pix, const QRect &from)
-        {
-                return drawPixmapRight(r.x(), r.y(), r.width(), r.height(), outerw, pix, from);
-        }
-
-        void drawPixmapRight(int x, int y, int outerw, const QPixmap &pix)
-        {
-                drawPixmap(QPoint((outerw - x - (pix.width() / pix.devicePixelRatio())), y), pix);
-        }
-
-        void drawPixmapRight(const QPoint &p, int outerw, const QPixmap &pix)
-        {
-                return drawPixmapRight(p.x(), p.y(), outerw, pix);
-        }
-
-        void drawAvatar(const QPixmap &pix, int w, int h, int d)
-        {
-                QPainterPath pp;
-                pp.addEllipse((w - d) / 2, (h - d) / 2, d, d);
-
-                QRect region((w - d) / 2, (h - d) / 2, d, d);
-
-                setClipPath(pp);
-                drawPixmap(region, pix);
-        }
-
-        void drawLetterAvatar(const QString &c,
-                              const QColor &penColor,
-                              const QColor &brushColor,
-                              int w,
-                              int h,
-                              int d)
-        {
-                QRect region((w - d) / 2, (h - d) / 2, d, d);
-
-                setPen(Qt::NoPen);
-                setBrush(brushColor);
-
-                drawEllipse(region.center(), d / 2, d / 2);
-
-                setBrush(Qt::NoBrush);
-                drawEllipse(region.center(), d / 2, d / 2);
-
-                setPen(penColor);
-                drawText(region.translated(0, -1), Qt::AlignCenter, c);
-        }
+    explicit Painter(QPaintDevice *device)
+      : QPainter(device)
+    {}
+
+    void drawTextLeft(int x, int y, const QString &text)
+    {
+        QFontMetrics m(fontMetrics());
+        drawText(x, y + m.ascent(), text);
+    }
+
+    void drawTextRight(int x, int y, int outerw, const QString &text, int textWidth = -1)
+    {
+        QFontMetrics m(fontMetrics());
+        if (textWidth < 0) {
+            textWidth = m.horizontalAdvance(text);
+        }
+        drawText((outerw - x - textWidth), y + m.ascent(), text);
+    }
+
+    void drawPixmapLeft(int x, int y, const QPixmap &pix, const QRect &from)
+    {
+        drawPixmap(QPoint(x, y), pix, from);
+    }
+
+    void drawPixmapLeft(const QPoint &p, const QPixmap &pix, const QRect &from)
+    {
+        return drawPixmapLeft(p.x(), p.y(), pix, from);
+    }
+
+    void drawPixmapLeft(int x, int y, int w, int h, const QPixmap &pix, const QRect &from)
+    {
+        drawPixmap(QRect(x, y, w, h), pix, from);
+    }
+
+    void drawPixmapLeft(const QRect &r, const QPixmap &pix, const QRect &from)
+    {
+        return drawPixmapLeft(r.x(), r.y(), r.width(), r.height(), pix, from);
+    }
+
+    void drawPixmapLeft(int x, int y, int outerw, const QPixmap &pix)
+    {
+        Q_UNUSED(outerw);
+        drawPixmap(QPoint(x, y), pix);
+    }
+
+    void drawPixmapLeft(const QPoint &p, int outerw, const QPixmap &pix)
+    {
+        return drawPixmapLeft(p.x(), p.y(), outerw, pix);
+    }
+
+    void drawPixmapRight(int x, int y, int outerw, const QPixmap &pix, const QRect &from)
+    {
+        drawPixmap(QPoint((outerw - x - (from.width() / pix.devicePixelRatio())), y), pix, from);
+    }
+
+    void drawPixmapRight(const QPoint &p, int outerw, const QPixmap &pix, const QRect &from)
+    {
+        return drawPixmapRight(p.x(), p.y(), outerw, pix, from);
+    }
+    void
+    drawPixmapRight(int x, int y, int w, int h, int outerw, const QPixmap &pix, const QRect &from)
+    {
+        drawPixmap(QRect((outerw - x - w), y, w, h), pix, from);
+    }
+
+    void drawPixmapRight(const QRect &r, int outerw, const QPixmap &pix, const QRect &from)
+    {
+        return drawPixmapRight(r.x(), r.y(), r.width(), r.height(), outerw, pix, from);
+    }
+
+    void drawPixmapRight(int x, int y, int outerw, const QPixmap &pix)
+    {
+        drawPixmap(QPoint((outerw - x - (pix.width() / pix.devicePixelRatio())), y), pix);
+    }
+
+    void drawPixmapRight(const QPoint &p, int outerw, const QPixmap &pix)
+    {
+        return drawPixmapRight(p.x(), p.y(), outerw, pix);
+    }
+
+    void drawAvatar(const QPixmap &pix, int w, int h, int d)
+    {
+        QPainterPath pp;
+        pp.addEllipse((w - d) / 2, (h - d) / 2, d, d);
+
+        QRect region((w - d) / 2, (h - d) / 2, d, d);
+
+        setClipPath(pp);
+        drawPixmap(region, pix);
+    }
+
+    void drawLetterAvatar(const QString &c,
+                          const QColor &penColor,
+                          const QColor &brushColor,
+                          int w,
+                          int h,
+                          int d)
+    {
+        QRect region((w - d) / 2, (h - d) / 2, d, d);
+
+        setPen(Qt::NoPen);
+        setBrush(brushColor);
+
+        drawEllipse(region.center(), d / 2, d / 2);
+
+        setBrush(Qt::NoBrush);
+        drawEllipse(region.center(), d / 2, d / 2);
+
+        setPen(penColor);
+        drawText(region.translated(0, -1), Qt::AlignCenter, c);
+    }
 };
 
 class PainterHighQualityEnabler
 {
 public:
-        PainterHighQualityEnabler(Painter &p)
-          : _painter(p)
-        {
-                hints_ = QPainter::Antialiasing | QPainter::SmoothPixmapTransform |
-                         QPainter::TextAntialiasing;
+    PainterHighQualityEnabler(Painter &p)
+      : _painter(p)
+    {
+        hints_ =
+          QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing;
 
-                _painter.setRenderHints(hints_);
-        }
+        _painter.setRenderHints(hints_);
+    }
 
-        ~PainterHighQualityEnabler()
-        {
-                if (hints_)
-                        _painter.setRenderHints(hints_, false);
-        }
+    ~PainterHighQualityEnabler()
+    {
+        if (hints_)
+            _painter.setRenderHints(hints_, false);
+    }
 
-        PainterHighQualityEnabler(const PainterHighQualityEnabler &other) = delete;
-        PainterHighQualityEnabler &operator=(const PainterHighQualityEnabler &other) = delete;
+    PainterHighQualityEnabler(const PainterHighQualityEnabler &other) = delete;
+    PainterHighQualityEnabler &operator=(const PainterHighQualityEnabler &other) = delete;
 
 private:
-        Painter &_painter;
-        QPainter::RenderHints hints_ = {};
+    Painter &_painter;
+    QPainter::RenderHints hints_ = {};
 };
diff --git a/src/ui/RaisedButton.cpp b/src/ui/RaisedButton.cpp
index 563cb8e5..fd0cbd76 100644
--- a/src/ui/RaisedButton.cpp
+++ b/src/ui/RaisedButton.cpp
@@ -10,68 +10,68 @@
 void
 RaisedButton::init()
 {
-        shadow_state_machine_ = new QStateMachine(this);
-        normal_state_         = new QState;
-        pressed_state_        = new QState;
-        effect_               = new QGraphicsDropShadowEffect;
+    shadow_state_machine_ = new QStateMachine(this);
+    normal_state_         = new QState;
+    pressed_state_        = new QState;
+    effect_               = new QGraphicsDropShadowEffect;
 
-        effect_->setBlurRadius(7);
-        effect_->setOffset(QPointF(0, 2));
-        effect_->setColor(QColor(0, 0, 0, 75));
+    effect_->setBlurRadius(7);
+    effect_->setOffset(QPointF(0, 2));
+    effect_->setColor(QColor(0, 0, 0, 75));
 
-        setBackgroundMode(Qt::OpaqueMode);
-        setMinimumHeight(42);
-        setGraphicsEffect(effect_);
-        setBaseOpacity(0.3);
+    setBackgroundMode(Qt::OpaqueMode);
+    setMinimumHeight(42);
+    setGraphicsEffect(effect_);
+    setBaseOpacity(0.3);
 
-        shadow_state_machine_->addState(normal_state_);
-        shadow_state_machine_->addState(pressed_state_);
+    shadow_state_machine_->addState(normal_state_);
+    shadow_state_machine_->addState(pressed_state_);
 
-        normal_state_->assignProperty(effect_, "offset", QPointF(0, 2));
-        normal_state_->assignProperty(effect_, "blurRadius", 7);
+    normal_state_->assignProperty(effect_, "offset", QPointF(0, 2));
+    normal_state_->assignProperty(effect_, "blurRadius", 7);
 
-        pressed_state_->assignProperty(effect_, "offset", QPointF(0, 5));
-        pressed_state_->assignProperty(effect_, "blurRadius", 29);
+    pressed_state_->assignProperty(effect_, "offset", QPointF(0, 5));
+    pressed_state_->assignProperty(effect_, "blurRadius", 29);
 
-        QAbstractTransition *transition;
+    QAbstractTransition *transition;
 
-        transition = new QEventTransition(this, QEvent::MouseButtonPress);
-        transition->setTargetState(pressed_state_);
-        normal_state_->addTransition(transition);
+    transition = new QEventTransition(this, QEvent::MouseButtonPress);
+    transition->setTargetState(pressed_state_);
+    normal_state_->addTransition(transition);
 
-        transition = new QEventTransition(this, QEvent::MouseButtonDblClick);
-        transition->setTargetState(pressed_state_);
-        normal_state_->addTransition(transition);
+    transition = new QEventTransition(this, QEvent::MouseButtonDblClick);
+    transition->setTargetState(pressed_state_);
+    normal_state_->addTransition(transition);
 
-        transition = new QEventTransition(this, QEvent::MouseButtonRelease);
-        transition->setTargetState(normal_state_);
-        pressed_state_->addTransition(transition);
+    transition = new QEventTransition(this, QEvent::MouseButtonRelease);
+    transition->setTargetState(normal_state_);
+    pressed_state_->addTransition(transition);
 
-        QPropertyAnimation *animation;
+    QPropertyAnimation *animation;
 
-        animation = new QPropertyAnimation(effect_, "offset", this);
-        animation->setDuration(100);
-        shadow_state_machine_->addDefaultAnimation(animation);
+    animation = new QPropertyAnimation(effect_, "offset", this);
+    animation->setDuration(100);
+    shadow_state_machine_->addDefaultAnimation(animation);
 
-        animation = new QPropertyAnimation(effect_, "blurRadius", this);
-        animation->setDuration(100);
-        shadow_state_machine_->addDefaultAnimation(animation);
+    animation = new QPropertyAnimation(effect_, "blurRadius", this);
+    animation->setDuration(100);
+    shadow_state_machine_->addDefaultAnimation(animation);
 
-        shadow_state_machine_->setInitialState(normal_state_);
-        shadow_state_machine_->start();
+    shadow_state_machine_->setInitialState(normal_state_);
+    shadow_state_machine_->start();
 }
 
 RaisedButton::RaisedButton(QWidget *parent)
   : FlatButton(parent)
 {
-        init();
+    init();
 }
 
 RaisedButton::RaisedButton(const QString &text, QWidget *parent)
   : FlatButton(parent)
 {
-        init();
-        setText(text);
+    init();
+    setText(text);
 }
 
 RaisedButton::~RaisedButton() {}
@@ -79,15 +79,15 @@ RaisedButton::~RaisedButton() {}
 bool
 RaisedButton::event(QEvent *event)
 {
-        if (QEvent::EnabledChange == event->type()) {
-                if (isEnabled()) {
-                        shadow_state_machine_->start();
-                        effect_->setEnabled(true);
-                } else {
-                        shadow_state_machine_->stop();
-                        effect_->setEnabled(false);
-                }
+    if (QEvent::EnabledChange == event->type()) {
+        if (isEnabled()) {
+            shadow_state_machine_->start();
+            effect_->setEnabled(true);
+        } else {
+            shadow_state_machine_->stop();
+            effect_->setEnabled(false);
         }
+    }
 
-        return FlatButton::event(event);
+    return FlatButton::event(event);
 }
diff --git a/src/ui/RaisedButton.h b/src/ui/RaisedButton.h
index dcb579bb..277fa7ff 100644
--- a/src/ui/RaisedButton.h
+++ b/src/ui/RaisedButton.h
@@ -12,21 +12,21 @@
 
 class RaisedButton : public FlatButton
 {
-        Q_OBJECT
+    Q_OBJECT
 
 public:
-        explicit RaisedButton(QWidget *parent = nullptr);
-        explicit RaisedButton(const QString &text, QWidget *parent = nullptr);
-        ~RaisedButton() override;
+    explicit RaisedButton(QWidget *parent = nullptr);
+    explicit RaisedButton(const QString &text, QWidget *parent = nullptr);
+    ~RaisedButton() override;
 
 protected:
-        bool event(QEvent *event) override;
+    bool event(QEvent *event) override;
 
 private:
-        void init();
+    void init();
 
-        QStateMachine *shadow_state_machine_;
-        QState *normal_state_;
-        QState *pressed_state_;
-        QGraphicsDropShadowEffect *effect_;
+    QStateMachine *shadow_state_machine_;
+    QState *normal_state_;
+    QState *pressed_state_;
+    QGraphicsDropShadowEffect *effect_;
 };
diff --git a/src/ui/Ripple.cpp b/src/ui/Ripple.cpp
index f0455f0b..72cf2da2 100644
--- a/src/ui/Ripple.cpp
+++ b/src/ui/Ripple.cpp
@@ -14,7 +14,7 @@ Ripple::Ripple(const QPoint &center, QObject *parent)
   , opacity_(0)
   , center_(center)
 {
-        init();
+    init();
 }
 
 Ripple::Ripple(const QPoint &center, RippleOverlay *overlay, QObject *parent)
@@ -26,86 +26,86 @@ Ripple::Ripple(const QPoint &center, RippleOverlay *overlay, QObject *parent)
   , opacity_(0)
   , center_(center)
 {
-        init();
+    init();
 }
 
 void
 Ripple::setRadius(qreal radius)
 {
-        Q_ASSERT(overlay_);
+    Q_ASSERT(overlay_);
 
-        if (radius_ == radius)
-                return;
+    if (radius_ == radius)
+        return;
 
-        radius_ = radius;
-        overlay_->update();
+    radius_ = radius;
+    overlay_->update();
 }
 
 void
 Ripple::setOpacity(qreal opacity)
 {
-        Q_ASSERT(overlay_);
+    Q_ASSERT(overlay_);
 
-        if (opacity_ == opacity)
-                return;
+    if (opacity_ == opacity)
+        return;
 
-        opacity_ = opacity;
-        overlay_->update();
+    opacity_ = opacity;
+    overlay_->update();
 }
 
 void
 Ripple::setColor(const QColor &color)
 {
-        if (brush_.color() == color)
-                return;
+    if (brush_.color() == color)
+        return;
 
-        brush_.setColor(color);
+    brush_.setColor(color);
 
-        if (overlay_)
-                overlay_->update();
+    if (overlay_)
+        overlay_->update();
 }
 
 void
 Ripple::setBrush(const QBrush &brush)
 {
-        brush_ = brush;
+    brush_ = brush;
 
-        if (overlay_)
-                overlay_->update();
+    if (overlay_)
+        overlay_->update();
 }
 
 void
 Ripple::destroy()
 {
-        Q_ASSERT(overlay_);
+    Q_ASSERT(overlay_);
 
-        overlay_->removeRipple(this);
+    overlay_->removeRipple(this);
 }
 
 QPropertyAnimation *
 Ripple::animate(const QByteArray &property, const QEasingCurve &easing, int duration)
 {
-        QPropertyAnimation *animation = new QPropertyAnimation;
-        animation->setTargetObject(this);
-        animation->setPropertyName(property);
-        animation->setEasingCurve(easing);
-        animation->setDuration(duration);
+    QPropertyAnimation *animation = new QPropertyAnimation;
+    animation->setTargetObject(this);
+    animation->setPropertyName(property);
+    animation->setEasingCurve(easing);
+    animation->setDuration(duration);
 
-        addAnimation(animation);
+    addAnimation(animation);
 
-        return animation;
+    return animation;
 }
 
 void
 Ripple::init()
 {
-        setOpacityStartValue(0.5);
-        setOpacityEndValue(0);
-        setRadiusStartValue(0);
-        setRadiusEndValue(300);
+    setOpacityStartValue(0.5);
+    setOpacityEndValue(0);
+    setRadiusStartValue(0);
+    setRadiusEndValue(300);
 
-        brush_.setColor(Qt::black);
-        brush_.setStyle(Qt::SolidPattern);
+    brush_.setColor(Qt::black);
+    brush_.setStyle(Qt::SolidPattern);
 
-        connect(this, SIGNAL(finished()), this, SLOT(destroy()));
+    connect(this, SIGNAL(finished()), this, SLOT(destroy()));
 }
diff --git a/src/ui/Ripple.h b/src/ui/Ripple.h
index 2ad42b9e..df09caba 100644
--- a/src/ui/Ripple.h
+++ b/src/ui/Ripple.h
@@ -14,136 +14,136 @@ class RippleOverlay;
 
 class Ripple : public QParallelAnimationGroup
 {
-        Q_OBJECT
+    Q_OBJECT
 
-        Q_PROPERTY(qreal radius WRITE setRadius READ radius)
-        Q_PROPERTY(qreal opacity WRITE setOpacity READ opacity)
+    Q_PROPERTY(qreal radius WRITE setRadius READ radius)
+    Q_PROPERTY(qreal opacity WRITE setOpacity READ opacity)
 
 public:
-        explicit Ripple(const QPoint &center, QObject *parent = nullptr);
-        Ripple(const QPoint &center, RippleOverlay *overlay, QObject *parent = nullptr);
+    explicit Ripple(const QPoint &center, QObject *parent = nullptr);
+    Ripple(const QPoint &center, RippleOverlay *overlay, QObject *parent = nullptr);
 
-        inline void setOverlay(RippleOverlay *overlay);
+    inline void setOverlay(RippleOverlay *overlay);
 
-        void setRadius(qreal radius);
-        void setOpacity(qreal opacity);
-        void setColor(const QColor &color);
-        void setBrush(const QBrush &brush);
+    void setRadius(qreal radius);
+    void setOpacity(qreal opacity);
+    void setColor(const QColor &color);
+    void setBrush(const QBrush &brush);
 
-        inline qreal radius() const;
-        inline qreal opacity() const;
-        inline QColor color() const;
-        inline QBrush brush() const;
-        inline QPoint center() const;
+    inline qreal radius() const;
+    inline qreal opacity() const;
+    inline QColor color() const;
+    inline QBrush brush() const;
+    inline QPoint center() const;
 
-        inline QPropertyAnimation *radiusAnimation() const;
-        inline QPropertyAnimation *opacityAnimation() const;
+    inline QPropertyAnimation *radiusAnimation() const;
+    inline QPropertyAnimation *opacityAnimation() const;
 
-        inline void setOpacityStartValue(qreal value);
-        inline void setOpacityEndValue(qreal value);
-        inline void setRadiusStartValue(qreal value);
-        inline void setRadiusEndValue(qreal value);
-        inline void setDuration(int msecs);
+    inline void setOpacityStartValue(qreal value);
+    inline void setOpacityEndValue(qreal value);
+    inline void setRadiusStartValue(qreal value);
+    inline void setRadiusEndValue(qreal value);
+    inline void setDuration(int msecs);
 
 protected slots:
-        void destroy();
+    void destroy();
 
 private:
-        Q_DISABLE_COPY(Ripple)
+    Q_DISABLE_COPY(Ripple)
 
-        QPropertyAnimation *animate(const QByteArray &property,
-                                    const QEasingCurve &easing = QEasingCurve::OutQuad,
-                                    int duration               = 800);
+    QPropertyAnimation *animate(const QByteArray &property,
+                                const QEasingCurve &easing = QEasingCurve::OutQuad,
+                                int duration               = 800);
 
-        void init();
+    void init();
 
-        RippleOverlay *overlay_;
+    RippleOverlay *overlay_;
 
-        QPropertyAnimation *const radius_anim_;
-        QPropertyAnimation *const opacity_anim_;
+    QPropertyAnimation *const radius_anim_;
+    QPropertyAnimation *const opacity_anim_;
 
-        qreal radius_;
-        qreal opacity_;
+    qreal radius_;
+    qreal opacity_;
 
-        QPoint center_;
-        QBrush brush_;
+    QPoint center_;
+    QBrush brush_;
 };
 
 inline void
 Ripple::setOverlay(RippleOverlay *overlay)
 {
-        overlay_ = overlay;
+    overlay_ = overlay;
 }
 
 inline qreal
 Ripple::radius() const
 {
-        return radius_;
+    return radius_;
 }
 
 inline qreal
 Ripple::opacity() const
 {
-        return opacity_;
+    return opacity_;
 }
 
 inline QColor
 Ripple::color() const
 {
-        return brush_.color();
+    return brush_.color();
 }
 
 inline QBrush
 Ripple::brush() const
 {
-        return brush_;
+    return brush_;
 }
 
 inline QPoint
 Ripple::center() const
 {
-        return center_;
+    return center_;
 }
 
 inline QPropertyAnimation *
 Ripple::radiusAnimation() const
 {
-        return radius_anim_;
+    return radius_anim_;
 }
 
 inline QPropertyAnimation *
 Ripple::opacityAnimation() const
 {
-        return opacity_anim_;
+    return opacity_anim_;
 }
 
 inline void
 Ripple::setOpacityStartValue(qreal value)
 {
-        opacity_anim_->setStartValue(value);
+    opacity_anim_->setStartValue(value);
 }
 
 inline void
 Ripple::setOpacityEndValue(qreal value)
 {
-        opacity_anim_->setEndValue(value);
+    opacity_anim_->setEndValue(value);
 }
 
 inline void
 Ripple::setRadiusStartValue(qreal value)
 {
-        radius_anim_->setStartValue(value);
+    radius_anim_->setStartValue(value);
 }
 
 inline void
 Ripple::setRadiusEndValue(qreal value)
 {
-        radius_anim_->setEndValue(value);
+    radius_anim_->setEndValue(value);
 }
 
 inline void
 Ripple::setDuration(int msecs)
 {
-        radius_anim_->setDuration(msecs);
-        opacity_anim_->setDuration(msecs);
+    radius_anim_->setDuration(msecs);
+    opacity_anim_->setDuration(msecs);
 }
diff --git a/src/ui/RippleOverlay.cpp b/src/ui/RippleOverlay.cpp
index 00915deb..6745cc37 100644
--- a/src/ui/RippleOverlay.cpp
+++ b/src/ui/RippleOverlay.cpp
@@ -11,56 +11,56 @@ RippleOverlay::RippleOverlay(QWidget *parent)
   : OverlayWidget(parent)
   , use_clip_(false)
 {
-        setAttribute(Qt::WA_TransparentForMouseEvents);
-        setAttribute(Qt::WA_NoSystemBackground);
+    setAttribute(Qt::WA_TransparentForMouseEvents);
+    setAttribute(Qt::WA_NoSystemBackground);
 }
 
 void
 RippleOverlay::addRipple(Ripple *ripple)
 {
-        ripple->setOverlay(this);
-        ripples_.push_back(ripple);
-        ripple->start();
+    ripple->setOverlay(this);
+    ripples_.push_back(ripple);
+    ripple->start();
 }
 
 void
 RippleOverlay::addRipple(const QPoint &position, qreal radius)
 {
-        Ripple *ripple = new Ripple(position);
-        ripple->setRadiusEndValue(radius);
-        addRipple(ripple);
+    Ripple *ripple = new Ripple(position);
+    ripple->setRadiusEndValue(radius);
+    addRipple(ripple);
 }
 
 void
 RippleOverlay::removeRipple(Ripple *ripple)
 {
-        if (ripples_.removeOne(ripple))
-                delete ripple;
+    if (ripples_.removeOne(ripple))
+        delete ripple;
 }
 
 void
 RippleOverlay::paintEvent(QPaintEvent *event)
 {
-        Q_UNUSED(event)
+    Q_UNUSED(event)
 
-        QPainter painter(this);
-        painter.setRenderHint(QPainter::Antialiasing);
-        painter.setPen(Qt::NoPen);
+    QPainter painter(this);
+    painter.setRenderHint(QPainter::Antialiasing);
+    painter.setPen(Qt::NoPen);
 
-        if (use_clip_)
-                painter.setClipPath(clip_path_);
+    if (use_clip_)
+        painter.setClipPath(clip_path_);
 
-        for (auto it = ripples_.constBegin(); it != ripples_.constEnd(); ++it)
-                paintRipple(&painter, *it);
+    for (auto it = ripples_.constBegin(); it != ripples_.constEnd(); ++it)
+        paintRipple(&painter, *it);
 }
 
 void
 RippleOverlay::paintRipple(QPainter *painter, Ripple *ripple)
 {
-        const qreal radius   = ripple->radius();
-        const QPointF center = ripple->center();
+    const qreal radius   = ripple->radius();
+    const QPointF center = ripple->center();
 
-        painter->setOpacity(ripple->opacity());
-        painter->setBrush(ripple->brush());
-        painter->drawEllipse(center, radius, radius);
+    painter->setOpacity(ripple->opacity());
+    painter->setBrush(ripple->brush());
+    painter->drawEllipse(center, radius, radius);
 }
diff --git a/src/ui/RippleOverlay.h b/src/ui/RippleOverlay.h
index 7ae3e4f1..3256c28d 100644
--- a/src/ui/RippleOverlay.h
+++ b/src/ui/RippleOverlay.h
@@ -12,50 +12,50 @@ class Ripple;
 
 class RippleOverlay : public OverlayWidget
 {
-        Q_OBJECT
+    Q_OBJECT
 
 public:
-        explicit RippleOverlay(QWidget *parent = nullptr);
+    explicit RippleOverlay(QWidget *parent = nullptr);
 
-        void addRipple(Ripple *ripple);
-        void addRipple(const QPoint &position, qreal radius = 300);
+    void addRipple(Ripple *ripple);
+    void addRipple(const QPoint &position, qreal radius = 300);
 
-        void removeRipple(Ripple *ripple);
+    void removeRipple(Ripple *ripple);
 
-        inline void setClipping(bool enable);
-        inline bool hasClipping() const;
+    inline void setClipping(bool enable);
+    inline bool hasClipping() const;
 
-        inline void setClipPath(const QPainterPath &path);
+    inline void setClipPath(const QPainterPath &path);
 
 protected:
-        void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
+    void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
 
 private:
-        Q_DISABLE_COPY(RippleOverlay)
+    Q_DISABLE_COPY(RippleOverlay)
 
-        void paintRipple(QPainter *painter, Ripple *ripple);
+    void paintRipple(QPainter *painter, Ripple *ripple);
 
-        QList<Ripple *> ripples_;
-        QPainterPath clip_path_;
-        bool use_clip_;
+    QList<Ripple *> ripples_;
+    QPainterPath clip_path_;
+    bool use_clip_;
 };
 
 inline void
 RippleOverlay::setClipping(bool enable)
 {
-        use_clip_ = enable;
-        update();
+    use_clip_ = enable;
+    update();
 }
 
 inline bool
 RippleOverlay::hasClipping() const
 {
-        return use_clip_;
+    return use_clip_;
 }
 
 inline void
 RippleOverlay::setClipPath(const QPainterPath &path)
 {
-        clip_path_ = path;
-        update();
+    clip_path_ = path;
+    update();
 }
diff --git a/src/ui/RoomSettings.cpp b/src/ui/RoomSettings.cpp
index 2fb93325..ed8a7cd8 100644
--- a/src/ui/RoomSettings.cpp
+++ b/src/ui/RoomSettings.cpp
@@ -27,479 +27,473 @@ EditModal::EditModal(const QString &roomId, QWidget *parent)
   : QWidget(parent)
   , roomId_{roomId}
 {
-        setAutoFillBackground(true);
-        setAttribute(Qt::WA_DeleteOnClose, true);
-        setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
-        setWindowModality(Qt::WindowModal);
-
-        QFont largeFont;
-        largeFont.setPointSizeF(largeFont.pointSizeF() * 1.4);
-        setMinimumWidth(conf::window::minModalWidth);
-        setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
-
-        auto layout = new QVBoxLayout(this);
-
-        applyBtn_  = new QPushButton(tr("Apply"), this);
-        cancelBtn_ = new QPushButton(tr("Cancel"), this);
-        cancelBtn_->setDefault(true);
-
-        auto btnLayout = new QHBoxLayout;
-        btnLayout->addStretch(1);
-        btnLayout->setSpacing(15);
-        btnLayout->addWidget(cancelBtn_);
-        btnLayout->addWidget(applyBtn_);
-
-        nameInput_ = new TextField(this);
-        nameInput_->setLabel(tr("Name").toUpper());
-        topicInput_ = new TextField(this);
-        topicInput_->setLabel(tr("Topic").toUpper());
-
-        errorField_ = new QLabel(this);
-        errorField_->setWordWrap(true);
-        errorField_->hide();
-
-        layout->addWidget(nameInput_);
-        layout->addWidget(topicInput_);
-        layout->addLayout(btnLayout, 1);
-
-        auto labelLayout = new QHBoxLayout;
-        labelLayout->setAlignment(Qt::AlignHCenter);
-        labelLayout->addWidget(errorField_);
-        layout->addLayout(labelLayout);
-
-        connect(applyBtn_, &QPushButton::clicked, this, &EditModal::applyClicked);
-        connect(cancelBtn_, &QPushButton::clicked, this, &EditModal::close);
-
-        auto window = QApplication::activeWindow();
-
-        if (window != nullptr) {
-                auto center = window->frameGeometry().center();
-                move(center.x() - (width() * 0.5), center.y() - (height() * 0.5));
-        }
+    setAutoFillBackground(true);
+    setAttribute(Qt::WA_DeleteOnClose, true);
+    setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint);
+    setWindowModality(Qt::WindowModal);
+
+    QFont largeFont;
+    largeFont.setPointSizeF(largeFont.pointSizeF() * 1.4);
+    setMinimumWidth(conf::window::minModalWidth);
+    setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
+
+    auto layout = new QVBoxLayout(this);
+
+    applyBtn_  = new QPushButton(tr("Apply"), this);
+    cancelBtn_ = new QPushButton(tr("Cancel"), this);
+    cancelBtn_->setDefault(true);
+
+    auto btnLayout = new QHBoxLayout;
+    btnLayout->addStretch(1);
+    btnLayout->setSpacing(15);
+    btnLayout->addWidget(cancelBtn_);
+    btnLayout->addWidget(applyBtn_);
+
+    nameInput_ = new TextField(this);
+    nameInput_->setLabel(tr("Name").toUpper());
+    topicInput_ = new TextField(this);
+    topicInput_->setLabel(tr("Topic").toUpper());
+
+    errorField_ = new QLabel(this);
+    errorField_->setWordWrap(true);
+    errorField_->hide();
+
+    layout->addWidget(nameInput_);
+    layout->addWidget(topicInput_);
+    layout->addLayout(btnLayout, 1);
+
+    auto labelLayout = new QHBoxLayout;
+    labelLayout->setAlignment(Qt::AlignHCenter);
+    labelLayout->addWidget(errorField_);
+    layout->addLayout(labelLayout);
+
+    connect(applyBtn_, &QPushButton::clicked, this, &EditModal::applyClicked);
+    connect(cancelBtn_, &QPushButton::clicked, this, &EditModal::close);
+
+    auto window = QApplication::activeWindow();
+
+    if (window != nullptr) {
+        auto center = window->frameGeometry().center();
+        move(center.x() - (width() * 0.5), center.y() - (height() * 0.5));
+    }
 }
 
 void
 EditModal::topicEventSent(const QString &topic)
 {
-        errorField_->hide();
-        emit topicChanged(topic);
-        close();
+    errorField_->hide();
+    emit topicChanged(topic);
+    close();
 }
 
 void
 EditModal::nameEventSent(const QString &name)
 {
-        errorField_->hide();
-        emit nameChanged(name);
-        close();
+    errorField_->hide();
+    emit nameChanged(name);
+    close();
 }
 
 void
 EditModal::error(const QString &msg)
 {
-        errorField_->setText(msg);
-        errorField_->show();
+    errorField_->setText(msg);
+    errorField_->show();
 }
 
 void
 EditModal::applyClicked()
 {
-        // Check if the values are changed from the originals.
-        auto newName  = nameInput_->text().trimmed();
-        auto newTopic = topicInput_->text().trimmed();
+    // Check if the values are changed from the originals.
+    auto newName  = nameInput_->text().trimmed();
+    auto newTopic = topicInput_->text().trimmed();
 
-        errorField_->hide();
+    errorField_->hide();
 
-        if (newName == initialName_ && newTopic == initialTopic_) {
-                close();
-                return;
-        }
+    if (newName == initialName_ && newTopic == initialTopic_) {
+        close();
+        return;
+    }
 
-        using namespace mtx::events;
-        auto proxy = std::make_shared<ThreadProxy>();
-        connect(proxy.get(), &ThreadProxy::topicEventSent, this, &EditModal::topicEventSent);
-        connect(proxy.get(), &ThreadProxy::nameEventSent, this, &EditModal::nameEventSent);
-        connect(proxy.get(), &ThreadProxy::error, this, &EditModal::error);
-
-        if (newName != initialName_ && !newName.isEmpty()) {
-                state::Name body;
-                body.name = newName.toStdString();
-
-                http::client()->send_state_event(
-                  roomId_.toStdString(),
-                  body,
-                  [proxy, newName](const mtx::responses::EventId &, mtx::http::RequestErr err) {
-                          if (err) {
-                                  emit proxy->error(
-                                    QString::fromStdString(err->matrix_error.error));
-                                  return;
-                          }
-
-                          emit proxy->nameEventSent(newName);
-                  });
-        }
+    using namespace mtx::events;
+    auto proxy = std::make_shared<ThreadProxy>();
+    connect(proxy.get(), &ThreadProxy::topicEventSent, this, &EditModal::topicEventSent);
+    connect(proxy.get(), &ThreadProxy::nameEventSent, this, &EditModal::nameEventSent);
+    connect(proxy.get(), &ThreadProxy::error, this, &EditModal::error);
 
-        if (newTopic != initialTopic_ && !newTopic.isEmpty()) {
-                state::Topic body;
-                body.topic = newTopic.toStdString();
-
-                http::client()->send_state_event(
-                  roomId_.toStdString(),
-                  body,
-                  [proxy, newTopic](const mtx::responses::EventId &, mtx::http::RequestErr err) {
-                          if (err) {
-                                  emit proxy->error(
-                                    QString::fromStdString(err->matrix_error.error));
-                                  return;
-                          }
-
-                          emit proxy->topicEventSent(newTopic);
-                  });
-        }
+    if (newName != initialName_ && !newName.isEmpty()) {
+        state::Name body;
+        body.name = newName.toStdString();
+
+        http::client()->send_state_event(
+          roomId_.toStdString(),
+          body,
+          [proxy, newName](const mtx::responses::EventId &, mtx::http::RequestErr err) {
+              if (err) {
+                  emit proxy->error(QString::fromStdString(err->matrix_error.error));
+                  return;
+              }
+
+              emit proxy->nameEventSent(newName);
+          });
+    }
+
+    if (newTopic != initialTopic_ && !newTopic.isEmpty()) {
+        state::Topic body;
+        body.topic = newTopic.toStdString();
+
+        http::client()->send_state_event(
+          roomId_.toStdString(),
+          body,
+          [proxy, newTopic](const mtx::responses::EventId &, mtx::http::RequestErr err) {
+              if (err) {
+                  emit proxy->error(QString::fromStdString(err->matrix_error.error));
+                  return;
+              }
+
+              emit proxy->topicEventSent(newTopic);
+          });
+    }
 }
 
 void
 EditModal::setFields(const QString &roomName, const QString &roomTopic)
 {
-        initialName_  = roomName;
-        initialTopic_ = roomTopic;
+    initialName_  = roomName;
+    initialTopic_ = roomTopic;
 
-        nameInput_->setText(roomName);
-        topicInput_->setText(roomTopic);
+    nameInput_->setText(roomName);
+    topicInput_->setText(roomTopic);
 }
 
 RoomSettings::RoomSettings(QString roomid, QObject *parent)
   : QObject(parent)
   , roomid_{std::move(roomid)}
 {
-        retrieveRoomInfo();
-
-        // get room setting notifications
-        http::client()->get_pushrules(
-          "global",
-          "override",
-          roomid_.toStdString(),
-          [this](const mtx::pushrules::PushRule &rule, mtx::http::RequestErr &err) {
-                  if (err) {
-                          if (err->status_code == 404)
-                                  http::client()->get_pushrules(
-                                    "global",
-                                    "room",
-                                    roomid_.toStdString(),
-                                    [this](const mtx::pushrules::PushRule &rule,
-                                           mtx::http::RequestErr &err) {
-                                            if (err) {
-                                                    notifications_ = 2; // all messages
-                                                    emit notificationsChanged();
-                                                    return;
-                                            }
-
-                                            if (rule.enabled) {
-                                                    notifications_ = 1; // mentions only
-                                                    emit notificationsChanged();
-                                            }
-                                    });
-                          return;
-                  }
-
-                  if (rule.enabled) {
-                          notifications_ = 0; // muted
-                          emit notificationsChanged();
-                  } else {
-                          notifications_ = 2; // all messages
-                          emit notificationsChanged();
-                  }
-          });
-
-        // access rules
-        if (info_.join_rule == state::JoinRule::Public) {
-                if (info_.guest_access) {
-                        accessRules_ = 0;
-                } else {
-                        accessRules_ = 1;
-                }
-        } else if (info_.join_rule == state::JoinRule::Invite) {
-                accessRules_ = 2;
-        } else if (info_.join_rule == state::JoinRule::Knock) {
-                accessRules_ = 3;
-        } else if (info_.join_rule == state::JoinRule::Restricted) {
-                accessRules_ = 4;
+    retrieveRoomInfo();
+
+    // get room setting notifications
+    http::client()->get_pushrules(
+      "global",
+      "override",
+      roomid_.toStdString(),
+      [this](const mtx::pushrules::PushRule &rule, mtx::http::RequestErr &err) {
+          if (err) {
+              if (err->status_code == 404)
+                  http::client()->get_pushrules(
+                    "global",
+                    "room",
+                    roomid_.toStdString(),
+                    [this](const mtx::pushrules::PushRule &rule, mtx::http::RequestErr &err) {
+                        if (err) {
+                            notifications_ = 2; // all messages
+                            emit notificationsChanged();
+                            return;
+                        }
+
+                        if (rule.enabled) {
+                            notifications_ = 1; // mentions only
+                            emit notificationsChanged();
+                        }
+                    });
+              return;
+          }
+
+          if (rule.enabled) {
+              notifications_ = 0; // muted
+              emit notificationsChanged();
+          } else {
+              notifications_ = 2; // all messages
+              emit notificationsChanged();
+          }
+      });
+
+    // access rules
+    if (info_.join_rule == state::JoinRule::Public) {
+        if (info_.guest_access) {
+            accessRules_ = 0;
+        } else {
+            accessRules_ = 1;
         }
-        emit accessJoinRulesChanged();
+    } else if (info_.join_rule == state::JoinRule::Invite) {
+        accessRules_ = 2;
+    } else if (info_.join_rule == state::JoinRule::Knock) {
+        accessRules_ = 3;
+    } else if (info_.join_rule == state::JoinRule::Restricted) {
+        accessRules_ = 4;
+    }
+    emit accessJoinRulesChanged();
 }
 
 QString
 RoomSettings::roomName() const
 {
-        return utils::replaceEmoji(QString::fromStdString(info_.name).toHtmlEscaped());
+    return utils::replaceEmoji(QString::fromStdString(info_.name).toHtmlEscaped());
 }
 
 QString
 RoomSettings::roomTopic() const
 {
-        return utils::replaceEmoji(utils::linkifyMessage(
-          QString::fromStdString(info_.topic).toHtmlEscaped().replace("\n", "<br>")));
+    return utils::replaceEmoji(utils::linkifyMessage(
+      QString::fromStdString(info_.topic).toHtmlEscaped().replace("\n", "<br>")));
 }
 
 QString
 RoomSettings::roomId() const
 {
-        return roomid_;
+    return roomid_;
 }
 
 QString
 RoomSettings::roomVersion() const
 {
-        return QString::fromStdString(info_.version);
+    return QString::fromStdString(info_.version);
 }
 
 bool
 RoomSettings::isLoading() const
 {
-        return isLoading_;
+    return isLoading_;
 }
 
 QString
 RoomSettings::roomAvatarUrl()
 {
-        return QString::fromStdString(info_.avatar_url);
+    return QString::fromStdString(info_.avatar_url);
 }
 
 int
 RoomSettings::memberCount() const
 {
-        return info_.member_count;
+    return info_.member_count;
 }
 
 void
 RoomSettings::retrieveRoomInfo()
 {
-        try {
-                usesEncryption_ = cache::isRoomEncrypted(roomid_.toStdString());
-                info_           = cache::singleRoomInfo(roomid_.toStdString());
-        } catch (const lmdb::error &) {
-                nhlog::db()->warn("failed to retrieve room info from cache: {}",
-                                  roomid_.toStdString());
-        }
+    try {
+        usesEncryption_ = cache::isRoomEncrypted(roomid_.toStdString());
+        info_           = cache::singleRoomInfo(roomid_.toStdString());
+    } catch (const lmdb::error &) {
+        nhlog::db()->warn("failed to retrieve room info from cache: {}", roomid_.toStdString());
+    }
 }
 
 int
 RoomSettings::notifications()
 {
-        return notifications_;
+    return notifications_;
 }
 
 int
 RoomSettings::accessJoinRules()
 {
-        return accessRules_;
+    return accessRules_;
 }
 
 void
 RoomSettings::enableEncryption()
 {
-        if (usesEncryption_)
-                return;
-
-        const auto room_id = roomid_.toStdString();
-        http::client()->enable_encryption(
-          room_id, [room_id, this](const mtx::responses::EventId &, mtx::http::RequestErr err) {
-                  if (err) {
-                          int status_code = static_cast<int>(err->status_code);
-                          nhlog::net()->warn("failed to enable encryption in room ({}): {} {}",
-                                             room_id,
-                                             err->matrix_error.error,
-                                             status_code);
-                          emit displayError(
-                            tr("Failed to enable encryption: %1")
-                              .arg(QString::fromStdString(err->matrix_error.error)));
-                          usesEncryption_ = false;
-                          emit encryptionChanged();
-                          return;
-                  }
-
-                  nhlog::net()->info("enabled encryption on room ({})", room_id);
-          });
-
-        usesEncryption_ = true;
-        emit encryptionChanged();
+    if (usesEncryption_)
+        return;
+
+    const auto room_id = roomid_.toStdString();
+    http::client()->enable_encryption(
+      room_id, [room_id, this](const mtx::responses::EventId &, mtx::http::RequestErr err) {
+          if (err) {
+              int status_code = static_cast<int>(err->status_code);
+              nhlog::net()->warn("failed to enable encryption in room ({}): {} {}",
+                                 room_id,
+                                 err->matrix_error.error,
+                                 status_code);
+              emit displayError(tr("Failed to enable encryption: %1")
+                                  .arg(QString::fromStdString(err->matrix_error.error)));
+              usesEncryption_ = false;
+              emit encryptionChanged();
+              return;
+          }
+
+          nhlog::net()->info("enabled encryption on room ({})", room_id);
+      });
+
+    usesEncryption_ = true;
+    emit encryptionChanged();
 }
 
 bool
 RoomSettings::canChangeJoinRules() const
 {
-        try {
-                return cache::hasEnoughPowerLevel({EventType::RoomJoinRules},
-                                                  roomid_.toStdString(),
-                                                  utils::localUser().toStdString());
-        } catch (const lmdb::error &e) {
-                nhlog::db()->warn("lmdb error: {}", e.what());
-        }
-
-        return false;
+    try {
+        return cache::hasEnoughPowerLevel(
+          {EventType::RoomJoinRules}, roomid_.toStdString(), utils::localUser().toStdString());
+    } catch (const lmdb::error &e) {
+        nhlog::db()->warn("lmdb error: {}", e.what());
+    }
+
+    return false;
 }
 
 bool
 RoomSettings::canChangeNameAndTopic() const
 {
-        try {
-                return cache::hasEnoughPowerLevel({EventType::RoomName, EventType::RoomTopic},
-                                                  roomid_.toStdString(),
-                                                  utils::localUser().toStdString());
-        } catch (const lmdb::error &e) {
-                nhlog::db()->warn("lmdb error: {}", e.what());
-        }
-
-        return false;
+    try {
+        return cache::hasEnoughPowerLevel({EventType::RoomName, EventType::RoomTopic},
+                                          roomid_.toStdString(),
+                                          utils::localUser().toStdString());
+    } catch (const lmdb::error &e) {
+        nhlog::db()->warn("lmdb error: {}", e.what());
+    }
+
+    return false;
 }
 
 bool
 RoomSettings::canChangeAvatar() const
 {
-        try {
-                return cache::hasEnoughPowerLevel(
-                  {EventType::RoomAvatar}, roomid_.toStdString(), utils::localUser().toStdString());
-        } catch (const lmdb::error &e) {
-                nhlog::db()->warn("lmdb error: {}", e.what());
-        }
-
-        return false;
+    try {
+        return cache::hasEnoughPowerLevel(
+          {EventType::RoomAvatar}, roomid_.toStdString(), utils::localUser().toStdString());
+    } catch (const lmdb::error &e) {
+        nhlog::db()->warn("lmdb error: {}", e.what());
+    }
+
+    return false;
 }
 
 bool
 RoomSettings::isEncryptionEnabled() const
 {
-        return usesEncryption_;
+    return usesEncryption_;
 }
 
 bool
 RoomSettings::supportsKnocking() const
 {
-        return info_.version != "" && info_.version != "1" && info_.version != "2" &&
-               info_.version != "3" && info_.version != "4" && info_.version != "5" &&
-               info_.version != "6";
+    return info_.version != "" && info_.version != "1" && info_.version != "2" &&
+           info_.version != "3" && info_.version != "4" && info_.version != "5" &&
+           info_.version != "6";
 }
 bool
 RoomSettings::supportsRestricted() const
 {
-        return info_.version != "" && info_.version != "1" && info_.version != "2" &&
-               info_.version != "3" && info_.version != "4" && info_.version != "5" &&
-               info_.version != "6" && info_.version != "7";
+    return info_.version != "" && info_.version != "1" && info_.version != "2" &&
+           info_.version != "3" && info_.version != "4" && info_.version != "5" &&
+           info_.version != "6" && info_.version != "7";
 }
 
 void
 RoomSettings::openEditModal()
 {
-        retrieveRoomInfo();
-
-        auto modal = new EditModal(roomid_);
-        modal->setFields(QString::fromStdString(info_.name), QString::fromStdString(info_.topic));
-        modal->raise();
-        modal->show();
-        connect(modal, &EditModal::nameChanged, this, [this](const QString &newName) {
-                info_.name = newName.toStdString();
-                emit roomNameChanged();
-        });
-
-        connect(modal, &EditModal::topicChanged, this, [this](const QString &newTopic) {
-                info_.topic = newTopic.toStdString();
-                emit roomTopicChanged();
-        });
+    retrieveRoomInfo();
+
+    auto modal = new EditModal(roomid_);
+    modal->setFields(QString::fromStdString(info_.name), QString::fromStdString(info_.topic));
+    modal->raise();
+    modal->show();
+    connect(modal, &EditModal::nameChanged, this, [this](const QString &newName) {
+        info_.name = newName.toStdString();
+        emit roomNameChanged();
+    });
+
+    connect(modal, &EditModal::topicChanged, this, [this](const QString &newTopic) {
+        info_.topic = newTopic.toStdString();
+        emit roomTopicChanged();
+    });
 }
 
 void
 RoomSettings::changeNotifications(int currentIndex)
 {
-        notifications_ = currentIndex;
-
-        std::string room_id = roomid_.toStdString();
-        if (notifications_ == 0) {
-                // mute room
-                // delete old rule first, then add new rule
-                mtx::pushrules::PushRule rule;
-                rule.actions = {mtx::pushrules::actions::dont_notify{}};
-                mtx::pushrules::PushCondition condition;
-                condition.kind    = "event_match";
-                condition.key     = "room_id";
-                condition.pattern = room_id;
-                rule.conditions   = {condition};
-
-                http::client()->put_pushrules(
-                  "global", "override", room_id, rule, [room_id](mtx::http::RequestErr &err) {
-                          if (err)
-                                  nhlog::net()->error("failed to set pushrule for room {}: {} {}",
-                                                      room_id,
-                                                      static_cast<int>(err->status_code),
-                                                      err->matrix_error.error);
-                          http::client()->delete_pushrules(
-                            "global", "room", room_id, [room_id](mtx::http::RequestErr &) {});
-                  });
-        } else if (notifications_ == 1) {
-                // mentions only
-                // delete old rule first, then add new rule
-                mtx::pushrules::PushRule rule;
-                rule.actions = {mtx::pushrules::actions::dont_notify{}};
-                http::client()->put_pushrules(
-                  "global", "room", room_id, rule, [room_id](mtx::http::RequestErr &err) {
-                          if (err)
-                                  nhlog::net()->error("failed to set pushrule for room {}: {} {}",
-                                                      room_id,
-                                                      static_cast<int>(err->status_code),
-                                                      err->matrix_error.error);
-                          http::client()->delete_pushrules(
-                            "global", "override", room_id, [room_id](mtx::http::RequestErr &) {});
-                  });
-        } else {
-                // all messages
-                http::client()->delete_pushrules(
-                  "global", "override", room_id, [room_id](mtx::http::RequestErr &) {
-                          http::client()->delete_pushrules(
-                            "global", "room", room_id, [room_id](mtx::http::RequestErr &) {});
-                  });
-        }
+    notifications_ = currentIndex;
+
+    std::string room_id = roomid_.toStdString();
+    if (notifications_ == 0) {
+        // mute room
+        // delete old rule first, then add new rule
+        mtx::pushrules::PushRule rule;
+        rule.actions = {mtx::pushrules::actions::dont_notify{}};
+        mtx::pushrules::PushCondition condition;
+        condition.kind    = "event_match";
+        condition.key     = "room_id";
+        condition.pattern = room_id;
+        rule.conditions   = {condition};
+
+        http::client()->put_pushrules(
+          "global", "override", room_id, rule, [room_id](mtx::http::RequestErr &err) {
+              if (err)
+                  nhlog::net()->error("failed to set pushrule for room {}: {} {}",
+                                      room_id,
+                                      static_cast<int>(err->status_code),
+                                      err->matrix_error.error);
+              http::client()->delete_pushrules(
+                "global", "room", room_id, [room_id](mtx::http::RequestErr &) {});
+          });
+    } else if (notifications_ == 1) {
+        // mentions only
+        // delete old rule first, then add new rule
+        mtx::pushrules::PushRule rule;
+        rule.actions = {mtx::pushrules::actions::dont_notify{}};
+        http::client()->put_pushrules(
+          "global", "room", room_id, rule, [room_id](mtx::http::RequestErr &err) {
+              if (err)
+                  nhlog::net()->error("failed to set pushrule for room {}: {} {}",
+                                      room_id,
+                                      static_cast<int>(err->status_code),
+                                      err->matrix_error.error);
+              http::client()->delete_pushrules(
+                "global", "override", room_id, [room_id](mtx::http::RequestErr &) {});
+          });
+    } else {
+        // all messages
+        http::client()->delete_pushrules(
+          "global", "override", room_id, [room_id](mtx::http::RequestErr &) {
+              http::client()->delete_pushrules(
+                "global", "room", room_id, [room_id](mtx::http::RequestErr &) {});
+          });
+    }
 }
 
 void
 RoomSettings::changeAccessRules(int index)
 {
-        using namespace mtx::events::state;
-
-        auto guest_access = [](int index) -> state::GuestAccess {
-                state::GuestAccess event;
-
-                if (index == 0)
-                        event.guest_access = state::AccessState::CanJoin;
-                else
-                        event.guest_access = state::AccessState::Forbidden;
-
-                return event;
-        }(index);
-
-        auto join_rule = [](int index) -> state::JoinRules {
-                state::JoinRules event;
-
-                switch (index) {
-                case 0:
-                case 1:
-                        event.join_rule = state::JoinRule::Public;
-                        break;
-                case 2:
-                        event.join_rule = state::JoinRule::Invite;
-                        break;
-                case 3:
-                        event.join_rule = state::JoinRule::Knock;
-                        break;
-                case 4:
-                        event.join_rule = state::JoinRule::Restricted;
-                        break;
-                default:
-                        event.join_rule = state::JoinRule::Invite;
-                }
+    using namespace mtx::events::state;
+
+    auto guest_access = [](int index) -> state::GuestAccess {
+        state::GuestAccess event;
+
+        if (index == 0)
+            event.guest_access = state::AccessState::CanJoin;
+        else
+            event.guest_access = state::AccessState::Forbidden;
+
+        return event;
+    }(index);
+
+    auto join_rule = [](int index) -> state::JoinRules {
+        state::JoinRules event;
+
+        switch (index) {
+        case 0:
+        case 1:
+            event.join_rule = state::JoinRule::Public;
+            break;
+        case 2:
+            event.join_rule = state::JoinRule::Invite;
+            break;
+        case 3:
+            event.join_rule = state::JoinRule::Knock;
+            break;
+        case 4:
+            event.join_rule = state::JoinRule::Restricted;
+            break;
+        default:
+            event.join_rule = state::JoinRule::Invite;
+        }
 
-                return event;
-        }(index);
+        return event;
+    }(index);
 
-        updateAccessRules(roomid_.toStdString(), join_rule, guest_access);
+    updateAccessRules(roomid_.toStdString(), join_rule, guest_access);
 }
 
 void
@@ -507,139 +501,134 @@ RoomSettings::updateAccessRules(const std::string &room_id,
                                 const mtx::events::state::JoinRules &join_rule,
                                 const mtx::events::state::GuestAccess &guest_access)
 {
-        isLoading_ = true;
-        emit loadingChanged();
+    isLoading_ = true;
+    emit loadingChanged();
+
+    http::client()->send_state_event(
+      room_id,
+      join_rule,
+      [this, room_id, guest_access](const mtx::responses::EventId &, mtx::http::RequestErr err) {
+          if (err) {
+              nhlog::net()->warn("failed to send m.room.join_rule: {} {}",
+                                 static_cast<int>(err->status_code),
+                                 err->matrix_error.error);
+              emit displayError(QString::fromStdString(err->matrix_error.error));
+              isLoading_ = false;
+              emit loadingChanged();
+              return;
+          }
+
+          http::client()->send_state_event(
+            room_id,
+            guest_access,
+            [this](const mtx::responses::EventId &, mtx::http::RequestErr err) {
+                if (err) {
+                    nhlog::net()->warn("failed to send m.room.guest_access: {} {}",
+                                       static_cast<int>(err->status_code),
+                                       err->matrix_error.error);
+                    emit displayError(QString::fromStdString(err->matrix_error.error));
+                }
 
-        http::client()->send_state_event(
-          room_id,
-          join_rule,
-          [this, room_id, guest_access](const mtx::responses::EventId &,
-                                        mtx::http::RequestErr err) {
-                  if (err) {
-                          nhlog::net()->warn("failed to send m.room.join_rule: {} {}",
-                                             static_cast<int>(err->status_code),
-                                             err->matrix_error.error);
-                          emit displayError(QString::fromStdString(err->matrix_error.error));
-                          isLoading_ = false;
-                          emit loadingChanged();
-                          return;
-                  }
-
-                  http::client()->send_state_event(
-                    room_id,
-                    guest_access,
-                    [this](const mtx::responses::EventId &, mtx::http::RequestErr err) {
-                            if (err) {
-                                    nhlog::net()->warn("failed to send m.room.guest_access: {} {}",
-                                                       static_cast<int>(err->status_code),
-                                                       err->matrix_error.error);
-                                    emit displayError(
-                                      QString::fromStdString(err->matrix_error.error));
-                            }
-
-                            isLoading_ = false;
-                            emit loadingChanged();
-                    });
-          });
+                isLoading_ = false;
+                emit loadingChanged();
+            });
+      });
 }
 
 void
 RoomSettings::stopLoading()
 {
-        isLoading_ = false;
-        emit loadingChanged();
+    isLoading_ = false;
+    emit loadingChanged();
 }
 
 void
 RoomSettings::avatarChanged()
 {
-        retrieveRoomInfo();
-        emit avatarUrlChanged();
+    retrieveRoomInfo();
+    emit avatarUrlChanged();
 }
 
 void
 RoomSettings::updateAvatar()
 {
-        const QString picturesFolder =
-          QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
-        const QString fileName = QFileDialog::getOpenFileName(
-          nullptr, tr("Select an avatar"), picturesFolder, tr("All Files (*)"));
-
-        if (fileName.isEmpty())
-                return;
-
-        QMimeDatabase db;
-        QMimeType mime = db.mimeTypeForFile(fileName, QMimeDatabase::MatchContent);
-
-        const auto format = mime.name().split("/")[0];
-
-        QFile file{fileName, this};
-        if (format != "image") {
-                emit displayError(tr("The selected file is not an image"));
-                return;
-        }
-
-        if (!file.open(QIODevice::ReadOnly)) {
-                emit displayError(tr("Error while reading file: %1").arg(file.errorString()));
-                return;
-        }
-
-        isLoading_ = true;
-        emit loadingChanged();
-
-        // Events emitted from the http callbacks (different threads) will
-        // be queued back into the UI thread through this proxy object.
-        auto proxy = std::make_shared<ThreadProxy>();
-        connect(proxy.get(), &ThreadProxy::error, this, &RoomSettings::displayError);
-        connect(proxy.get(), &ThreadProxy::stopLoading, this, &RoomSettings::stopLoading);
-
-        const auto bin        = file.peek(file.size());
-        const auto payload    = std::string(bin.data(), bin.size());
-        const auto dimensions = QImageReader(&file).size();
-
-        // First we need to create a new mxc URI
-        // (i.e upload media to the Matrix content repository) for the new avatar.
-        http::client()->upload(
-          payload,
-          mime.name().toStdString(),
-          QFileInfo(fileName).fileName().toStdString(),
-          [proxy = std::move(proxy),
-           dimensions,
-           payload,
-           mimetype = mime.name().toStdString(),
-           size     = payload.size(),
-           room_id  = roomid_.toStdString(),
-           content  = std::move(bin)](const mtx::responses::ContentURI &res,
-                                     mtx::http::RequestErr err) {
-                  if (err) {
-                          emit proxy->stopLoading();
-                          emit proxy->error(
-                            tr("Failed to upload image: %s")
-                              .arg(QString::fromStdString(err->matrix_error.error)));
-                          return;
-                  }
-
-                  using namespace mtx::events;
-                  state::Avatar avatar_event;
-                  avatar_event.image_info.w        = dimensions.width();
-                  avatar_event.image_info.h        = dimensions.height();
-                  avatar_event.image_info.mimetype = mimetype;
-                  avatar_event.image_info.size     = size;
-                  avatar_event.url                 = res.content_uri;
-
-                  http::client()->send_state_event(
-                    room_id,
-                    avatar_event,
-                    [content = std::move(content), proxy = std::move(proxy)](
-                      const mtx::responses::EventId &, mtx::http::RequestErr err) {
-                            if (err) {
-                                    emit proxy->error(
-                                      tr("Failed to upload image: %s")
+    const QString picturesFolder =
+      QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
+    const QString fileName = QFileDialog::getOpenFileName(
+      nullptr, tr("Select an avatar"), picturesFolder, tr("All Files (*)"));
+
+    if (fileName.isEmpty())
+        return;
+
+    QMimeDatabase db;
+    QMimeType mime = db.mimeTypeForFile(fileName, QMimeDatabase::MatchContent);
+
+    const auto format = mime.name().split("/")[0];
+
+    QFile file{fileName, this};
+    if (format != "image") {
+        emit displayError(tr("The selected file is not an image"));
+        return;
+    }
+
+    if (!file.open(QIODevice::ReadOnly)) {
+        emit displayError(tr("Error while reading file: %1").arg(file.errorString()));
+        return;
+    }
+
+    isLoading_ = true;
+    emit loadingChanged();
+
+    // Events emitted from the http callbacks (different threads) will
+    // be queued back into the UI thread through this proxy object.
+    auto proxy = std::make_shared<ThreadProxy>();
+    connect(proxy.get(), &ThreadProxy::error, this, &RoomSettings::displayError);
+    connect(proxy.get(), &ThreadProxy::stopLoading, this, &RoomSettings::stopLoading);
+
+    const auto bin        = file.peek(file.size());
+    const auto payload    = std::string(bin.data(), bin.size());
+    const auto dimensions = QImageReader(&file).size();
+
+    // First we need to create a new mxc URI
+    // (i.e upload media to the Matrix content repository) for the new avatar.
+    http::client()->upload(
+      payload,
+      mime.name().toStdString(),
+      QFileInfo(fileName).fileName().toStdString(),
+      [proxy = std::move(proxy),
+       dimensions,
+       payload,
+       mimetype = mime.name().toStdString(),
+       size     = payload.size(),
+       room_id  = roomid_.toStdString(),
+       content = std::move(bin)](const mtx::responses::ContentURI &res, mtx::http::RequestErr err) {
+          if (err) {
+              emit proxy->stopLoading();
+              emit proxy->error(tr("Failed to upload image: %s")
+                                  .arg(QString::fromStdString(err->matrix_error.error)));
+              return;
+          }
+
+          using namespace mtx::events;
+          state::Avatar avatar_event;
+          avatar_event.image_info.w        = dimensions.width();
+          avatar_event.image_info.h        = dimensions.height();
+          avatar_event.image_info.mimetype = mimetype;
+          avatar_event.image_info.size     = size;
+          avatar_event.url                 = res.content_uri;
+
+          http::client()->send_state_event(
+            room_id,
+            avatar_event,
+            [content = std::move(content),
+             proxy = std::move(proxy)](const mtx::responses::EventId &, mtx::http::RequestErr err) {
+                if (err) {
+                    emit proxy->error(tr("Failed to upload image: %s")
                                         .arg(QString::fromStdString(err->matrix_error.error)));
-                                    return;
-                            }
+                    return;
+                }
 
-                            emit proxy->stopLoading();
-                    });
-          });
+                emit proxy->stopLoading();
+            });
+      });
 }
diff --git a/src/ui/RoomSettings.h b/src/ui/RoomSettings.h
index ab768ffe..6ec645e0 100644
--- a/src/ui/RoomSettings.h
+++ b/src/ui/RoomSettings.h
@@ -19,121 +19,121 @@ class TextField;
 /// outside of main with the UI code.
 class ThreadProxy : public QObject
 {
-        Q_OBJECT
+    Q_OBJECT
 
 signals:
-        void error(const QString &msg);
-        void nameEventSent(const QString &);
-        void topicEventSent(const QString &);
-        void stopLoading();
+    void error(const QString &msg);
+    void nameEventSent(const QString &);
+    void topicEventSent(const QString &);
+    void stopLoading();
 };
 
 class EditModal : public QWidget
 {
-        Q_OBJECT
+    Q_OBJECT
 
 public:
-        EditModal(const QString &roomId, QWidget *parent = nullptr);
+    EditModal(const QString &roomId, QWidget *parent = nullptr);
 
-        void setFields(const QString &roomName, const QString &roomTopic);
+    void setFields(const QString &roomName, const QString &roomTopic);
 
 signals:
-        void nameChanged(const QString &roomName);
-        void topicChanged(const QString &topic);
+    void nameChanged(const QString &roomName);
+    void topicChanged(const QString &topic);
 
 private slots:
-        void topicEventSent(const QString &topic);
-        void nameEventSent(const QString &name);
-        void error(const QString &msg);
+    void topicEventSent(const QString &topic);
+    void nameEventSent(const QString &name);
+    void error(const QString &msg);
 
-        void applyClicked();
+    void applyClicked();
 
 private:
-        QString roomId_;
-        QString initialName_;
-        QString initialTopic_;
+    QString roomId_;
+    QString initialName_;
+    QString initialTopic_;
 
-        QLabel *errorField_;
+    QLabel *errorField_;
 
-        TextField *nameInput_;
-        TextField *topicInput_;
+    TextField *nameInput_;
+    TextField *topicInput_;
 
-        QPushButton *applyBtn_;
-        QPushButton *cancelBtn_;
+    QPushButton *applyBtn_;
+    QPushButton *cancelBtn_;
 };
 
 class RoomSettings : public QObject
 {
-        Q_OBJECT
-        Q_PROPERTY(QString roomId READ roomId CONSTANT)
-        Q_PROPERTY(QString roomVersion READ roomVersion CONSTANT)
-        Q_PROPERTY(QString roomName READ roomName NOTIFY roomNameChanged)
-        Q_PROPERTY(QString roomTopic READ roomTopic NOTIFY roomTopicChanged)
-        Q_PROPERTY(QString roomAvatarUrl READ roomAvatarUrl NOTIFY avatarUrlChanged)
-        Q_PROPERTY(int memberCount READ memberCount CONSTANT)
-        Q_PROPERTY(int notifications READ notifications NOTIFY notificationsChanged)
-        Q_PROPERTY(int accessJoinRules READ accessJoinRules NOTIFY accessJoinRulesChanged)
-        Q_PROPERTY(bool isLoading READ isLoading NOTIFY loadingChanged)
-        Q_PROPERTY(bool canChangeAvatar READ canChangeAvatar CONSTANT)
-        Q_PROPERTY(bool canChangeJoinRules READ canChangeJoinRules CONSTANT)
-        Q_PROPERTY(bool canChangeNameAndTopic READ canChangeNameAndTopic CONSTANT)
-        Q_PROPERTY(bool isEncryptionEnabled READ isEncryptionEnabled NOTIFY encryptionChanged)
-        Q_PROPERTY(bool supportsKnocking READ supportsKnocking CONSTANT)
-        Q_PROPERTY(bool supportsRestricted READ supportsRestricted CONSTANT)
+    Q_OBJECT
+    Q_PROPERTY(QString roomId READ roomId CONSTANT)
+    Q_PROPERTY(QString roomVersion READ roomVersion CONSTANT)
+    Q_PROPERTY(QString roomName READ roomName NOTIFY roomNameChanged)
+    Q_PROPERTY(QString roomTopic READ roomTopic NOTIFY roomTopicChanged)
+    Q_PROPERTY(QString roomAvatarUrl READ roomAvatarUrl NOTIFY avatarUrlChanged)
+    Q_PROPERTY(int memberCount READ memberCount CONSTANT)
+    Q_PROPERTY(int notifications READ notifications NOTIFY notificationsChanged)
+    Q_PROPERTY(int accessJoinRules READ accessJoinRules NOTIFY accessJoinRulesChanged)
+    Q_PROPERTY(bool isLoading READ isLoading NOTIFY loadingChanged)
+    Q_PROPERTY(bool canChangeAvatar READ canChangeAvatar CONSTANT)
+    Q_PROPERTY(bool canChangeJoinRules READ canChangeJoinRules CONSTANT)
+    Q_PROPERTY(bool canChangeNameAndTopic READ canChangeNameAndTopic CONSTANT)
+    Q_PROPERTY(bool isEncryptionEnabled READ isEncryptionEnabled NOTIFY encryptionChanged)
+    Q_PROPERTY(bool supportsKnocking READ supportsKnocking CONSTANT)
+    Q_PROPERTY(bool supportsRestricted READ supportsRestricted CONSTANT)
 
 public:
-        RoomSettings(QString roomid, QObject *parent = nullptr);
-
-        QString roomId() const;
-        QString roomName() const;
-        QString roomTopic() const;
-        QString roomVersion() const;
-        QString roomAvatarUrl();
-        int memberCount() const;
-        int notifications();
-        int accessJoinRules();
-        bool isLoading() const;
-        //! Whether the user has enough power level to send m.room.join_rules events.
-        bool canChangeJoinRules() const;
-        //! Whether the user has enough power level to send m.room.name & m.room.topic events.
-        bool canChangeNameAndTopic() const;
-        //! Whether the user has enough power level to send m.room.avatar event.
-        bool canChangeAvatar() const;
-        bool isEncryptionEnabled() const;
-        bool supportsKnocking() const;
-        bool supportsRestricted() const;
-
-        Q_INVOKABLE void enableEncryption();
-        Q_INVOKABLE void updateAvatar();
-        Q_INVOKABLE void openEditModal();
-        Q_INVOKABLE void changeAccessRules(int index);
-        Q_INVOKABLE void changeNotifications(int currentIndex);
+    RoomSettings(QString roomid, QObject *parent = nullptr);
+
+    QString roomId() const;
+    QString roomName() const;
+    QString roomTopic() const;
+    QString roomVersion() const;
+    QString roomAvatarUrl();
+    int memberCount() const;
+    int notifications();
+    int accessJoinRules();
+    bool isLoading() const;
+    //! Whether the user has enough power level to send m.room.join_rules events.
+    bool canChangeJoinRules() const;
+    //! Whether the user has enough power level to send m.room.name & m.room.topic events.
+    bool canChangeNameAndTopic() const;
+    //! Whether the user has enough power level to send m.room.avatar event.
+    bool canChangeAvatar() const;
+    bool isEncryptionEnabled() const;
+    bool supportsKnocking() const;
+    bool supportsRestricted() const;
+
+    Q_INVOKABLE void enableEncryption();
+    Q_INVOKABLE void updateAvatar();
+    Q_INVOKABLE void openEditModal();
+    Q_INVOKABLE void changeAccessRules(int index);
+    Q_INVOKABLE void changeNotifications(int currentIndex);
 
 signals:
-        void loadingChanged();
-        void roomNameChanged();
-        void roomTopicChanged();
-        void avatarUrlChanged();
-        void encryptionChanged();
-        void notificationsChanged();
-        void accessJoinRulesChanged();
-        void displayError(const QString &errorMessage);
+    void loadingChanged();
+    void roomNameChanged();
+    void roomTopicChanged();
+    void avatarUrlChanged();
+    void encryptionChanged();
+    void notificationsChanged();
+    void accessJoinRulesChanged();
+    void displayError(const QString &errorMessage);
 
 public slots:
-        void stopLoading();
-        void avatarChanged();
+    void stopLoading();
+    void avatarChanged();
 
 private:
-        void retrieveRoomInfo();
-        void updateAccessRules(const std::string &room_id,
-                               const mtx::events::state::JoinRules &,
-                               const mtx::events::state::GuestAccess &);
+    void retrieveRoomInfo();
+    void updateAccessRules(const std::string &room_id,
+                           const mtx::events::state::JoinRules &,
+                           const mtx::events::state::GuestAccess &);
 
 private:
-        QString roomid_;
-        bool usesEncryption_ = false;
-        bool isLoading_      = false;
-        RoomInfo info_;
-        int notifications_ = 0;
-        int accessRules_   = 0;
+    QString roomid_;
+    bool usesEncryption_ = false;
+    bool isLoading_      = false;
+    RoomInfo info_;
+    int notifications_ = 0;
+    int accessRules_   = 0;
 };
diff --git a/src/ui/SnackBar.cpp b/src/ui/SnackBar.cpp
index 18990c47..90187154 100644
--- a/src/ui/SnackBar.cpp
+++ b/src/ui/SnackBar.cpp
@@ -15,121 +15,121 @@ SnackBar::SnackBar(QWidget *parent)
   : OverlayWidget(parent)
   , offset_anim(this, "offset", this)
 {
-        QFont font;
-        font.setPointSizeF(font.pointSizeF() * 1.2);
-        font.setWeight(50);
-        setFont(font);
+    QFont font;
+    font.setPointSizeF(font.pointSizeF() * 1.2);
+    font.setWeight(50);
+    setFont(font);
 
-        boxHeight_ = QFontMetrics(font).height() * 2;
-        offset_    = STARTING_OFFSET;
-        position_  = SnackBarPosition::Top;
+    boxHeight_ = QFontMetrics(font).height() * 2;
+    offset_    = STARTING_OFFSET;
+    position_  = SnackBarPosition::Top;
 
-        hideTimer_.setSingleShot(true);
+    hideTimer_.setSingleShot(true);
 
-        offset_anim.setStartValue(1.0);
-        offset_anim.setEndValue(0.0);
-        offset_anim.setDuration(100);
-        offset_anim.setEasingCurve(QEasingCurve::OutCubic);
+    offset_anim.setStartValue(1.0);
+    offset_anim.setEndValue(0.0);
+    offset_anim.setDuration(100);
+    offset_anim.setEasingCurve(QEasingCurve::OutCubic);
 
-        connect(this, &SnackBar::offsetChanged, this, [this]() mutable { repaint(); });
-        connect(
-          &offset_anim, &QPropertyAnimation::finished, this, [this]() { hideTimer_.start(10000); });
+    connect(this, &SnackBar::offsetChanged, this, [this]() mutable { repaint(); });
+    connect(
+      &offset_anim, &QPropertyAnimation::finished, this, [this]() { hideTimer_.start(10000); });
 
-        connect(&hideTimer_, SIGNAL(timeout()), this, SLOT(hideMessage()));
+    connect(&hideTimer_, SIGNAL(timeout()), this, SLOT(hideMessage()));
 
-        hide();
+    hide();
 }
 
 void
 SnackBar::start()
 {
-        if (messages_.empty())
-                return;
+    if (messages_.empty())
+        return;
 
-        show();
-        raise();
+    show();
+    raise();
 
-        offset_anim.start();
+    offset_anim.start();
 }
 
 void
 SnackBar::hideMessage()
 {
-        stopTimers();
-        hide();
+    stopTimers();
+    hide();
 
-        if (!messages_.empty())
-                // Moving on to the next message.
-                messages_.pop_front();
+    if (!messages_.empty())
+        // Moving on to the next message.
+        messages_.pop_front();
 
-        // Resetting the starting position of the widget.
-        offset_ = STARTING_OFFSET;
+    // Resetting the starting position of the widget.
+    offset_ = STARTING_OFFSET;
 
-        if (!messages_.empty())
-                start();
+    if (!messages_.empty())
+        start();
 }
 
 void
 SnackBar::stopTimers()
 {
-        hideTimer_.stop();
+    hideTimer_.stop();
 }
 
 void
 SnackBar::showMessage(const QString &msg)
 {
-        messages_.push_back(msg);
+    messages_.push_back(msg);
 
-        // There is already an active message.
-        if (isVisible())
-                return;
+    // There is already an active message.
+    if (isVisible())
+        return;
 
-        start();
+    start();
 }
 
 void
 SnackBar::mousePressEvent(QMouseEvent *)
 {
-        hideMessage();
+    hideMessage();
 }
 
 void
 SnackBar::paintEvent(QPaintEvent *event)
 {
-        Q_UNUSED(event)
+    Q_UNUSED(event)
 
-        if (messages_.empty())
-                return;
+    if (messages_.empty())
+        return;
 
-        auto message_ = messages_.front();
+    auto message_ = messages_.front();
 
-        QPainter p(this);
-        p.setRenderHint(QPainter::Antialiasing);
+    QPainter p(this);
+    p.setRenderHint(QPainter::Antialiasing);
 
-        QBrush brush;
-        brush.setStyle(Qt::SolidPattern);
-        brush.setColor(bgColor_);
-        p.setBrush(brush);
+    QBrush brush;
+    brush.setStyle(Qt::SolidPattern);
+    brush.setColor(bgColor_);
+    p.setBrush(brush);
 
-        QRect r(0, 0, std::max(MIN_WIDTH, width() * MIN_WIDTH_PERCENTAGE), boxHeight_);
+    QRect r(0, 0, std::max(MIN_WIDTH, width() * MIN_WIDTH_PERCENTAGE), boxHeight_);
 
-        p.setPen(Qt::white);
-        QRect br = p.boundingRect(r, Qt::AlignHCenter | Qt::AlignTop | Qt::TextWordWrap, message_);
+    p.setPen(Qt::white);
+    QRect br = p.boundingRect(r, Qt::AlignHCenter | Qt::AlignTop | Qt::TextWordWrap, message_);
 
-        p.setPen(Qt::NoPen);
-        r = br.united(r).adjusted(-BOX_PADDING, -BOX_PADDING, BOX_PADDING, BOX_PADDING);
+    p.setPen(Qt::NoPen);
+    r = br.united(r).adjusted(-BOX_PADDING, -BOX_PADDING, BOX_PADDING, BOX_PADDING);
 
-        const qreal s = 1 - offset_;
+    const qreal s = 1 - offset_;
 
-        if (position_ == SnackBarPosition::Bottom)
-                p.translate((width() - (r.width() - 2 * BOX_PADDING)) / 2,
-                            height() - BOX_PADDING - s * (r.height()));
-        else
-                p.translate((width() - (r.width() - 2 * BOX_PADDING)) / 2,
-                            s * (r.height()) - 2 * BOX_PADDING);
+    if (position_ == SnackBarPosition::Bottom)
+        p.translate((width() - (r.width() - 2 * BOX_PADDING)) / 2,
+                    height() - BOX_PADDING - s * (r.height()));
+    else
+        p.translate((width() - (r.width() - 2 * BOX_PADDING)) / 2,
+                    s * (r.height()) - 2 * BOX_PADDING);
 
-        br.moveCenter(r.center());
-        p.drawRoundedRect(r.adjusted(0, 0, 0, 4), 4, 4);
-        p.setPen(textColor_);
-        p.drawText(br, Qt::AlignHCenter | Qt::AlignTop | Qt::TextWordWrap, message_);
+    br.moveCenter(r.center());
+    p.drawRoundedRect(r.adjusted(0, 0, 0, 4), 4, 4);
+    p.setPen(textColor_);
+    p.drawText(br, Qt::AlignHCenter | Qt::AlignTop | Qt::TextWordWrap, message_);
 }
diff --git a/src/ui/SnackBar.h b/src/ui/SnackBar.h
index 8d127933..0459950f 100644
--- a/src/ui/SnackBar.h
+++ b/src/ui/SnackBar.h
@@ -14,79 +14,79 @@
 
 enum class SnackBarPosition
 {
-        Bottom,
-        Top,
+    Bottom,
+    Top,
 };
 
 class SnackBar : public OverlayWidget
 {
-        Q_OBJECT
+    Q_OBJECT
 
-        Q_PROPERTY(QColor bgColor READ backgroundColor WRITE setBackgroundColor)
-        Q_PROPERTY(QColor textColor READ textColor WRITE setTextColor)
-        Q_PROPERTY(double offset READ offset WRITE setOffset NOTIFY offsetChanged)
+    Q_PROPERTY(QColor bgColor READ backgroundColor WRITE setBackgroundColor)
+    Q_PROPERTY(QColor textColor READ textColor WRITE setTextColor)
+    Q_PROPERTY(double offset READ offset WRITE setOffset NOTIFY offsetChanged)
 
 public:
-        explicit SnackBar(QWidget *parent);
-
-        QColor backgroundColor() const { return bgColor_; }
-        void setBackgroundColor(const QColor &color)
-        {
-                bgColor_ = color;
-                update();
-        }
-
-        QColor textColor() const { return textColor_; }
-        void setTextColor(const QColor &color)
-        {
-                textColor_ = color;
-                update();
-        }
-        void setPosition(SnackBarPosition pos)
-        {
-                position_ = pos;
-                update();
-        }
-
-        double offset() { return offset_; }
-        void setOffset(double offset)
-        {
-                if (offset != offset_) {
-                        offset_ = offset;
-                        emit offsetChanged();
-                }
+    explicit SnackBar(QWidget *parent);
+
+    QColor backgroundColor() const { return bgColor_; }
+    void setBackgroundColor(const QColor &color)
+    {
+        bgColor_ = color;
+        update();
+    }
+
+    QColor textColor() const { return textColor_; }
+    void setTextColor(const QColor &color)
+    {
+        textColor_ = color;
+        update();
+    }
+    void setPosition(SnackBarPosition pos)
+    {
+        position_ = pos;
+        update();
+    }
+
+    double offset() { return offset_; }
+    void setOffset(double offset)
+    {
+        if (offset != offset_) {
+            offset_ = offset;
+            emit offsetChanged();
         }
+    }
 
 public slots:
-        void showMessage(const QString &msg);
+    void showMessage(const QString &msg);
 
 signals:
-        void offsetChanged();
+    void offsetChanged();
 
 protected:
-        void paintEvent(QPaintEvent *event) override;
-        void mousePressEvent(QMouseEvent *event) override;
+    void paintEvent(QPaintEvent *event) override;
+    void mousePressEvent(QMouseEvent *event) override;
 
 private slots:
-        void hideMessage();
+    void hideMessage();
 
 private:
-        void stopTimers();
-        void start();
+    void stopTimers();
+    void start();
 
-        QColor bgColor_;
-        QColor textColor_;
+    QColor bgColor_;
+    QColor textColor_;
 
-        qreal bgOpacity_;
-        qreal offset_;
+    qreal bgOpacity_;
+    qreal offset_;
 
-        std::deque<QString> messages_;
+    std::deque<QString> messages_;
 
-        QTimer hideTimer_;
+    QTimer hideTimer_;
 
-        double boxHeight_;
+    double boxHeight_;
 
-        QPropertyAnimation offset_anim;
+    QPropertyAnimation offset_anim;
 
-        SnackBarPosition position_;
+    SnackBarPosition position_;
 };
diff --git a/src/ui/TextField.cpp b/src/ui/TextField.cpp
index 7d015e89..8f1a6aa5 100644
--- a/src/ui/TextField.cpp
+++ b/src/ui/TextField.cpp
@@ -15,363 +15,363 @@
 TextField::TextField(QWidget *parent)
   : QLineEdit(parent)
 {
-        // Get rid of the focus border on macOS.
-        setAttribute(Qt::WA_MacShowFocusRect, 0);
+    // Get rid of the focus border on macOS.
+    setAttribute(Qt::WA_MacShowFocusRect, 0);
 
-        QPalette pal;
+    QPalette pal;
 
-        state_machine_    = new TextFieldStateMachine(this);
-        label_            = nullptr;
-        label_font_size_  = 15;
-        show_label_       = false;
-        background_color_ = pal.color(QPalette::Window);
-        is_valid_         = true;
+    state_machine_    = new TextFieldStateMachine(this);
+    label_            = nullptr;
+    label_font_size_  = 15;
+    show_label_       = false;
+    background_color_ = pal.color(QPalette::Window);
+    is_valid_         = true;
 
-        setFrame(false);
-        setAttribute(Qt::WA_Hover);
-        setMouseTracking(true);
-        setTextMargins(0, 4, 0, 6);
+    setFrame(false);
+    setAttribute(Qt::WA_Hover);
+    setMouseTracking(true);
+    setTextMargins(0, 4, 0, 6);
 
-        state_machine_->start();
-        QCoreApplication::processEvents();
+    state_machine_->start();
+    QCoreApplication::processEvents();
 }
 
 void
 TextField::setBackgroundColor(const QColor &color)
 {
-        background_color_ = color;
+    background_color_ = color;
 }
 
 QColor
 TextField::backgroundColor() const
 {
-        return background_color_;
+    return background_color_;
 }
 
 void
 TextField::setShowLabel(bool value)
 {
-        if (show_label_ == value) {
-                return;
-        }
-
-        show_label_ = value;
-
-        if (!label_ && value) {
-                label_ = new TextFieldLabel(this);
-                state_machine_->setLabel(label_);
-        }
-
-        if (value) {
-                setContentsMargins(0, 23, 0, 0);
-        } else {
-                setContentsMargins(0, 0, 0, 0);
-        }
+    if (show_label_ == value) {
+        return;
+    }
+
+    show_label_ = value;
+
+    if (!label_ && value) {
+        label_ = new TextFieldLabel(this);
+        state_machine_->setLabel(label_);
+    }
+
+    if (value) {
+        setContentsMargins(0, 23, 0, 0);
+    } else {
+        setContentsMargins(0, 0, 0, 0);
+    }
 }
 
 bool
 TextField::hasLabel() const
 {
-        return show_label_;
+    return show_label_;
 }
 
 void
 TextField::setValid(bool valid)
 {
-        is_valid_ = valid;
+    is_valid_ = valid;
 }
 
 bool
 TextField::isValid() const
 {
-        QString s = text();
-        int pos   = 0;
-        if (regexp_.pattern().isEmpty()) {
-                return is_valid_;
-        }
-        QRegularExpressionValidator v(QRegularExpression(regexp_), 0);
-        return v.validate(s, pos) == QValidator::Acceptable;
+    QString s = text();
+    int pos   = 0;
+    if (regexp_.pattern().isEmpty()) {
+        return is_valid_;
+    }
+    QRegularExpressionValidator v(QRegularExpression(regexp_), 0);
+    return v.validate(s, pos) == QValidator::Acceptable;
 }
 
 void
 TextField::setLabelFontSize(qreal size)
 {
-        label_font_size_ = size;
+    label_font_size_ = size;
 
-        if (label_) {
-                QFont font(label_->font());
-                font.setPointSizeF(size);
-                label_->setFont(font);
-                label_->update();
-        }
+    if (label_) {
+        QFont font(label_->font());
+        font.setPointSizeF(size);
+        label_->setFont(font);
+        label_->update();
+    }
 }
 
 qreal
 TextField::labelFontSize() const
 {
-        return label_font_size_;
+    return label_font_size_;
 }
 
 void
 TextField::setLabel(const QString &label)
 {
-        label_text_ = label;
-        setShowLabel(true);
-        label_->update();
+    label_text_ = label;
+    setShowLabel(true);
+    label_->update();
 }
 
 QString
 TextField::label() const
 {
-        return label_text_;
+    return label_text_;
 }
 
 void
 TextField::setLabelColor(const QColor &color)
 {
-        label_color_ = color;
-        update();
+    label_color_ = color;
+    update();
 }
 
 QColor
 TextField::labelColor() const
 {
-        if (!label_color_.isValid()) {
-                return QPalette().color(QPalette::Text);
-        }
+    if (!label_color_.isValid()) {
+        return QPalette().color(QPalette::Text);
+    }
 
-        return label_color_;
+    return label_color_;
 }
 
 void
 TextField::setInkColor(const QColor &color)
 {
-        ink_color_ = color;
-        update();
+    ink_color_ = color;
+    update();
 }
 
 QColor
 TextField::inkColor() const
 {
-        if (!ink_color_.isValid()) {
-                return QPalette().color(QPalette::Text);
-        }
+    if (!ink_color_.isValid()) {
+        return QPalette().color(QPalette::Text);
+    }
 
-        return ink_color_;
+    return ink_color_;
 }
 
 void
 TextField::setUnderlineColor(const QColor &color)
 {
-        underline_color_ = color;
-        update();
+    underline_color_ = color;
+    update();
 }
 
 void
 TextField::setRegexp(const QRegularExpression &regexp)
 {
-        regexp_ = regexp;
+    regexp_ = regexp;
 }
 
 QColor
 TextField::underlineColor() const
 {
-        if (!underline_color_.isValid()) {
-                if ((hasAcceptableInput() && isValid()) || !isModified())
-                        return QPalette().color(QPalette::Highlight);
-                else
-                        return Qt::red;
-        }
-
-        return underline_color_;
+    if (!underline_color_.isValid()) {
+        if ((hasAcceptableInput() && isValid()) || !isModified())
+            return QPalette().color(QPalette::Highlight);
+        else
+            return Qt::red;
+    }
+
+    return underline_color_;
 }
 
 bool
 TextField::event(QEvent *event)
 {
-        switch (event->type()) {
-        case QEvent::Resize:
-        case QEvent::Move: {
-                if (label_)
-                        label_->setGeometry(rect());
-                break;
-        }
-        default:
-                break;
-        }
-
-        return QLineEdit::event(event);
+    switch (event->type()) {
+    case QEvent::Resize:
+    case QEvent::Move: {
+        if (label_)
+            label_->setGeometry(rect());
+        break;
+    }
+    default:
+        break;
+    }
+
+    return QLineEdit::event(event);
 }
 
 void
 TextField::paintEvent(QPaintEvent *event)
 {
-        QLineEdit::paintEvent(event);
+    QLineEdit::paintEvent(event);
 
-        QPainter painter(this);
+    QPainter painter(this);
 
-        if (text().isEmpty()) {
-                painter.setOpacity(1 - state_machine_->progress());
-                painter.fillRect(rect(), backgroundColor());
-        }
+    if (text().isEmpty()) {
+        painter.setOpacity(1 - state_machine_->progress());
+        painter.fillRect(rect(), backgroundColor());
+    }
 
-        const int y  = height() - 1;
-        const int wd = width() - 5;
+    const int y  = height() - 1;
+    const int wd = width() - 5;
 
-        QPen pen;
-        pen.setWidth(1);
-        pen.setColor(underlineColor());
-        painter.setPen(pen);
-        painter.setOpacity(1);
-        painter.drawLine(2, y, wd, y);
+    QPen pen;
+    pen.setWidth(1);
+    pen.setColor(underlineColor());
+    painter.setPen(pen);
+    painter.setOpacity(1);
+    painter.drawLine(2, y, wd, y);
 
-        QBrush brush;
-        brush.setStyle(Qt::SolidPattern);
-        brush.setColor(inkColor());
+    QBrush brush;
+    brush.setStyle(Qt::SolidPattern);
+    brush.setColor(inkColor());
 
-        const qreal progress = state_machine_->progress();
+    const qreal progress = state_machine_->progress();
 
-        if (progress > 0) {
-                painter.setPen(Qt::NoPen);
-                painter.setBrush(brush);
-                const int w = (1 - progress) * static_cast<qreal>(wd / 2);
-                painter.drawRect(w + 2.5, height() - 2, wd - 2 * w, 2);
-        }
+    if (progress > 0) {
+        painter.setPen(Qt::NoPen);
+        painter.setBrush(brush);
+        const int w = (1 - progress) * static_cast<qreal>(wd / 2);
+        painter.drawRect(w + 2.5, height() - 2, wd - 2 * w, 2);
+    }
 }
 
 TextFieldStateMachine::TextFieldStateMachine(TextField *parent)
   : QStateMachine(parent)
   , text_field_(parent)
 {
-        normal_state_  = new QState;
-        focused_state_ = new QState;
+    normal_state_  = new QState;
+    focused_state_ = new QState;
 
-        label_       = nullptr;
-        offset_anim_ = nullptr;
-        color_anim_  = nullptr;
-        progress_    = 0.0;
+    label_       = nullptr;
+    offset_anim_ = nullptr;
+    color_anim_  = nullptr;
+    progress_    = 0.0;
 
-        addState(normal_state_);
-        addState(focused_state_);
+    addState(normal_state_);
+    addState(focused_state_);
 
-        setInitialState(normal_state_);
+    setInitialState(normal_state_);
 
-        QEventTransition *transition;
-        QPropertyAnimation *animation;
+    QEventTransition *transition;
+    QPropertyAnimation *animation;
 
-        transition = new QEventTransition(parent, QEvent::FocusIn);
-        transition->setTargetState(focused_state_);
-        normal_state_->addTransition(transition);
+    transition = new QEventTransition(parent, QEvent::FocusIn);
+    transition->setTargetState(focused_state_);
+    normal_state_->addTransition(transition);
 
-        animation = new QPropertyAnimation(this, "progress", this);
-        animation->setEasingCurve(QEasingCurve::InCubic);
-        animation->setDuration(310);
-        transition->addAnimation(animation);
+    animation = new QPropertyAnimation(this, "progress", this);
+    animation->setEasingCurve(QEasingCurve::InCubic);
+    animation->setDuration(310);
+    transition->addAnimation(animation);
 
-        transition = new QEventTransition(parent, QEvent::FocusOut);
-        transition->setTargetState(normal_state_);
-        focused_state_->addTransition(transition);
+    transition = new QEventTransition(parent, QEvent::FocusOut);
+    transition->setTargetState(normal_state_);
+    focused_state_->addTransition(transition);
 
-        animation = new QPropertyAnimation(this, "progress", this);
-        animation->setEasingCurve(QEasingCurve::OutCubic);
-        animation->setDuration(310);
-        transition->addAnimation(animation);
+    animation = new QPropertyAnimation(this, "progress", this);
+    animation->setEasingCurve(QEasingCurve::OutCubic);
+    animation->setDuration(310);
+    transition->addAnimation(animation);
 
-        normal_state_->assignProperty(this, "progress", 0);
-        focused_state_->assignProperty(this, "progress", 1);
+    normal_state_->assignProperty(this, "progress", 0);
+    focused_state_->assignProperty(this, "progress", 1);
 
-        setupProperties();
+    setupProperties();
 
-        connect(text_field_, SIGNAL(textChanged(QString)), this, SLOT(setupProperties()));
+    connect(text_field_, SIGNAL(textChanged(QString)), this, SLOT(setupProperties()));
 }
 
 void
 TextFieldStateMachine::setLabel(TextFieldLabel *label)
 {
-        if (label_) {
-                delete label_;
-        }
-
-        if (offset_anim_) {
-                removeDefaultAnimation(offset_anim_);
-                delete offset_anim_;
-        }
-
-        if (color_anim_) {
-                removeDefaultAnimation(color_anim_);
-                delete color_anim_;
-        }
-
-        label_ = label;
-
-        if (label_) {
-                offset_anim_ = new QPropertyAnimation(label_, "offset", this);
-                offset_anim_->setDuration(210);
-                offset_anim_->setEasingCurve(QEasingCurve::OutCubic);
-                addDefaultAnimation(offset_anim_);
-
-                color_anim_ = new QPropertyAnimation(label_, "color", this);
-                color_anim_->setDuration(210);
-                addDefaultAnimation(color_anim_);
-        }
-
-        setupProperties();
+    if (label_) {
+        delete label_;
+    }
+
+    if (offset_anim_) {
+        removeDefaultAnimation(offset_anim_);
+        delete offset_anim_;
+    }
+
+    if (color_anim_) {
+        removeDefaultAnimation(color_anim_);
+        delete color_anim_;
+    }
+
+    label_ = label;
+
+    if (label_) {
+        offset_anim_ = new QPropertyAnimation(label_, "offset", this);
+        offset_anim_->setDuration(210);
+        offset_anim_->setEasingCurve(QEasingCurve::OutCubic);
+        addDefaultAnimation(offset_anim_);
+
+        color_anim_ = new QPropertyAnimation(label_, "color", this);
+        color_anim_->setDuration(210);
+        addDefaultAnimation(color_anim_);
+    }
+
+    setupProperties();
 }
 
 void
 TextFieldStateMachine::setupProperties()
 {
-        if (label_) {
-                const int m = text_field_->textMargins().top();
-
-                if (text_field_->text().isEmpty()) {
-                        normal_state_->assignProperty(label_, "offset", QPointF(0, 26));
-                } else {
-                        normal_state_->assignProperty(label_, "offset", QPointF(0, 0 - m));
-                }
-
-                focused_state_->assignProperty(label_, "offset", QPointF(0, 0 - m));
-                focused_state_->assignProperty(label_, "color", text_field_->inkColor());
-                normal_state_->assignProperty(label_, "color", text_field_->labelColor());
-
-                if (0 != label_->offset().y() && !text_field_->text().isEmpty()) {
-                        label_->setOffset(QPointF(0, 0 - m));
-                } else if (!text_field_->hasFocus() && label_->offset().y() <= 0 &&
-                           text_field_->text().isEmpty()) {
-                        label_->setOffset(QPointF(0, 26));
-                }
+    if (label_) {
+        const int m = text_field_->textMargins().top();
+
+        if (text_field_->text().isEmpty()) {
+            normal_state_->assignProperty(label_, "offset", QPointF(0, 26));
+        } else {
+            normal_state_->assignProperty(label_, "offset", QPointF(0, 0 - m));
+        }
+
+        focused_state_->assignProperty(label_, "offset", QPointF(0, 0 - m));
+        focused_state_->assignProperty(label_, "color", text_field_->inkColor());
+        normal_state_->assignProperty(label_, "color", text_field_->labelColor());
+
+        if (0 != label_->offset().y() && !text_field_->text().isEmpty()) {
+            label_->setOffset(QPointF(0, 0 - m));
+        } else if (!text_field_->hasFocus() && label_->offset().y() <= 0 &&
+                   text_field_->text().isEmpty()) {
+            label_->setOffset(QPointF(0, 26));
         }
+    }
 
-        text_field_->update();
+    text_field_->update();
 }
 
 TextFieldLabel::TextFieldLabel(TextField *parent)
   : QWidget(parent)
   , text_field_(parent)
 {
-        x_     = 0;
-        y_     = 26;
-        scale_ = 1;
-        color_ = parent->labelColor();
-
-        QFont font;
-        font.setWeight(60);
-        font.setLetterSpacing(QFont::PercentageSpacing, 102);
-        setFont(font);
+    x_     = 0;
+    y_     = 26;
+    scale_ = 1;
+    color_ = parent->labelColor();
+
+    QFont font;
+    font.setWeight(60);
+    font.setLetterSpacing(QFont::PercentageSpacing, 102);
+    setFont(font);
 }
 
 void
 TextFieldLabel::paintEvent(QPaintEvent *)
 {
-        if (!text_field_->hasLabel())
-                return;
+    if (!text_field_->hasLabel())
+        return;
 
-        QPainter painter(this);
-        painter.setRenderHint(QPainter::Antialiasing);
-        painter.scale(scale_, scale_);
-        painter.setPen(color_);
-        painter.setOpacity(1);
+    QPainter painter(this);
+    painter.setRenderHint(QPainter::Antialiasing);
+    painter.scale(scale_, scale_);
+    painter.setPen(color_);
+    painter.setOpacity(1);
 
-        QPointF pos(2 + x_, height() - 36 + y_);
-        painter.drawText(pos.x(), pos.y(), text_field_->label());
+    QPointF pos(2 + x_, height() - 36 + y_);
+    painter.drawText(pos.x(), pos.y(), text_field_->label());
 }
diff --git a/src/ui/TextField.h b/src/ui/TextField.h
index ac4c396e..47257019 100644
--- a/src/ui/TextField.h
+++ b/src/ui/TextField.h
@@ -18,163 +18,163 @@ class TextFieldStateMachine;
 
 class TextField : public QLineEdit
 {
-        Q_OBJECT
+    Q_OBJECT
 
-        Q_PROPERTY(QColor inkColor WRITE setInkColor READ inkColor)
-        Q_PROPERTY(QColor labelColor WRITE setLabelColor READ labelColor)
-        Q_PROPERTY(QColor underlineColor WRITE setUnderlineColor READ underlineColor)
-        Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor)
+    Q_PROPERTY(QColor inkColor WRITE setInkColor READ inkColor)
+    Q_PROPERTY(QColor labelColor WRITE setLabelColor READ labelColor)
+    Q_PROPERTY(QColor underlineColor WRITE setUnderlineColor READ underlineColor)
+    Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor)
 
 public:
-        explicit TextField(QWidget *parent = nullptr);
-
-        void setInkColor(const QColor &color);
-        void setBackgroundColor(const QColor &color);
-        void setLabel(const QString &label);
-        void setLabelColor(const QColor &color);
-        void setLabelFontSize(qreal size);
-        void setShowLabel(bool value);
-        void setUnderlineColor(const QColor &color);
-        void setRegexp(const QRegularExpression &regexp);
-        void setValid(bool valid);
-
-        QColor inkColor() const;
-        QColor labelColor() const;
-        QColor underlineColor() const;
-        QColor backgroundColor() const;
-        QString label() const;
-        bool hasLabel() const;
-        bool isValid() const;
-        qreal labelFontSize() const;
+    explicit TextField(QWidget *parent = nullptr);
+
+    void setInkColor(const QColor &color);
+    void setBackgroundColor(const QColor &color);
+    void setLabel(const QString &label);
+    void setLabelColor(const QColor &color);
+    void setLabelFontSize(qreal size);
+    void setShowLabel(bool value);
+    void setUnderlineColor(const QColor &color);
+    void setRegexp(const QRegularExpression &regexp);
+    void setValid(bool valid);
+
+    QColor inkColor() const;
+    QColor labelColor() const;
+    QColor underlineColor() const;
+    QColor backgroundColor() const;
+    QString label() const;
+    bool hasLabel() const;
+    bool isValid() const;
+    qreal labelFontSize() const;
 
 protected:
-        bool event(QEvent *event) override;
-        void paintEvent(QPaintEvent *event) override;
+    bool event(QEvent *event) override;
+    void paintEvent(QPaintEvent *event) override;
 
 private:
-        void init();
-
-        QColor ink_color_;
-        QColor background_color_;
-        QColor label_color_;
-        QColor underline_color_;
-        QString label_text_;
-        TextFieldLabel *label_;
-        TextFieldStateMachine *state_machine_;
-        bool show_label_;
-        QRegularExpression regexp_;
-        bool is_valid_;
-        qreal label_font_size_;
+    void init();
+
+    QColor ink_color_;
+    QColor background_color_;
+    QColor label_color_;
+    QColor underline_color_;
+    QString label_text_;
+    TextFieldLabel *label_;
+    TextFieldStateMachine *state_machine_;
+    bool show_label_;
+    QRegularExpression regexp_;
+    bool is_valid_;
+    qreal label_font_size_;
 };
 
 class TextFieldLabel : public QWidget
 {
-        Q_OBJECT
+    Q_OBJECT
 
-        Q_PROPERTY(qreal scale WRITE setScale READ scale)
-        Q_PROPERTY(QPointF offset WRITE setOffset READ offset)
-        Q_PROPERTY(QColor color WRITE setColor READ color)
+    Q_PROPERTY(qreal scale WRITE setScale READ scale)
+    Q_PROPERTY(QPointF offset WRITE setOffset READ offset)
+    Q_PROPERTY(QColor color WRITE setColor READ color)
 
 public:
-        TextFieldLabel(TextField *parent);
+    TextFieldLabel(TextField *parent);
 
-        inline void setColor(const QColor &color);
-        inline void setOffset(const QPointF &pos);
-        inline void setScale(qreal scale);
+    inline void setColor(const QColor &color);
+    inline void setOffset(const QPointF &pos);
+    inline void setScale(qreal scale);
 
-        inline QColor color() const;
-        inline QPointF offset() const;
-        inline qreal scale() const;
+    inline QColor color() const;
+    inline QPointF offset() const;
+    inline qreal scale() const;
 
 protected:
-        void paintEvent(QPaintEvent *event) override;
+    void paintEvent(QPaintEvent *event) override;
 
 private:
-        TextField *const text_field_;
+    TextField *const text_field_;
 
-        QColor color_;
-        qreal scale_;
-        qreal x_;
-        qreal y_;
+    QColor color_;
+    qreal scale_;
+    qreal x_;
+    qreal y_;
 };
 
 inline void
 TextFieldLabel::setColor(const QColor &color)
 {
-        color_ = color;
-        update();
+    color_ = color;
+    update();
 }
 
 inline void
 TextFieldLabel::setOffset(const QPointF &pos)
 {
-        x_ = pos.x();
-        y_ = pos.y();
-        update();
+    x_ = pos.x();
+    y_ = pos.y();
+    update();
 }
 
 inline void
 TextFieldLabel::setScale(qreal scale)
 {
-        scale_ = scale;
-        update();
+    scale_ = scale;
+    update();
 }
 
 inline QPointF
 TextFieldLabel::offset() const
 {
-        return QPointF(x_, y_);
+    return QPointF(x_, y_);
 }
 inline qreal
 TextFieldLabel::scale() const
 {
-        return scale_;
+    return scale_;
 }
 inline QColor
 TextFieldLabel::color() const
 {
-        return color_;
+    return color_;
 }
 
 class TextFieldStateMachine : public QStateMachine
 {
-        Q_OBJECT
+    Q_OBJECT
 
-        Q_PROPERTY(qreal progress WRITE setProgress READ progress)
+    Q_PROPERTY(qreal progress WRITE setProgress READ progress)
 
 public:
-        TextFieldStateMachine(TextField *parent);
+    TextFieldStateMachine(TextField *parent);
 
-        inline void setProgress(qreal progress);
-        void setLabel(TextFieldLabel *label);
+    inline void setProgress(qreal progress);
+    void setLabel(TextFieldLabel *label);
 
-        inline qreal progress() const;
+    inline qreal progress() const;
 
 public slots:
-        void setupProperties();
+    void setupProperties();
 
 private:
-        QPropertyAnimation *color_anim_;
-        QPropertyAnimation *offset_anim_;
+    QPropertyAnimation *color_anim_;
+    QPropertyAnimation *offset_anim_;
 
-        QState *focused_state_;
-        QState *normal_state_;
+    QState *focused_state_;
+    QState *normal_state_;
 
-        TextField *text_field_;
-        TextFieldLabel *label_;
+    TextField *text_field_;
+    TextFieldLabel *label_;
 
-        qreal progress_;
+    qreal progress_;
 };
 
 inline void
 TextFieldStateMachine::setProgress(qreal progress)
 {
-        progress_ = progress;
-        text_field_->update();
+    progress_ = progress;
+    text_field_->update();
 }
 
 inline qreal
 TextFieldStateMachine::progress() const
 {
-        return progress_;
+    return progress_;
 }
diff --git a/src/ui/TextLabel.cpp b/src/ui/TextLabel.cpp
index 3568e15c..340d3b8f 100644
--- a/src/ui/TextLabel.cpp
+++ b/src/ui/TextLabel.cpp
@@ -14,12 +14,12 @@
 bool
 ContextMenuFilter::eventFilter(QObject *obj, QEvent *event)
 {
-        if (event->type() == QEvent::MouseButtonPress) {
-                emit contextMenuIsOpening();
-                return true;
-        }
+    if (event->type() == QEvent::MouseButtonPress) {
+        emit contextMenuIsOpening();
+        return true;
+    }
 
-        return QObject::eventFilter(obj, event);
+    return QObject::eventFilter(obj, event);
 }
 
 TextLabel::TextLabel(QWidget *parent)
@@ -29,94 +29,94 @@ TextLabel::TextLabel(QWidget *parent)
 TextLabel::TextLabel(const QString &text, QWidget *parent)
   : QTextBrowser(parent)
 {
-        document()->setDefaultStyleSheet(QString("a {color: %1; }").arg(utils::linkColor()));
-
-        setText(text);
-        setOpenExternalLinks(true);
-
-        // Make it look and feel like an ordinary label.
-        setReadOnly(true);
-        setFrameStyle(QFrame::NoFrame);
-        QPalette pal = palette();
-        pal.setColor(QPalette::Base, Qt::transparent);
-        setPalette(pal);
-
-        // Wrap anywhere but prefer words, adjust minimum height on the fly.
-        setLineWrapMode(QTextEdit::WidgetWidth);
-        setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
-        connect(document()->documentLayout(),
-                &QAbstractTextDocumentLayout::documentSizeChanged,
-                this,
-                &TextLabel::adjustHeight);
-        document()->setDocumentMargin(0);
-
-        setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
-        setFixedHeight(0);
-
-        connect(this, &TextLabel::linkActivated, this, &TextLabel::handleLinkActivation);
-
-        auto filter = new ContextMenuFilter(this);
-        installEventFilter(filter);
-        connect(filter, &ContextMenuFilter::contextMenuIsOpening, this, [this]() {
-                contextMenuRequested_ = true;
-        });
+    document()->setDefaultStyleSheet(QString("a {color: %1; }").arg(utils::linkColor()));
+
+    setText(text);
+    setOpenExternalLinks(true);
+
+    // Make it look and feel like an ordinary label.
+    setReadOnly(true);
+    setFrameStyle(QFrame::NoFrame);
+    QPalette pal = palette();
+    pal.setColor(QPalette::Base, Qt::transparent);
+    setPalette(pal);
+
+    // Wrap anywhere but prefer words, adjust minimum height on the fly.
+    setLineWrapMode(QTextEdit::WidgetWidth);
+    setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
+    connect(document()->documentLayout(),
+            &QAbstractTextDocumentLayout::documentSizeChanged,
+            this,
+            &TextLabel::adjustHeight);
+    document()->setDocumentMargin(0);
+
+    setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+    setFixedHeight(0);
+
+    connect(this, &TextLabel::linkActivated, this, &TextLabel::handleLinkActivation);
+
+    auto filter = new ContextMenuFilter(this);
+    installEventFilter(filter);
+    connect(filter, &ContextMenuFilter::contextMenuIsOpening, this, [this]() {
+        contextMenuRequested_ = true;
+    });
 }
 
 void
 TextLabel::focusOutEvent(QFocusEvent *e)
 {
-        QTextBrowser::focusOutEvent(e);
+    QTextBrowser::focusOutEvent(e);
 
-        // We keep the selection available for the context menu.
-        if (contextMenuRequested_) {
-                contextMenuRequested_ = false;
-                return;
-        }
+    // We keep the selection available for the context menu.
+    if (contextMenuRequested_) {
+        contextMenuRequested_ = false;
+        return;
+    }
 
-        QTextCursor cursor = textCursor();
-        cursor.clearSelection();
-        setTextCursor(cursor);
+    QTextCursor cursor = textCursor();
+    cursor.clearSelection();
+    setTextCursor(cursor);
 }
 
 void
 TextLabel::mousePressEvent(QMouseEvent *e)
 {
-        link_ = (e->button() & Qt::LeftButton) ? anchorAt(e->pos()) : QString();
-        QTextBrowser::mousePressEvent(e);
+    link_ = (e->button() & Qt::LeftButton) ? anchorAt(e->pos()) : QString();
+    QTextBrowser::mousePressEvent(e);
 }
 
 void
 TextLabel::mouseReleaseEvent(QMouseEvent *e)
 {
-        if (e->button() & Qt::LeftButton && !link_.isEmpty() && anchorAt(e->pos()) == link_) {
-                emit linkActivated(link_);
-                return;
-        }
+    if (e->button() & Qt::LeftButton && !link_.isEmpty() && anchorAt(e->pos()) == link_) {
+        emit linkActivated(link_);
+        return;
+    }
 
-        QTextBrowser::mouseReleaseEvent(e);
+    QTextBrowser::mouseReleaseEvent(e);
 }
 
 void
 TextLabel::wheelEvent(QWheelEvent *event)
 {
-        event->ignore();
+    event->ignore();
 }
 
 void
 TextLabel::handleLinkActivation(const QUrl &url)
 {
-        auto parts          = url.toString().split('/');
-        auto defaultHandler = [](const QUrl &url) { QDesktopServices::openUrl(url); };
+    auto parts          = url.toString().split('/');
+    auto defaultHandler = [](const QUrl &url) { QDesktopServices::openUrl(url); };
 
-        if (url.host() != "matrix.to" || parts.isEmpty())
-                return defaultHandler(url);
+    if (url.host() != "matrix.to" || parts.isEmpty())
+        return defaultHandler(url);
 
-        try {
-                using namespace mtx::identifiers;
-                parse<User>(parts.last().toStdString());
-        } catch (const std::exception &) {
-                return defaultHandler(url);
-        }
+    try {
+        using namespace mtx::identifiers;
+        parse<User>(parts.last().toStdString());
+    } catch (const std::exception &) {
+        return defaultHandler(url);
+    }
 
-        emit userProfileTriggered(parts.last());
+    emit userProfileTriggered(parts.last());
 }
diff --git a/src/ui/TextLabel.h b/src/ui/TextLabel.h
index bc095823..313ad97c 100644
--- a/src/ui/TextLabel.h
+++ b/src/ui/TextLabel.h
@@ -15,45 +15,45 @@ class QWheelEvent;
 
 class ContextMenuFilter : public QObject
 {
-        Q_OBJECT
+    Q_OBJECT
 
 public:
-        explicit ContextMenuFilter(QWidget *parent)
-          : QObject(parent)
-        {}
+    explicit ContextMenuFilter(QWidget *parent)
+      : QObject(parent)
+    {}
 
 signals:
-        void contextMenuIsOpening();
+    void contextMenuIsOpening();
 
 protected:
-        bool eventFilter(QObject *obj, QEvent *event) override;
+    bool eventFilter(QObject *obj, QEvent *event) override;
 };
 
 class TextLabel : public QTextBrowser
 {
-        Q_OBJECT
+    Q_OBJECT
 
 public:
-        TextLabel(const QString &text, QWidget *parent = nullptr);
-        TextLabel(QWidget *parent = nullptr);
+    TextLabel(const QString &text, QWidget *parent = nullptr);
+    TextLabel(QWidget *parent = nullptr);
 
-        void wheelEvent(QWheelEvent *event) override;
-        void clearLinks() { link_.clear(); }
+    void wheelEvent(QWheelEvent *event) override;
+    void clearLinks() { link_.clear(); }
 
 protected:
-        void mousePressEvent(QMouseEvent *e) override;
-        void mouseReleaseEvent(QMouseEvent *e) override;
-        void focusOutEvent(QFocusEvent *e) override;
+    void mousePressEvent(QMouseEvent *e) override;
+    void mouseReleaseEvent(QMouseEvent *e) override;
+    void focusOutEvent(QFocusEvent *e) override;
 
 private slots:
-        void adjustHeight(const QSizeF &size) { setFixedHeight(size.height()); }
-        void handleLinkActivation(const QUrl &link);
+    void adjustHeight(const QSizeF &size) { setFixedHeight(size.height()); }
+    void handleLinkActivation(const QUrl &link);
 
 signals:
-        void userProfileTriggered(const QString &user_id);
-        void linkActivated(const QUrl &link);
+    void userProfileTriggered(const QString &user_id);
+    void linkActivated(const QUrl &link);
 
 private:
-        QString link_;
-        bool contextMenuRequested_ = false;
+    QString link_;
+    bool contextMenuRequested_ = false;
 };
diff --git a/src/ui/Theme.cpp b/src/ui/Theme.cpp
index 732a0443..d6f0b72f 100644
--- a/src/ui/Theme.cpp
+++ b/src/ui/Theme.cpp
@@ -9,66 +9,66 @@ Q_DECLARE_METATYPE(Theme)
 QPalette
 Theme::paletteFromTheme(std::string_view theme)
 {
-        [[maybe_unused]] static auto meta = qRegisterMetaType<Theme>("Theme");
-        static QPalette original;
-        if (theme == "light") {
-                QPalette lightActive(
-                  /*windowText*/ QColor("#333"),
-                  /*button*/ QColor("white"),
-                  /*light*/ QColor(0xef, 0xef, 0xef),
-                  /*dark*/ QColor(70, 77, 93),
-                  /*mid*/ QColor(220, 220, 220),
-                  /*text*/ QColor("#333"),
-                  /*bright_text*/ QColor("#f2f5f8"),
-                  /*base*/ QColor("#fff"),
-                  /*window*/ QColor("white"));
-                lightActive.setColor(QPalette::AlternateBase, QColor("#eee"));
-                lightActive.setColor(QPalette::Highlight, QColor("#38a3d8"));
-                lightActive.setColor(QPalette::HighlightedText, QColor("#f4f4f5"));
-                lightActive.setColor(QPalette::ToolTipBase, lightActive.base().color());
-                lightActive.setColor(QPalette::ToolTipText, lightActive.text().color());
-                lightActive.setColor(QPalette::Link, QColor("#0077b5"));
-                lightActive.setColor(QPalette::ButtonText, QColor("#555459"));
-                return lightActive;
-        } else if (theme == "dark") {
-                QPalette darkActive(
-                  /*windowText*/ QColor("#caccd1"),
-                  /*button*/ QColor(0xff, 0xff, 0xff),
-                  /*light*/ QColor("#caccd1"),
-                  /*dark*/ QColor(60, 70, 77),
-                  /*mid*/ QColor("#202228"),
-                  /*text*/ QColor("#caccd1"),
-                  /*bright_text*/ QColor("#f4f5f8"),
-                  /*base*/ QColor("#202228"),
-                  /*window*/ QColor("#2d3139"));
-                darkActive.setColor(QPalette::AlternateBase, QColor("#2d3139"));
-                darkActive.setColor(QPalette::Highlight, QColor("#38a3d8"));
-                darkActive.setColor(QPalette::HighlightedText, QColor("#f4f5f8"));
-                darkActive.setColor(QPalette::ToolTipBase, darkActive.base().color());
-                darkActive.setColor(QPalette::ToolTipText, darkActive.text().color());
-                darkActive.setColor(QPalette::Link, QColor("#38a3d8"));
-                darkActive.setColor(QPalette::ButtonText, "#828284");
-                return darkActive;
-        } else {
-                return original;
-        }
+    [[maybe_unused]] static auto meta = qRegisterMetaType<Theme>("Theme");
+    static QPalette original;
+    if (theme == "light") {
+        QPalette lightActive(
+          /*windowText*/ QColor("#333"),
+          /*button*/ QColor("white"),
+          /*light*/ QColor(0xef, 0xef, 0xef),
+          /*dark*/ QColor(70, 77, 93),
+          /*mid*/ QColor(220, 220, 220),
+          /*text*/ QColor("#333"),
+          /*bright_text*/ QColor("#f2f5f8"),
+          /*base*/ QColor("#fff"),
+          /*window*/ QColor("white"));
+        lightActive.setColor(QPalette::AlternateBase, QColor("#eee"));
+        lightActive.setColor(QPalette::Highlight, QColor("#38a3d8"));
+        lightActive.setColor(QPalette::HighlightedText, QColor("#f4f4f5"));
+        lightActive.setColor(QPalette::ToolTipBase, lightActive.base().color());
+        lightActive.setColor(QPalette::ToolTipText, lightActive.text().color());
+        lightActive.setColor(QPalette::Link, QColor("#0077b5"));
+        lightActive.setColor(QPalette::ButtonText, QColor("#555459"));
+        return lightActive;
+    } else if (theme == "dark") {
+        QPalette darkActive(
+          /*windowText*/ QColor("#caccd1"),
+          /*button*/ QColor(0xff, 0xff, 0xff),
+          /*light*/ QColor("#caccd1"),
+          /*dark*/ QColor(60, 70, 77),
+          /*mid*/ QColor("#202228"),
+          /*text*/ QColor("#caccd1"),
+          /*bright_text*/ QColor("#f4f5f8"),
+          /*base*/ QColor("#202228"),
+          /*window*/ QColor("#2d3139"));
+        darkActive.setColor(QPalette::AlternateBase, QColor("#2d3139"));
+        darkActive.setColor(QPalette::Highlight, QColor("#38a3d8"));
+        darkActive.setColor(QPalette::HighlightedText, QColor("#f4f5f8"));
+        darkActive.setColor(QPalette::ToolTipBase, darkActive.base().color());
+        darkActive.setColor(QPalette::ToolTipText, darkActive.text().color());
+        darkActive.setColor(QPalette::Link, QColor("#38a3d8"));
+        darkActive.setColor(QPalette::ButtonText, "#828284");
+        return darkActive;
+    } else {
+        return original;
+    }
 }
 
 Theme::Theme(std::string_view theme)
 {
-        auto p     = paletteFromTheme(theme);
-        separator_ = p.mid().color();
-        if (theme == "light") {
-                sidebarBackground_ = QColor("#233649");
-                alternateButton_   = QColor("#ccc");
-                red_               = QColor("#a82353");
-        } else if (theme == "dark") {
-                sidebarBackground_ = QColor("#2d3139");
-                alternateButton_   = QColor("#414A59");
-                red_               = QColor("#a82353");
-        } else {
-                sidebarBackground_ = p.window().color();
-                alternateButton_   = p.dark().color();
-                red_               = QColor("red");
-        }
+    auto p     = paletteFromTheme(theme);
+    separator_ = p.mid().color();
+    if (theme == "light") {
+        sidebarBackground_ = QColor("#233649");
+        alternateButton_   = QColor("#ccc");
+        red_               = QColor("#a82353");
+    } else if (theme == "dark") {
+        sidebarBackground_ = QColor("#2d3139");
+        alternateButton_   = QColor("#414A59");
+        red_               = QColor("#a82353");
+    } else {
+        sidebarBackground_ = p.window().color();
+        alternateButton_   = p.dark().color();
+        red_               = QColor("red");
+    }
 }
diff --git a/src/ui/Theme.h b/src/ui/Theme.h
index cc39714b..f3e7c287 100644
--- a/src/ui/Theme.h
+++ b/src/ui/Theme.h
@@ -16,62 +16,62 @@ const int AvatarSize = 40;
 
 enum class ButtonPreset
 {
-        FlatPreset,
-        CheckablePreset
+    FlatPreset,
+    CheckablePreset
 };
 
 enum class RippleStyle
 {
-        CenteredRipple,
-        PositionedRipple,
-        NoRipple
+    CenteredRipple,
+    PositionedRipple,
+    NoRipple
 };
 
 enum class OverlayStyle
 {
-        NoOverlay,
-        TintedOverlay,
-        GrayOverlay
+    NoOverlay,
+    TintedOverlay,
+    GrayOverlay
 };
 
 enum class Role
 {
-        Default,
-        Primary,
-        Secondary
+    Default,
+    Primary,
+    Secondary
 };
 
 enum class ButtonIconPlacement
 {
-        LeftIcon,
-        RightIcon
+    LeftIcon,
+    RightIcon
 };
 
 enum class ProgressType
 {
-        DeterminateProgress,
-        IndeterminateProgress
+    DeterminateProgress,
+    IndeterminateProgress
 };
 
 } // namespace ui
 
 class Theme : public QPalette
 {
-        Q_GADGET
-        Q_PROPERTY(QColor sidebarBackground READ sidebarBackground CONSTANT)
-        Q_PROPERTY(QColor alternateButton READ alternateButton CONSTANT)
-        Q_PROPERTY(QColor separator READ separator CONSTANT)
-        Q_PROPERTY(QColor red READ red CONSTANT)
+    Q_GADGET
+    Q_PROPERTY(QColor sidebarBackground READ sidebarBackground CONSTANT)
+    Q_PROPERTY(QColor alternateButton READ alternateButton CONSTANT)
+    Q_PROPERTY(QColor separator READ separator CONSTANT)
+    Q_PROPERTY(QColor red READ red CONSTANT)
 public:
-        Theme() {}
-        explicit Theme(std::string_view theme);
-        static QPalette paletteFromTheme(std::string_view theme);
+    Theme() {}
+    explicit Theme(std::string_view theme);
+    static QPalette paletteFromTheme(std::string_view theme);
 
-        QColor sidebarBackground() const { return sidebarBackground_; }
-        QColor alternateButton() const { return alternateButton_; }
-        QColor separator() const { return separator_; }
-        QColor red() const { return red_; }
+    QColor sidebarBackground() const { return sidebarBackground_; }
+    QColor alternateButton() const { return alternateButton_; }
+    QColor separator() const { return separator_; }
+    QColor red() const { return red_; }
 
 private:
-        QColor sidebarBackground_, separator_, red_, alternateButton_;
+    QColor sidebarBackground_, separator_, red_, alternateButton_;
 };
diff --git a/src/ui/ThemeManager.cpp b/src/ui/ThemeManager.cpp
index b7b3df40..0c84777a 100644
--- a/src/ui/ThemeManager.cpp
+++ b/src/ui/ThemeManager.cpp
@@ -11,32 +11,32 @@ ThemeManager::ThemeManager() {}
 QColor
 ThemeManager::themeColor(const QString &key) const
 {
-        if (key == "Black")
-                return QColor("#171919");
-
-        else if (key == "BrightWhite")
-                return QColor("#EBEBEB");
-        else if (key == "FadedWhite")
-                return QColor("#C9C9C9");
-        else if (key == "MediumWhite")
-                return QColor("#929292");
-
-        else if (key == "BrightGreen")
-                return QColor("#1C3133");
-        else if (key == "DarkGreen")
-                return QColor("#577275");
-        else if (key == "LightGreen")
-                return QColor("#46A451");
-
-        else if (key == "Gray")
-                return QColor("#5D6565");
-        else if (key == "Red")
-                return QColor("#E22826");
-        else if (key == "Blue")
-                return QColor("#81B3A9");
-
-        else if (key == "Transparent")
-                return QColor(0, 0, 0, 0);
-
-        return (QColor(0, 0, 0, 0));
+    if (key == "Black")
+        return QColor("#171919");
+
+    else if (key == "BrightWhite")
+        return QColor("#EBEBEB");
+    else if (key == "FadedWhite")
+        return QColor("#C9C9C9");
+    else if (key == "MediumWhite")
+        return QColor("#929292");
+
+    else if (key == "BrightGreen")
+        return QColor("#1C3133");
+    else if (key == "DarkGreen")
+        return QColor("#577275");
+    else if (key == "LightGreen")
+        return QColor("#46A451");
+
+    else if (key == "Gray")
+        return QColor("#5D6565");
+    else if (key == "Red")
+        return QColor("#E22826");
+    else if (key == "Blue")
+        return QColor("#81B3A9");
+
+    else if (key == "Transparent")
+        return QColor(0, 0, 0, 0);
+
+    return (QColor(0, 0, 0, 0));
 }
diff --git a/src/ui/ThemeManager.h b/src/ui/ThemeManager.h
index cbb355fd..5e86c68f 100644
--- a/src/ui/ThemeManager.h
+++ b/src/ui/ThemeManager.h
@@ -8,23 +8,23 @@
 
 class ThemeManager : public QCommonStyle
 {
-        Q_OBJECT
+    Q_OBJECT
 
 public:
-        inline static ThemeManager &instance();
+    inline static ThemeManager &instance();
 
-        QColor themeColor(const QString &key) const;
+    QColor themeColor(const QString &key) const;
 
 private:
-        ThemeManager();
+    ThemeManager();
 
-        ThemeManager(ThemeManager const &);
-        void operator=(ThemeManager const &);
+    ThemeManager(ThemeManager const &);
+    void operator=(ThemeManager const &);
 };
 
 inline ThemeManager &
 ThemeManager::instance()
 {
-        static ThemeManager instance;
-        return instance;
+    static ThemeManager instance;
+    return instance;
 }
diff --git a/src/ui/ToggleButton.cpp b/src/ui/ToggleButton.cpp
index 33bf8f92..04f752d7 100644
--- a/src/ui/ToggleButton.cpp
+++ b/src/ui/ToggleButton.cpp
@@ -12,84 +12,84 @@
 void
 Toggle::paintEvent(QPaintEvent *event)
 {
-        Q_UNUSED(event);
+    Q_UNUSED(event);
 }
 
 Toggle::Toggle(QWidget *parent)
   : QAbstractButton{parent}
 {
-        init();
+    init();
 
-        connect(this, &QAbstractButton::toggled, this, &Toggle::setState);
+    connect(this, &QAbstractButton::toggled, this, &Toggle::setState);
 }
 
 void
 Toggle::setState(bool isEnabled)
 {
-        setChecked(isEnabled);
-        thumb_->setShift(isEnabled ? Position::Left : Position::Right);
-        setupProperties();
+    setChecked(isEnabled);
+    thumb_->setShift(isEnabled ? Position::Left : Position::Right);
+    setupProperties();
 }
 
 void
 Toggle::init()
 {
-        track_ = new ToggleTrack(this);
-        thumb_ = new ToggleThumb(this);
+    track_ = new ToggleTrack(this);
+    thumb_ = new ToggleThumb(this);
 
-        setCursor(QCursor(Qt::PointingHandCursor));
-        setCheckable(true);
-        setChecked(false);
+    setCursor(QCursor(Qt::PointingHandCursor));
+    setCheckable(true);
+    setChecked(false);
 
-        setState(false);
-        setupProperties();
+    setState(false);
+    setupProperties();
 
-        QCoreApplication::processEvents();
+    QCoreApplication::processEvents();
 }
 
 void
 Toggle::setupProperties()
 {
-        if (isEnabled()) {
-                Position position = thumb_->shift();
+    if (isEnabled()) {
+        Position position = thumb_->shift();
 
-                thumb_->setThumbColor(trackColor());
+        thumb_->setThumbColor(trackColor());
 
-                if (position == Position::Left)
-                        track_->setTrackColor(activeColor());
-                else if (position == Position::Right)
-                        track_->setTrackColor(inactiveColor());
-        }
+        if (position == Position::Left)
+            track_->setTrackColor(activeColor());
+        else if (position == Position::Right)
+            track_->setTrackColor(inactiveColor());
+    }
 
-        update();
+    update();
 }
 
 void
 Toggle::setDisabledColor(const QColor &color)
 {
-        disabledColor_ = color;
-        setupProperties();
+    disabledColor_ = color;
+    setupProperties();
 }
 
 void
 Toggle::setActiveColor(const QColor &color)
 {
-        activeColor_ = color;
-        setupProperties();
+    activeColor_ = color;
+    setupProperties();
 }
 
 void
 Toggle::setInactiveColor(const QColor &color)
 {
-        inactiveColor_ = color;
-        setupProperties();
+    inactiveColor_ = color;
+    setupProperties();
 }
 
 void
 Toggle::setTrackColor(const QColor &color)
 {
-        trackColor_ = color;
-        setupProperties();
+    trackColor_ = color;
+    setupProperties();
 }
 
 ToggleThumb::ToggleThumb(Toggle *parent)
@@ -98,119 +98,119 @@ ToggleThumb::ToggleThumb(Toggle *parent)
   , position_{Position::Right}
   , offset_{0}
 {
-        parent->installEventFilter(this);
+    parent->installEventFilter(this);
 }
 
 void
 ToggleThumb::setShift(Position position)
 {
-        if (position_ != position) {
-                position_ = position;
-                updateOffset();
-        }
+    if (position_ != position) {
+        position_ = position;
+        updateOffset();
+    }
 }
 
 bool
 ToggleThumb::eventFilter(QObject *obj, QEvent *event)
 {
-        const QEvent::Type type = event->type();
+    const QEvent::Type type = event->type();
 
-        if (QEvent::Resize == type || QEvent::Move == type) {
-                setGeometry(toggle_->rect().adjusted(8, 8, -8, -8));
-                updateOffset();
-        }
+    if (QEvent::Resize == type || QEvent::Move == type) {
+        setGeometry(toggle_->rect().adjusted(8, 8, -8, -8));
+        updateOffset();
+    }
 
-        return QWidget::eventFilter(obj, event);
+    return QWidget::eventFilter(obj, event);
 }
 
 void
 ToggleThumb::paintEvent(QPaintEvent *event)
 {
-        Q_UNUSED(event)
+    Q_UNUSED(event)
 
-        QPainter painter(this);
-        painter.setRenderHint(QPainter::Antialiasing);
+    QPainter painter(this);
+    painter.setRenderHint(QPainter::Antialiasing);
 
-        QBrush brush;
-        brush.setStyle(Qt::SolidPattern);
-        brush.setColor(toggle_->isEnabled() ? thumbColor_ : Qt::white);
+    QBrush brush;
+    brush.setStyle(Qt::SolidPattern);
+    brush.setColor(toggle_->isEnabled() ? thumbColor_ : Qt::white);
 
-        painter.setBrush(brush);
-        painter.setPen(Qt::NoPen);
+    painter.setBrush(brush);
+    painter.setPen(Qt::NoPen);
 
-        int s;
-        QRectF r;
+    int s;
+    QRectF r;
 
-        s = height() - 10;
-        r = QRectF(5 + offset_, 5, s, s);
+    s = height() - 10;
+    r = QRectF(5 + offset_, 5, s, s);
 
-        painter.drawEllipse(r);
+    painter.drawEllipse(r);
 
-        if (!toggle_->isEnabled()) {
-                brush.setColor(toggle_->disabledColor());
-                painter.setBrush(brush);
-                painter.drawEllipse(r);
-        }
+    if (!toggle_->isEnabled()) {
+        brush.setColor(toggle_->disabledColor());
+        painter.setBrush(brush);
+        painter.drawEllipse(r);
+    }
 }
 
 void
 ToggleThumb::updateOffset()
 {
-        const QSize s(size());
-        offset_ = position_ == Position::Left ? static_cast<qreal>(s.width() - s.height()) : 0;
-        update();
+    const QSize s(size());
+    offset_ = position_ == Position::Left ? static_cast<qreal>(s.width() - s.height()) : 0;
+    update();
 }
 
 ToggleTrack::ToggleTrack(Toggle *parent)
   : QWidget{parent}
   , toggle_{parent}
 {
-        Q_ASSERT(parent);
+    Q_ASSERT(parent);
 
-        parent->installEventFilter(this);
+    parent->installEventFilter(this);
 }
 
 void
 ToggleTrack::setTrackColor(const QColor &color)
 {
-        trackColor_ = color;
-        update();
+    trackColor_ = color;
+    update();
 }
 
 bool
 ToggleTrack::eventFilter(QObject *obj, QEvent *event)
 {
-        const QEvent::Type type = event->type();
+    const QEvent::Type type = event->type();
 
-        if (QEvent::Resize == type || QEvent::Move == type) {
-                setGeometry(toggle_->rect());
-        }
+    if (QEvent::Resize == type || QEvent::Move == type) {
+        setGeometry(toggle_->rect());
+    }
 
-        return QWidget::eventFilter(obj, event);
+    return QWidget::eventFilter(obj, event);
 }
 
 void
 ToggleTrack::paintEvent(QPaintEvent *event)
 {
-        Q_UNUSED(event)
+    Q_UNUSED(event)
 
-        QPainter painter(this);
-        painter.setRenderHint(QPainter::Antialiasing);
+    QPainter painter(this);
+    painter.setRenderHint(QPainter::Antialiasing);
 
-        QBrush brush;
-        if (toggle_->isEnabled()) {
-                brush.setColor(trackColor_);
-                painter.setOpacity(0.8);
-        } else {
-                brush.setColor(toggle_->disabledColor());
-                painter.setOpacity(0.6);
-        }
+    QBrush brush;
+    if (toggle_->isEnabled()) {
+        brush.setColor(trackColor_);
+        painter.setOpacity(0.8);
+    } else {
+        brush.setColor(toggle_->disabledColor());
+        painter.setOpacity(0.6);
+    }
 
-        brush.setStyle(Qt::SolidPattern);
-        painter.setBrush(brush);
-        painter.setPen(Qt::NoPen);
+    brush.setStyle(Qt::SolidPattern);
+    painter.setBrush(brush);
+    painter.setPen(Qt::NoPen);
 
-        const int h = height() / 2;
-        const QRect r(0, h / 2, width(), h);
-        painter.drawRoundedRect(r.adjusted(14, 4, -14, -4), h / 2 - 4, h / 2 - 4);
+    const int h = height() / 2;
+    const QRect r(0, h / 2, width(), h);
+    painter.drawRoundedRect(r.adjusted(14, 4, -14, -4), h / 2 - 4, h / 2 - 4);
 }
diff --git a/src/ui/ToggleButton.h b/src/ui/ToggleButton.h
index 2413b086..15d5e192 100644
--- a/src/ui/ToggleButton.h
+++ b/src/ui/ToggleButton.h
@@ -12,103 +12,103 @@ class ToggleThumb;
 
 enum class Position
 {
-        Left,
-        Right
+    Left,
+    Right
 };
 
 class Toggle : public QAbstractButton
 {
-        Q_OBJECT
+    Q_OBJECT
 
-        Q_PROPERTY(QColor activeColor WRITE setActiveColor READ activeColor)
-        Q_PROPERTY(QColor disabledColor WRITE setDisabledColor READ disabledColor)
-        Q_PROPERTY(QColor inactiveColor WRITE setInactiveColor READ inactiveColor)
-        Q_PROPERTY(QColor trackColor WRITE setTrackColor READ trackColor)
+    Q_PROPERTY(QColor activeColor WRITE setActiveColor READ activeColor)
+    Q_PROPERTY(QColor disabledColor WRITE setDisabledColor READ disabledColor)
+    Q_PROPERTY(QColor inactiveColor WRITE setInactiveColor READ inactiveColor)
+    Q_PROPERTY(QColor trackColor WRITE setTrackColor READ trackColor)
 
 public:
-        Toggle(QWidget *parent = nullptr);
+    Toggle(QWidget *parent = nullptr);
 
-        void setState(bool isEnabled);
+    void setState(bool isEnabled);
 
-        void setActiveColor(const QColor &color);
-        void setDisabledColor(const QColor &color);
-        void setInactiveColor(const QColor &color);
-        void setTrackColor(const QColor &color);
+    void setActiveColor(const QColor &color);
+    void setDisabledColor(const QColor &color);
+    void setInactiveColor(const QColor &color);
+    void setTrackColor(const QColor &color);
 
-        QColor activeColor() const { return activeColor_; };
-        QColor disabledColor() const { return disabledColor_; };
-        QColor inactiveColor() const { return inactiveColor_; };
-        QColor trackColor() const { return trackColor_.isValid() ? trackColor_ : QColor("#eee"); };
+    QColor activeColor() const { return activeColor_; };
+    QColor disabledColor() const { return disabledColor_; };
+    QColor inactiveColor() const { return inactiveColor_; };
+    QColor trackColor() const { return trackColor_.isValid() ? trackColor_ : QColor("#eee"); };
 
-        QSize sizeHint() const override { return QSize(64, 48); };
+    QSize sizeHint() const override { return QSize(64, 48); };
 
 protected:
-        void paintEvent(QPaintEvent *event) override;
+    void paintEvent(QPaintEvent *event) override;
 
 private:
-        void init();
-        void setupProperties();
+    void init();
+    void setupProperties();
 
-        ToggleTrack *track_;
-        ToggleThumb *thumb_;
+    ToggleTrack *track_;
+    ToggleThumb *thumb_;
 
-        QColor disabledColor_;
-        QColor activeColor_;
-        QColor inactiveColor_;
-        QColor trackColor_;
+    QColor disabledColor_;
+    QColor activeColor_;
+    QColor inactiveColor_;
+    QColor trackColor_;
 };
 
 class ToggleThumb : public QWidget
 {
-        Q_OBJECT
+    Q_OBJECT
 
-        Q_PROPERTY(QColor thumbColor WRITE setThumbColor READ thumbColor)
+    Q_PROPERTY(QColor thumbColor WRITE setThumbColor READ thumbColor)
 
 public:
-        ToggleThumb(Toggle *parent);
+    ToggleThumb(Toggle *parent);
 
-        Position shift() const { return position_; };
-        qreal offset() const { return offset_; };
-        QColor thumbColor() const { return thumbColor_; };
+    Position shift() const { return position_; };
+    qreal offset() const { return offset_; };
+    QColor thumbColor() const { return thumbColor_; };
 
-        void setShift(Position position);
-        void setThumbColor(const QColor &color)
-        {
-                thumbColor_ = color;
-                update();
-        };
+    void setShift(Position position);
+    void setThumbColor(const QColor &color)
+    {
+        thumbColor_ = color;
+        update();
+    };
 
 protected:
-        bool eventFilter(QObject *obj, QEvent *event) override;
-        void paintEvent(QPaintEvent *event) override;
+    bool eventFilter(QObject *obj, QEvent *event) override;
+    void paintEvent(QPaintEvent *event) override;
 
 private:
-        void updateOffset();
+    void updateOffset();
 
-        Toggle *const toggle_;
-        QColor thumbColor_;
+    Toggle *const toggle_;
+    QColor thumbColor_;
 
-        Position position_;
-        qreal offset_;
+    Position position_;
+    qreal offset_;
 };
 
 class ToggleTrack : public QWidget
 {
-        Q_OBJECT
+    Q_OBJECT
 
-        Q_PROPERTY(QColor trackColor WRITE setTrackColor READ trackColor)
+    Q_PROPERTY(QColor trackColor WRITE setTrackColor READ trackColor)
 
 public:
-        ToggleTrack(Toggle *parent);
+    ToggleTrack(Toggle *parent);
 
-        void setTrackColor(const QColor &color);
-        QColor trackColor() const { return trackColor_; };
+    void setTrackColor(const QColor &color);
+    QColor trackColor() const { return trackColor_; };
 
 protected:
-        bool eventFilter(QObject *obj, QEvent *event) override;
-        void paintEvent(QPaintEvent *event) override;
+    bool eventFilter(QObject *obj, QEvent *event) override;
+    void paintEvent(QPaintEvent *event) override;
 
 private:
-        Toggle *const toggle_;
-        QColor trackColor_;
+    Toggle *const toggle_;
+    QColor trackColor_;
 };
diff --git a/src/ui/UserProfile.cpp b/src/ui/UserProfile.cpp
index fbd0f4f7..58150ed7 100644
--- a/src/ui/UserProfile.cpp
+++ b/src/ui/UserProfile.cpp
@@ -27,210 +27,200 @@ UserProfile::UserProfile(QString roomid,
   , manager(manager_)
   , model(parent)
 {
-        globalAvatarUrl = "";
-
-        connect(this,
-                &UserProfile::globalUsernameRetrieved,
-                this,
-                &UserProfile::setGlobalUsername,
-                Qt::QueuedConnection);
-
-        if (isGlobalUserProfile()) {
-                getGlobalProfileData();
-        }
-
-        if (!cache::client() || !cache::client()->isDatabaseReady() ||
-            !ChatPage::instance()->timelineManager())
-                return;
-
-        connect(cache::client(),
-                &Cache::verificationStatusChanged,
-                this,
-                [this](const std::string &user_id) {
-                        if (user_id != this->userid_.toStdString())
-                                return;
-
-                        auto status = cache::verificationStatus(user_id);
-                        if (!status)
-                                return;
-                        this->isUserVerified = status->user_verified;
-                        emit userStatusChanged();
-
-                        for (auto &deviceInfo : deviceList_.deviceList_) {
-                                deviceInfo.verification_status =
-                                  std::find(status->verified_devices.begin(),
-                                            status->verified_devices.end(),
-                                            deviceInfo.device_id.toStdString()) ==
-                                      status->verified_devices.end()
-                                    ? verification::UNVERIFIED
-                                    : verification::VERIFIED;
-                        }
-                        deviceList_.reset(deviceList_.deviceList_);
-                        emit devicesChanged();
-                });
-        fetchDeviceList(this->userid_);
+    globalAvatarUrl = "";
+
+    connect(this,
+            &UserProfile::globalUsernameRetrieved,
+            this,
+            &UserProfile::setGlobalUsername,
+            Qt::QueuedConnection);
+
+    if (isGlobalUserProfile()) {
+        getGlobalProfileData();
+    }
+
+    if (!cache::client() || !cache::client()->isDatabaseReady() ||
+        !ChatPage::instance()->timelineManager())
+        return;
+
+    connect(
+      cache::client(), &Cache::verificationStatusChanged, this, [this](const std::string &user_id) {
+          if (user_id != this->userid_.toStdString())
+              return;
+
+          auto status = cache::verificationStatus(user_id);
+          if (!status)
+              return;
+          this->isUserVerified = status->user_verified;
+          emit userStatusChanged();
+
+          for (auto &deviceInfo : deviceList_.deviceList_) {
+              deviceInfo.verification_status =
+                std::find(status->verified_devices.begin(),
+                          status->verified_devices.end(),
+                          deviceInfo.device_id.toStdString()) == status->verified_devices.end()
+                  ? verification::UNVERIFIED
+                  : verification::VERIFIED;
+          }
+          deviceList_.reset(deviceList_.deviceList_);
+          emit devicesChanged();
+      });
+    fetchDeviceList(this->userid_);
 }
 
 QHash<int, QByteArray>
 DeviceInfoModel::roleNames() const
 {
-        return {
-          {DeviceId, "deviceId"},
-          {DeviceName, "deviceName"},
-          {VerificationStatus, "verificationStatus"},
-        };
+    return {
+      {DeviceId, "deviceId"},
+      {DeviceName, "deviceName"},
+      {VerificationStatus, "verificationStatus"},
+    };
 }
 
 QVariant
 DeviceInfoModel::data(const QModelIndex &index, int role) const
 {
-        if (!index.isValid() || index.row() >= (int)deviceList_.size() || index.row() < 0)
-                return {};
-
-        switch (role) {
-        case DeviceId:
-                return deviceList_[index.row()].device_id;
-        case DeviceName:
-                return deviceList_[index.row()].display_name;
-        case VerificationStatus:
-                return QVariant::fromValue(deviceList_[index.row()].verification_status);
-        default:
-                return {};
-        }
+    if (!index.isValid() || index.row() >= (int)deviceList_.size() || index.row() < 0)
+        return {};
+
+    switch (role) {
+    case DeviceId:
+        return deviceList_[index.row()].device_id;
+    case DeviceName:
+        return deviceList_[index.row()].display_name;
+    case VerificationStatus:
+        return QVariant::fromValue(deviceList_[index.row()].verification_status);
+    default:
+        return {};
+    }
 }
 
 void
 DeviceInfoModel::reset(const std::vector<DeviceInfo> &deviceList)
 {
-        beginResetModel();
-        this->deviceList_ = std::move(deviceList);
-        endResetModel();
+    beginResetModel();
+    this->deviceList_ = std::move(deviceList);
+    endResetModel();
 }
 
 DeviceInfoModel *
 UserProfile::deviceList()
 {
-        return &this->deviceList_;
+    return &this->deviceList_;
 }
 
 QString
 UserProfile::userid()
 {
-        return this->userid_;
+    return this->userid_;
 }
 
 QString
 UserProfile::displayName()
 {
-        return isGlobalUserProfile() ? globalUsername : cache::displayName(roomid_, userid_);
+    return isGlobalUserProfile() ? globalUsername : cache::displayName(roomid_, userid_);
 }
 
 QString
 UserProfile::avatarUrl()
 {
-        return isGlobalUserProfile() ? globalAvatarUrl : cache::avatarUrl(roomid_, userid_);
+    return isGlobalUserProfile() ? globalAvatarUrl : cache::avatarUrl(roomid_, userid_);
 }
 
 bool
 UserProfile::isGlobalUserProfile() const
 {
-        return roomid_ == "";
+    return roomid_ == "";
 }
 
 crypto::Trust
 UserProfile::getUserStatus()
 {
-        return isUserVerified;
+    return isUserVerified;
 }
 
 bool
 UserProfile::userVerificationEnabled() const
 {
-        return hasMasterKey;
+    return hasMasterKey;
 }
 bool
 UserProfile::isSelf() const
 {
-        return this->userid_ == utils::localUser();
+    return this->userid_ == utils::localUser();
 }
 
 void
 UserProfile::fetchDeviceList(const QString &userID)
 {
-        auto localUser = utils::localUser();
-
-        if (!cache::client() || !cache::client()->isDatabaseReady())
-                return;
-
-        cache::client()->query_keys(
-          userID.toStdString(),
-          [other_user_id = userID.toStdString(), this](const UserKeyCache &other_user_keys,
-                                                       mtx::http::RequestErr err) {
-                  if (err) {
-                          nhlog::net()->warn("failed to query device keys: {},{}",
-                                             mtx::errors::to_string(err->matrix_error.errcode),
-                                             static_cast<int>(err->status_code));
-                          return;
-                  }
-
-                  // Ensure local key cache is up to date
-                  cache::client()->query_keys(
-                    utils::localUser().toStdString(),
-                    [other_user_id, other_user_keys, this](const UserKeyCache &,
-                                                           mtx::http::RequestErr err) {
-                            using namespace mtx;
-                            std::string local_user_id = utils::localUser().toStdString();
-
-                            if (err) {
-                                    nhlog::net()->warn(
-                                      "failed to query device keys: {},{}",
-                                      mtx::errors::to_string(err->matrix_error.errcode),
-                                      static_cast<int>(err->status_code));
-                                    return;
-                            }
-
-                            this->hasMasterKey = !other_user_keys.master_keys.keys.empty();
-
-                            std::vector<DeviceInfo> deviceInfo;
-                            auto devices = other_user_keys.device_keys;
-                            auto verificationStatus =
-                              cache::client()->verificationStatus(other_user_id);
-
-                            isUserVerified = verificationStatus.user_verified;
-                            emit userStatusChanged();
-
-                            for (const auto &d : devices) {
-                                    auto device = d.second;
-                                    verification::Status verified =
-                                      verification::Status::UNVERIFIED;
-
-                                    if (std::find(verificationStatus.verified_devices.begin(),
-                                                  verificationStatus.verified_devices.end(),
-                                                  device.device_id) !=
-                                          verificationStatus.verified_devices.end() &&
-                                        mtx::crypto::verify_identity_signature(
-                                          device,
-                                          DeviceId(device.device_id),
-                                          UserId(other_user_id)))
-                                            verified = verification::Status::VERIFIED;
-
-                                    deviceInfo.push_back(
-                                      {QString::fromStdString(d.first),
-                                       QString::fromStdString(
-                                         device.unsigned_info.device_display_name),
-                                       verified});
-                            }
-
-                            this->deviceList_.queueReset(std::move(deviceInfo));
-                            emit devicesChanged();
-                    });
-          });
+    auto localUser = utils::localUser();
+
+    if (!cache::client() || !cache::client()->isDatabaseReady())
+        return;
+
+    cache::client()->query_keys(
+      userID.toStdString(),
+      [other_user_id = userID.toStdString(), this](const UserKeyCache &other_user_keys,
+                                                   mtx::http::RequestErr err) {
+          if (err) {
+              nhlog::net()->warn("failed to query device keys: {},{}",
+                                 mtx::errors::to_string(err->matrix_error.errcode),
+                                 static_cast<int>(err->status_code));
+              return;
+          }
+
+          // Ensure local key cache is up to date
+          cache::client()->query_keys(
+            utils::localUser().toStdString(),
+            [other_user_id, other_user_keys, this](const UserKeyCache &,
+                                                   mtx::http::RequestErr err) {
+                using namespace mtx;
+                std::string local_user_id = utils::localUser().toStdString();
+
+                if (err) {
+                    nhlog::net()->warn("failed to query device keys: {},{}",
+                                       mtx::errors::to_string(err->matrix_error.errcode),
+                                       static_cast<int>(err->status_code));
+                    return;
+                }
+
+                this->hasMasterKey = !other_user_keys.master_keys.keys.empty();
+
+                std::vector<DeviceInfo> deviceInfo;
+                auto devices            = other_user_keys.device_keys;
+                auto verificationStatus = cache::client()->verificationStatus(other_user_id);
+
+                isUserVerified = verificationStatus.user_verified;
+                emit userStatusChanged();
+
+                for (const auto &d : devices) {
+                    auto device                   = d.second;
+                    verification::Status verified = verification::Status::UNVERIFIED;
+
+                    if (std::find(verificationStatus.verified_devices.begin(),
+                                  verificationStatus.verified_devices.end(),
+                                  device.device_id) != verificationStatus.verified_devices.end() &&
+                        mtx::crypto::verify_identity_signature(
+                          device, DeviceId(device.device_id), UserId(other_user_id)))
+                        verified = verification::Status::VERIFIED;
+
+                    deviceInfo.push_back(
+                      {QString::fromStdString(d.first),
+                       QString::fromStdString(device.unsigned_info.device_display_name),
+                       verified});
+                }
+
+                this->deviceList_.queueReset(std::move(deviceInfo));
+                emit devicesChanged();
+            });
+      });
 }
 
 void
 UserProfile::banUser()
 {
-        ChatPage::instance()->banUser(this->userid_, "");
+    ChatPage::instance()->banUser(this->userid_, "");
 }
 
 // void ignoreUser(){
@@ -240,188 +230,180 @@ UserProfile::banUser()
 void
 UserProfile::kickUser()
 {
-        ChatPage::instance()->kickUser(this->userid_, "");
+    ChatPage::instance()->kickUser(this->userid_, "");
 }
 
 void
 UserProfile::startChat()
 {
-        ChatPage::instance()->startChat(this->userid_);
+    ChatPage::instance()->startChat(this->userid_);
 }
 
 void
 UserProfile::changeUsername(QString username)
 {
-        if (isGlobalUserProfile()) {
-                // change global
-                http::client()->set_displayname(
-                  username.toStdString(), [](mtx::http::RequestErr err) {
-                          if (err) {
-                                  nhlog::net()->warn("could not change username");
-                                  return;
-                          }
-                  });
-        } else {
-                // change room username
-                mtx::events::state::Member member;
-                member.display_name = username.toStdString();
-                member.avatar_url =
-                  cache::avatarUrl(roomid_,
-                                   QString::fromStdString(http::client()->user_id().to_string()))
-                    .toStdString();
-                member.membership = mtx::events::state::Membership::Join;
-
-                updateRoomMemberState(std::move(member));
-        }
+    if (isGlobalUserProfile()) {
+        // change global
+        http::client()->set_displayname(username.toStdString(), [](mtx::http::RequestErr err) {
+            if (err) {
+                nhlog::net()->warn("could not change username");
+                return;
+            }
+        });
+    } else {
+        // change room username
+        mtx::events::state::Member member;
+        member.display_name = username.toStdString();
+        member.avatar_url =
+          cache::avatarUrl(roomid_, QString::fromStdString(http::client()->user_id().to_string()))
+            .toStdString();
+        member.membership = mtx::events::state::Membership::Join;
+
+        updateRoomMemberState(std::move(member));
+    }
 }
 
 void
 UserProfile::verify(QString device)
 {
-        if (!device.isEmpty())
-                manager->verifyDevice(userid_, device);
-        else {
-                manager->verifyUser(userid_);
-        }
+    if (!device.isEmpty())
+        manager->verifyDevice(userid_, device);
+    else {
+        manager->verifyUser(userid_);
+    }
 }
 
 void
 UserProfile::unverify(QString device)
 {
-        cache::markDeviceUnverified(userid_.toStdString(), device.toStdString());
+    cache::markDeviceUnverified(userid_.toStdString(), device.toStdString());
 }
 
 void
 UserProfile::setGlobalUsername(const QString &globalUser)
 {
-        globalUsername = globalUser;
-        emit displayNameChanged();
+    globalUsername = globalUser;
+    emit displayNameChanged();
 }
 
 void
 UserProfile::changeAvatar()
 {
-        const QString picturesFolder =
-          QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
-        const QString fileName = QFileDialog::getOpenFileName(
-          nullptr, tr("Select an avatar"), picturesFolder, tr("All Files (*)"));
-
-        if (fileName.isEmpty())
-                return;
-
-        QMimeDatabase db;
-        QMimeType mime = db.mimeTypeForFile(fileName, QMimeDatabase::MatchContent);
-
-        const auto format = mime.name().split("/")[0];
-
-        QFile file{fileName, this};
-        if (format != "image") {
-                emit displayError(tr("The selected file is not an image"));
-                return;
-        }
-
-        if (!file.open(QIODevice::ReadOnly)) {
-                emit displayError(tr("Error while reading file: %1").arg(file.errorString()));
-                return;
-        }
-
-        const auto bin     = file.peek(file.size());
-        const auto payload = std::string(bin.data(), bin.size());
-
-        isLoading_ = true;
-        emit loadingChanged();
-
-        // First we need to create a new mxc URI
-        // (i.e upload media to the Matrix content repository) for the new avatar.
-        http::client()->upload(
-          payload,
-          mime.name().toStdString(),
-          QFileInfo(fileName).fileName().toStdString(),
-          [this,
-           payload,
-           mimetype = mime.name().toStdString(),
-           size     = payload.size(),
-           room_id  = roomid_.toStdString(),
-           content  = std::move(bin)](const mtx::responses::ContentURI &res,
-                                     mtx::http::RequestErr err) {
+    const QString picturesFolder =
+      QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
+    const QString fileName = QFileDialog::getOpenFileName(
+      nullptr, tr("Select an avatar"), picturesFolder, tr("All Files (*)"));
+
+    if (fileName.isEmpty())
+        return;
+
+    QMimeDatabase db;
+    QMimeType mime = db.mimeTypeForFile(fileName, QMimeDatabase::MatchContent);
+
+    const auto format = mime.name().split("/")[0];
+
+    QFile file{fileName, this};
+    if (format != "image") {
+        emit displayError(tr("The selected file is not an image"));
+        return;
+    }
+
+    if (!file.open(QIODevice::ReadOnly)) {
+        emit displayError(tr("Error while reading file: %1").arg(file.errorString()));
+        return;
+    }
+
+    const auto bin     = file.peek(file.size());
+    const auto payload = std::string(bin.data(), bin.size());
+
+    isLoading_ = true;
+    emit loadingChanged();
+
+    // First we need to create a new mxc URI
+    // (i.e upload media to the Matrix content repository) for the new avatar.
+    http::client()->upload(
+      payload,
+      mime.name().toStdString(),
+      QFileInfo(fileName).fileName().toStdString(),
+      [this,
+       payload,
+       mimetype = mime.name().toStdString(),
+       size     = payload.size(),
+       room_id  = roomid_.toStdString(),
+       content = std::move(bin)](const mtx::responses::ContentURI &res, mtx::http::RequestErr err) {
+          if (err) {
+              nhlog::ui()->error("Failed to upload image", err->matrix_error.error);
+              return;
+          }
+
+          if (isGlobalUserProfile()) {
+              http::client()->set_avatar_url(res.content_uri, [this](mtx::http::RequestErr err) {
                   if (err) {
-                          nhlog::ui()->error("Failed to upload image", err->matrix_error.error);
-                          return;
+                      nhlog::ui()->error("Failed to set user avatar url", err->matrix_error.error);
                   }
 
-                  if (isGlobalUserProfile()) {
-                          http::client()->set_avatar_url(
-                            res.content_uri, [this](mtx::http::RequestErr err) {
-                                    if (err) {
-                                            nhlog::ui()->error("Failed to set user avatar url",
-                                                               err->matrix_error.error);
-                                    }
-
-                                    isLoading_ = false;
-                                    emit loadingChanged();
-                                    getGlobalProfileData();
-                            });
-                  } else {
-                          // change room username
-                          mtx::events::state::Member member;
-                          member.display_name = cache::displayName(roomid_, userid_).toStdString();
-                          member.avatar_url   = res.content_uri;
-                          member.membership   = mtx::events::state::Membership::Join;
-
-                          updateRoomMemberState(std::move(member));
-                  }
-          });
+                  isLoading_ = false;
+                  emit loadingChanged();
+                  getGlobalProfileData();
+              });
+          } else {
+              // change room username
+              mtx::events::state::Member member;
+              member.display_name = cache::displayName(roomid_, userid_).toStdString();
+              member.avatar_url   = res.content_uri;
+              member.membership   = mtx::events::state::Membership::Join;
+
+              updateRoomMemberState(std::move(member));
+          }
+      });
 }
 
 void
 UserProfile::updateRoomMemberState(mtx::events::state::Member member)
 {
-        http::client()->send_state_event(roomid_.toStdString(),
-                                         http::client()->user_id().to_string(),
-                                         member,
-                                         [](mtx::responses::EventId, mtx::http::RequestErr err) {
-                                                 if (err)
-                                                         nhlog::net()->error(
-                                                           "Failed to update room member state : ",
-                                                           err->matrix_error.error);
-                                         });
+    http::client()->send_state_event(
+      roomid_.toStdString(),
+      http::client()->user_id().to_string(),
+      member,
+      [](mtx::responses::EventId, mtx::http::RequestErr err) {
+          if (err)
+              nhlog::net()->error("Failed to update room member state : ", err->matrix_error.error);
+      });
 }
 
 void
 UserProfile::updateAvatarUrl()
 {
-        isLoading_ = false;
-        emit loadingChanged();
+    isLoading_ = false;
+    emit loadingChanged();
 
-        emit avatarUrlChanged();
+    emit avatarUrlChanged();
 }
 
 bool
 UserProfile::isLoading() const
 {
-        return isLoading_;
+    return isLoading_;
 }
 
 void
 UserProfile::getGlobalProfileData()
 {
-        http::client()->get_profile(
-          userid_.toStdString(),
-          [this](const mtx::responses::Profile &res, mtx::http::RequestErr err) {
-                  if (err) {
-                          nhlog::net()->warn("failed to retrieve profile info for {}",
-                                             userid_.toStdString());
-                          return;
-                  }
-
-                  emit globalUsernameRetrieved(QString::fromStdString(res.display_name));
-                  globalAvatarUrl = QString::fromStdString(res.avatar_url);
-                  emit avatarUrlChanged();
-          });
+    http::client()->get_profile(
+      userid_.toStdString(), [this](const mtx::responses::Profile &res, mtx::http::RequestErr err) {
+          if (err) {
+              nhlog::net()->warn("failed to retrieve profile info for {}", userid_.toStdString());
+              return;
+          }
+
+          emit globalUsernameRetrieved(QString::fromStdString(res.display_name));
+          globalAvatarUrl = QString::fromStdString(res.avatar_url);
+          emit avatarUrlChanged();
+      });
 }
 
 void
 UserProfile::openGlobalProfile()
 {
-        emit manager->openGlobalUserProfile(userid_);
+    emit manager->openGlobalUserProfile(userid_);
 }
diff --git a/src/ui/UserProfile.h b/src/ui/UserProfile.h
index fd8772d5..a148c431 100644
--- a/src/ui/UserProfile.h
+++ b/src/ui/UserProfile.h
@@ -18,9 +18,9 @@ Q_NAMESPACE
 
 enum Status
 {
-        VERIFIED,
-        UNVERIFIED,
-        BLOCKED
+    VERIFIED,
+    UNVERIFIED,
+    BLOCKED
 };
 Q_ENUM_NS(Status)
 }
@@ -32,128 +32,127 @@ class TimelineViewManager;
 class DeviceInfo
 {
 public:
-        DeviceInfo(const QString deviceID,
-                   const QString displayName,
-                   verification::Status verification_status_)
-          : device_id(deviceID)
-          , display_name(displayName)
-          , verification_status(verification_status_)
-        {}
-        DeviceInfo()
-          : verification_status(verification::UNVERIFIED)
-        {}
-
-        QString device_id;
-        QString display_name;
-
-        verification::Status verification_status;
+    DeviceInfo(const QString deviceID,
+               const QString displayName,
+               verification::Status verification_status_)
+      : device_id(deviceID)
+      , display_name(displayName)
+      , verification_status(verification_status_)
+    {}
+    DeviceInfo()
+      : verification_status(verification::UNVERIFIED)
+    {}
+
+    QString device_id;
+    QString display_name;
+
+    verification::Status verification_status;
 };
 
 class DeviceInfoModel : public QAbstractListModel
 {
-        Q_OBJECT
+    Q_OBJECT
 public:
-        enum Roles
-        {
-                DeviceId,
-                DeviceName,
-                VerificationStatus,
-        };
-
-        explicit DeviceInfoModel(QObject *parent = nullptr)
-        {
-                (void)parent;
-                connect(this, &DeviceInfoModel::queueReset, this, &DeviceInfoModel::reset);
-        };
-        QHash<int, QByteArray> roleNames() const override;
-        int rowCount(const QModelIndex &parent = QModelIndex()) const override
-        {
-                (void)parent;
-                return (int)deviceList_.size();
-        }
-        QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+    enum Roles
+    {
+        DeviceId,
+        DeviceName,
+        VerificationStatus,
+    };
+
+    explicit DeviceInfoModel(QObject *parent = nullptr)
+    {
+        (void)parent;
+        connect(this, &DeviceInfoModel::queueReset, this, &DeviceInfoModel::reset);
+    };
+    QHash<int, QByteArray> roleNames() const override;
+    int rowCount(const QModelIndex &parent = QModelIndex()) const override
+    {
+        (void)parent;
+        return (int)deviceList_.size();
+    }
+    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
 
 signals:
-        void queueReset(const std::vector<DeviceInfo> &deviceList);
+    void queueReset(const std::vector<DeviceInfo> &deviceList);
 public slots:
-        void reset(const std::vector<DeviceInfo> &deviceList);
+    void reset(const std::vector<DeviceInfo> &deviceList);
 
 private:
-        std::vector<DeviceInfo> deviceList_;
+    std::vector<DeviceInfo> deviceList_;
 
-        friend class UserProfile;
+    friend class UserProfile;
 };
 
 class UserProfile : public QObject
 {
-        Q_OBJECT
-        Q_PROPERTY(QString displayName READ displayName NOTIFY displayNameChanged)
-        Q_PROPERTY(QString userid READ userid CONSTANT)
-        Q_PROPERTY(QString avatarUrl READ avatarUrl NOTIFY avatarUrlChanged)
-        Q_PROPERTY(DeviceInfoModel *deviceList READ deviceList NOTIFY devicesChanged)
-        Q_PROPERTY(bool isGlobalUserProfile READ isGlobalUserProfile CONSTANT)
-        Q_PROPERTY(int userVerified READ getUserStatus NOTIFY userStatusChanged)
-        Q_PROPERTY(bool isLoading READ isLoading NOTIFY loadingChanged)
-        Q_PROPERTY(
-          bool userVerificationEnabled READ userVerificationEnabled NOTIFY userStatusChanged)
-        Q_PROPERTY(bool isSelf READ isSelf CONSTANT)
-        Q_PROPERTY(TimelineModel *room READ room CONSTANT)
+    Q_OBJECT
+    Q_PROPERTY(QString displayName READ displayName NOTIFY displayNameChanged)
+    Q_PROPERTY(QString userid READ userid CONSTANT)
+    Q_PROPERTY(QString avatarUrl READ avatarUrl NOTIFY avatarUrlChanged)
+    Q_PROPERTY(DeviceInfoModel *deviceList READ deviceList NOTIFY devicesChanged)
+    Q_PROPERTY(bool isGlobalUserProfile READ isGlobalUserProfile CONSTANT)
+    Q_PROPERTY(int userVerified READ getUserStatus NOTIFY userStatusChanged)
+    Q_PROPERTY(bool isLoading READ isLoading NOTIFY loadingChanged)
+    Q_PROPERTY(bool userVerificationEnabled READ userVerificationEnabled NOTIFY userStatusChanged)
+    Q_PROPERTY(bool isSelf READ isSelf CONSTANT)
+    Q_PROPERTY(TimelineModel *room READ room CONSTANT)
 public:
-        UserProfile(QString roomid,
-                    QString userid,
-                    TimelineViewManager *manager_,
-                    TimelineModel *parent = nullptr);
-
-        DeviceInfoModel *deviceList();
-
-        QString userid();
-        QString displayName();
-        QString avatarUrl();
-        bool isGlobalUserProfile() const;
-        crypto::Trust getUserStatus();
-        bool userVerificationEnabled() const;
-        bool isSelf() const;
-        bool isLoading() const;
-        TimelineModel *room() const { return model; }
-
-        Q_INVOKABLE void verify(QString device = "");
-        Q_INVOKABLE void unverify(QString device = "");
-        Q_INVOKABLE void fetchDeviceList(const QString &userID);
-        Q_INVOKABLE void banUser();
-        // Q_INVOKABLE void ignoreUser();
-        Q_INVOKABLE void kickUser();
-        Q_INVOKABLE void startChat();
-        Q_INVOKABLE void changeUsername(QString username);
-        Q_INVOKABLE void changeAvatar();
-        Q_INVOKABLE void openGlobalProfile();
+    UserProfile(QString roomid,
+                QString userid,
+                TimelineViewManager *manager_,
+                TimelineModel *parent = nullptr);
+
+    DeviceInfoModel *deviceList();
+
+    QString userid();
+    QString displayName();
+    QString avatarUrl();
+    bool isGlobalUserProfile() const;
+    crypto::Trust getUserStatus();
+    bool userVerificationEnabled() const;
+    bool isSelf() const;
+    bool isLoading() const;
+    TimelineModel *room() const { return model; }
+
+    Q_INVOKABLE void verify(QString device = "");
+    Q_INVOKABLE void unverify(QString device = "");
+    Q_INVOKABLE void fetchDeviceList(const QString &userID);
+    Q_INVOKABLE void banUser();
+    // Q_INVOKABLE void ignoreUser();
+    Q_INVOKABLE void kickUser();
+    Q_INVOKABLE void startChat();
+    Q_INVOKABLE void changeUsername(QString username);
+    Q_INVOKABLE void changeAvatar();
+    Q_INVOKABLE void openGlobalProfile();
 
 signals:
-        void userStatusChanged();
-        void loadingChanged();
-        void displayNameChanged();
-        void avatarUrlChanged();
-        void displayError(const QString &errorMessage);
-        void globalUsernameRetrieved(const QString &globalUser);
-        void devicesChanged();
+    void userStatusChanged();
+    void loadingChanged();
+    void displayNameChanged();
+    void avatarUrlChanged();
+    void displayError(const QString &errorMessage);
+    void globalUsernameRetrieved(const QString &globalUser);
+    void devicesChanged();
 
 public slots:
-        void updateAvatarUrl();
+    void updateAvatarUrl();
 
 protected slots:
-        void setGlobalUsername(const QString &globalUser);
+    void setGlobalUsername(const QString &globalUser);
 
 private:
-        void updateRoomMemberState(mtx::events::state::Member member);
-        void getGlobalProfileData();
+    void updateRoomMemberState(mtx::events::state::Member member);
+    void getGlobalProfileData();
 
 private:
-        QString roomid_, userid_;
-        QString globalUsername;
-        QString globalAvatarUrl;
-        DeviceInfoModel deviceList_;
-        crypto::Trust isUserVerified = crypto::Trust::Unverified;
-        bool hasMasterKey            = false;
-        bool isLoading_              = false;
-        TimelineViewManager *manager;
-        TimelineModel *model;
+    QString roomid_, userid_;
+    QString globalUsername;
+    QString globalAvatarUrl;
+    DeviceInfoModel deviceList_;
+    crypto::Trust isUserVerified = crypto::Trust::Unverified;
+    bool hasMasterKey            = false;
+    bool isLoading_              = false;
+    TimelineViewManager *manager;
+    TimelineModel *model;
 };