diff --git a/resources/qml/EncryptionIndicator.qml b/resources/qml/EncryptionIndicator.qml
index 9fe40deab2200cbad6ca6a0ab2b67c7d513dafeb..5338b6bedb2a7631c8ec096776dd89a262c512a0 100644
--- a/resources/qml/EncryptionIndicator.qml
+++ b/resources/qml/EncryptionIndicator.qml
@@ -14,10 +14,12 @@ Image {
     property int trust: Crypto.Unverified
     property string unencryptedIcon: ":/icons/icons/ui/shield-filled-cross.svg"
     property color unencryptedColor: Nheko.theme.error
+    property color unencryptedHoverColor: unencryptedColor
+    property bool hovered: ma.hovered
 
     property string sourceUrl: {
         if (!encrypted)
-        return "image://colorimage/"+unencryptedIcon+"?";
+        return "image://colorimage/" + unencryptedIcon + "?";
 
         switch (trust) {
             case Crypto.Verified:
@@ -46,10 +48,10 @@ Image {
                 return sourceUrl + Nheko.theme.error;
             }
         } else {
-            return sourceUrl + unencryptedColor;
+            return sourceUrl + (stateImg.hovered ? unencryptedHoverColor : unencryptedColor);
         }
     }
-    ToolTip.visible: ma.hovered
+    ToolTip.visible: stateImg.hovered
     ToolTip.text: {
         if (!encrypted)
             return qsTr("This message is not encrypted!");
diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml
index f31123e53198e24910aec16c5021e0939afb10d1..6029a31d3f9bd72963c2da90fea48b5baa13ca1d 100644
--- a/resources/qml/MessageInput.qml
+++ b/resources/qml/MessageInput.qml
@@ -4,6 +4,7 @@
 
 import "./emoji"
 import "./voip"
+import "./ui"
 import QtQuick 2.12
 import QtQuick.Controls 2.3
 import QtQuick.Layouts 1.2
@@ -90,8 +91,9 @@ Rectangle {
                 color: Nheko.colors.window
                 visible: room && room.input.uploading
 
-                NhekoBusyIndicator {
-                    anchors.fill: parent
+                Spinner {
+                    anchors.centerIn: parent
+                    height: parent.height / 2
                     running: parent.visible
                 }
 
diff --git a/resources/qml/MessageView.qml b/resources/qml/MessageView.qml
index 45b4402287270fa86524b663e22290192c489173..f9aaf9ddf283cc2dd4bd99a966d40aad4505af59 100644
--- a/resources/qml/MessageView.qml
+++ b/resources/qml/MessageView.qml
@@ -206,7 +206,7 @@ Item {
         Shortcut {
             sequence: StandardKey.MoveToPreviousPage
             onActivated: {
-                chat.contentY = chat.contentY - chat.height / 2;
+                chat.contentY = chat.contentY - chat.height * 0.9;
                 chat.returnToBounds();
             }
         }
@@ -214,7 +214,7 @@ Item {
         Shortcut {
             sequence: StandardKey.MoveToNextPage
             onActivated: {
-                chat.contentY = chat.contentY + chat.height / 2;
+                chat.contentY = chat.contentY + chat.height * 0.9;
                 chat.returnToBounds();
             }
         }
diff --git a/resources/qml/NhekoBusyIndicator.qml b/resources/qml/NhekoBusyIndicator.qml
deleted file mode 100644
index f3d1e8a4862b1bb92c9536280973859a6991c6de..0000000000000000000000000000000000000000
--- a/resources/qml/NhekoBusyIndicator.qml
+++ /dev/null
@@ -1,69 +0,0 @@
-// SPDX-FileCopyrightText: Nheko Contributors
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-import QtQuick 2.9
-import QtQuick.Controls 2.3
-import QtQuick.Layouts 1.2
-import im.nheko 1.0
-
-BusyIndicator {
-    id: control
-
-    contentItem: Item {
-        implicitWidth: 64
-        implicitHeight: 64
-
-        Item {
-            id: item
-
-            height: Math.min(parent.height, parent.width)
-            width: height
-            opacity: control.running ? 1 : 0
-
-            RotationAnimator {
-                target: item
-                running: control.visible && control.running
-                from: 0
-                to: 360
-                loops: Animation.Infinite
-                duration: 2000
-            }
-
-            Repeater {
-                id: repeater
-
-                model: 6
-
-                Rectangle {
-                    implicitWidth: radius * 2
-                    implicitHeight: radius * 2
-                    radius: item.height / 8
-                    color: Nheko.colors.text
-                    opacity: (index + 2) / (repeater.count + 2)
-                    transform: [
-                        Translate {
-                            y: item.height / 2
-                        },
-                        Rotation {
-                            angle: index / repeater.count * 360
-                            origin.x: item.height / 2
-                            origin.y: item.height / 2
-                        }
-                    ]
-                }
-
-            }
-
-            Behavior on opacity {
-                OpacityAnimator {
-                    duration: 250
-                }
-
-            }
-
-        }
-
-    }
-
-}
diff --git a/resources/qml/Root.qml b/resources/qml/Root.qml
index d0a8f2e8a71dbd29425dc68215bc0e95ff2b6d14..9584eb8de0ed5e40a2740078be115f2140d7f13d 100644
--- a/resources/qml/Root.qml
+++ b/resources/qml/Root.qml
@@ -268,8 +268,6 @@ Pane {
             var component = Qt.createComponent("qrc:/qml/dialogs/InviteDialog.qml")
             if (component.status == Component.Ready) {
                 var dialog = component.createObject(timelineRoot, {
-                    "roomId": Rooms.currentRoom.roomId,
-                    "plainRoomName": Rooms.currentRoom.plainRoomName,
                     "invitees": invitees
                 });
                 dialog.show();
diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml
index e836f60f4a3c5ce8e1f8212d575634a8fd9fe27d..c7b554b86b7b6a3a43f95981b2f440ec247add92 100644
--- a/resources/qml/TimelineView.qml
+++ b/resources/qml/TimelineView.qml
@@ -279,6 +279,13 @@ Item {
             onClicked: Rooms.declineInvite(roomPreview.roomid)
         }
 
+        FlatButton {
+            visible: !!room
+            Layout.alignment: Qt.AlignHCenter
+            text: qsTr("leave")
+            onClicked: TimelineManager.openLeaveRoomDialog(room.roomId)
+        }
+
         ScrollView {
             id: reasonField
             property bool showReason: false
diff --git a/resources/qml/ToggleButton.qml b/resources/qml/ToggleButton.qml
index b7adf21f920c0f6794e56c252c2cdaaf7f75933e..20e82ad67fa357e97867339a2d30345e43673ebe 100644
--- a/resources/qml/ToggleButton.qml
+++ b/resources/qml/ToggleButton.qml
@@ -25,7 +25,7 @@ Switch {
             width: parent.width - height
             x: radius
             y: parent.height / 2 - height / 2
-            color: toggleButton.checked ? "skyblue" : "grey"
+            color: toggleButton.checked ? Nheko.colors.highlight : "grey"
             border.color: "#cccccc"
         }
 
diff --git a/resources/qml/TopBar.qml b/resources/qml/TopBar.qml
index 0e4ca4e7b86f6a30cb481b9f1054650a6403a291..f23645a71336c42abbf6f5dcf2a832c7b2e668bb 100644
--- a/resources/qml/TopBar.qml
+++ b/resources/qml/TopBar.qml
@@ -242,26 +242,26 @@ Pane {
                     enabled: false
                     unencryptedIcon: ":/icons/icons/ui/people.svg"
                     unencryptedColor: Nheko.colors.buttonText
-                }
-
-                background: null
-
-                ToolTip.delay: Nheko.tooltipDelay
-                ToolTip.text: {
-                    if (!isEncrypted)
-                    return qsTr("Show room members.");
-
-                    switch (trustlevel) {
-                        case Crypto.Verified:
-                        return qsTr("This room contains only verified devices.");
-                        case Crypto.TOFU:
-                        return qsTr("This room contains verified devices and devices which have never changed their master key.");
-                        default:
-                        return qsTr("This room contains unverified devices!");
+                    unencryptedHoverColor: Nheko.colors.highlight
+                    hovered: parent.hovered
+
+                    ToolTip.delay: Nheko.tooltipDelay
+                    ToolTip.text: {
+                        if (!isEncrypted)
+                        return qsTr("Show room members.");
+
+                        switch (trustlevel) {
+                            case Crypto.Verified:
+                            return qsTr("This room contains only verified devices.");
+                            case Crypto.TOFU:
+                            return qsTr("This room contains verified devices and devices which have never changed their master key.");
+                            default:
+                            return qsTr("This room contains unverified devices!");
+                        }
                     }
                 }
-                ToolTip.visible: hovered
 
+                background: null
                 onClicked: TimelineManager.openRoomMembers(room)
             }
 
diff --git a/resources/qml/dialogs/InviteDialog.qml b/resources/qml/dialogs/InviteDialog.qml
index ee555795b5cc1dd4934b51c76216b50341eeff9f..b142818d872f98498d1dcd773b3c255f30f81c49 100644
--- a/resources/qml/dialogs/InviteDialog.qml
+++ b/resources/qml/dialogs/InviteDialog.qml
@@ -12,8 +12,6 @@ import im.nheko 1.0
 ApplicationWindow {
     id: inviteDialogRoot
 
-    property string roomId
-    property string plainRoomName
     property InviteesModel invitees
     property var friendsCompleter
     property var profile
@@ -39,7 +37,7 @@ ApplicationWindow {
         close();
     }
 
-    title: qsTr("Invite users to %1").arg(plainRoomName)
+    title: qsTr("Invite users to %1").arg(invitees.room.plainRoomName)
     height: 380
     width: 340
     palette: Nheko.colors
diff --git a/resources/qml/dialogs/ReadReceipts.qml b/resources/qml/dialogs/ReadReceipts.qml
index f90da997e3daaf868ca9cc1dd2dd9167867accc3..3d23a5fc697244b388b2322deef8e753edacc622 100644
--- a/resources/qml/dialogs/ReadReceipts.qml
+++ b/resources/qml/dialogs/ReadReceipts.qml
@@ -78,6 +78,8 @@ ApplicationWindow {
                         anchors.margins: Nheko.paddingSmall
 
                         Avatar {
+                            id: avatar
+
                             width: Nheko.avatarSize
                             height: Nheko.avatarSize
                             userid: model.mxid
@@ -88,25 +90,26 @@ ApplicationWindow {
 
                         ColumnLayout {
                             spacing: Nheko.paddingSmall
+                            Layout.fillWidth: true
 
-                            Label {
+                            ElidedLabel {
                                 text: model.displayName
                                 color: TimelineManager.userColor(model ? model.mxid : "", Nheko.colors.window)
                                 font.pointSize: fontMetrics.font.pointSize
+                                elideWidth: del.width - Nheko.paddingMedium - avatar.width
+                                Layout.fillWidth: true
                             }
 
-                            Label {
+                            ElidedLabel {
                                 text: model.timestamp
                                 color: Nheko.colors.buttonText
                                 font.pointSize: fontMetrics.font.pointSize * 0.9
+                                elideWidth: del.width - Nheko.paddingMedium - avatar.width
+                                Layout.fillWidth: true
                             }
 
                         }
 
-                        Item {
-                            Layout.fillWidth: true
-                        }
-
                     }
 
                     CursorShape {
diff --git a/resources/qml/dialogs/RoomMembers.qml b/resources/qml/dialogs/RoomMembers.qml
index ea4451bb5e14f7f280f38ae4646a1b30854b6363..1cfbe0779d4e1f8b9501c5fc56fedd181febe418 100644
--- a/resources/qml/dialogs/RoomMembers.qml
+++ b/resources/qml/dialogs/RoomMembers.qml
@@ -146,12 +146,14 @@ ApplicationWindow {
 
                         ColumnLayout {
                             spacing: Nheko.paddingSmall
+                            Layout.fillWidth: true
 
                             ElidedLabel {
                                 fullText: model.displayName
                                 color: TimelineManager.userColor(model ? model.mxid : "", del.background.color)
                                 font.pixelSize: fontMetrics.font.pixelSize
                                 elideWidth: del.width - Nheko.paddingMedium * 2 - avatar.width - encryptInd.width
+                                Layout.fillWidth: true
                             }
 
                             ElidedLabel {
@@ -159,14 +161,11 @@ ApplicationWindow {
                                 color: del.hovered ? Nheko.colors.brightText : Nheko.colors.buttonText
                                 font.pixelSize: Math.ceil(fontMetrics.font.pixelSize * 0.9)
                                 elideWidth: del.width - Nheko.paddingMedium * 2 - avatar.width - encryptInd.width
+                                Layout.fillWidth: true
                             }
 
                         }
 
-                        Item {
-                            Layout.fillWidth: true
-                        }
-
                         Image {
                             property bool isAdmin: room.permissions.changeLevel(MtxEvent.PowerLevels) <= model.powerlevel
                             property bool isModerator: room.permissions.redactLevel() <= model.powerlevel
diff --git a/resources/qml/dialogs/RoomSettings.qml b/resources/qml/dialogs/RoomSettings.qml
index 5544841f401d22d079d1695b3e475d13820bc74e..845f4d7a15a1469d3993b6407dd93aed40b1bf26 100644
--- a/resources/qml/dialogs/RoomSettings.qml
+++ b/resources/qml/dialogs/RoomSettings.qml
@@ -395,7 +395,8 @@ ApplicationWindow {
                             checked = true;
                             return ;
                         }
-                        confirmEncryptionDialog.open();
+                        if (checked === true)
+                            confirmEncryptionDialog.open();
                     }
                     Layout.alignment: Qt.AlignRight
                 }
diff --git a/resources/res.qrc b/resources/res.qrc
index 88159d400f784cf1f2b6be9a3bde24b18bffce68..9c7d0c87c3a46c63c305009548a73c7767e3d390 100644
--- a/resources/res.qrc
+++ b/resources/res.qrc
@@ -111,7 +111,6 @@
         <file>qml/UploadBox.qml</file>
         <file>qml/MessageInput.qml</file>
         <file>qml/MessageView.qml</file>
-        <file>qml/NhekoBusyIndicator.qml</file>
         <file>qml/PrivacyScreen.qml</file>
         <file>qml/Reactions.qml</file>
         <file>qml/ReplyPopup.qml</file>
diff --git a/src/InviteesModel.cpp b/src/InviteesModel.cpp
index 2b95a36fdcce9ebe2d4842776a576cec860e00f1..7b49c2343ee1f4ecd87018b04c97b3e647cef88c 100644
--- a/src/InviteesModel.cpp
+++ b/src/InviteesModel.cpp
@@ -9,8 +9,9 @@
 #include "MatrixClient.h"
 #include "mtx/responses/profile.hpp"
 
-InviteesModel::InviteesModel(QObject *parent)
+InviteesModel::InviteesModel(TimelineModel *room, QObject *parent)
   : QAbstractListModel{parent}
+  , room_{room}
 {
 }
 
diff --git a/src/InviteesModel.h b/src/InviteesModel.h
index 8fe8fc2212c12f75ee92f02f5739b6c0e76a99c0..ab8fbdb4ba7d7d45b2a866ee2cfed0f05a4441d5 100644
--- a/src/InviteesModel.h
+++ b/src/InviteesModel.h
@@ -8,6 +8,8 @@
 #include <QAbstractListModel>
 #include <QVector>
 
+class TimelineModel;
+
 class Invitee final : public QObject
 {
     Q_OBJECT
@@ -34,6 +36,7 @@ class InviteesModel final : public QAbstractListModel
     Q_OBJECT
 
     Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
+    Q_PROPERTY(TimelineModel *room READ room CONSTANT)
 
 public:
     enum Roles
@@ -43,7 +46,9 @@ public:
         AvatarUrl,
     };
 
-    InviteesModel(QObject *parent = nullptr);
+    InviteesModel(TimelineModel *room, QObject *parent = nullptr);
+
+    TimelineModel *room() const { return room_; }
 
     Q_INVOKABLE void addUser(QString mxid, QString displayName = "", QString avatarUrl = "");
     Q_INVOKABLE void removeUser(QString mxid);
@@ -63,6 +68,7 @@ signals:
 
 private:
     QVector<Invitee *> invitees_;
+    TimelineModel *room_;
 };
 
 #endif // INVITEESMODEL_H
diff --git a/src/Utils.cpp b/src/Utils.cpp
index b753cfdbe41a711210f5ff951c2c8e3c484be2e6..63dcdd00a1f2573d0225c979689fc729485f127c 100644
--- a/src/Utils.cpp
+++ b/src/Utils.cpp
@@ -141,7 +141,9 @@ utils::replaceEmoji(const QString &body)
         if (!insideTag && utils::codepointIsEmoji(code)) {
             if (!insideFontBlock) {
                 fmtBody += QStringLiteral("<font face=\"") % UserSettings::instance()->emojiFont() %
-                           QStringLiteral("\">");
+                           (UserSettings::instance()->enlargeEmojiOnlyMessages()
+                              ? QStringLiteral("\" size=\"4\">")
+                              : QStringLiteral("\">"));
                 insideFontBlock = true;
             } else if (code == 0xfe0f) {
                 // BUG(Nico):
diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp
index cdcc689d094eddcc549330cf3081f5222b8781c4..c19d0c3ff5294f643aeaa961c3c309a62f53576f 100644
--- a/src/timeline/TimelineViewManager.cpp
+++ b/src/timeline/TimelineViewManager.cpp
@@ -180,7 +180,7 @@ TimelineViewManager::openRoomSettings(QString room_id)
 void
 TimelineViewManager::openInviteUsers(QString roomId)
 {
-    InviteesModel *model = new InviteesModel{};
+    InviteesModel *model = new InviteesModel{rooms_->getRoomById(roomId).data()};
     connect(model, &InviteesModel::accept, this, [this, model, roomId]() {
         emit inviteUsers(roomId, model->mxids());
     });