From c775a93f775dafcd53bce580f9c856eab4a17978 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Mon, 11 Apr 2022 04:18:16 +0200 Subject: [PATCH] Fix some qt6 issues --- resources/qml/Avatar.qml | 6 +- resources/qml/ChatPage.qml | 2 +- resources/qml/CommunitiesList.qml | 36 +++---- resources/qml/Completer.qml | 31 +++--- resources/qml/ElidedLabel.qml | 2 +- resources/qml/EncryptionIndicator.qml | 2 +- resources/qml/ForwardCompleter.qml | 12 +-- resources/qml/ImageButton.qml | 4 +- resources/qml/MatrixText.qml | 2 +- resources/qml/MatrixTextField.qml | 12 +-- resources/qml/MessageInput.qml | 12 +-- resources/qml/MessageView.qml | 35 +++---- resources/qml/NhekoBusyIndicator.qml | 2 +- resources/qml/NotificationWarning.qml | 2 +- resources/qml/QuickSwitcher.qml | 4 +- resources/qml/Reactions.qml | 16 +-- resources/qml/ReplyPopup.qml | 6 +- resources/qml/RoomList.qml | 51 +++++----- resources/qml/Root.qml | 4 +- resources/qml/ScrollHelper.qml | 97 ------------------- resources/qml/SelfVerificationCheck.qml | 22 ++--- resources/qml/TimelineRow.qml | 16 +-- resources/qml/TimelineView.qml | 8 +- resources/qml/TopBar.qml | 24 ++--- resources/qml/TypingIndicator.qml | 6 +- resources/qml/UploadBox.qml | 6 +- resources/qml/components/AvatarListTile.qml | 30 +++--- resources/qml/components/FlatButton.qml | 4 +- resources/qml/components/MainWindowDialog.qml | 2 +- resources/qml/components/TextButton.qml | 4 +- resources/qml/delegates/Encrypted.qml | 6 +- resources/qml/delegates/FileMessage.qml | 8 +- resources/qml/delegates/ImageMessage.qml | 8 +- resources/qml/delegates/MessageDelegate.qml | 6 +- resources/qml/delegates/NoticeMessage.qml | 2 +- resources/qml/delegates/Pill.qml | 4 +- resources/qml/delegates/Placeholder.qml | 2 +- .../qml/delegates/PlayableMediaMessage.qml | 6 +- resources/qml/delegates/Redacted.qml | 6 +- resources/qml/delegates/Reply.qml | 6 +- resources/qml/delegates/TextMessage.qml | 12 +-- .../DeviceVerification.qml | 4 +- .../device-verification/DigitVerification.qml | 10 +- .../device-verification/EmojiVerification.qml | 8 +- resources/qml/device-verification/Failed.qml | 4 +- .../NewVerificationRequest.qml | 4 +- resources/qml/device-verification/Success.qml | 4 +- resources/qml/device-verification/Waiting.qml | 6 +- resources/qml/dialogs/CreateDirect.qml | 6 +- resources/qml/dialogs/CreateRoom.qml | 10 +- .../qml/dialogs/ImagePackEditorDialog.qml | 25 ++--- .../qml/dialogs/ImagePackSettingsDialog.qml | 32 +++--- resources/qml/dialogs/InputDialog.qml | 2 +- resources/qml/dialogs/InviteDialog.qml | 12 +-- resources/qml/dialogs/JoinRoomDialog.qml | 6 +- .../qml/dialogs/PhoneNumberInputDialog.qml | 2 +- resources/qml/dialogs/RawMessageDialog.qml | 10 +- resources/qml/dialogs/ReadReceipts.qml | 14 +-- resources/qml/dialogs/RoomDirectory.qml | 21 ++-- resources/qml/dialogs/RoomMembers.qml | 15 +-- resources/qml/dialogs/RoomSettings.qml | 39 ++++---- resources/qml/dialogs/UserProfile.qml | 21 ++-- resources/qml/emoji/EmojiPicker.qml | 31 +++--- resources/qml/emoji/StickerPicker.qml | 25 ++--- resources/qml/pages/LoginPage.qml | 6 +- resources/qml/pages/RegisterPage.qml | 8 +- resources/qml/pages/UserSettingsPage.qml | 10 +- resources/qml/pages/WelcomePage.qml | 4 +- resources/qml/ui/NhekoSlider.qml | 4 +- resources/qml/ui/Snackbar.qml | 4 +- resources/qml/ui/media/MediaControls.qml | 8 +- resources/qml/voip/CallDevices.qml | 10 +- resources/qml/voip/CallInvite.qml | 16 +-- resources/qml/voip/CallInviteBar.qml | 4 +- resources/qml/voip/DeviceError.qml | 8 +- resources/qml/voip/PlaceCall.qml | 12 +-- resources/qml/voip/ScreenShare.qml | 12 +-- resources/res.qrc | 1 - src/MxcImageProvider.cpp | 3 + 79 files changed, 388 insertions(+), 559 deletions(-) delete mode 100644 resources/qml/ScrollHelper.qml diff --git a/resources/qml/Avatar.qml b/resources/qml/Avatar.qml index 09529fcd..593decb7 100644 --- a/resources/qml/Avatar.qml +++ b/resources/qml/Avatar.qml @@ -25,7 +25,7 @@ AbstractButton { background: Rectangle { id: bg radius: Settings.avatarCircles ? height / 2 : height / 8 - color: Nheko.colors.alternateBase + color: timelineRoot.palette.alternateBase } Label { @@ -40,7 +40,7 @@ AbstractButton { verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignHCenter visible: img.status != Image.Ready && !Settings.useIdenticon - color: Nheko.colors.text + color: timelineRoot.palette.text } Image { @@ -104,7 +104,7 @@ AbstractButton { } Ripple { - color: Qt.rgba(Nheko.colors.alternateBase.r, Nheko.colors.alternateBase.g, Nheko.colors.alternateBase.b, 0.5) + color: Qt.rgba(timelineRoot.palette.alternateBase.r, timelineRoot.palette.alternateBase.g, timelineRoot.palette.alternateBase.b, 0.5) } } diff --git a/resources/qml/ChatPage.qml b/resources/qml/ChatPage.qml index c39f442e..559fbc11 100644 --- a/resources/qml/ChatPage.qml +++ b/resources/qml/ChatPage.qml @@ -15,7 +15,7 @@ import QtQml 2.15 Rectangle { id: chatPage - color: Nheko.colors.window + color: timelineRoot.palette.window ColumnLayout { spacing: 0 diff --git a/resources/qml/CommunitiesList.qml b/resources/qml/CommunitiesList.qml index 61287789..64929e17 100644 --- a/resources/qml/CommunitiesList.qml +++ b/resources/qml/CommunitiesList.qml @@ -26,12 +26,6 @@ Page { height: parent.height model: Communities.filtered() - ScrollHelper { - flickable: parent - anchors.fill: parent - enabled: !Settings.mobileMode - } - Platform.Menu { id: communityContextMenu @@ -52,11 +46,11 @@ Page { delegate: ItemDelegate { id: communityItem - property color backgroundColor: Nheko.colors.window - property color importantText: Nheko.colors.text - property color unimportantText: Nheko.colors.buttonText - property color bubbleBackground: Nheko.colors.highlight - property color bubbleText: Nheko.colors.highlightedText + property color backgroundColor: timelineRoot.palette.window + property color importantText: timelineRoot.palette.text + property color unimportantText: timelineRoot.palette.buttonText + property color bubbleBackground: timelineRoot.palette.highlight + property color bubbleText: timelineRoot.palette.highlightedText height: avatarSize + 2 * Nheko.paddingMedium width: ListView.view.width @@ -73,11 +67,11 @@ Page { PropertyChanges { target: communityItem - backgroundColor: Nheko.colors.dark - importantText: Nheko.colors.brightText - unimportantText: Nheko.colors.brightText - bubbleBackground: Nheko.colors.highlight - bubbleText: Nheko.colors.highlightedText + backgroundColor: timelineRoot.palette.dark + importantText: timelineRoot.palette.brightText + unimportantText: timelineRoot.palette.brightText + bubbleBackground: timelineRoot.palette.highlight + bubbleText: timelineRoot.palette.highlightedText } }, @@ -87,11 +81,11 @@ Page { PropertyChanges { target: communityItem - backgroundColor: Nheko.colors.highlight - importantText: Nheko.colors.highlightedText - unimportantText: Nheko.colors.highlightedText - bubbleBackground: Nheko.colors.highlightedText - bubbleText: Nheko.colors.highlight + backgroundColor: timelineRoot.palette.highlight + importantText: timelineRoot.palette.highlightedText + unimportantText: timelineRoot.palette.highlightedText + bubbleBackground: timelineRoot.palette.highlightedText + bubbleText: timelineRoot.palette.highlight } } diff --git a/resources/qml/Completer.qml b/resources/qml/Completer.qml index a16ffa65..d173de87 100644 --- a/resources/qml/Completer.qml +++ b/resources/qml/Completer.qml @@ -93,11 +93,6 @@ Control { // that until we find something better. Put is all together and you have the formula below! implicitHeight: Math.min(contentHeight, 6*rowSpacing + 7*(popup.avatarHeight + 2*rowMargin)) clip: true - ScrollHelper { - flickable: parent - anchors.fill: parent - enabled: !Settings.mobileMode - } Timer { id: deadTimer @@ -117,7 +112,7 @@ Control { delegate: Rectangle { property variant modelData: model - color: model.index == popup.currentIndex ? Nheko.colors.highlight : Nheko.colors.base + color: model.index == popup.currentIndex ? timelineRoot.palette.highlight : timelineRoot.palette.base height: chooser.child.implicitHeight + 2 * popup.rowMargin implicitWidth: fullWidth ? ListView.view.width : chooser.child.implicitWidth + 4 @@ -134,7 +129,7 @@ Control { } } Ripple { - color: Qt.rgba(Nheko.colors.base.r, Nheko.colors.base.g, Nheko.colors.base.b, 0.5) + color: Qt.rgba(timelineRoot.palette.base.r, timelineRoot.palette.base.g, timelineRoot.palette.base.b, 0.5) } DelegateChooser { @@ -165,12 +160,12 @@ Control { Label { text: model.displayName - color: model.index == popup.currentIndex ? Nheko.colors.highlightedText : Nheko.colors.text + color: model.index == popup.currentIndex ? timelineRoot.palette.highlightedText : timelineRoot.palette.text } Label { text: "(" + model.userid + ")" - color: model.index == popup.currentIndex ? Nheko.colors.highlightedText : Nheko.colors.buttonText + color: model.index == popup.currentIndex ? timelineRoot.palette.highlightedText : timelineRoot.palette.buttonText } } @@ -188,13 +183,13 @@ Control { Label { text: model.unicode - color: model.index == popup.currentIndex ? Nheko.colors.highlightedText : Nheko.colors.text + color: model.index == popup.currentIndex ? timelineRoot.palette.highlightedText : timelineRoot.palette.text font: Settings.emojiFont } Label { text: model.shortName - color: model.index == popup.currentIndex ? Nheko.colors.highlightedText : Nheko.colors.text + color: model.index == popup.currentIndex ? timelineRoot.palette.highlightedText : timelineRoot.palette.text } } @@ -222,12 +217,12 @@ Control { Label { text: model.shortcode - color: model.index == popup.currentIndex ? Nheko.colors.highlightedText : Nheko.colors.text + color: model.index == popup.currentIndex ? timelineRoot.palette.highlightedText : timelineRoot.palette.text } Label { text: "(" + model.packname + ")" - color: model.index == popup.currentIndex ? Nheko.colors.highlightedText : Nheko.colors.buttonText + color: model.index == popup.currentIndex ? timelineRoot.palette.highlightedText : timelineRoot.palette.buttonText } } @@ -258,7 +253,7 @@ Control { Label { text: model.roomName font.pixelSize: popup.avatarHeight * 0.5 - color: model.index == popup.currentIndex ? Nheko.colors.highlightedText : Nheko.colors.text + color: model.index == popup.currentIndex ? timelineRoot.palette.highlightedText : timelineRoot.palette.text textFormat: Text.RichText } @@ -286,13 +281,13 @@ Control { Label { text: model.roomName - color: model.index == popup.currentIndex ? Nheko.colors.highlightedText : Nheko.colors.text + color: model.index == popup.currentIndex ? timelineRoot.palette.highlightedText : timelineRoot.palette.text textFormat: Text.RichText } Label { text: "(" + model.roomAlias + ")" - color: model.index == popup.currentIndex ? Nheko.colors.highlightedText : Nheko.colors.buttonText + color: model.index == popup.currentIndex ? timelineRoot.palette.highlightedText : timelineRoot.palette.buttonText textFormat: Text.RichText } @@ -308,8 +303,8 @@ Control { background: Rectangle { - color: Nheko.colors.base - border.color: Nheko.colors.mid + color: timelineRoot.palette.base + border.color: timelineRoot.palette.mid } } diff --git a/resources/qml/ElidedLabel.qml b/resources/qml/ElidedLabel.qml index 11df479a..f5d10a21 100644 --- a/resources/qml/ElidedLabel.qml +++ b/resources/qml/ElidedLabel.qml @@ -14,7 +14,7 @@ Label { property alias elideWidth: metrics.elideWidth property int fullTextWidth: Math.ceil(metrics.advanceWidth) - color: Nheko.colors.text + color: timelineRoot.palette.text text: (textFormat == Text.PlainText) ? metrics.elidedText : TimelineManager.escapeEmoji(TimelineManager.htmlEscape(metrics.elidedText)) maximumLineCount: 1 elide: Text.ElideRight diff --git a/resources/qml/EncryptionIndicator.qml b/resources/qml/EncryptionIndicator.qml index b0f479fa..0b8fe089 100644 --- a/resources/qml/EncryptionIndicator.qml +++ b/resources/qml/EncryptionIndicator.qml @@ -40,7 +40,7 @@ Image { case Crypto.Verified: return sourceUrl + "green"; case Crypto.TOFU: - return sourceUrl + Nheko.colors.buttonText; + return sourceUrl + timelineRoot.palette.buttonText; default: return sourceUrl + Nheko.theme.error; } diff --git a/resources/qml/ForwardCompleter.qml b/resources/qml/ForwardCompleter.qml index 76d77bfd..07a6c548 100644 --- a/resources/qml/ForwardCompleter.qml +++ b/resources/qml/ForwardCompleter.qml @@ -20,7 +20,7 @@ Popup { x: Math.round(parent.width / 2 - width / 2) y: Math.round(parent.height / 4) modal: true - palette: Nheko.colors + palette: timelineRoot.palette parent: Overlay.overlay width: timelineRoot.width * 0.8 leftPadding: 10 @@ -40,7 +40,7 @@ Popup { text: qsTr("Forward Message") font.bold: true bottomPadding: 10 - color: Nheko.colors.text + color: timelineRoot.palette.text } Reply { @@ -51,7 +51,7 @@ Popup { width: parent.width - userColor: TimelineManager.userColor(modelData.userId, Nheko.colors.window) + userColor: TimelineManager.userColor(modelData.userId, timelineRoot.palette.window) blurhash: modelData.blurhash ?? "" body: modelData.body ?? "" formattedBody: modelData.formattedBody ?? "" @@ -73,7 +73,7 @@ Popup { id: roomTextInput width: forwardMessagePopup.width - forwardMessagePopup.leftPadding * 2 - color: Nheko.colors.text + color: timelineRoot.palette.text onTextEdited: { completerPopup.completer.searchString = text; } @@ -124,11 +124,11 @@ Popup { } background: Rectangle { - color: Nheko.colors.window + color: timelineRoot.palette.window } Overlay.modal: Rectangle { - color: Qt.rgba(Nheko.colors.window.r, Nheko.colors.window.g, Nheko.colors.window.b, 0.7) + color: Qt.rgba(timelineRoot.palette.window.r, timelineRoot.palette.window.g, timelineRoot.palette.window.b, 0.7) } } diff --git a/resources/qml/ImageButton.qml b/resources/qml/ImageButton.qml index ffd3e920..b55c423e 100644 --- a/resources/qml/ImageButton.qml +++ b/resources/qml/ImageButton.qml @@ -13,8 +13,8 @@ AbstractButton { property alias cursor: mouseArea.cursorShape property string image: undefined - property color highlightColor: Nheko.colors.highlight - property color buttonTextColor: Nheko.colors.buttonText + property color highlightColor: timelineRoot.palette.highlight + property color buttonTextColor: timelineRoot.palette.buttonText property bool changeColorOnHover: true property bool ripple: true diff --git a/resources/qml/MatrixText.qml b/resources/qml/MatrixText.qml index 69eb7cdb..a3dec527 100644 --- a/resources/qml/MatrixText.qml +++ b/resources/qml/MatrixText.qml @@ -19,7 +19,7 @@ TextEdit { selectByMouse: !Settings.mobileMode // this always has to be enabled, otherwise you can't click links anymore! //enabled: selectByMouse - color: Nheko.colors.text + color: timelineRoot.palette.text onLinkActivated: Nheko.openLink(link) ToolTip.visible: hoveredLink || false ToolTip.text: hoveredLink diff --git a/resources/qml/MatrixTextField.qml b/resources/qml/MatrixTextField.qml index 3f0f77ed..5563d0ab 100644 --- a/resources/qml/MatrixTextField.qml +++ b/resources/qml/MatrixTextField.qml @@ -11,7 +11,7 @@ import im.nheko 1.0 ColumnLayout { id: c - property color backgroundColor: Nheko.colors.base + property color backgroundColor: timelineRoot.palette.base property alias color: labelC.color property alias textPadding: input.padding property alias text: input.text @@ -61,8 +61,8 @@ ColumnLayout { y: contentHeight + input.padding + Nheko.paddingSmall enabled: false - palette: Nheko.colors - color: Nheko.colors.text + palette: timelineRoot.palette + color: timelineRoot.palette.text font.pixelSize: input.font.pixelSize font.weight: Font.DemiBold font.letterSpacing: input.font.pixelSize * 0.02 @@ -114,7 +114,7 @@ ColumnLayout { id: input Layout.fillWidth: true - palette: Nheko.colors + palette: timelineRoot.palette color: labelC.color opacity: labelC.text ? 0 : 1 focus: true @@ -136,7 +136,7 @@ ColumnLayout { Layout.fillWidth: true - color: Nheko.colors.highlight + color: timelineRoot.palette.highlight height: 1 Rectangle { @@ -146,7 +146,7 @@ ColumnLayout { anchors.horizontalCenter: parent.horizontalCenter height: parent.height*2 width: 0 - color: Nheko.colors.text + color: timelineRoot.palette.text states: State { name: "focused" diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml index 76c498d9..8950d48b 100644 --- a/resources/qml/MessageInput.qml +++ b/resources/qml/MessageInput.qml @@ -14,7 +14,7 @@ import im.nheko 1.0 Rectangle { id: inputBar - color: Nheko.colors.window + color: timelineRoot.palette.window Layout.fillWidth: true Layout.preferredHeight: row.implicitHeight Layout.minimumHeight: 40 @@ -84,7 +84,7 @@ Rectangle { Rectangle { anchors.fill: parent - color: Nheko.colors.window + color: timelineRoot.palette.window visible: room && room.input.uploading NhekoBusyIndicator { @@ -137,8 +137,8 @@ Rectangle { selectByMouse: true placeholderText: qsTr("Write a message...") - placeholderTextColor: Nheko.colors.buttonText - color: Nheko.colors.text + placeholderTextColor: timelineRoot.palette.buttonText + color: timelineRoot.palette.text width: textInput.width verticalAlignment: TextEdit.AlignVCenter wrapMode: TextEdit.Wrap @@ -428,7 +428,7 @@ Rectangle { StickerPicker { id: stickerPopup - colors: Nheko.colors + colors: timelineRoot.palette } } @@ -471,7 +471,7 @@ Rectangle { anchors.centerIn: parent visible: room ? (!room.permissions.canSend(MtxEvent.TextMessage)) : false text: qsTr("You don't have permission to send messages in this room") - color: Nheko.colors.text + color: timelineRoot.palette.text } } diff --git a/resources/qml/MessageView.qml b/resources/qml/MessageView.qml index b20a1d88..c4c1acc5 100644 --- a/resources/qml/MessageView.qml +++ b/resources/qml/MessageView.qml @@ -72,8 +72,8 @@ Item { z: 10 background: Rectangle { - color: Nheko.colors.window - border.color: Nheko.colors.buttonText + color: timelineRoot.palette.window + border.color: timelineRoot.palette.buttonText border.width: 1 radius: padding } @@ -108,7 +108,7 @@ Item { id: editButton visible: !!row.model && row.model.isEditable - buttonTextColor: Nheko.colors.buttonText + buttonTextColor: timelineRoot.palette.buttonText width: 16 hoverEnabled: true image: ":/icons/icons/ui/edit.svg" @@ -168,11 +168,6 @@ Item { } - ScrollHelper { - flickable: parent - anchors.fill: parent - } - Shortcut { sequence: StandardKey.MoveToPreviousPage onActivated: { @@ -269,7 +264,7 @@ Item { anchors.horizontalCenter: parent ? parent.horizontalCenter : undefined visible: room && previousMessageDay !== day text: room ? room.formatDateSeparator(timestamp) : "" - color: Nheko.colors.text + color: timelineRoot.palette.text height: Math.round(fontMetrics.height * 1.4) width: contentWidth * 1.2 horizontalAlignment: Text.AlignHCenter @@ -277,7 +272,7 @@ Item { background: Rectangle { radius: parent.height / 2 - color: Nheko.colors.window + color: timelineRoot.palette.window } } @@ -318,7 +313,7 @@ Item { contentItem: ElidedLabel { id: userName_ fullText: userName - color: TimelineManager.userColor(userId, Nheko.colors.base) + color: TimelineManager.userColor(userId, timelineRoot.palette.base) textFormat: Text.RichText elideWidth: Math.min(userInfo.remainingWidth-Math.min(statusMsg.implicitWidth,userInfo.remainingWidth/3), userName_.fullTextWidth) } @@ -340,7 +335,7 @@ Item { Label { id: statusMsg - color: Nheko.colors.buttonText + color: timelineRoot.palette.buttonText text: Presence.userStatus(userId) textFormat: Text.PlainText elide: Text.ElideRight @@ -405,7 +400,7 @@ Item { anchors.horizontalCenter: parent ? parent.horizontalCenter : undefined width: chat.delegateMaxWidth - height: section.active ? section.height + timelinerow.height : timelinerow.height + height: section.active ? (section.item?.implicitHeight ?? 0) + timelinerow.height : timelinerow.height Loader { id: section @@ -462,7 +457,7 @@ Item { timestamp: wrapper.timestamp status: wrapper.status relatedEventCacheBuster: wrapper.relatedEventCacheBuster - y: section.visible && section.active ? section.y + section.height : 0 + y: section.item?.implicitHeight ?? 0 onHoveredChanged: { if (!Settings.mobileMode && hovered) { @@ -479,7 +474,7 @@ Item { visible: true z: 1 enabled: false - color: Nheko.colors.highlight + color: timelineRoot.palette.highlight states: State { name: "revealed" @@ -537,7 +532,7 @@ Item { anchors.margins: Nheko.paddingLarge visible: chat.model && chat.model.paginationInProgress // hacky, but works - height: loadingSpinner.height + 2 * Nheko.paddingLarge + height: (loadingSpinner.item?.implicitHeight ?? 0) + 2 * Nheko.paddingLarge Spinner { id: loadingSpinner @@ -545,7 +540,7 @@ Item { anchors.centerIn: parent anchors.margins: Nheko.paddingLarge running: chat.model && chat.model.paginationInProgress - foreground: Nheko.colors.mid + foreground: timelineRoot.palette.mid z: 3 } @@ -771,9 +766,9 @@ Item { hoverEnabled: true background: Rectangle { - color: toEndButton.down ? Nheko.colors.highlight : Nheko.colors.button + color: toEndButton.down ? timelineRoot.palette.highlight : timelineRoot.palette.button opacity: enabled ? 1 : 0.3 - border.color: toEndButton.hovered ? Nheko.colors.highlight : Nheko.colors.buttonText + border.color: toEndButton.hovered ? timelineRoot.palette.highlight : timelineRoot.palette.buttonText border.width: 1 radius: toEndButton.radius } @@ -794,7 +789,7 @@ Item { id: buttonImg anchors.fill: parent anchors.margins: Nheko.paddingMedium - source: "image://colorimage/:/icons/icons/ui/download.svg?" + (toEndButton.down ? Nheko.colors.highlightedText : Nheko.colors.buttonText) + source: "image://colorimage/:/icons/icons/ui/download.svg?" + (toEndButton.down ? timelineRoot.palette.highlightedText : timelineRoot.palette.buttonText) fillMode: Image.PreserveAspectFit } diff --git a/resources/qml/NhekoBusyIndicator.qml b/resources/qml/NhekoBusyIndicator.qml index aafe8900..f4731d47 100644 --- a/resources/qml/NhekoBusyIndicator.qml +++ b/resources/qml/NhekoBusyIndicator.qml @@ -40,7 +40,7 @@ BusyIndicator { implicitWidth: radius * 2 implicitHeight: radius * 2 radius: item.height / 6 - color: Nheko.colors.text + color: timelineRoot.palette.text opacity: (index + 2) / (repeater.count + 2) transform: [ Translate { diff --git a/resources/qml/NotificationWarning.qml b/resources/qml/NotificationWarning.qml index 285e5a5c..fba16e93 100644 --- a/resources/qml/NotificationWarning.qml +++ b/resources/qml/NotificationWarning.qml @@ -17,7 +17,7 @@ Item { id: warningRect visible: (room && room.permissions.canPingRoom() && room.input.containsAtRoom) - color: Nheko.colors.base + color: timelineRoot.palette.base anchors.fill: parent z: 3 diff --git a/resources/qml/QuickSwitcher.qml b/resources/qml/QuickSwitcher.qml index ac5d3aea..e0d8d687 100644 --- a/resources/qml/QuickSwitcher.qml +++ b/resources/qml/QuickSwitcher.qml @@ -20,7 +20,7 @@ Popup { modal: true closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside parent: Overlay.overlay - palette: Nheko.colors + palette: timelineRoot.palette onOpened: { roomTextInput.forceActiveFocus(); } @@ -35,7 +35,7 @@ Popup { width: parent.width font.pixelSize: Math.ceil(quickSwitcher.textHeight * 0.6) - color: Nheko.colors.text + color: timelineRoot.palette.text onTextEdited: { completerPopup.completer.searchString = text; } diff --git a/resources/qml/Reactions.qml b/resources/qml/Reactions.qml index aaf32647..7fbf15b0 100644 --- a/resources/qml/Reactions.qml +++ b/resources/qml/Reactions.qml @@ -13,9 +13,9 @@ Flow { id: reactionFlow // highlight colors for selfReactedEvent background - property real highlightHue: Nheko.colors.highlight.hslHue - property real highlightSat: Nheko.colors.highlight.hslSaturation - property real highlightLight: Nheko.colors.highlight.hslLightness + property real highlightHue: timelineRoot.palette.highlight.hslHue + property real highlightSat: timelineRoot.palette.highlight.hslSaturation + property real highlightLight: timelineRoot.palette.highlight.hslLightness property string eventId property alias reactions: repeater.model @@ -74,7 +74,7 @@ Flow { return textMetrics.elidedText; } font.family: Settings.emojiFont - color: reaction.hovered ? Nheko.colors.highlight : Nheko.colors.text + color: reaction.hovered ? timelineRoot.palette.highlight : timelineRoot.palette.text maximumLineCount: 1 } @@ -83,7 +83,7 @@ Flow { height: Math.floor(reactionCounter.implicitHeight * 1.4) width: 1 - color: (reaction.hovered || modelData.selfReactedEvent !== '') ? Nheko.colors.highlight : Nheko.colors.text + color: (reaction.hovered || modelData.selfReactedEvent !== '') ? timelineRoot.palette.highlight : timelineRoot.palette.text } Text { @@ -92,7 +92,7 @@ Flow { anchors.verticalCenter: divider.verticalCenter text: modelData.count font: reaction.font - color: reaction.hovered ? Nheko.colors.highlight : Nheko.colors.text + color: reaction.hovered ? timelineRoot.palette.highlight : timelineRoot.palette.text } } @@ -101,8 +101,8 @@ Flow { anchors.centerIn: parent implicitWidth: reaction.implicitWidth implicitHeight: reaction.implicitHeight - border.color: (reaction.hovered || modelData.selfReactedEvent !== '') ? Nheko.colors.highlight : Nheko.colors.text - color: modelData.selfReactedEvent !== '' ? Qt.hsla(highlightHue, highlightSat, highlightLight, 0.2) : Nheko.colors.window + border.color: (reaction.hovered || modelData.selfReactedEvent !== '') ? timelineRoot.palette.highlight : timelineRoot.palette.text + color: modelData.selfReactedEvent !== '' ? Qt.hsla(highlightHue, highlightSat, highlightLight, 0.2) : timelineRoot.palette.window border.width: 1 radius: reaction.height / 2 } diff --git a/resources/qml/ReplyPopup.qml b/resources/qml/ReplyPopup.qml index 914f5d33..68d98d63 100644 --- a/resources/qml/ReplyPopup.qml +++ b/resources/qml/ReplyPopup.qml @@ -16,7 +16,7 @@ Rectangle { visible: room && (room.reply || room.edit) // Height of child, plus margins, plus border implicitHeight: (room && room.reply ? replyPreview.height : closeEditButton.height) + Nheko.paddingSmall - color: Nheko.colors.window + color: timelineRoot.palette.window z: 3 Reply { @@ -32,7 +32,7 @@ Rectangle { anchors.rightMargin: replyPopup.width < 450? 2*(22+16) : 3*(22+16) anchors.top: parent.top anchors.topMargin: Nheko.paddingSmall - userColor: TimelineManager.userColor(modelData.userId, Nheko.colors.window) + userColor: TimelineManager.userColor(modelData.userId, timelineRoot.palette.window) blurhash: modelData.blurhash ?? "" body: modelData.body ?? "" formattedBody: modelData.formattedBody ?? "" @@ -47,7 +47,7 @@ Rectangle { isOnlyEmoji: modelData.isOnlyEmoji ?? false userId: modelData.userId ?? "" userName: modelData.userName ?? "" - encryptionError: modelData.encryptionError ?? "" + encryptionError: modelData.encryptionError ?? 0 width: parent.width } diff --git a/resources/qml/RoomList.qml b/resources/qml/RoomList.qml index 078baede..660c0edb 100644 --- a/resources/qml/RoomList.qml +++ b/resources/qml/RoomList.qml @@ -49,11 +49,6 @@ Page { model: Rooms reuseItems: true - ScrollHelper { - flickable: parent - anchors.fill: parent - } - Connections { function onCurrentRoomChanged() { if (Rooms.currentRoom) @@ -97,8 +92,8 @@ Page { Instantiator { model: Communities.tagsWithDefault - onObjectAdded: roomContextMenu.insertItem(index + 2, object) - onObjectRemoved: roomContextMenu.removeItem(object) + onObjectAdded: (index, object) => roomContextMenu.insertItem(index + 2, object) + onObjectRemoved: object => roomContextMenu.removeItem(object) delegate: Platform.MenuItem { property string t: modelData @@ -132,11 +127,11 @@ Page { delegate: ItemDelegate { id: roomItem - property color backgroundColor: Nheko.colors.window - property color importantText: Nheko.colors.text - property color unimportantText: Nheko.colors.buttonText - property color bubbleBackground: Nheko.colors.highlight - property color bubbleText: Nheko.colors.highlightedText + property color backgroundColor: timelineRoot.palette.window + property color importantText: timelineRoot.palette.text + property color unimportantText: timelineRoot.palette.buttonText + property color bubbleBackground: timelineRoot.palette.highlight + property color bubbleText: timelineRoot.palette.highlightedText required property string roomName required property string roomId required property string avatarUrl @@ -152,7 +147,7 @@ Page { required property string directChatOtherUserId Ripple { - color: Qt.rgba(Nheko.colors.dark.r, Nheko.colors.dark.g, Nheko.colors.dark.b, 0.5) + color: Qt.rgba(timelineRoot.palette.dark.r, timelineRoot.palette.dark.g, timelineRoot.palette.dark.b, 0.5) } height: avatarSize + 2 * Nheko.paddingMedium @@ -184,11 +179,11 @@ Page { PropertyChanges { target: roomItem - backgroundColor: Nheko.colors.dark - importantText: Nheko.colors.brightText - unimportantText: Nheko.colors.brightText - bubbleBackground: Nheko.colors.highlight - bubbleText: Nheko.colors.highlightedText + backgroundColor: timelineRoot.palette.dark + importantText: timelineRoot.palette.brightText + unimportantText: timelineRoot.palette.brightText + bubbleBackground: timelineRoot.palette.highlight + bubbleText: timelineRoot.palette.highlightedText } }, @@ -198,11 +193,11 @@ Page { PropertyChanges { target: roomItem - backgroundColor: Nheko.colors.highlight - importantText: Nheko.colors.highlightedText - unimportantText: Nheko.colors.highlightedText - bubbleBackground: Nheko.colors.highlightedText - bubbleText: Nheko.colors.highlight + backgroundColor: timelineRoot.palette.highlight + importantText: timelineRoot.palette.highlightedText + unimportantText: timelineRoot.palette.highlightedText + bubbleBackground: timelineRoot.palette.highlightedText + bubbleText: timelineRoot.palette.highlight } } @@ -378,7 +373,7 @@ Page { anchors.verticalCenter: parent.verticalCenter height: parent.height - Nheko.paddingSmall * 2 width: 3 - color: Nheko.colors.highlight + color: timelineRoot.palette.highlight visible: hasUnreadMessages } @@ -416,7 +411,7 @@ Page { padding: Nheko.paddingMedium Layout.minimumHeight: 40 - background: Rectangle {color: Nheko.colors.window} + background: Rectangle {color: timelineRoot.palette.window} InputDialog { id: statusDialog @@ -497,7 +492,7 @@ Page { ElidedLabel { Layout.alignment: Qt.AlignTop - color: Nheko.colors.buttonText + color: timelineRoot.palette.buttonText font.pointSize: fontMetrics.font.pointSize * 0.9 elideWidth: col.width fullText: userInfoGrid.profile ? userInfoGrid.profile.userid : "" @@ -552,7 +547,7 @@ Page { Layout.margins: Nheko.paddingMedium Layout.rightMargin: Nheko.paddingSmall - color: Nheko.colors.buttonText + color: timelineRoot.palette.buttonText Layout.fillWidth: true text: { switch (SelfVerificationStatus.status) { @@ -636,7 +631,7 @@ Page { horizontalPadding: Nheko.paddingMedium verticalPadding: 0 - background: Rectangle {color: Nheko.colors.window} + background: Rectangle {color: timelineRoot.palette.window} contentItem: RowLayout { id: buttonRow diff --git a/resources/qml/Root.qml b/resources/qml/Root.qml index c8c6b461..da4e903e 100644 --- a/resources/qml/Root.qml +++ b/resources/qml/Root.qml @@ -35,8 +35,8 @@ Pane { alternateBase: "#2d3139" highlight: "#38a3d8" highlightedText: "#f4f5f8" - toolTipBase: base - toolTipText: text + toolTipBase: timelineRoot.palette.base + toolTipText: timelineRoot.palette.text link: "#38a3d8" buttonText: "#828284" diff --git a/resources/qml/ScrollHelper.qml b/resources/qml/ScrollHelper.qml deleted file mode 100644 index c87b730e..00000000 --- a/resources/qml/ScrollHelper.qml +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (C) 2016 Michael Bohlender, -// Copyright (C) 2017 Christian Mollekopf, -// SPDX-FileCopyrightText: 2021 Nheko Contributors -// SPDX-FileCopyrightText: 2022 Nheko Contributors -// -// SPDX-License-Identifier: GPL-3.0-or-later - -/* -* Shamelessly stolen from: -* https://cgit.kde.org/kube.git/tree/framework/qml/ScrollHelper.qml -* -* The MouseArea + interactive: false + maximumFlickVelocity are required -* to fix scrolling for desktop systems where we don't want flicking behaviour. -* -* See also: -* ScrollView.qml in qtquickcontrols -* qquickwheelarea.cpp in qtquickcontrols -*/ - -import QtQuick 2.9 -import QtQuick.Controls 2.3 - -MouseArea { - // console.warn("Delta: ", wheel.pixelDelta.y); - // console.warn("Old position: ", flickable.contentY); - // console.warn("New position: ", newPos); - // breaks ListView's with headers... - //if (typeof (flickableItem.headerItem) !== "undefined" && flickableItem.headerItem) - // minYExtent += flickableItem.headerItem.height; - - id: root - - property Flickable flickable - property alias enabled: root.enabled - - function calculateNewPosition(flickableItem, wheel) { - //Nothing to scroll - if (flickableItem.contentHeight < flickableItem.height) - return flickableItem.contentY; - - //Ignore 0 events (happens at least with Christians trackpad) - if (wheel.pixelDelta.y == 0 && wheel.angleDelta.y == 0) - return flickableItem.contentY; - - //pixelDelta seems to be the same as angleDelta/8 - var pixelDelta = 0; - //The pixelDelta is a smaller number if both are provided, so pixelDelta can be 0 while angleDelta is still something. So we check the angleDelta - if (wheel.angleDelta.y) { - var wheelScrollLines = 3; //Default value of QApplication wheelScrollLines property - var pixelPerLine = 20; //Default value in Qt, originally comes from QTextEdit - var ticks = (wheel.angleDelta.y / 8) / 15; //Divide by 8 gives us pixels typically come in 15pixel steps. - pixelDelta = ticks * pixelPerLine * wheelScrollLines; - } else { - pixelDelta = wheel.pixelDelta.y; - } - pixelDelta = Math.round(pixelDelta); - if (!pixelDelta) - return flickableItem.contentY; - - var minYExtent = flickableItem.originY + flickableItem.topMargin; - var maxYExtent = (flickableItem.contentHeight + flickableItem.bottomMargin + flickableItem.originY) - flickableItem.height; - //Avoid overscrolling - return Math.max(minYExtent, Math.min(maxYExtent, flickableItem.contentY - pixelDelta)); - } - - propagateComposedEvents: true - //Place the mouse area under the flickable - z: -1 - onFlickableChanged: { - if (enabled) { - flickable.maximumFlickVelocity = 100000; - flickable.boundsBehavior = Flickable.StopAtBounds; - root.parent = flickable; - } - } - acceptedButtons: Qt.NoButton - onWheel: { - var newPos = calculateNewPosition(flickable, wheel); - // Show the scrollbars - flickable.flick(0, 0); - flickable.contentY = newPos; - cancelFlickStateTimer.restart(); - } - - Timer { - id: cancelFlickStateTimer - - //How long the scrollbar will remain visible - interval: 500 - // Hide the scrollbars - onTriggered: { - flickable.cancelFlick(); - flickable.movementEnded(); - } - } - -} diff --git a/resources/qml/SelfVerificationCheck.qml b/resources/qml/SelfVerificationCheck.qml index 336b966d..70d464e8 100644 --- a/resources/qml/SelfVerificationCheck.qml +++ b/resources/qml/SelfVerificationCheck.qml @@ -38,7 +38,7 @@ Item { Layout.maximumWidth: (Overlay.overlay ? Overlay.overlay.width : 400) - Nheko.paddingMedium * 4 Layout.fillWidth: true text: qsTr("This is your recovery key. You will need it to restore access to your encrypted messages and verification keys. Keep this safe. Don't share it with anyone and don't lose it! Do not pass go! Do not collect $200!") - color: Nheko.colors.text + color: timelineRoot.palette.text wrapMode: Text.Wrap } @@ -50,7 +50,7 @@ Item { readOnly: true selectByMouse: true text: showRecoverKeyDialog.recoveryKey - color: Nheko.colors.text + color: timelineRoot.palette.text font.bold: true wrapMode: TextEdit.Wrap } @@ -58,7 +58,7 @@ Item { } background: Rectangle { - color: Nheko.colors.window + color: timelineRoot.palette.window border.color: Nheko.theme.separator border.width: 1 radius: Nheko.paddingSmall @@ -102,7 +102,7 @@ Item { Layout.columnSpan: 2 font.pointSize: fontMetrics.font.pointSize * 2 text: qsTr("Setup Encryption") - color: Nheko.colors.text + color: timelineRoot.palette.text wrapMode: Text.Wrap } @@ -112,7 +112,7 @@ Item { Layout.columnSpan: 2 Layout.maximumWidth: grid.width - Nheko.paddingMedium * 2 text: qsTr("Hello and welcome to Matrix!\nIt seems like you are new. Before you can securely encrypt your messages, we need to setup a few small things. You can either press accept immediately or adjust a few basic options. We also try to explain a few of the basics. You can skip those parts, but they might prove to be helpful!") - color: Nheko.colors.text + color: timelineRoot.palette.text wrapMode: Text.Wrap } @@ -122,7 +122,7 @@ Item { Layout.columnSpan: 1 Layout.maximumWidth: Math.floor(grid.width / 2) - Nheko.paddingMedium * 2 text: "Store secrets online.\nYou have a few secrets to make all the encryption magic work. While you can keep them stored only locally, we recommend storing them encrypted on the server. Otherwise it will be painful to recover them. Only disable this if you are paranoid and like losing your data!" - color: Nheko.colors.text + color: timelineRoot.palette.text wrapMode: Text.Wrap } @@ -149,7 +149,7 @@ Item { Layout.maximumWidth: Math.floor(grid.width / 2) - Nheko.paddingMedium * 2 visible: storeSecretsOnline.checked text: "Set an online backup password.\nWe recommend you DON'T set a password and instead only rely on the recovery key. You will get a recovery key in any case when storing the cross-signing secrets online, but passwords are usually not very random, so they are easier to attack than a completely random recovery key. If you choose to use a password, DON'T make it the same as your login password, otherwise your server can read all your encrypted messages. (You don't want that.)" - color: Nheko.colors.text + color: timelineRoot.palette.text wrapMode: Text.Wrap } @@ -188,7 +188,7 @@ Item { Layout.columnSpan: 1 Layout.maximumWidth: Math.floor(grid.width / 2) - Nheko.paddingMedium * 2 text: "Use online key backup.\nStore the keys for your messages securely encrypted online. In general you do want this, because it protects your messages from becoming unreadable, if you log out by accident. It does however carry a small security risk, if you ever share your recovery key by accident. Currently this also has some other weaknesses, that might allow the server to insert new keys into your backup. The server will however never be able to read your messages." - color: Nheko.colors.text + color: timelineRoot.palette.text wrapMode: Text.Wrap } @@ -210,7 +210,7 @@ Item { } background: Rectangle { - color: Nheko.colors.window + color: timelineRoot.palette.window border.color: Nheko.theme.separator border.width: 1 radius: Nheko.paddingSmall @@ -236,7 +236,7 @@ Item { //Layout.columnSpan: 2 font.pointSize: fontMetrics.font.pointSize * 2 text: qsTr("Activate Encryption") - color: Nheko.colors.text + color: timelineRoot.palette.text wrapMode: Text.Wrap } @@ -246,7 +246,7 @@ Item { //Layout.columnSpan: 2 Layout.maximumWidth: grid.width - Nheko.paddingMedium * 2 text: qsTr("It seems like you have encryption already configured for this account. To be able to access your encrypted messages and make this device appear as trusted, you can either verify an existing device or (if you have one) enter your recovery passphrase. Please select one of the options below.\nIf you choose verify, you need to have the other device available. If you choose \"enter passphrase\", you will need your recovery key or passphrase. If you click cancel, you can choose to verify yourself at a later point.") - color: Nheko.colors.text + color: timelineRoot.palette.text wrapMode: Text.Wrap } diff --git a/resources/qml/TimelineRow.qml b/resources/qml/TimelineRow.qml index 3a7bf561..c2cfd772 100644 --- a/resources/qml/TimelineRow.qml +++ b/resources/qml/TimelineRow.qml @@ -52,7 +52,7 @@ AbstractButton { height: row.height+(reactionRow.height > 0 ? reactionRow.height-2 : 0 ) Rectangle { - color: (Settings.messageHoverHighlight && hovered) ? Nheko.colors.alternateBase : "transparent" + color: (Settings.messageHoverHighlight && hovered) ? timelineRoot.palette.alternateBase : "transparent" anchors.fill: parent // this looks better without margins TapHandler { @@ -111,8 +111,8 @@ AbstractButton { width: Settings.bubbles? Math.min(maxWidth,Math.max(reply.implicitWidth+8,contentItem.implicitWidth+metadata.width+20)) : maxWidth height: msg.height+msg.anchors.margins*2 - property color userColor: TimelineManager.userColor(userId, Nheko.colors.base) - property color bgColor: Nheko.colors.base + property color userColor: TimelineManager.userColor(userId, timelineRoot.palette.base) + property color bgColor: timelineRoot.palette.base color: (Settings.bubbles && !isStateEvent) ? Qt.tint(bgColor, Qt.hsla(userColor.hslHue, 0.5, userColor.hslLightness, 0.2)) : "#00000000" radius: 4 @@ -144,7 +144,7 @@ AbstractButton { return replyTo != "" ? room.dataById(replyTo, role, r.eventId) : null; } visible: replyTo - userColor: r.relatedEventCacheBuster, TimelineManager.userColor(userId, Nheko.colors.base) + userColor: r.relatedEventCacheBuster, TimelineManager.userColor(userId, timelineRoot.palette.base) blurhash: r.relatedEventCacheBuster, fromModel(Room.Blurhash) ?? "" body: r.relatedEventCacheBuster, fromModel(Room.Body) ?? "" formattedBody: r.relatedEventCacheBuster, fromModel(Room.FormattedBody) ?? "" @@ -161,11 +161,11 @@ AbstractButton { userId: r.relatedEventCacheBuster, fromModel(Room.UserId) ?? "" userName: r.relatedEventCacheBuster, fromModel(Room.UserName) ?? "" thumbnailUrl: r.relatedEventCacheBuster, fromModel(Room.ThumbnailUrl) ?? "" - duration: r.relatedEventCacheBuster, fromModel(Room.Duration) ?? "" + duration: r.relatedEventCacheBuster, fromModel(Room.Duration) ?? 0 roomTopic: r.relatedEventCacheBuster, fromModel(Room.RoomTopic) ?? "" roomName: r.relatedEventCacheBuster, fromModel(Room.RoomName) ?? "" callType: r.relatedEventCacheBuster, fromModel(Room.CallType) ?? "" - encryptionError: r.relatedEventCacheBuster, fromModel(Room.EncryptionError) ?? "" + encryptionError: r.relatedEventCacheBuster, fromModel(Room.EncryptionError) ?? 0 relatedEventCacheBuster: r.relatedEventCacheBuster, fromModel(Room.RelatedEventCacheBuster) ?? 0 } @@ -235,7 +235,7 @@ AbstractButton { width: parent.iconSize sourceSize.width: parent.iconSize * Screen.devicePixelRatio sourceSize.height: parent.iconSize * Screen.devicePixelRatio - source: "image://colorimage/:/icons/icons/ui/edit.svg?" + ((eventId == chat.model.edit) ? Nheko.colors.highlight : Nheko.colors.buttonText) + source: "image://colorimage/:/icons/icons/ui/edit.svg?" + ((eventId == chat.model.edit) ? timelineRoot.palette.highlight : timelineRoot.palette.buttonText) ToolTip.visible: editHovered.hovered ToolTip.delay: Nheko.tooltipDelay ToolTip.text: qsTr("Edited") @@ -264,7 +264,7 @@ AbstractButton { Layout.alignment: Qt.AlignRight | Qt.AlignTop Layout.preferredWidth: implicitWidth text: timestamp.toLocaleTimeString(Locale.ShortFormat) - color: Nheko.inactiveColors.text + color: timelineRoot.palette.inactive.text ToolTip.visible: ma.hovered ToolTip.delay: Nheko.tooltipDelay ToolTip.text: Qt.formatDateTime(timestamp, Qt.DefaultLocaleLongDate) diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index 3f439439..ea3e4e3d 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -35,13 +35,13 @@ Item { anchors.centerIn: parent text: qsTr("No room open") font.pointSize: 24 - color: Nheko.colors.text + color: timelineRoot.palette.text } Spinner { visible: TimelineManager.isInitialSync anchors.centerIn: parent - foreground: Nheko.colors.mid + foreground: timelineRoot.palette.mid running: TimelineManager.isInitialSync // height is somewhat arbitrary here... don't set width because width scales w/ height height: parent.height / 16 @@ -72,7 +72,7 @@ Item { Layout.fillWidth: true Layout.fillHeight: true - color: Nheko.colors.base + color: timelineRoot.palette.base ColumnLayout { anchors.fill: parent @@ -226,7 +226,7 @@ Item { readOnly: true background: null selectByMouse: true - color: Nheko.colors.text + color: timelineRoot.palette.text horizontalAlignment: TextEdit.AlignHCenter onLinkActivated: Nheko.openLink(link) diff --git a/resources/qml/TopBar.qml b/resources/qml/TopBar.qml index 32149cc8..9aa17cf6 100644 --- a/resources/qml/TopBar.qml +++ b/resources/qml/TopBar.qml @@ -31,7 +31,7 @@ Pane { padding: 0 background: Rectangle { - color: Nheko.colors.window + color: timelineRoot.palette.window } TapHandler { @@ -114,7 +114,7 @@ Pane { Layout.fillWidth: true Layout.column: 2 Layout.row: 0 - color: Nheko.colors.text + color: timelineRoot.palette.text font.pointSize: fontMetrics.font.pointSize * 1.1 text: roomName maximumLineCount: 1 @@ -257,7 +257,7 @@ Pane { visible: !!room && room.pinnedMessages.length > 0 && !Settings.hiddenPins.includes(roomId) clip: true - palette: Nheko.colors + palette: timelineRoot.palette ScrollBar.horizontal.visible: false ListView { @@ -275,7 +275,7 @@ Pane { Layout.fillWidth: true Layout.preferredHeight: height - userColor: TimelineManager.userColor(e.userId, Nheko.colors.window) + userColor: TimelineManager.userColor(e.userId, timelineRoot.palette.window) blurhash: e.blurhash ?? "" body: e.body ?? "" formattedBody: e.formattedBody ?? "" @@ -310,12 +310,6 @@ Pane { } } - - ScrollHelper { - flickable: parent - anchors.fill: parent - enabled: !Settings.mobileMode - } } } @@ -332,7 +326,7 @@ Pane { visible: !!room && room.widgetLinks.length > 0 && !Settings.hiddenWidgets.includes(roomId) clip: true - palette: Nheko.colors + palette: timelineRoot.palette ScrollBar.horizontal.visible: false ListView { @@ -342,16 +336,10 @@ Pane { delegate: MatrixText { required property var modelData - color: Nheko.colors.text + color: timelineRoot.palette.text text: modelData } - - ScrollHelper { - flickable: parent - anchors.fill: parent - enabled: !Settings.mobileMode - } } } } diff --git a/resources/qml/TypingIndicator.qml b/resources/qml/TypingIndicator.qml index 0b92b2d2..353369c2 100644 --- a/resources/qml/TypingIndicator.qml +++ b/resources/qml/TypingIndicator.qml @@ -16,7 +16,7 @@ Item { id: typingRect visible: (room && room.typingUsers.length > 0) - color: Nheko.colors.base + color: timelineRoot.palette.base anchors.fill: parent z: 3 @@ -28,8 +28,8 @@ Item { anchors.right: parent.right anchors.rightMargin: 10 anchors.bottom: parent.bottom - color: Nheko.colors.text - text: room ? room.formatTypingUsers(room.typingUsers, Nheko.colors.base) : "" + color: timelineRoot.palette.text + text: room ? room.formatTypingUsers(room.typingUsers, timelineRoot.palette.base) : "" textFormat: Text.RichText } diff --git a/resources/qml/UploadBox.qml b/resources/qml/UploadBox.qml index ba00f205..dd7fd943 100644 --- a/resources/qml/UploadBox.qml +++ b/resources/qml/UploadBox.qml @@ -40,7 +40,7 @@ Page { width: uploadPopup.availableHeight - buttons.height background: Rectangle { - color: Nheko.colors.window + color: timelineRoot.palette.window radius: Nheko.paddingMedium } contentItem: ColumnLayout { @@ -60,7 +60,7 @@ Page { case MediaUpload.Image: return "image"; default: return "zip"; } - source: (modelData.thumbnail != "") ? modelData.thumbnail : ("image://colorimage/:/icons/icons/ui/"+typeStr+".svg?" + Nheko.colors.buttonText) + source: (modelData.thumbnail != "") ? modelData.thumbnail : ("image://colorimage/:/icons/icons/ui/"+typeStr+".svg?" + timelineRoot.palette.buttonText) } MatrixTextField { Layout.fillWidth: true @@ -84,6 +84,6 @@ Page { } background: Rectangle { - color: Nheko.colors.base + color: timelineRoot.palette.base } } diff --git a/resources/qml/components/AvatarListTile.qml b/resources/qml/components/AvatarListTile.qml index 910e0e47..93f10d06 100644 --- a/resources/qml/components/AvatarListTile.qml +++ b/resources/qml/components/AvatarListTile.qml @@ -12,11 +12,11 @@ import im.nheko 1.0 Rectangle { id: tile - property color background: Nheko.colors.window - property color importantText: Nheko.colors.text - property color unimportantText: Nheko.colors.buttonText - property color bubbleBackground: Nheko.colors.highlight - property color bubbleText: Nheko.colors.highlightedText + property color background: timelineRoot.palette.window + property color importantText: timelineRoot.palette.text + property color unimportantText: timelineRoot.palette.buttonText + property color bubbleBackground: timelineRoot.palette.highlight + property color bubbleText: timelineRoot.palette.highlightedText property int avatarSize: Math.ceil(fontMetrics.lineSpacing * 2.3) required property string avatarUrl required property string title @@ -38,11 +38,11 @@ Rectangle { PropertyChanges { target: tile - background: Nheko.colors.dark - importantText: Nheko.colors.brightText - unimportantText: Nheko.colors.brightText - bubbleBackground: Nheko.colors.highlight - bubbleText: Nheko.colors.highlightedText + background: timelineRoot.palette.dark + importantText: timelineRoot.palette.brightText + unimportantText: timelineRoot.palette.brightText + bubbleBackground: timelineRoot.palette.highlight + bubbleText: timelineRoot.palette.highlightedText } }, @@ -52,11 +52,11 @@ Rectangle { PropertyChanges { target: tile - background: Nheko.colors.highlight - importantText: Nheko.colors.highlightedText - unimportantText: Nheko.colors.highlightedText - bubbleBackground: Nheko.colors.highlightedText - bubbleText: Nheko.colors.highlight + background: timelineRoot.palette.highlight + importantText: timelineRoot.palette.highlightedText + unimportantText: timelineRoot.palette.highlightedText + bubbleBackground: timelineRoot.palette.highlightedText + bubbleText: timelineRoot.palette.highlight } } diff --git a/resources/qml/components/FlatButton.qml b/resources/qml/components/FlatButton.qml index e19f9681..69f60a42 100644 --- a/resources/qml/components/FlatButton.qml +++ b/resources/qml/components/FlatButton.qml @@ -49,7 +49,7 @@ Button { font.capitalization: Font.AllUppercase font.pointSize: Math.ceil(fontMetrics.font.pointSize * 1.5) //font.capitalization: Font.AllUppercase - color: Nheko.colors.light + color: timelineRoot.palette.light horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter elide: Text.ElideRight @@ -60,7 +60,7 @@ Button { //height: control.contentItem.implicitHeight * 2 //width: control.contentItem.implicitWidth * 2 radius: height / 8 - color: Qt.lighter(Nheko.colors.dark, control.down ? 1.4 : (control.hovered ? 1.2 : 1)) + color: Qt.lighter(timelineRoot.palette.dark, control.down ? 1.4 : (control.hovered ? 1.2 : 1)) } } diff --git a/resources/qml/components/MainWindowDialog.qml b/resources/qml/components/MainWindowDialog.qml index def4f96b..c5abb564 100644 --- a/resources/qml/components/MainWindowDialog.qml +++ b/resources/qml/components/MainWindowDialog.qml @@ -33,7 +33,7 @@ Dialog { ] background: Rectangle { - color: Nheko.colors.window + color: timelineRoot.palette.window border.color: Nheko.theme.separator border.width: 1 radius: Nheko.paddingSmall diff --git a/resources/qml/components/TextButton.qml b/resources/qml/components/TextButton.qml index a37f3aee..68299332 100644 --- a/resources/qml/components/TextButton.qml +++ b/resources/qml/components/TextButton.qml @@ -12,8 +12,8 @@ AbstractButton { id: button property alias cursor: mouseArea.cursorShape - property color highlightColor: Nheko.colors.highlight - property color buttonTextColor: Nheko.colors.buttonText + property color highlightColor: timelineRoot.palette.highlight + property color buttonTextColor: timelineRoot.palette.buttonText focusPolicy: Qt.NoFocus width: buttonText.implicitWidth diff --git a/resources/qml/delegates/Encrypted.qml b/resources/qml/delegates/Encrypted.qml index ecc771f5..7f16003a 100644 --- a/resources/qml/delegates/Encrypted.qml +++ b/resources/qml/delegates/Encrypted.qml @@ -19,7 +19,7 @@ Rectangle { width: parent.width? parent.width : 0 implicitWidth: encryptedText.implicitWidth+24+Nheko.paddingMedium*3 // Column doesn't provide a useful implicitWidth, should be replaced by ColumnLayout height: contents.implicitHeight + Nheko.paddingMedium * 2 - color: Nheko.colors.alternateBase + color: timelineRoot.palette.alternateBase RowLayout { id: contents @@ -59,12 +59,12 @@ Rectangle { return qsTr("Unknown decryption error"); } } - color: Nheko.colors.text + color: timelineRoot.palette.text width: parent.width } Button { - palette: Nheko.colors + palette: timelineRoot.palette visible: encryptionError == Olm.MissingSession || encryptionError == Olm.MissingSessionIndex text: qsTr("Request key") onClicked: room.requestKeyForEvent(eventId) diff --git a/resources/qml/delegates/FileMessage.qml b/resources/qml/delegates/FileMessage.qml index daae8635..42516973 100644 --- a/resources/qml/delegates/FileMessage.qml +++ b/resources/qml/delegates/FileMessage.qml @@ -28,7 +28,7 @@ Item { Rectangle { id: button - color: Nheko.colors.light + color: timelineRoot.palette.light radius: 22 height: 44 width: 44 @@ -68,7 +68,7 @@ Item { text: filename textFormat: Text.PlainText elide: Text.ElideRight - color: Nheko.colors.text + color: timelineRoot.palette.text } Text { @@ -78,7 +78,7 @@ Item { text: filesize textFormat: Text.PlainText elide: Text.ElideRight - color: Nheko.colors.text + color: timelineRoot.palette.text } } @@ -86,7 +86,7 @@ Item { } Rectangle { - color: Nheko.colors.alternateBase + color: timelineRoot.palette.alternateBase z: -1 radius: 10 anchors.fill: parent diff --git a/resources/qml/delegates/ImageMessage.qml b/resources/qml/delegates/ImageMessage.qml index 23cca019..80317b0e 100644 --- a/resources/qml/delegates/ImageMessage.qml +++ b/resources/qml/delegates/ImageMessage.qml @@ -23,7 +23,7 @@ AbstractButton { property int tempWidth: originalWidth < 1? 400: originalWidth implicitWidth: Math.round(tempWidth*Math.min((timelineView.height/divisor)/(tempWidth*proportionalHeight), 1)) - width: Math.min(parent.width,implicitWidth) + width: Math.min(parent?.width ?? implicitWidth,implicitWidth) height: width*proportionalHeight hoverEnabled: true @@ -35,7 +35,7 @@ AbstractButton { anchors.fill: parent visible: img.status != Image.Ready - source: blurhash ? ("image://blurhash/" + blurhash) : ("image://colorimage/:/icons/icons/ui/image-failed.svg?" + Nheko.colors.buttonText) + source: blurhash ? ("image://blurhash/" + blurhash) : ("image://colorimage/:/icons/icons/ui/image-failed.svg?" + timelineRoot.palette.buttonText) asynchronous: true fillMode: Image.PreserveAspectFit sourceSize.width: parent.width * Screen.devicePixelRatio @@ -81,7 +81,7 @@ AbstractButton { width: parent.width implicitHeight: imgcaption.implicitHeight anchors.bottom: overlay.bottom - color: Nheko.colors.window + color: timelineRoot.palette.window opacity: 0.75 } @@ -94,7 +94,7 @@ AbstractButton { verticalAlignment: Text.AlignVCenter // See this MSC: https://github.com/matrix-org/matrix-doc/pull/2530 text: filename ? filename : body - color: Nheko.colors.text + color: timelineRoot.palette.text } } diff --git a/resources/qml/delegates/MessageDelegate.qml b/resources/qml/delegates/MessageDelegate.qml index 44da16bf..b91223be 100644 --- a/resources/qml/delegates/MessageDelegate.qml +++ b/resources/qml/delegates/MessageDelegate.qml @@ -92,7 +92,7 @@ Item { NoticeMessage { formatted: TimelineManager.escapeEmoji(d.userName) + " " + d.formattedBody - color: TimelineManager.userColor(d.userId, Nheko.colors.base) + color: TimelineManager.userColor(d.userId, timelineRoot.palette.base) body: d.body isOnlyEmoji: d.isOnlyEmoji isReply: d.isReply @@ -446,7 +446,7 @@ Item { roleValue: MtxEvent.Member ColumnLayout { - width: parent.width + width: parent?.width NoticeMessage { body: formatted @@ -459,7 +459,7 @@ Item { Button { visible: d.relatedEventCacheBuster, room.showAcceptKnockButton(d.eventId) - palette: Nheko.colors + palette: timelineRoot.palette text: qsTr("Allow them in") onClicked: room.acceptKnock(eventId) } diff --git a/resources/qml/delegates/NoticeMessage.qml b/resources/qml/delegates/NoticeMessage.qml index 342469db..8736c081 100644 --- a/resources/qml/delegates/NoticeMessage.qml +++ b/resources/qml/delegates/NoticeMessage.qml @@ -10,7 +10,7 @@ import im.nheko 1.0 TextMessage { property bool isStateEvent font.italic: true - color: Nheko.colors.buttonText + color: timelineRoot.palette.buttonText font.pointSize: isStateEvent? 0.8*Settings.fontSize : Settings.fontSize horizontalAlignment: isStateEvent? Text.AlignHCenter : undefined } diff --git a/resources/qml/delegates/Pill.qml b/resources/qml/delegates/Pill.qml index 8b67c346..87a848c2 100644 --- a/resources/qml/delegates/Pill.qml +++ b/resources/qml/delegates/Pill.qml @@ -9,14 +9,14 @@ import im.nheko 1.0 Label { property bool isStateEvent - color: Nheko.colors.text + color: timelineRoot.palette.text horizontalAlignment: Text.AlignHCenter height: Math.round(fontMetrics.height * 1.4) width: contentWidth * 1.2 background: Rectangle { radius: parent.height / 2 - color: Nheko.colors.alternateBase + color: timelineRoot.palette.alternateBase } } diff --git a/resources/qml/delegates/Placeholder.qml b/resources/qml/delegates/Placeholder.qml index f63e62f5..fc5e8d1f 100644 --- a/resources/qml/delegates/Placeholder.qml +++ b/resources/qml/delegates/Placeholder.qml @@ -11,5 +11,5 @@ MatrixText { text: qsTr("unimplemented event: ") + typeString // width: parent.width - color: Nheko.inactiveColors.text + color: timelineRoot.palette.inactive.text } diff --git a/resources/qml/delegates/PlayableMediaMessage.qml b/resources/qml/delegates/PlayableMediaMessage.qml index 5cb52f60..edd78d4b 100644 --- a/resources/qml/delegates/PlayableMediaMessage.qml +++ b/resources/qml/delegates/PlayableMediaMessage.qml @@ -48,7 +48,7 @@ Item { Rectangle { id: videoContainer - color: type == MtxEvent.VideoMessage ? Nheko.colors.window : "transparent" + color: type == MtxEvent.VideoMessage ? timelineRoot.palette.window : "transparent" width: parent.width height: parent.height - fileInfoLabel.height @@ -101,10 +101,10 @@ Item { text: body + " [" + filesize + "]" textFormat: Text.RichText elide: Text.ElideRight - color: Nheko.colors.text + color: timelineRoot.palette.text background: Rectangle { - color: Nheko.colors.base + color: timelineRoot.palette.base } } diff --git a/resources/qml/delegates/Redacted.qml b/resources/qml/delegates/Redacted.qml index dcdb7248..fb881828 100644 --- a/resources/qml/delegates/Redacted.qml +++ b/resources/qml/delegates/Redacted.qml @@ -14,7 +14,7 @@ Rectangle{ implicitWidth: redactedLayout.implicitWidth + 2 * Nheko.paddingMedium width: Math.min(parent.width,implicitWidth+1) radius: fontMetrics.lineSpacing / 2 + 2 * Nheko.paddingSmall - color: Nheko.colors.alternateBase + color: timelineRoot.palette.alternateBase property int metadataWidth property bool fitsMetadata: parent.width - redactedLayout.width > metadataWidth + 4 @@ -29,7 +29,7 @@ Rectangle{ Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter Layout.preferredWidth: fontMetrics.font.pixelSize Layout.preferredHeight: fontMetrics.font.pixelSize - source: "image://colorimage/:/icons/icons/ui/delete.svg?" + Nheko.colors.text + source: "image://colorimage/:/icons/icons/ui/delete.svg?" + timelineRoot.palette.text } Label { id: redactedLabel @@ -40,7 +40,7 @@ Rectangle{ property var redactedPair: room.formatRedactedEvent(eventId) text: redactedPair["first"] wrapMode: Label.WordWrap - color: Nheko.colors.text + color: timelineRoot.palette.text ToolTip.text: redactedPair["second"] ToolTip.visible: hh.hovered diff --git a/resources/qml/delegates/Reply.qml b/resources/qml/delegates/Reply.qml index 87eb371a..55607952 100644 --- a/resources/qml/delegates/Reply.qml +++ b/resources/qml/delegates/Reply.qml @@ -54,7 +54,7 @@ AbstractButton { anchors.top: replyContainer.top anchors.bottom: replyContainer.bottom width: 4 - color: TimelineManager.userColor(userId, Nheko.colors.base) + color: TimelineManager.userColor(userId, timelineRoot.palette.base) } onClicked: { @@ -134,8 +134,8 @@ AbstractButton { z: -1 anchors.fill: replyContainer - property color userColor: TimelineManager.userColor(userId, Nheko.colors.base) - property color bgColor: Nheko.colors.base + property color userColor: TimelineManager.userColor(userId, timelineRoot.palette.base) + property color bgColor: timelineRoot.palette.base color: Qt.tint(bgColor, Qt.hsla(userColor.hslHue, 0.5, userColor.hslLightness, 0.1)) } diff --git a/resources/qml/delegates/TextMessage.qml b/resources/qml/delegates/TextMessage.qml index 6031093e..9c8ba791 100644 --- a/resources/qml/delegates/TextMessage.qml +++ b/resources/qml/delegates/TextMessage.qml @@ -19,8 +19,8 @@ MatrixText { // table border-collapse doesn't seem to work text: " - " + formatted.replace(/
/g, "
").replace(//g, "").replace(/<\/del>/g, "").replace(//g, "").replace(/<\/strike>/g, "")
-    width: parent.width
+    " + formatted.replace(/
/g, "
").replace(//g, "").replace(/<\/del>/g, "").replace(//g, "").replace(/<\/strike>/g, "")
+    width: parent?.width
     height: isReply ? Math.round(Math.min(timelineView.height / 8, implicitHeight)) : implicitHeight
     clip: isReply
     selectByMouse: !Settings.mobileMode && !isReply
diff --git a/resources/qml/device-verification/DeviceVerification.qml b/resources/qml/device-verification/DeviceVerification.qml
index 90dc9ac4..1ba50cd7 100644
--- a/resources/qml/device-verification/DeviceVerification.qml
+++ b/resources/qml/device-verification/DeviceVerification.qml
@@ -16,8 +16,8 @@ ApplicationWindow {
     onClosing: VerificationManager.removeVerificationFlow(flow)
     title: stack.currentItem.title_
     modality: Qt.NonModal
-    palette: Nheko.colors
-    color: Nheko.colors.window
+    palette: timelineRoot.palette
+    color: timelineRoot.palette.window
     minimumHeight: stack.implicitHeight
     width: stack.implicitWidth
     flags: Qt.Dialog | Qt.WindowCloseButtonHint | Qt.WindowTitleHint
diff --git a/resources/qml/device-verification/DigitVerification.qml b/resources/qml/device-verification/DigitVerification.qml
index 3a8b0df5..8c12a84b 100644
--- a/resources/qml/device-verification/DigitVerification.qml
+++ b/resources/qml/device-verification/DigitVerification.qml
@@ -11,7 +11,7 @@ import im.nheko 1.0
 Pane {
     property string title: qsTr("Verification Code")
     background: Rectangle {
-        color: Nheko.colors.window
+        color: timelineRoot.palette.window
     }
 
     ColumnLayout {
@@ -23,7 +23,7 @@ Pane {
             Layout.fillWidth: true
             wrapMode: Text.Wrap
             text: qsTr("Please verify the following digits. You should see the same numbers on both sides. If they differ, please press 'They do not match!' to abort verification!")
-            color: Nheko.colors.text
+            color: timelineRoot.palette.text
             verticalAlignment: Text.AlignVCenter
         }
 
@@ -34,19 +34,19 @@ Pane {
             Label {
                 font.pixelSize: Qt.application.font.pixelSize * 2
                 text: flow.sasList[0]
-                color: Nheko.colors.text
+                color: timelineRoot.palette.text
             }
 
             Label {
                 font.pixelSize: Qt.application.font.pixelSize * 2
                 text: flow.sasList[1]
-                color: Nheko.colors.text
+                color: timelineRoot.palette.text
             }
 
             Label {
                 font.pixelSize: Qt.application.font.pixelSize * 2
                 text: flow.sasList[2]
-                color: Nheko.colors.text
+                color: timelineRoot.palette.text
             }
 
         }
diff --git a/resources/qml/device-verification/EmojiVerification.qml b/resources/qml/device-verification/EmojiVerification.qml
index 4c5bfb1a..cbb4fd30 100644
--- a/resources/qml/device-verification/EmojiVerification.qml
+++ b/resources/qml/device-verification/EmojiVerification.qml
@@ -11,7 +11,7 @@ import im.nheko 1.0
 Pane {
     property string title: qsTr("Verification Code")
     background: Rectangle {
-        color: Nheko.colors.window
+        color: timelineRoot.palette.window
     }
 
     ColumnLayout {
@@ -23,7 +23,7 @@ Pane {
             Layout.fillWidth: true
             wrapMode: Text.Wrap
             text: qsTr("Please verify the following emoji. You should see the same emoji on both sides. If they differ, please press 'They do not match!' to abort verification!")
-            color: Nheko.colors.text
+            color: timelineRoot.palette.text
             verticalAlignment: Text.AlignVCenter
         }
 
@@ -379,13 +379,13 @@ Pane {
                             text: col.emoji.emoji
                             font.pixelSize: Qt.application.font.pixelSize * 2
                             font.family: Settings.emojiFont
-                            color: Nheko.colors.text
+                            color: timelineRoot.palette.text
                         }
 
                         Label {
                             Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
                             text: col.emoji.description
-                            color: Nheko.colors.text
+                            color: timelineRoot.palette.text
                         }
 
                     }
diff --git a/resources/qml/device-verification/Failed.qml b/resources/qml/device-verification/Failed.qml
index d070b5a6..d640ab35 100644
--- a/resources/qml/device-verification/Failed.qml
+++ b/resources/qml/device-verification/Failed.qml
@@ -11,7 +11,7 @@ import im.nheko 1.0
 Pane {
     property string title: qsTr("Verification failed")
     background: Rectangle {
-        color: Nheko.colors.window
+        color: timelineRoot.palette.window
     }
 
     ColumnLayout {
@@ -42,7 +42,7 @@ Pane {
                     return qsTr("Unknown verification error.");
                 }
             }
-            color: Nheko.colors.text
+            color: timelineRoot.palette.text
             verticalAlignment: Text.AlignVCenter
         }
 
diff --git a/resources/qml/device-verification/NewVerificationRequest.qml b/resources/qml/device-verification/NewVerificationRequest.qml
index b7ed9586..46016d61 100644
--- a/resources/qml/device-verification/NewVerificationRequest.qml
+++ b/resources/qml/device-verification/NewVerificationRequest.qml
@@ -11,7 +11,7 @@ import im.nheko 1.0
 Pane {
     property string title: flow.sender ? qsTr("Send Verification Request") : qsTr("Received Verification Request")
     background: Rectangle {
-        color: Nheko.colors.window
+        color: timelineRoot.palette.window
     }
 
     ColumnLayout {
@@ -42,7 +42,7 @@ Pane {
                         return qsTr("Your device (%1) has requested to be verified.").arg(flow.deviceId);
                 }
             }
-            color: Nheko.colors.text
+            color: timelineRoot.palette.text
             verticalAlignment: Text.AlignVCenter
         }
 
diff --git a/resources/qml/device-verification/Success.qml b/resources/qml/device-verification/Success.qml
index 8d7c8419..2df1ebf6 100644
--- a/resources/qml/device-verification/Success.qml
+++ b/resources/qml/device-verification/Success.qml
@@ -11,7 +11,7 @@ import im.nheko 1.0
 Pane {
     property string title: qsTr("Successful Verification")
     background: Rectangle {
-        color: Nheko.colors.window
+        color: timelineRoot.palette.window
     }
 
     ColumnLayout {
@@ -25,7 +25,7 @@ Pane {
             Layout.fillWidth: true
             wrapMode: Text.Wrap
             text: qsTr("Verification successful! Both sides verified their devices!")
-            color: Nheko.colors.text
+            color: timelineRoot.palette.text
             verticalAlignment: Text.AlignVCenter
         }
 
diff --git a/resources/qml/device-verification/Waiting.qml b/resources/qml/device-verification/Waiting.qml
index e75a97ce..0f44bd65 100644
--- a/resources/qml/device-verification/Waiting.qml
+++ b/resources/qml/device-verification/Waiting.qml
@@ -12,7 +12,7 @@ import im.nheko 1.0
 Pane {
     property string title: qsTr("Waiting for other party…")
     background: Rectangle {
-        color: Nheko.colors.window
+        color: timelineRoot.palette.window
     }
 
     ColumnLayout {
@@ -35,14 +35,14 @@ Pane {
                     return qsTr("Waiting for other side to complete the verification process.");
                 }
             }
-            color: Nheko.colors.text
+            color: timelineRoot.palette.text
             verticalAlignment: Text.AlignVCenter
         }
 
         Item { Layout.fillHeight: true; }
         Spinner {
             Layout.alignment: Qt.AlignHCenter
-            foreground: Nheko.colors.mid
+            foreground: timelineRoot.palette.mid
         }
         Item { Layout.fillHeight: true; }
 
diff --git a/resources/qml/dialogs/CreateDirect.qml b/resources/qml/dialogs/CreateDirect.qml
index 85768cad..72ea2f55 100644
--- a/resources/qml/dialogs/CreateDirect.qml
+++ b/resources/qml/dialogs/CreateDirect.qml
@@ -56,14 +56,14 @@ ApplicationWindow {
             Label {
                 Layout.fillWidth: true
                 text: profile? profile.displayName : ""
-                color: TimelineManager.userColor(userID.text, Nheko.colors.window)
+                color: TimelineManager.userColor(userID.text, timelineRoot.palette.window)
                 font.pointSize: fontMetrics.font.pointSize
             }
 
             Label {
                 Layout.fillWidth: true
                 text: userID.text
-                color: Nheko.colors.buttonText
+                color: timelineRoot.palette.buttonText
                 font.pointSize: fontMetrics.font.pointSize * 0.9
             }
         }
@@ -89,7 +89,7 @@ ApplicationWindow {
                 Layout.fillWidth: true
                 Layout.alignment: Qt.AlignLeft
                 text: qsTr("Encryption")
-                color: Nheko.colors.text
+                color: timelineRoot.palette.text
             }
             ToggleButton {
                 Layout.alignment: Qt.AlignRight
diff --git a/resources/qml/dialogs/CreateRoom.qml b/resources/qml/dialogs/CreateRoom.qml
index 5d224885..15cf94a8 100644
--- a/resources/qml/dialogs/CreateRoom.qml
+++ b/resources/qml/dialogs/CreateRoom.qml
@@ -62,7 +62,7 @@ ApplicationWindow {
             Label {
                 Layout.preferredWidth: implicitWidth
                 text: qsTr("#")
-                color: Nheko.colors.text
+                color: timelineRoot.palette.text
             }
             MatrixTextField {
                 id: newRoomAlias
@@ -73,14 +73,14 @@ ApplicationWindow {
                 Layout.preferredWidth: implicitWidth
                 property string userName: userInfoGrid.profile.userid
                 text: userName.substring(userName.indexOf(":"))
-                color: Nheko.colors.text
+                color: timelineRoot.palette.text
             }
         }
         Label {
             Layout.preferredWidth: implicitWidth
             Layout.alignment: Qt.AlignLeft
             text: qsTr("Public")
-            color: Nheko.colors.text
+            color: timelineRoot.palette.text
             HoverHandler {
                 id: privateHover
             }
@@ -98,7 +98,7 @@ ApplicationWindow {
             Layout.preferredWidth: implicitWidth
             Layout.alignment: Qt.AlignLeft
             text: qsTr("Trusted")
-            color: Nheko.colors.text
+            color: timelineRoot.palette.text
             HoverHandler {
                 id: trustedHover
             }
@@ -117,7 +117,7 @@ ApplicationWindow {
             Layout.preferredWidth: implicitWidth
             Layout.alignment: Qt.AlignLeft
             text: qsTr("Encryption")
-            color: Nheko.colors.text
+            color: timelineRoot.palette.text
             HoverHandler {
                 id: encryptionHover
             }
diff --git a/resources/qml/dialogs/ImagePackEditorDialog.qml b/resources/qml/dialogs/ImagePackEditorDialog.qml
index 891d9c3d..93169234 100644
--- a/resources/qml/dialogs/ImagePackEditorDialog.qml
+++ b/resources/qml/dialogs/ImagePackEditorDialog.qml
@@ -23,8 +23,8 @@ ApplicationWindow {
     title: qsTr("Editing image pack")
     height: 600
     width: 600
-    palette: Nheko.colors
-    color: Nheko.colors.base
+    palette: timelineRoot.palette
+    color: timelineRoot.palette.base
     modality: Qt.WindowModal
     flags: Qt.Dialog | Qt.WindowCloseButtonHint | Qt.WindowTitleHint
 
@@ -51,11 +51,6 @@ ApplicationWindow {
 
                 model: imagePack
 
-                ScrollHelper {
-                    flickable: parent
-                    anchors.fill: parent
-                    enabled: !Settings.mobileMode
-                }
 
                 header: AvatarListTile {
                     title: imagePack.packname
@@ -74,13 +69,13 @@ ApplicationWindow {
                         anchors.verticalCenter: parent.verticalCenter
                         height: parent.height - Nheko.paddingSmall * 2
                         width: 3
-                        color: Nheko.colors.highlight
+                        color: timelineRoot.palette.highlight
                     }
 
                 }
 
                 footer: Button {
-                    palette: Nheko.colors
+                    palette: timelineRoot.palette
                     onClicked: addFilesDialog.open()
                     width: ListView.view.width
                     text: qsTr("Add images")
@@ -101,11 +96,11 @@ ApplicationWindow {
                 delegate: AvatarListTile {
                     id: packItem
 
-                    property color background: Nheko.colors.window
-                    property color importantText: Nheko.colors.text
-                    property color unimportantText: Nheko.colors.buttonText
-                    property color bubbleBackground: Nheko.colors.highlight
-                    property color bubbleText: Nheko.colors.highlightedText
+                    property color background: timelineRoot.palette.window
+                    property color importantText: timelineRoot.palette.text
+                    property color unimportantText: timelineRoot.palette.buttonText
+                    property color bubbleBackground: timelineRoot.palette.highlight
+                    property color bubbleText: timelineRoot.palette.highlightedText
                     required property string shortCode
                     required property string url
                     required property string body
@@ -130,7 +125,7 @@ ApplicationWindow {
             id: packinfoC
 
             Rectangle {
-                color: Nheko.colors.window
+                color: timelineRoot.palette.window
 
                 GridLayout {
                     anchors.fill: parent
diff --git a/resources/qml/dialogs/ImagePackSettingsDialog.qml b/resources/qml/dialogs/ImagePackSettingsDialog.qml
index 24f70f68..776cd4d5 100644
--- a/resources/qml/dialogs/ImagePackSettingsDialog.qml
+++ b/resources/qml/dialogs/ImagePackSettingsDialog.qml
@@ -24,8 +24,8 @@ ApplicationWindow {
     title: qsTr("Image pack settings")
     height: 600
     width: 800
-    palette: Nheko.colors
-    color: Nheko.colors.base
+    palette: timelineRoot.palette
+    color: timelineRoot.palette.base
     modality: Qt.NonModal
     flags: Qt.Dialog | Qt.WindowCloseButtonHint | Qt.WindowTitleHint
 
@@ -57,15 +57,10 @@ ApplicationWindow {
                 model: packlist
                 clip: true
 
-                ScrollHelper {
-                    flickable: parent
-                    anchors.fill: parent
-                    enabled: !Settings.mobileMode
-                }
 
                 footer: ColumnLayout {
                     Button {
-                        palette: Nheko.colors
+                        palette: timelineRoot.palette
                         onClicked: {
                             var dialog = packEditor.createObject(timelineRoot, {
                                 "imagePack": packlist.newPack(false)
@@ -79,7 +74,7 @@ ApplicationWindow {
                     }
 
                     Button {
-                        palette: Nheko.colors
+                        palette: timelineRoot.palette
                         onClicked: {
                             var dialog = packEditor.createObject(timelineRoot, {
                                 "imagePack": packlist.newPack(true)
@@ -97,11 +92,11 @@ ApplicationWindow {
                 delegate: AvatarListTile {
                     id: packItem
 
-                    property color background: Nheko.colors.window
-                    property color importantText: Nheko.colors.text
-                    property color unimportantText: Nheko.colors.buttonText
-                    property color bubbleBackground: Nheko.colors.highlight
-                    property color bubbleText: Nheko.colors.highlightedText
+                    property color background: timelineRoot.palette.window
+                    property color importantText: timelineRoot.palette.text
+                    property color unimportantText: timelineRoot.palette.buttonText
+                    property color bubbleBackground: timelineRoot.palette.highlight
+                    property color bubbleText: timelineRoot.palette.highlightedText
                     required property string displayName
                     required property bool fromAccountData
                     required property bool fromCurrentRoom
@@ -133,7 +128,7 @@ ApplicationWindow {
             id: packinfoC
 
             Rectangle {
-                color: Nheko.colors.window
+                color: timelineRoot.palette.window
 
                 ColumnLayout {
                     id: packinfo
@@ -216,11 +211,6 @@ ApplicationWindow {
                         currentIndex: -1 // prevent sorting from stealing focus
                         cacheBuffer: 500
 
-                        ScrollHelper {
-                            flickable: parent
-                            anchors.fill: parent
-                            enabled: !Settings.mobileMode
-                        }
 
                         // Individual emoji
                         delegate: AbstractButton {
@@ -239,7 +229,7 @@ ApplicationWindow {
 
                             background: Rectangle {
                                 anchors.fill: parent
-                                color: hovered ? Nheko.colors.highlight : 'transparent'
+                                color: hovered ? timelineRoot.palette.highlight : 'transparent'
                                 radius: 5
                             }
 
diff --git a/resources/qml/dialogs/InputDialog.qml b/resources/qml/dialogs/InputDialog.qml
index a674c3fb..421d85bc 100644
--- a/resources/qml/dialogs/InputDialog.qml
+++ b/resources/qml/dialogs/InputDialog.qml
@@ -38,7 +38,7 @@ ApplicationWindow {
         Label {
             id: promptLabel
 
-            color: Nheko.colors.text
+            color: timelineRoot.palette.text
         }
 
         MatrixTextField {
diff --git a/resources/qml/dialogs/InviteDialog.qml b/resources/qml/dialogs/InviteDialog.qml
index e7dd4e3a..0ee00769 100644
--- a/resources/qml/dialogs/InviteDialog.qml
+++ b/resources/qml/dialogs/InviteDialog.qml
@@ -34,8 +34,8 @@ ApplicationWindow {
     title: qsTr("Invite users to %1").arg(plainRoomName)
     height: 380
     width: 340
-    palette: Nheko.colors
-    color: Nheko.colors.window
+    palette: timelineRoot.palette
+    color: timelineRoot.palette.window
     flags: Qt.Dialog | Qt.WindowCloseButtonHint | Qt.WindowTitleHint
 
     Shortcut {
@@ -56,7 +56,7 @@ ApplicationWindow {
         Label {
             text: qsTr("User ID to invite")
             Layout.fillWidth: true
-            color: Nheko.colors.text
+            color: timelineRoot.palette.text
         }
 
         RowLayout {
@@ -67,7 +67,7 @@ ApplicationWindow {
 
                 property bool isValidMxid: text.match("@.+?:.{3,}")
 
-                backgroundColor: Nheko.colors.window
+                backgroundColor: timelineRoot.palette.window
                 placeholderText: qsTr("@joe:matrix.org", "Example user id. The name 'joe' can be localized however you want.")
                 Layout.fillWidth: true
                 onAccepted: {
@@ -107,7 +107,7 @@ ApplicationWindow {
                 height: layout.implicitHeight + Nheko.paddingSmall * 2
                 onClicked: TimelineManager.openGlobalUserProfile(model.mxid)
                 background: Rectangle {
-                    color: del.hovered ? Nheko.colors.dark : inviteDialogRoot.color
+                    color: del.hovered ? timelineRoot.palette.dark : inviteDialogRoot.color
                 }
 
                 RowLayout {
@@ -137,7 +137,7 @@ ApplicationWindow {
 
                         Label {
                             text: model.mxid
-                            color: del.hovered ? Nheko.colors.brightText : Nheko.colors.buttonText
+                            color: del.hovered ? timelineRoot.palette.brightText : timelineRoot.palette.buttonText
                             font.pointSize: fontMetrics.font.pointSize * 0.9
                         }
 
diff --git a/resources/qml/dialogs/JoinRoomDialog.qml b/resources/qml/dialogs/JoinRoomDialog.qml
index 263481aa..d8e6bfd3 100644
--- a/resources/qml/dialogs/JoinRoomDialog.qml
+++ b/resources/qml/dialogs/JoinRoomDialog.qml
@@ -15,8 +15,8 @@ ApplicationWindow {
     title: qsTr("Join room")
     modality: Qt.WindowModal
     flags: Qt.Dialog | Qt.WindowCloseButtonHint | Qt.WindowTitleHint
-    palette: Nheko.colors
-    color: Nheko.colors.window
+    palette: timelineRoot.palette
+    color: timelineRoot.palette.window
     width: 350
     height: fontMetrics.lineSpacing * 7
 
@@ -34,7 +34,7 @@ ApplicationWindow {
             id: promptLabel
 
             text: qsTr("Room ID or alias")
-            color: Nheko.colors.text
+            color: timelineRoot.palette.text
         }
 
         MatrixTextField {
diff --git a/resources/qml/dialogs/PhoneNumberInputDialog.qml b/resources/qml/dialogs/PhoneNumberInputDialog.qml
index 9c36c98f..882014ee 100644
--- a/resources/qml/dialogs/PhoneNumberInputDialog.qml
+++ b/resources/qml/dialogs/PhoneNumberInputDialog.qml
@@ -33,7 +33,7 @@ ApplicationWindow {
             id: promptLabel
 
             Layout.columnSpan: 2
-            color: Nheko.colors.text
+            color: timelineRoot.palette.text
         }
 
         ComboBox {
diff --git a/resources/qml/dialogs/RawMessageDialog.qml b/resources/qml/dialogs/RawMessageDialog.qml
index 774b078b..8ee7d32e 100644
--- a/resources/qml/dialogs/RawMessageDialog.qml
+++ b/resources/qml/dialogs/RawMessageDialog.qml
@@ -14,8 +14,8 @@ ApplicationWindow {
 
     height: 420
     width: 420
-    palette: Nheko.colors
-    color: Nheko.colors.window
+    palette: timelineRoot.palette
+    color: timelineRoot.palette.window
     flags: Qt.Tool | Qt.WindowStaysOnTopHint | Qt.WindowCloseButtonHint | Qt.WindowTitleHint
 
     Shortcut {
@@ -26,21 +26,21 @@ ApplicationWindow {
     ScrollView {
         anchors.margins: Nheko.paddingMedium
         anchors.fill: parent
-        palette: Nheko.colors
+        palette: timelineRoot.palette
         padding: Nheko.paddingMedium
 
         TextArea {
             id: rawMessageView
 
             font: Nheko.monospaceFont()
-            color: Nheko.colors.text
+            color: timelineRoot.palette.text
             readOnly: true
             textFormat: Text.PlainText
 
             anchors.fill: parent
 
             background: Rectangle {
-                color: Nheko.colors.base
+                color: timelineRoot.palette.base
             }
 
         }
diff --git a/resources/qml/dialogs/ReadReceipts.qml b/resources/qml/dialogs/ReadReceipts.qml
index da87996e..60eb256d 100644
--- a/resources/qml/dialogs/ReadReceipts.qml
+++ b/resources/qml/dialogs/ReadReceipts.qml
@@ -19,8 +19,8 @@ ApplicationWindow {
     width: 340
     minimumHeight: 380
     minimumWidth: headerTitle.width + 2 * Nheko.paddingMedium
-    palette: Nheko.colors
-    color: Nheko.colors.window
+    palette: timelineRoot.palette
+    color: timelineRoot.palette.window
     flags: Qt.Dialog | Qt.WindowCloseButtonHint | Qt.WindowTitleHint
 
     Shortcut {
@@ -36,14 +36,14 @@ ApplicationWindow {
         Label {
             id: headerTitle
 
-            color: Nheko.colors.text
+            color: timelineRoot.palette.text
             Layout.alignment: Qt.AlignCenter
             text: qsTr("Read receipts")
             font.pointSize: fontMetrics.font.pointSize * 1.5
         }
 
         ScrollView {
-            palette: Nheko.colors
+            palette: timelineRoot.palette
             padding: Nheko.paddingMedium
             ScrollBar.horizontal.visible: false
             Layout.fillHeight: true
@@ -68,7 +68,7 @@ ApplicationWindow {
                     ToolTip.visible: hovered
                     ToolTip.text: model.mxid
                     background: Rectangle {
-                        color: del.hovered ? Nheko.colors.dark : readReceiptsRoot.color
+                        color: del.hovered ? timelineRoot.palette.dark : readReceiptsRoot.color
                     }
 
                     RowLayout {
@@ -92,13 +92,13 @@ ApplicationWindow {
 
                             Label {
                                 text: model.displayName
-                                color: TimelineManager.userColor(model ? model.mxid : "", Nheko.colors.window)
+                                color: TimelineManager.userColor(model ? model.mxid : "", timelineRoot.palette.window)
                                 font.pointSize: fontMetrics.font.pointSize
                             }
 
                             Label {
                                 text: model.timestamp
-                                color: Nheko.colors.buttonText
+                                color: timelineRoot.palette.buttonText
                                 font.pointSize: fontMetrics.font.pointSize * 0.9
                             }
 
diff --git a/resources/qml/dialogs/RoomDirectory.qml b/resources/qml/dialogs/RoomDirectory.qml
index 90475eea..e8eebeef 100644
--- a/resources/qml/dialogs/RoomDirectory.qml
+++ b/resources/qml/dialogs/RoomDirectory.qml
@@ -20,8 +20,8 @@ ApplicationWindow {
     minimumHeight: 340
     height: 420
     width: 650
-    palette: Nheko.colors
-    color: Nheko.colors.window
+    palette: timelineRoot.palette
+    color: timelineRoot.palette.window
     modality: Qt.WindowModal
     flags: Qt.Dialog | Qt.WindowCloseButtonHint | Qt.WindowTitleHint
     title: qsTr("Explore Public Rooms")
@@ -37,17 +37,12 @@ ApplicationWindow {
         anchors.fill: parent
         model: publicRooms
 
-        ScrollHelper {
-            flickable: parent
-            anchors.fill: parent
-        }
-
         delegate: Rectangle {
             id: roomDirDelegate
 
-            property color background: Nheko.colors.window
-            property color importantText: Nheko.colors.text
-            property color unimportantText: Nheko.colors.buttonText
+            property color background: timelineRoot.palette.window
+            property color importantText: timelineRoot.palette.text
+            property color unimportantText: timelineRoot.palette.buttonText
             property int avatarSize: fontMetrics.height * 3.2
 
             color: background
@@ -145,7 +140,7 @@ ApplicationWindow {
                 anchors.centerIn: parent
                 anchors.margins: Nheko.paddingLarge
                 running: visible
-                foreground: Nheko.colors.mid
+                foreground: timelineRoot.palette.mid
             }
 
         }
@@ -169,7 +164,7 @@ ApplicationWindow {
             Layout.fillWidth: true
             selectByMouse: true
             font.pixelSize: fontMetrics.font.pixelSize
-            color: Nheko.colors.text
+            color: timelineRoot.palette.text
             placeholderText: qsTr("Search for public rooms")
             onTextChanged: searchTimer.restart()
 
@@ -181,7 +176,7 @@ ApplicationWindow {
 
             Layout.minimumWidth: 0.3 * header.width
             Layout.maximumWidth: 0.3 * header.width
-            color: Nheko.colors.text
+            color: timelineRoot.palette.text
             placeholderText: qsTr("Choose custom homeserver")
             onTextChanged: publicRooms.setMatrixServer(text)
         }
diff --git a/resources/qml/dialogs/RoomMembers.qml b/resources/qml/dialogs/RoomMembers.qml
index 8a12e5bc..823868bb 100644
--- a/resources/qml/dialogs/RoomMembers.qml
+++ b/resources/qml/dialogs/RoomMembers.qml
@@ -21,8 +21,8 @@ ApplicationWindow {
     height: 650
     width: 420
     minimumHeight: 420
-    palette: Nheko.colors
-    color: Nheko.colors.window
+    palette: timelineRoot.palette
+    color: timelineRoot.palette.window
     flags: Qt.Dialog | Qt.WindowCloseButtonHint | Qt.WindowTitleHint
 
     Shortcut {
@@ -95,7 +95,7 @@ ApplicationWindow {
         }
 
         ScrollView {
-            palette: Nheko.colors
+            palette: timelineRoot.palette
             padding: Nheko.paddingMedium
             ScrollBar.horizontal.visible: false
             Layout.fillHeight: true
@@ -109,11 +109,6 @@ ApplicationWindow {
                 boundsBehavior: Flickable.StopAtBounds
                 model: members
 
-                ScrollHelper {
-                    flickable: parent
-                    anchors.fill: parent
-                    enabled: !Settings.mobileMode
-                }
 
                 delegate: ItemDelegate {
                     id: del
@@ -124,7 +119,7 @@ ApplicationWindow {
                     height: memberLayout.implicitHeight + Nheko.paddingSmall * 2
                     hoverEnabled: true
                     background: Rectangle {
-                        color: del.hovered ? Nheko.colors.dark : roomMembersRoot.color
+                        color: del.hovered ? timelineRoot.palette.dark : roomMembersRoot.color
                     }
 
                     RowLayout {
@@ -157,7 +152,7 @@ ApplicationWindow {
 
                             ElidedLabel {
                                 fullText: model.mxid
-                                color: del.hovered ? Nheko.colors.brightText : Nheko.colors.buttonText
+                                color: del.hovered ? timelineRoot.palette.brightText : timelineRoot.palette.buttonText
                                 font.pixelSize: Math.ceil(fontMetrics.font.pixelSize * 0.9)
                                 elideWidth: del.width - Nheko.paddingMedium * 2 - avatar.width - encryptInd.width
                             }
diff --git a/resources/qml/dialogs/RoomSettings.qml b/resources/qml/dialogs/RoomSettings.qml
index 110475c7..0089796b 100644
--- a/resources/qml/dialogs/RoomSettings.qml
+++ b/resources/qml/dialogs/RoomSettings.qml
@@ -21,8 +21,8 @@ ApplicationWindow {
     minimumHeight: 450
     width: 450
     height: 680
-    palette: Nheko.colors
-    color: Nheko.colors.window
+    palette: timelineRoot.palette
+    color: timelineRoot.palette.window
     modality: Qt.NonModal
     flags: Qt.Dialog | Qt.WindowCloseButtonHint | Qt.WindowTitleHint
     title: qsTr("Room Settings")
@@ -31,10 +31,7 @@ ApplicationWindow {
         sequence: StandardKey.Cancel
         onActivated: roomSettingsDialog.close()
     }
-    ScrollHelper {
-        flickable: flickable
-        anchors.fill: flickable
-    }
+
     Flickable {
         id: flickable
         boundsBehavior: Flickable.StopAtBounds
@@ -66,7 +63,7 @@ ApplicationWindow {
             Spinner {
                 Layout.alignment: Qt.AlignHCenter
                 visible: roomSettings.isLoading
-                foreground: Nheko.colors.mid
+                foreground: timelineRoot.palette.mid
                 running: roomSettings.isLoading
             }
 
@@ -117,7 +114,7 @@ ApplicationWindow {
                 textFormat: isNameEditingAllowed ? TextEdit.PlainText : TextEdit.RichText
                 text: isNameEditingAllowed ? roomSettings.plainRoomName : roomSettings.roomName
                 font.pixelSize: fontMetrics.font.pixelSize * 2
-                color: Nheko.colors.text
+                color: timelineRoot.palette.text
 
                 Layout.alignment: Qt.AlignHCenter
                 Layout.maximumWidth: parent.width - (Nheko.paddingSmall * 2) - nameChangeButton.anchors.leftMargin - (nameChangeButton.width * 2)
@@ -162,7 +159,7 @@ ApplicationWindow {
                 Label {
                     text: qsTr("%n member(s)", "", roomSettings.memberCount)
                     Layout.alignment: Qt.AlignHCenter
-                    color: Nheko.colors.text
+                    color: timelineRoot.palette.text
 
                     TapHandler {
                         onSingleTapped: TimelineManager.openRoomMembers(Rooms.getRoomById(roomSettings.roomId))
@@ -195,7 +192,7 @@ ApplicationWindow {
                 wrapMode: TextEdit.WordWrap
                 background: null
                 selectByMouse: !Settings.mobileMode
-                color: Nheko.colors.text
+                color: timelineRoot.palette.text
                 horizontalAlignment: TextEdit.AlignHCenter
                 onLinkActivated: Nheko.openLink(link)
 
@@ -245,7 +242,7 @@ ApplicationWindow {
                 Label {
                     text: qsTr("SETTINGS")
                     font.bold: true
-                    color: Nheko.colors.text
+                    color: timelineRoot.palette.text
                 }
 
                 Item {
@@ -255,7 +252,7 @@ ApplicationWindow {
                 Label {
                     text: qsTr("Notifications")
                     Layout.fillWidth: true
-                    color: Nheko.colors.text
+                    color: timelineRoot.palette.text
                 }
 
                 ComboBox {
@@ -271,7 +268,7 @@ ApplicationWindow {
                 Label {
                     text: qsTr("Room access")
                     Layout.fillWidth: true
-                    color: Nheko.colors.text
+                    color: timelineRoot.palette.text
                 }
 
                 ComboBox {
@@ -296,7 +293,7 @@ ApplicationWindow {
 
                 Label {
                     text: qsTr("Encryption")
-                    color: Nheko.colors.text
+                    color: timelineRoot.palette.text
                 }
 
                 ToggleButton {
@@ -334,7 +331,7 @@ ApplicationWindow {
 
                 Label {
                     text: qsTr("Sticker & Emote Settings")
-                    color: Nheko.colors.text
+                    color: timelineRoot.palette.text
                 }
 
                 Button {
@@ -346,7 +343,7 @@ ApplicationWindow {
 
                 Label {
                     text: qsTr("Hidden events")
-                    color: Nheko.colors.text
+                    color: timelineRoot.palette.text
                 }
 
                 HiddenEventsDialog {
@@ -375,7 +372,7 @@ ApplicationWindow {
                 Label {
                     text: qsTr("INFO")
                     font.bold: true
-                    color: Nheko.colors.text
+                    color: timelineRoot.palette.text
                 }
 
                 Item {
@@ -384,7 +381,7 @@ ApplicationWindow {
 
                 Label {
                     text: qsTr("Internal ID")
-                    color: Nheko.colors.text
+                    color: timelineRoot.palette.text
                 }
 
                 AbstractButton { // AbstractButton does not allow setting text color
@@ -395,7 +392,7 @@ ApplicationWindow {
                         id: idLabel
                         text: roomSettings.roomId
                         font.pixelSize: Math.floor(fontMetrics.font.pixelSize * 0.8)
-                        color: Nheko.colors.text
+                        color: timelineRoot.palette.text
                         width: parent.width
                         horizontalAlignment: Text.AlignRight
                         wrapMode: Text.WrapAnywhere
@@ -419,14 +416,14 @@ ApplicationWindow {
 
                 Label {
                     text: qsTr("Room Version")
-                    color: Nheko.colors.text
+                    color: timelineRoot.palette.text
                 }
 
                 Label {
                     text: roomSettings.roomVersion
                     font.pixelSize: fontMetrics.font.pixelSize
                     Layout.alignment: Qt.AlignRight
-                    color: Nheko.colors.text
+                    color: timelineRoot.palette.text
                 }
 
             }
diff --git a/resources/qml/dialogs/UserProfile.qml b/resources/qml/dialogs/UserProfile.qml
index 60f1eb8d..46fe48f7 100644
--- a/resources/qml/dialogs/UserProfile.qml
+++ b/resources/qml/dialogs/UserProfile.qml
@@ -21,8 +21,8 @@ ApplicationWindow {
     width: 420
     minimumWidth: 150
     minimumHeight: 150
-    palette: Nheko.colors
-    color: Nheko.colors.window
+    palette: timelineRoot.palette
+    color: timelineRoot.palette.window
     title: profile.isGlobalUserProfile ? qsTr("Global User Profile") : qsTr("Room User Profile")
     modality: Qt.NonModal
     flags: Qt.Dialog | Qt.WindowCloseButtonHint | Qt.WindowTitleHint
@@ -45,11 +45,6 @@ ApplicationWindow {
         anchors.margins: 10
         footerPositioning: ListView.OverlayFooter
 
-        ScrollHelper {
-            flickable: parent
-            anchors.fill: parent
-            enabled: !Settings.mobileMode
-        }
 
         header: ColumnLayout {
             id: contentL
@@ -87,7 +82,7 @@ ApplicationWindow {
                 Layout.alignment: Qt.AlignHCenter
                 running: profile.isLoading
                 visible: profile.isLoading
-                foreground: Nheko.colors.mid
+                foreground: timelineRoot.palette.mid
             }
 
             Text {
@@ -135,7 +130,7 @@ ApplicationWindow {
                 readOnly: !isUsernameEditingAllowed
                 text: profile.displayName
                 font.pixelSize: 20
-                color: TimelineManager.userColor(profile.userid, Nheko.colors.window)
+                color: TimelineManager.userColor(profile.userid, timelineRoot.palette.window)
                 font.bold: true
                 Layout.alignment: Qt.AlignHCenter
                 Layout.maximumWidth: parent.width - (Nheko.paddingSmall * 2) - usernameChangeButton.anchors.leftMargin - (usernameChangeButton.width * 2)
@@ -300,7 +295,7 @@ ApplicationWindow {
                         Layout.alignment: Qt.AlignLeft
                         elide: Text.ElideRight
                         font.bold: true
-                        color: Nheko.colors.text
+                        color: timelineRoot.palette.text
                         text: deviceId
                     }
 
@@ -346,7 +341,7 @@ ApplicationWindow {
 
                         readOnly: !deviceNameRow.isEditingAllowed
                         text: deviceName
-                        color: Nheko.colors.text
+                        color: timelineRoot.palette.text
                         Layout.alignment: Qt.AlignLeft
                         Layout.fillWidth: true
                         selectByMouse: true
@@ -381,7 +376,7 @@ ApplicationWindow {
                     Layout.fillWidth: true
                     Layout.alignment: Qt.AlignLeft
                     elide: Text.ElideRight
-                    color: Nheko.colors.text
+                    color: timelineRoot.palette.text
                     text: qsTr("Last seen %1 from %2").arg(new Date(lastTs).toLocaleString(Locale.ShortFormat)).arg(lastIp ? lastIp : "???")
                 }
 
@@ -429,7 +424,7 @@ ApplicationWindow {
 
             background: Rectangle {
                 anchors.fill: parent
-                color: Nheko.colors.window
+                color: timelineRoot.palette.window
             }
 
         }
diff --git a/resources/qml/emoji/EmojiPicker.qml b/resources/qml/emoji/EmojiPicker.qml
index d234eda9..fe5c505b 100644
--- a/resources/qml/emoji/EmojiPicker.qml
+++ b/resources/qml/emoji/EmojiPicker.qml
@@ -19,9 +19,9 @@ Menu {
     property alias model: gridView.model
     property var textArea
     property string emojiCategory: "people"
-    property real highlightHue: Nheko.colors.highlight.hslHue
-    property real highlightSat: Nheko.colors.highlight.hslSaturation
-    property real highlightLight: Nheko.colors.highlight.hslLightness
+    property real highlightHue: timelineRoot.palette.highlight.hslHue
+    property real highlightSat: timelineRoot.palette.highlight.hslSaturation
+    property real highlightLight: timelineRoot.palette.highlight.hslLightness
 
     function show(showAt, callback) {
         console.debug("Showing emojiPicker");
@@ -41,7 +41,7 @@ Menu {
     width: 7 * 52 + 20
 
     Rectangle {
-        color: Nheko.colors.window
+        color: timelineRoot.palette.window
         height: columnView.implicitHeight + 4
         width: 7 * 52 + 20
 
@@ -62,10 +62,10 @@ Menu {
 
                 Layout.topMargin: 3
                 Layout.preferredWidth: 7 * 52 + 20 - 6
-                palette: Nheko.colors
+                palette: timelineRoot.palette
                 background: null
-                placeholderTextColor: Nheko.colors.buttonText
-                color: Nheko.colors.text
+                placeholderTextColor: timelineRoot.palette.buttonText
+                color: timelineRoot.palette.text
                 placeholderText: qsTr("Search")
                 selectByMouse: true
                 rightPadding: clearSearch.width
@@ -91,7 +91,7 @@ Menu {
                     id: clearSearch
 
                     visible: emojiSearch.text !== ''
-                    icon.source: "image://colorimage/:/icons/icons/ui/round-remove-button.svg?" + (clearSearch.hovered ? Nheko.colors.highlight : Nheko.colors.buttonText)
+                    icon.source: "image://colorimage/:/icons/icons/ui/round-remove-button.svg?" + (clearSearch.hovered ? timelineRoot.palette.highlight : timelineRoot.palette.buttonText)
                     focusPolicy: Qt.NoFocus
                     onClicked: emojiSearch.clear()
                     hoverEnabled: true
@@ -106,7 +106,7 @@ Menu {
                     Image {
                         height: parent.height - 2 * Nheko.paddingSmall
                         width: height
-                        source: "image://colorimage/:/icons/icons/ui/round-remove-button.svg?" + (clearSearch.hovered ? Nheko.colors.highlight : Nheko.colors.buttonText)
+                        source: "image://colorimage/:/icons/icons/ui/round-remove-button.svg?" + (clearSearch.hovered ? timelineRoot.palette.highlight : timelineRoot.palette.buttonText)
 
                         anchors {
                             verticalCenter: parent.verticalCenter
@@ -134,11 +134,6 @@ Menu {
                 currentIndex: -1 // prevent sorting from stealing focus
                 cacheBuffer: 500
 
-                ScrollHelper {
-                    flickable: parent
-                    anchors.fill: parent
-                    enabled: !Settings.mobileMode
-                }
 
                 // Individual emoji
                 delegate: AbstractButton {
@@ -172,12 +167,12 @@ Menu {
                         font.family: Settings.emojiFont
                         font.pixelSize: 36
                         text: model.unicode.replace('\ufe0f', '')
-                        color: Nheko.colors.text
+                        color: timelineRoot.palette.text
                     }
 
                     background: Rectangle {
                         anchors.fill: parent
-                        color: hovered ? Nheko.colors.highlight : 'transparent'
+                        color: hovered ? timelineRoot.palette.highlight : 'transparent'
                         radius: 5
                     }
 
@@ -300,14 +295,14 @@ Menu {
                             mipmap: true
                             sourceSize.width: 32 * Screen.devicePixelRatio
                             sourceSize.height: 32 * Screen.devicePixelRatio
-                            source: "image://colorimage/" + model.image + "?" + (hovered ? Nheko.colors.highlight : Nheko.colors.buttonText)
+                            source: "image://colorimage/" + model.image + "?" + (hovered ? timelineRoot.palette.highlight : timelineRoot.palette.buttonText)
                         }
 
                         background: Rectangle {
                             anchors.fill: parent
                             color: emojiPopup.model.category === model.category ? Qt.hsla(highlightHue, highlightSat, highlightLight, 0.2) : 'transparent'
                             radius: 5
-                            border.color: emojiPopup.model.category === model.category ? Nheko.colors.highlight : 'transparent'
+                            border.color: emojiPopup.model.category === model.category ? timelineRoot.palette.highlight : 'transparent'
                         }
 
                     }
diff --git a/resources/qml/emoji/StickerPicker.qml b/resources/qml/emoji/StickerPicker.qml
index 41e8c3b6..56bf4f4b 100644
--- a/resources/qml/emoji/StickerPicker.qml
+++ b/resources/qml/emoji/StickerPicker.qml
@@ -18,9 +18,9 @@ Menu {
     property string roomid
     property alias model: gridView.model
     property var textArea
-    property real highlightHue: Nheko.colors.highlight.hslHue
-    property real highlightSat: Nheko.colors.highlight.hslSaturation
-    property real highlightLight: Nheko.colors.highlight.hslLightness
+    property real highlightHue: timelineRoot.palette.highlight.hslHue
+    property real highlightSat: timelineRoot.palette.highlight.hslSaturation
+    property real highlightLight: timelineRoot.palette.highlight.hslLightness
     readonly property int stickerDim: 128
     readonly property int stickerDimPad: 128 + Nheko.paddingSmall
     readonly property int stickersPerRow: 3
@@ -42,7 +42,7 @@ Menu {
     width: stickersPerRow * stickerDimPad + 20
 
     Rectangle {
-        color: Nheko.colors.window
+        color: timelineRoot.palette.window
         height: columnView.implicitHeight + 4
         width: stickersPerRow * stickerDimPad + 20
 
@@ -63,10 +63,10 @@ Menu {
 
                 Layout.topMargin: 3
                 Layout.preferredWidth: stickersPerRow * stickerDimPad + 20 - 6
-                palette: Nheko.colors
+                palette: timelineRoot.palette
                 background: null
-                placeholderTextColor: Nheko.colors.buttonText
-                color: Nheko.colors.text
+                placeholderTextColor: timelineRoot.palette.buttonText
+                color: timelineRoot.palette.text
                 placeholderText: qsTr("Search")
                 selectByMouse: true
                 rightPadding: clearSearch.width
@@ -89,7 +89,7 @@ Menu {
                     id: clearSearch
 
                     visible: emojiSearch.text !== ''
-                    icon.source: "image://colorimage/:/icons/icons/ui/round-remove-button.svg?" + (clearSearch.hovered ? Nheko.colors.highlight : Nheko.colors.buttonText)
+                    icon.source: "image://colorimage/:/icons/icons/ui/round-remove-button.svg?" + (clearSearch.hovered ? timelineRoot.palette.highlight : timelineRoot.palette.buttonText)
                     focusPolicy: Qt.NoFocus
                     onClicked: emojiSearch.clear()
                     hoverEnabled: true
@@ -104,7 +104,7 @@ Menu {
                     Image {
                         height: parent.height - 2 * Nheko.paddingSmall
                         width: height
-                        source: "image://colorimage/:/icons/icons/ui/round-remove-button.svg?" + (clearSearch.hovered ? Nheko.colors.highlight : Nheko.colors.buttonText)
+                        source: "image://colorimage/:/icons/icons/ui/round-remove-button.svg?" + (clearSearch.hovered ? timelineRoot.palette.highlight : timelineRoot.palette.buttonText)
 
                         anchors {
                             verticalCenter: parent.verticalCenter
@@ -133,11 +133,6 @@ Menu {
                 currentIndex: -1 // prevent sorting from stealing focus
                 cacheBuffer: 500
 
-                ScrollHelper {
-                    flickable: parent
-                    anchors.fill: parent
-                    enabled: !Settings.mobileMode
-                }
 
                 // Individual emoji
                 delegate: AbstractButton {
@@ -162,7 +157,7 @@ Menu {
 
                     background: Rectangle {
                         anchors.fill: parent
-                        color: hovered ? Nheko.colors.highlight : 'transparent'
+                        color: hovered ? timelineRoot.palette.highlight : 'transparent'
                         radius: 5
                     }
 
diff --git a/resources/qml/pages/LoginPage.qml b/resources/qml/pages/LoginPage.qml
index 87234a22..1c5a8983 100644
--- a/resources/qml/pages/LoginPage.qml
+++ b/resources/qml/pages/LoginPage.qml
@@ -25,7 +25,7 @@ Item {
         id: scroll
 
         clip: false
-        palette: Nheko.colors
+        palette: timelineRoot.palette
         ScrollBar.horizontal.visible: false
         anchors.left: parent.left
         anchors.right: parent.right
@@ -71,7 +71,7 @@ Item {
 
                     visible: running
                     running: login.lookingUpHs
-                    foreground: Nheko.colors.mid
+                    foreground: timelineRoot.palette.mid
                 }
             }
 
@@ -125,7 +125,7 @@ Item {
 
                     visible: running
                     running: login.loggingIn
-                    foreground: Nheko.colors.mid
+                    foreground: timelineRoot.palette.mid
                 }
             }
 
diff --git a/resources/qml/pages/RegisterPage.qml b/resources/qml/pages/RegisterPage.qml
index 44836ccb..eaec2941 100644
--- a/resources/qml/pages/RegisterPage.qml
+++ b/resources/qml/pages/RegisterPage.qml
@@ -25,7 +25,7 @@ Item {
         id: scroll
 
         clip: false
-        palette: Nheko.colors
+        palette: timelineRoot.palette
         ScrollBar.horizontal.visible: false
         anchors.left: parent.left
         anchors.right: parent.right
@@ -70,7 +70,7 @@ Item {
 
                     visible: running
                     running: regis.lookingUpHs
-                    foreground: Nheko.colors.mid
+                    foreground: timelineRoot.palette.mid
                 }
             }
 
@@ -100,7 +100,7 @@ Item {
 
                     visible: running
                     running: regis.lookingUpUsername
-                    foreground: Nheko.colors.mid
+                    foreground: timelineRoot.palette.mid
                 }
 
                 Image {
@@ -172,7 +172,7 @@ Item {
 
                     visible: running
                     running: regis.registering
-                    foreground: Nheko.colors.mid
+                    foreground: timelineRoot.palette.mid
                 }
             }
 
diff --git a/resources/qml/pages/UserSettingsPage.qml b/resources/qml/pages/UserSettingsPage.qml
index 6151e067..9fc0850f 100644
--- a/resources/qml/pages/UserSettingsPage.qml
+++ b/resources/qml/pages/UserSettingsPage.qml
@@ -17,12 +17,12 @@ Rectangle {
 
     property int collapsePoint: 800
     property bool collapsed: width < collapsePoint
-    color: Nheko.colors.window
+    color: timelineRoot.palette.window
 
     ScrollView {
         id: scroll
 
-        palette: Nheko.colors
+        palette: timelineRoot.palette
         ScrollBar.horizontal.visible: false
         anchors.fill: parent
         anchors.topMargin: (collapsed? backButton.height : 0)+Nheko.paddingLarge
@@ -52,7 +52,7 @@ Rectangle {
                     Label {
                         Layout.alignment: Qt.AlignLeft
                         Layout.fillWidth: true
-                        color: Nheko.colors.text
+                        color: timelineRoot.palette.text
                         text: model.name
                         //Layout.column: 0
                         Layout.columnSpan: (model.type == UserSettingsModel.SectionTitle && !userSettingsDialog.collapsed) ? 2 : 1
@@ -160,7 +160,7 @@ Rectangle {
                         DelegateChoice {
                             roleValue: UserSettingsModel.ReadOnlyText
                             TextEdit {
-                                color: Nheko.colors.text
+                                color: timelineRoot.palette.text
                                 text: model.value
                                 readOnly: true
                                 selectByMouse: !Settings.mobileMode
@@ -177,7 +177,7 @@ Rectangle {
                                     anchors.top: parent.top
                                     anchors.left: parent.left
                                     anchors.right: parent.right
-                                    color: Nheko.colors.buttonText
+                                    color: timelineRoot.palette.buttonText
                                     height: 1
                                 }
                             }
diff --git a/resources/qml/pages/WelcomePage.qml b/resources/qml/pages/WelcomePage.qml
index e1ecc31d..19bbba21 100644
--- a/resources/qml/pages/WelcomePage.qml
+++ b/resources/qml/pages/WelcomePage.qml
@@ -27,7 +27,7 @@ ColumnLayout {
         Layout.alignment: Qt.AlignHCenter
         Layout.fillWidth: true
         text: qsTr("Welcome to nheko! The desktop client for the Matrix protocol.")
-        color: Nheko.colors.text
+        color: timelineRoot.palette.text
         font.pointSize: fontMetrics.font.pointSize*2
         wrapMode: Text.Wrap
         horizontalAlignment: Text.AlignHCenter
@@ -37,7 +37,7 @@ ColumnLayout {
         Layout.alignment: Qt.AlignHCenter
         Layout.fillWidth: true
         text: qsTr("Enjoy your stay!")
-        color: Nheko.colors.text
+        color: timelineRoot.palette.text
         font.pointSize: fontMetrics.font.pointSize*1.5
         wrapMode: Text.Wrap
         horizontalAlignment: Text.AlignHCenter
diff --git a/resources/qml/ui/NhekoSlider.qml b/resources/qml/ui/NhekoSlider.qml
index 623eeb71..f8b3cd3b 100644
--- a/resources/qml/ui/NhekoSlider.qml
+++ b/resources/qml/ui/NhekoSlider.qml
@@ -10,7 +10,7 @@ import im.nheko 1.0
 Slider {
     id: control
 
-    property color progressColor: Nheko.colors.highlight
+    property color progressColor: timelineRoot.palette.highlight
     property bool alwaysShowSlider: true
     property int sliderRadius: 16
 
@@ -26,7 +26,7 @@ Slider {
         width: control.availableWidth - handle.width
         height: implicitHeight
         radius: height / 2
-        color: Nheko.colors.buttonText
+        color: timelineRoot.palette.buttonText
 
         Rectangle {
             width: control.visualPosition * parent.width
diff --git a/resources/qml/ui/Snackbar.qml b/resources/qml/ui/Snackbar.qml
index 80c0d888..fc6d68e4 100644
--- a/resources/qml/ui/Snackbar.qml
+++ b/resources/qml/ui/Snackbar.qml
@@ -45,7 +45,7 @@ Popup {
     padding: Nheko.paddingLarge
 
     contentItem: Label {
-        color: Nheko.colors.light
+        color: timelineRoot.palette.light
         width: Math.max(Overlay.overlay? Overlay.overlay.width/2 : 0, 400)
         text: snackbar.currentMessage
         font.bold: true
@@ -53,7 +53,7 @@ Popup {
 
     background: Rectangle {
         radius: Nheko.paddingLarge
-        color: Nheko.colors.dark
+        color: timelineRoot.palette.dark
         opacity: 0.8
     }
 
diff --git a/resources/qml/ui/media/MediaControls.qml b/resources/qml/ui/media/MediaControls.qml
index d73957ee..986b8f2e 100644
--- a/resources/qml/ui/media/MediaControls.qml
+++ b/resources/qml/ui/media/MediaControls.qml
@@ -51,7 +51,7 @@ Rectangle {
     }
 
     color: {
-        var wc = Nheko.colors.alternateBase;
+        var wc = timelineRoot.palette.alternateBase;
         return Qt.rgba(wc.r, wc.g, wc.b, 0.5);
     }
     opacity: control.shouldShowControls ? 1 : 0
@@ -96,7 +96,7 @@ Rectangle {
                 id: playbackStateImage
 
                 Layout.alignment: Qt.AlignLeft
-                buttonTextColor: Nheko.colors.text
+                buttonTextColor: timelineRoot.palette.text
                 Layout.preferredHeight: 24
                 Layout.preferredWidth: 24
                 image: {
@@ -116,7 +116,7 @@ Rectangle {
                 id: volumeButton
 
                 Layout.alignment: Qt.AlignLeft
-                buttonTextColor: Nheko.colors.text
+                buttonTextColor: timelineRoot.palette.text
                 Layout.preferredHeight: 24
                 Layout.preferredWidth: 24
                 image: {
@@ -215,7 +215,7 @@ Rectangle {
             Label {
                 Layout.alignment: Qt.AlignRight
                 text: (!control.mediaLoaded ? "-- " : durationToString(control.positionValue)) + " / " + durationToString(control.duration)
-                color: Nheko.colors.text
+                color: timelineRoot.palette.text
             }
 
             Item {
diff --git a/resources/qml/voip/CallDevices.qml b/resources/qml/voip/CallDevices.qml
index 60db762a..0874cd6a 100644
--- a/resources/qml/voip/CallDevices.qml
+++ b/resources/qml/voip/CallDevices.qml
@@ -10,7 +10,7 @@ import im.nheko 1.0
 
 Popup {
     modal: true
-    palette: Nheko.colors
+    palette: timelineRoot.palette
     // only set the anchors on Qt 5.12 or higher
     // see https://doc.qt.io/qt-5/qml-qtquick-controls2-popup.html#anchors.centerIn-prop
     Component.onCompleted: {
@@ -32,7 +32,7 @@ Popup {
                 Image {
                     Layout.preferredWidth: 22
                     Layout.preferredHeight: 22
-                    source: "image://colorimage/:/icons/icons/ui/microphone-unmute.svg?" + Nheko.colors.windowText
+                    source: "image://colorimage/:/icons/icons/ui/microphone-unmute.svg?" + timelineRoot.palette.windowText
                 }
 
                 ComboBox {
@@ -50,7 +50,7 @@ Popup {
                 Image {
                     Layout.preferredWidth: 22
                     Layout.preferredHeight: 22
-                    source: "image://colorimage/:/icons/icons/ui/video-call.svg?" + Nheko.colors.windowText
+                    source: "image://colorimage/:/icons/icons/ui/video-call.svg?" + timelineRoot.palette.windowText
                 }
 
                 ComboBox {
@@ -82,8 +82,8 @@ Popup {
     }
 
     background: Rectangle {
-        color: Nheko.colors.window
-        border.color: Nheko.colors.windowText
+        color: timelineRoot.palette.window
+        border.color: timelineRoot.palette.windowText
     }
 
 }
diff --git a/resources/qml/voip/CallInvite.qml b/resources/qml/voip/CallInvite.qml
index 7bab3616..b2643bac 100644
--- a/resources/qml/voip/CallInvite.qml
+++ b/resources/qml/voip/CallInvite.qml
@@ -15,7 +15,7 @@ Popup {
     closePolicy: Popup.NoAutoClose
     width: parent.width
     height: parent.height
-    palette: Nheko.colors
+    palette: timelineRoot.palette
 
     Component {
         id: deviceError
@@ -46,7 +46,7 @@ Popup {
             Layout.fillWidth: true
             text: CallManager.callPartyDisplayName
             font.pointSize: fontMetrics.font.pointSize * 2
-            color: Nheko.colors.windowText
+            color: timelineRoot.palette.windowText
             horizontalAlignment: Text.AlignHCenter
         }
 
@@ -69,14 +69,14 @@ Popup {
                 Layout.alignment: Qt.AlignCenter
                 Layout.preferredWidth: callInv.height / 10
                 Layout.preferredHeight: callInv.height / 10
-                source: "image://colorimage/" + image + "?" + Nheko.colors.windowText
+                source: "image://colorimage/" + image + "?" + timelineRoot.palette.windowText
             }
 
             Label {
                 Layout.alignment: Qt.AlignCenter
                 text: CallManager.callType == CallType.VIDEO ? qsTr("Video Call") : qsTr("Voice Call")
                 font.pointSize: fontMetrics.font.pointSize * 2
-                color: Nheko.colors.windowText
+                color: timelineRoot.palette.windowText
             }
 
         }
@@ -95,7 +95,7 @@ Popup {
                 Image {
                     Layout.preferredWidth: deviceCombos.imageSize
                     Layout.preferredHeight: deviceCombos.imageSize
-                    source: "image://colorimage/:/icons/icons/ui/microphone-unmute.svg?" + Nheko.colors.windowText
+                    source: "image://colorimage/:/icons/icons/ui/microphone-unmute.svg?" + timelineRoot.palette.windowText
                 }
 
                 ComboBox {
@@ -114,7 +114,7 @@ Popup {
                 Image {
                     Layout.preferredWidth: deviceCombos.imageSize
                     Layout.preferredHeight: deviceCombos.imageSize
-                    source: "image://colorimage/:/icons/icons/ui/video.svg?" + Nheko.colors.windowText
+                    source: "image://colorimage/:/icons/icons/ui/video.svg?" + timelineRoot.palette.windowText
                 }
 
                 ComboBox {
@@ -202,8 +202,8 @@ Popup {
     }
 
     background: Rectangle {
-        color: Nheko.colors.window
-        border.color: Nheko.colors.windowText
+        color: timelineRoot.palette.window
+        border.color: timelineRoot.palette.windowText
     }
 
 }
diff --git a/resources/qml/voip/CallInviteBar.qml b/resources/qml/voip/CallInviteBar.qml
index ab377ca8..36d05160 100644
--- a/resources/qml/voip/CallInviteBar.qml
+++ b/resources/qml/voip/CallInviteBar.qml
@@ -91,7 +91,7 @@ Rectangle {
             Layout.rightMargin: 4
             icon.source: CallManager.callType == CallType.VIDEO ? "qrc:/icons/icons/ui/video.svg" : "qrc:/icons/icons/ui/place-call.svg"
             text: qsTr("Accept")
-            palette: Nheko.colors
+            palette: timelineRoot.palette
             onClicked: {
                 if (CallManager.mics.length == 0) {
                     var dialog = deviceError.createObject(timelineRoot, {
@@ -127,7 +127,7 @@ Rectangle {
             Layout.rightMargin: 16
             icon.source: "qrc:/icons/icons/ui/end-call.svg"
             text: qsTr("Decline")
-            palette: Nheko.colors
+            palette: timelineRoot.palette
             onClicked: {
                 CallManager.hangUp();
             }
diff --git a/resources/qml/voip/DeviceError.qml b/resources/qml/voip/DeviceError.qml
index 3f37612c..48cbfc44 100644
--- a/resources/qml/voip/DeviceError.qml
+++ b/resources/qml/voip/DeviceError.qml
@@ -25,19 +25,19 @@ Popup {
         Image {
             Layout.preferredWidth: 16
             Layout.preferredHeight: 16
-            source: "image://colorimage/" + image + "?" + Nheko.colors.windowText
+            source: "image://colorimage/" + image + "?" + timelineRoot.palette.windowText
         }
 
         Label {
             text: errorString
-            color: Nheko.colors.windowText
+            color: timelineRoot.palette.windowText
         }
 
     }
 
     background: Rectangle {
-        color: Nheko.colors.window
-        border.color: Nheko.colors.windowText
+        color: timelineRoot.palette.window
+        border.color: timelineRoot.palette.windowText
     }
 
 }
diff --git a/resources/qml/voip/PlaceCall.qml b/resources/qml/voip/PlaceCall.qml
index 33ad4cfa..20af94df 100644
--- a/resources/qml/voip/PlaceCall.qml
+++ b/resources/qml/voip/PlaceCall.qml
@@ -18,7 +18,7 @@ Popup {
             anchors.centerIn = parent;
 
     }
-    palette: Nheko.colors
+    palette: timelineRoot.palette
 
     Component {
         id: deviceError
@@ -39,7 +39,7 @@ Popup {
 
             Label {
                 text: qsTr("Place a call to %1?").arg(room.roomName)
-                color: Nheko.colors.windowText
+                color: timelineRoot.palette.windowText
             }
 
             Item {
@@ -140,7 +140,7 @@ Popup {
                 Image {
                     Layout.preferredWidth: 22
                     Layout.preferredHeight: 22
-                    source: "image://colorimage/:/icons/icons/ui/microphone-unmute.svg?" + Nheko.colors.windowText
+                    source: "image://colorimage/:/icons/icons/ui/microphone-unmute.svg?" + timelineRoot.palette.windowText
                 }
 
                 ComboBox {
@@ -161,7 +161,7 @@ Popup {
                 Image {
                     Layout.preferredWidth: 22
                     Layout.preferredHeight: 22
-                    source: "image://colorimage/:/icons/icons/ui/video.svg?" + Nheko.colors.windowText
+                    source: "image://colorimage/:/icons/icons/ui/video.svg?" + timelineRoot.palette.windowText
                 }
 
                 ComboBox {
@@ -178,8 +178,8 @@ Popup {
     }
 
     background: Rectangle {
-        color: Nheko.colors.window
-        border.color: Nheko.colors.windowText
+        color: timelineRoot.palette.window
+        border.color: timelineRoot.palette.windowText
     }
 
 }
diff --git a/resources/qml/voip/ScreenShare.qml b/resources/qml/voip/ScreenShare.qml
index f27c4485..a96601f8 100644
--- a/resources/qml/voip/ScreenShare.qml
+++ b/resources/qml/voip/ScreenShare.qml
@@ -17,7 +17,7 @@ Popup {
     Component.onCompleted: {
         frameRateCombo.currentIndex = frameRateCombo.find(Settings.screenShareFrameRate);
     }
-    palette: Nheko.colors
+    palette: timelineRoot.palette
 
     ColumnLayout {
         Label {
@@ -27,7 +27,7 @@ Popup {
             Layout.rightMargin: 8
             Layout.alignment: Qt.AlignLeft
             text: qsTr("Share desktop with %1?").arg(room.roomName)
-            color: Nheko.colors.windowText
+            color: timelineRoot.palette.windowText
         }
 
         RowLayout {
@@ -38,7 +38,7 @@ Popup {
             Label {
                 Layout.alignment: Qt.AlignLeft
                 text: qsTr("Window:")
-                color: Nheko.colors.windowText
+                color: timelineRoot.palette.windowText
             }
 
             ComboBox {
@@ -58,7 +58,7 @@ Popup {
             Label {
                 Layout.alignment: Qt.AlignLeft
                 text: qsTr("Frame rate:")
-                color: Nheko.colors.windowText
+                color: timelineRoot.palette.windowText
             }
 
             ComboBox {
@@ -156,8 +156,8 @@ Popup {
     }
 
     background: Rectangle {
-        color: Nheko.colors.window
-        border.color: Nheko.colors.windowText
+        color: timelineRoot.palette.window
+        border.color: timelineRoot.palette.windowText
     }
 
 }
diff --git a/resources/res.qrc b/resources/res.qrc
index 3ce63f42..092b2de9 100644
--- a/resources/res.qrc
+++ b/resources/res.qrc
@@ -106,7 +106,6 @@
         qml/PrivacyScreen.qml
         qml/Reactions.qml
         qml/ReplyPopup.qml
-        qml/ScrollHelper.qml
         qml/StatusIndicator.qml
         qml/TimelineRow.qml
         qml/TopBar.qml
diff --git a/src/MxcImageProvider.cpp b/src/MxcImageProvider.cpp
index 6098f0c4..6b5f3b99 100644
--- a/src/MxcImageProvider.cpp
+++ b/src/MxcImageProvider.cpp
@@ -81,6 +81,9 @@ MxcImageRunnable::run()
 static QImage
 clipRadius(QImage img, double radius)
 {
+    if (img.isNull())
+        return img;
+
     QImage out(img.size(), QImage::Format_ARGB32_Premultiplied);
     out.fill(Qt::transparent);