summary refs log tree commit diff
diff options
context:
space:
mode:
authorNicolas Werner <nicolas.werner@hotmail.de>2021-05-13 08:23:56 +0200
committerNicolas Werner <nicolas.werner@hotmail.de>2021-05-13 08:23:56 +0200
commita7f8b23b524c5e3af72e42fde118706e94a454f3 (patch)
treec3918f64578ee97b89dba41ae169baea09a061e6
parentFix warning on gcc11 (diff)
downloadnheko-a7f8b23b524c5e3af72e42fde118706e94a454f3.tar.xz
Make palette global in Qml
-rw-r--r--CMakeLists.txt16
-rw-r--r--resources/qml/Avatar.qml6
-rw-r--r--resources/qml/Completer.qml22
-rw-r--r--resources/qml/EncryptionIndicator.qml2
-rw-r--r--resources/qml/ForwardCompleter.qml12
-rw-r--r--resources/qml/ImageButton.qml4
-rw-r--r--resources/qml/MatrixText.qml2
-rw-r--r--resources/qml/MatrixTextField.qml8
-rw-r--r--resources/qml/MessageInput.qml10
-rw-r--r--resources/qml/MessageView.qml18
-rw-r--r--resources/qml/NhekoBusyIndicator.qml3
-rw-r--r--resources/qml/QuickSwitcher.qml4
-rw-r--r--resources/qml/Reactions.qml16
-rw-r--r--resources/qml/ReplyPopup.qml4
-rw-r--r--resources/qml/RoomSettings.qml6
-rw-r--r--resources/qml/TimelineRow.qml8
-rw-r--r--resources/qml/TimelineView.qml24
-rw-r--r--resources/qml/TopBar.qml4
-rw-r--r--resources/qml/TypingIndicator.qml6
-rw-r--r--resources/qml/UserProfile.qml12
-rw-r--r--resources/qml/delegates/FileMessage.qml8
-rw-r--r--resources/qml/delegates/ImageMessage.qml6
-rw-r--r--resources/qml/delegates/MessageDelegate.qml2
-rw-r--r--resources/qml/delegates/NoticeMessage.qml4
-rw-r--r--resources/qml/delegates/Pill.qml4
-rw-r--r--resources/qml/delegates/Placeholder.qml3
-rw-r--r--resources/qml/delegates/PlayableMediaMessage.qml14
-rw-r--r--resources/qml/delegates/Reply.qml2
-rw-r--r--resources/qml/delegates/TextMessage.qml2
-rw-r--r--resources/qml/device-verification/AwaitingVerificationConfirmation.qml2
-rw-r--r--resources/qml/device-verification/DeviceVerification.qml2
-rw-r--r--resources/qml/device-verification/DigitVerification.qml8
-rw-r--r--resources/qml/device-verification/EmojiVerification.qml6
-rw-r--r--resources/qml/device-verification/Failed.qml2
-rw-r--r--resources/qml/device-verification/NewVerificationRequest.qml2
-rw-r--r--resources/qml/device-verification/Success.qml2
-rw-r--r--resources/qml/device-verification/Waiting.qml4
-rw-r--r--resources/qml/emoji/EmojiPicker.qml16
-rw-r--r--resources/qml/voip/CallDevices.qml10
-rw-r--r--resources/qml/voip/CallInvite.qml16
-rw-r--r--resources/qml/voip/CallInviteBar.qml4
-rw-r--r--resources/qml/voip/DeviceError.qml8
-rw-r--r--resources/qml/voip/PlaceCall.qml12
-rw-r--r--resources/qml/voip/ScreenShare.qml12
-rw-r--r--src/timeline/TimelineViewManager.cpp5
-rw-r--r--src/ui/NhekoGlobalObject.cpp27
-rw-r--r--src/ui/NhekoGlobalObject.h25
47 files changed, 226 insertions, 169 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 96948827..5155af40 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -284,11 +284,13 @@ set(SRC_FILES
 	src/ui/LoadingIndicator.cpp
 	src/ui/NhekoCursorShape.cpp
 	src/ui/NhekoDropArea.cpp
+	src/ui/NhekoGlobalObject.cpp
 	src/ui/OverlayModal.cpp
 	src/ui/OverlayWidget.cpp
 	src/ui/RaisedButton.cpp
 	src/ui/Ripple.cpp
 	src/ui/RippleOverlay.cpp
+	src/ui/RoomSettings.cpp
 	src/ui/SnackBar.cpp
 	src/ui/TextField.cpp
 	src/ui/TextLabel.cpp
@@ -296,7 +298,6 @@ set(SRC_FILES
 	src/ui/ThemeManager.cpp
 	src/ui/ToggleButton.cpp
 	src/ui/UserProfile.cpp
-	src/ui/RoomSettings.cpp
 
     # Generic notification stuff
     src/notifications/Manager.cpp
@@ -500,26 +501,27 @@ qt5_wrap_cpp(MOC_HEADERS
 	# UI components
 	src/ui/Avatar.h
 	src/ui/Badge.h
-	src/ui/LoadingIndicator.h
-	src/ui/InfoMessage.h
 	src/ui/FlatButton.h
-	src/ui/Label.h
 	src/ui/FloatingButton.h
+	src/ui/InfoMessage.h
+	src/ui/Label.h
+	src/ui/LoadingIndicator.h
 	src/ui/Menu.h
 	src/ui/NhekoCursorShape.h
 	src/ui/NhekoDropArea.h
+	src/ui/NhekoGlobalObject.h
 	src/ui/OverlayWidget.h
-	src/ui/SnackBar.h
 	src/ui/RaisedButton.h
 	src/ui/Ripple.h
 	src/ui/RippleOverlay.h
+	src/ui/RoomSettings.h
+	src/ui/SnackBar.h
 	src/ui/TextField.h
 	src/ui/TextLabel.h
-	src/ui/ToggleButton.h
 	src/ui/Theme.h
 	src/ui/ThemeManager.h
+	src/ui/ToggleButton.h
 	src/ui/UserProfile.h
-	src/ui/RoomSettings.h
 
 	src/notifications/Manager.h
 
diff --git a/resources/qml/Avatar.qml b/resources/qml/Avatar.qml
index 108bb768..84c22da1 100644
--- a/resources/qml/Avatar.qml
+++ b/resources/qml/Avatar.qml
@@ -20,7 +20,7 @@ Rectangle {
     width: 48
     height: 48
     radius: Settings.avatarCircles ? height / 2 : 3
-    color: colors.alternateBase
+    color: Nheko.colors.alternateBase
     Component.onCompleted: {
         mouseArea.clicked.connect(clicked);
     }
@@ -33,7 +33,7 @@ Rectangle {
         verticalAlignment: Text.AlignVCenter
         horizontalAlignment: Text.AlignHCenter
         visible: img.status != Image.Ready
-        color: colors.text
+        color: Nheko.colors.text
     }
 
     Image {
@@ -55,7 +55,7 @@ Rectangle {
 
             Ripple {
                 rippleTarget: mouseArea
-                color: Qt.rgba(colors.alternateBase.r, colors.alternateBase.g, colors.alternateBase.b, 0.5)
+                color: Qt.rgba(Nheko.colors.alternateBase.r, Nheko.colors.alternateBase.g, Nheko.colors.alternateBase.b, 0.5)
             }
 
         }
diff --git a/resources/qml/Completer.qml b/resources/qml/Completer.qml
index d648553f..2609371b 100644
--- a/resources/qml/Completer.qml
+++ b/resources/qml/Completer.qml
@@ -100,7 +100,7 @@ Popup {
         delegate: Rectangle {
             property variant modelData: model
 
-            color: model.index == popup.currentIndex ? colors.highlight : colors.base
+            color: model.index == popup.currentIndex ? Nheko.colors.highlight : Nheko.colors.base
             height: chooser.childrenRect.height + 2 * popup.rowMargin
             implicitWidth: fullWidth ? popup.width : chooser.childrenRect.width + 4
 
@@ -119,7 +119,7 @@ Popup {
 
                 Ripple {
                     rippleTarget: mouseArea
-                    color: Qt.rgba(colors.base.r, colors.base.g, colors.base.b, 0.5)
+                    color: Qt.rgba(Nheko.colors.base.r, Nheko.colors.base.g, Nheko.colors.base.b, 0.5)
                 }
 
             }
@@ -150,12 +150,12 @@ Popup {
 
                         Label {
                             text: model.displayName
-                            color: model.index == popup.currentIndex ? colors.highlightedText : colors.text
+                            color: model.index == popup.currentIndex ? Nheko.colors.highlightedText : Nheko.colors.text
                         }
 
                         Label {
                             text: "(" + model.userid + ")"
-                            color: model.index == popup.currentIndex ? colors.highlightedText : colors.buttonText
+                            color: model.index == popup.currentIndex ? Nheko.colors.highlightedText : Nheko.colors.buttonText
                         }
 
                     }
@@ -173,13 +173,13 @@ Popup {
 
                         Label {
                             text: model.unicode
-                            color: model.index == popup.currentIndex ? colors.highlightedText : colors.text
+                            color: model.index == popup.currentIndex ? Nheko.colors.highlightedText : Nheko.colors.text
                             font: Settings.emojiFont
                         }
 
                         Label {
                             text: model.shortName
-                            color: model.index == popup.currentIndex ? colors.highlightedText : colors.text
+                            color: model.index == popup.currentIndex ? Nheko.colors.highlightedText : Nheko.colors.text
                         }
 
                     }
@@ -209,7 +209,7 @@ Popup {
                         Label {
                             text: model.roomName
                             font.pixelSize: popup.avatarHeight * 0.5
-                            color: model.index == popup.currentIndex ? colors.highlightedText : colors.text
+                            color: model.index == popup.currentIndex ? Nheko.colors.highlightedText : Nheko.colors.text
                         }
 
                     }
@@ -235,12 +235,12 @@ Popup {
 
                         Label {
                             text: model.roomName
-                            color: model.index == popup.currentIndex ? colors.highlightedText : colors.text
+                            color: model.index == popup.currentIndex ? Nheko.colors.highlightedText : Nheko.colors.text
                         }
 
                         Label {
                             text: "(" + model.roomAlias + ")"
-                            color: model.index == popup.currentIndex ? colors.highlightedText : colors.buttonText
+                            color: model.index == popup.currentIndex ? Nheko.colors.highlightedText : Nheko.colors.buttonText
                         }
 
                     }
@@ -274,10 +274,10 @@ Popup {
     }
 
     background: Rectangle {
-        color: colors.base
+        color: Nheko.colors.base
         implicitHeight: popup.contentHeight
         implicitWidth: popup.contentWidth
-        border.color: colors.mid
+        border.color: Nheko.colors.mid
     }
 
 }
diff --git a/resources/qml/EncryptionIndicator.qml b/resources/qml/EncryptionIndicator.qml
index 1e5d4d38..52d2eeed 100644
--- a/resources/qml/EncryptionIndicator.qml
+++ b/resources/qml/EncryptionIndicator.qml
@@ -20,7 +20,7 @@ Image {
             case Crypto.Verified:
                 return "image://colorimage/:/icons/icons/ui/lock.png?green";
             case Crypto.TOFU:
-                return "image://colorimage/:/icons/icons/ui/lock.png?" + colors.buttonText;
+                return "image://colorimage/:/icons/icons/ui/lock.png?" + Nheko.colors.buttonText;
             default:
                 return "image://colorimage/:/icons/icons/ui/lock.png?#dd3d3d";
             }
diff --git a/resources/qml/ForwardCompleter.qml b/resources/qml/ForwardCompleter.qml
index 408cab12..1ec18540 100644
--- a/resources/qml/ForwardCompleter.qml
+++ b/resources/qml/ForwardCompleter.qml
@@ -19,7 +19,7 @@ Popup {
     x: Math.round(parent.width / 2 - width / 2)
     y: Math.round(parent.height / 2 - height / 2)
     modal: true
-    palette: colors
+    palette: Nheko.colors
     parent: Overlay.overlay
     width: implicitWidth >= (timelineRoot.width * 0.8) ? implicitWidth : (timelineRoot.width * 0.8)
     height: implicitHeight + completerPopup.height + padding * 2
@@ -44,7 +44,7 @@ Popup {
             text: qsTr("Forward Message")
             font.bold: true
             bottomPadding: 10
-            color: colors.text
+            color: Nheko.colors.text
         }
 
         Reply {
@@ -52,14 +52,14 @@ Popup {
 
             modelData: TimelineManager.timeline ? TimelineManager.timeline.getDump(mid, "") : {
             }
-            userColor: TimelineManager.userColor(modelData.userId, colors.window)
+            userColor: TimelineManager.userColor(modelData.userId, Nheko.colors.window)
         }
 
         MatrixTextField {
             id: roomTextInput
 
             width: forwardMessagePopup.width - forwardMessagePopup.leftPadding * 2
-            color: colors.text
+            color: Nheko.colors.text
             onTextEdited: {
                 completerPopup.completer.searchString = text;
             }
@@ -107,11 +107,11 @@ Popup {
     }
 
     background: Rectangle {
-        color: colors.window
+        color: Nheko.colors.window
     }
 
     Overlay.modal: Rectangle {
-        color: Qt.rgba(colors.window.r, colors.window.g, colors.window.b, 0.7)
+        color: Qt.rgba(Nheko.colors.window.r, Nheko.colors.window.g, Nheko.colors.window.b, 0.7)
     }
 
 }
diff --git a/resources/qml/ImageButton.qml b/resources/qml/ImageButton.qml
index 76cc0b42..60954bfd 100644
--- a/resources/qml/ImageButton.qml
+++ b/resources/qml/ImageButton.qml
@@ -12,8 +12,8 @@ AbstractButton {
 
     property alias cursor: mouseArea.cursorShape
     property string image: undefined
-    property color highlightColor: colors.highlight
-    property color buttonTextColor: colors.buttonText
+    property color highlightColor: Nheko.colors.highlight
+    property color buttonTextColor: Nheko.colors.buttonText
     property bool changeColorOnHover: true
 
     focusPolicy: Qt.NoFocus
diff --git a/resources/qml/MatrixText.qml b/resources/qml/MatrixText.qml
index 7cfa6735..fa1cd98c 100644
--- a/resources/qml/MatrixText.qml
+++ b/resources/qml/MatrixText.qml
@@ -13,7 +13,7 @@ TextEdit {
     wrapMode: Text.Wrap
     selectByMouse: !Settings.mobileMode
     enabled: selectByMouse
-    color: colors.text
+    color: Nheko.colors.text
     onLinkActivated: TimelineManager.openLink(link)
     ToolTip.visible: hoveredLink
     ToolTip.text: hoveredLink
diff --git a/resources/qml/MatrixTextField.qml b/resources/qml/MatrixTextField.qml
index 3bcc9675..42ea33be 100644
--- a/resources/qml/MatrixTextField.qml
+++ b/resources/qml/MatrixTextField.qml
@@ -9,14 +9,14 @@ import QtQuick.Layouts 1.12
 TextField {
     id: input
 
-    palette: colors
+    palette: Nheko.colors
 
     Rectangle {
         id: blueBar
 
         anchors.top: parent.bottom
         anchors.horizontalCenter: parent.horizontalCenter
-        color: colors.highlight
+        color: Nheko.colors.highlight
         height: 1
         width: parent.width
 
@@ -27,7 +27,7 @@ TextField {
             anchors.horizontalCenter: parent.horizontalCenter
             height: parent.height + 1
             width: 0
-            color: colors.text
+            color: Nheko.colors.text
 
             states: State {
                 name: "focused"
@@ -60,7 +60,7 @@ TextField {
     }
 
     background: Rectangle {
-        color: colors.base
+        color: Nheko.colors.base
     }
 
 }
diff --git a/resources/qml/MessageInput.qml b/resources/qml/MessageInput.qml
index c5dfbfa3..f4e253ad 100644
--- a/resources/qml/MessageInput.qml
+++ b/resources/qml/MessageInput.qml
@@ -12,7 +12,7 @@ import im.nheko 1.0
 Rectangle {
     id: inputBar
 
-    color: colors.window
+    color: Nheko.colors.window
     Layout.fillWidth: true
     Layout.preferredHeight: row.implicitHeight
     Layout.minimumHeight: 40
@@ -69,7 +69,7 @@ Rectangle {
 
             Rectangle {
                 anchors.fill: parent
-                color: colors.window
+                color: Nheko.colors.window
                 visible: TimelineManager.timeline && TimelineManager.timeline.input.uploading
 
                 NhekoBusyIndicator {
@@ -116,8 +116,8 @@ Rectangle {
 
                 selectByMouse: true
                 placeholderText: qsTr("Write a message...")
-                placeholderTextColor: colors.buttonText
-                color: colors.text
+                placeholderTextColor: Nheko.colors.buttonText
+                color: Nheko.colors.text
                 width: textInput.width
                 wrapMode: TextEdit.Wrap
                 padding: 8
@@ -357,7 +357,7 @@ Rectangle {
         anchors.centerIn: parent
         visible: TimelineManager.timeline ? (!TimelineManager.timeline.permissions.canSend(MtxEvent.TextMessage)) : false
         text: qsTr("You don't have permission to send messages in this room")
-        color: colors.text
+        color: Nheko.colors.text
     }
 
 }
diff --git a/resources/qml/MessageView.qml b/resources/qml/MessageView.qml
index 7dbe7e12..0da1dff3 100644
--- a/resources/qml/MessageView.qml
+++ b/resources/qml/MessageView.qml
@@ -13,7 +13,7 @@ import im.nheko 1.0
 
 ScrollView {
     clip: false
-    palette: colors
+    palette: Nheko.colors
     padding: 8
     ScrollBar.horizontal.visible: false
 
@@ -51,8 +51,8 @@ ScrollView {
             z: 10
             height: row.implicitHeight + padding * 2
             width: row.implicitWidth + padding * 2
-            color: colors.window
-            border.color: colors.buttonText
+            color: Nheko.colors.window
+            border.color: Nheko.colors.buttonText
             border.width: 1
             radius: padding
 
@@ -74,7 +74,7 @@ ScrollView {
                     id: editButton
 
                     visible: !!row.model && row.model.isEditable
-                    buttonTextColor: colors.buttonText
+                    buttonTextColor: Nheko.colors.buttonText
                     width: 16
                     hoverEnabled: true
                     image: ":/icons/icons/ui/edit.png"
@@ -220,7 +220,7 @@ ScrollView {
                     anchors.horizontalCenter: parent ? parent.horizontalCenter : undefined
                     visible: modelData && modelData.previousMessageDay !== modelData.day
                     text: modelData ? chat.model.formatDateSeparator(modelData.timestamp) : ""
-                    color: colors.text
+                    color: Nheko.colors.text
                     height: Math.round(fontMetrics.height * 1.4)
                     width: contentWidth * 1.2
                     horizontalAlignment: Text.AlignHCenter
@@ -228,7 +228,7 @@ ScrollView {
 
                     background: Rectangle {
                         radius: parent.height / 2
-                        color: colors.window
+                        color: Nheko.colors.window
                     }
 
                 }
@@ -267,7 +267,7 @@ ScrollView {
                         id: userName
 
                         text: modelData ? TimelineManager.escapeEmoji(modelData.userName) : ""
-                        color: TimelineManager.userColor(modelData ? modelData.userId : "", colors.window)
+                        color: TimelineManager.userColor(modelData ? modelData.userId : "", Nheko.colors.window)
                         textFormat: Text.RichText
                         ToolTip.visible: displayNameHover.hovered
                         ToolTip.text: modelData ? modelData.userId : ""
@@ -288,7 +288,7 @@ ScrollView {
                     }
 
                     Label {
-                        color: colors.buttonText
+                        color: Nheko.colors.buttonText
                         text: modelData ? TimelineManager.userStatus(modelData.userId) : ""
                         textFormat: Text.PlainText
                         elide: Text.ElideRight
@@ -317,7 +317,7 @@ ScrollView {
                 opacity: 0
                 visible: true
                 anchors.fill: timelinerow
-                color: colors.highlight
+                color: Nheko.colors.highlight
 
                 states: State {
                     name: "revealed"
diff --git a/resources/qml/NhekoBusyIndicator.qml b/resources/qml/NhekoBusyIndicator.qml
index 917e11dc..82dd26dd 100644
--- a/resources/qml/NhekoBusyIndicator.qml
+++ b/resources/qml/NhekoBusyIndicator.qml
@@ -5,6 +5,7 @@
 import QtQuick 2.9
 import QtQuick.Controls 2.3
 import QtQuick.Layouts 1.2
+import im.nheko 1.0
 
 BusyIndicator {
     id: control
@@ -38,7 +39,7 @@ BusyIndicator {
                     implicitWidth: radius * 2
                     implicitHeight: radius * 2
                     radius: item.height / 6
-                    color: colors.text
+                    color: Nheko.colors.text
                     opacity: (index + 2) / (repeater.count + 2)
                     transform: [
                         Translate {
diff --git a/resources/qml/QuickSwitcher.qml b/resources/qml/QuickSwitcher.qml
index 166c788d..a6373b1c 100644
--- a/resources/qml/QuickSwitcher.qml
+++ b/resources/qml/QuickSwitcher.qml
@@ -19,7 +19,7 @@ Popup {
     modal: true
     closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
     parent: Overlay.overlay
-    palette: colors
+    palette: Nheko.colors
     onOpened: {
         completerPopup.open();
         roomTextInput.forceActiveFocus();
@@ -34,7 +34,7 @@ Popup {
         anchors.fill: parent
         font.pixelSize: Math.ceil(quickSwitcher.textHeight * 0.6)
         padding: textMargin
-        color: colors.text
+        color: Nheko.colors.text
         onTextEdited: {
             completerPopup.completer.searchString = text;
         }
diff --git a/resources/qml/Reactions.qml b/resources/qml/Reactions.qml
index f53c89ad..064df543 100644
--- a/resources/qml/Reactions.qml
+++ b/resources/qml/Reactions.qml
@@ -12,9 +12,9 @@ Flow {
     id: reactionFlow
 
     // highlight colors for selfReactedEvent background
-    property real highlightHue: colors.highlight.hslHue
-    property real highlightSat: colors.highlight.hslSaturation
-    property real highlightLight: colors.highlight.hslLightness
+    property real highlightHue: Nheko.colors.highlight.hslHue
+    property real highlightSat: Nheko.colors.highlight.hslSaturation
+    property real highlightLight: Nheko.colors.highlight.hslLightness
     property string eventId
     property alias reactions: repeater.model
 
@@ -59,7 +59,7 @@ Flow {
                     anchors.baseline: reactionCounter.baseline
                     text: textMetrics.elidedText + (textMetrics.elidedText == modelData.key ? "" : "…")
                     font.family: Settings.emojiFont
-                    color: reaction.hovered ? colors.highlight : colors.text
+                    color: reaction.hovered ? Nheko.colors.highlight : Nheko.colors.text
                     maximumLineCount: 1
                 }
 
@@ -68,7 +68,7 @@ Flow {
 
                     height: Math.floor(reactionCounter.implicitHeight * 1.4)
                     width: 1
-                    color: (reaction.hovered || modelData.selfReactedEvent !== '') ? colors.highlight : colors.text
+                    color: (reaction.hovered || modelData.selfReactedEvent !== '') ? Nheko.colors.highlight : Nheko.colors.text
                 }
 
                 Text {
@@ -77,7 +77,7 @@ Flow {
                     anchors.verticalCenter: divider.verticalCenter
                     text: modelData.count
                     font: reaction.font
-                    color: reaction.hovered ? colors.highlight : colors.text
+                    color: reaction.hovered ? Nheko.colors.highlight : Nheko.colors.text
                 }
 
             }
@@ -86,8 +86,8 @@ Flow {
                 anchors.centerIn: parent
                 implicitWidth: reaction.implicitWidth
                 implicitHeight: reaction.implicitHeight
-                border.color: (reaction.hovered || modelData.selfReactedEvent !== '') ? colors.highlight : colors.text
-                color: modelData.selfReactedEvent !== '' ? Qt.hsla(highlightHue, highlightSat, highlightLight, 0.2) : colors.window
+                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.width: 1
                 radius: reaction.height / 2
             }
diff --git a/resources/qml/ReplyPopup.qml b/resources/qml/ReplyPopup.qml
index 37b6f6cc..1d85acb0 100644
--- a/resources/qml/ReplyPopup.qml
+++ b/resources/qml/ReplyPopup.qml
@@ -17,7 +17,7 @@ Rectangle {
     visible: room && (room.reply || room.edit)
     // Height of child, plus margins, plus border
     implicitHeight: (room && room.reply ? replyPreview.height : closeEditButton.height) + 10
-    color: colors.window
+    color: Nheko.colors.window
     z: 3
 
     Reply {
@@ -31,7 +31,7 @@ Rectangle {
         anchors.bottom: parent.bottom
         modelData: room ? room.getDump(room.reply, room.id) : {
         }
-        userColor: TimelineManager.userColor(modelData.userId, colors.window)
+        userColor: TimelineManager.userColor(modelData.userId, Nheko.colors.window)
     }
 
     ImageButton {
diff --git a/resources/qml/RoomSettings.qml b/resources/qml/RoomSettings.qml
index 58567916..ba577f33 100644
--- a/resources/qml/RoomSettings.qml
+++ b/resources/qml/RoomSettings.qml
@@ -18,8 +18,8 @@ ApplicationWindow {
     y: MainWindow.y + (MainWindow.height / 2) - (height / 2)
     minimumWidth: 420
     minimumHeight: 650
-    palette: colors
-    color: colors.window
+    palette: Nheko.colors
+    color: Nheko.colors.window
     modality: Qt.WindowModal
     flags: Qt.Dialog
     title: qsTr("Room Settings")
@@ -126,7 +126,7 @@ ApplicationWindow {
                 readOnly: true
                 background: null
                 selectByMouse: true
-                color: colors.text
+                color: Nheko.colors.text
                 horizontalAlignment: TextEdit.AlignHCenter
                 onLinkActivated: TimelineManager.openLink(link)
 
diff --git a/resources/qml/TimelineRow.qml b/resources/qml/TimelineRow.qml
index 09a55e60..bae3e5a3 100644
--- a/resources/qml/TimelineRow.qml
+++ b/resources/qml/TimelineRow.qml
@@ -16,7 +16,7 @@ Item {
     height: row.height
 
     Rectangle {
-        color: (Settings.messageHoverHighlight && hoverHandler.hovered) ? colors.alternateBase : "transparent"
+        color: (Settings.messageHoverHighlight && hoverHandler.hovered) ? Nheko.colors.alternateBase : "transparent"
         anchors.fill: row
     }
 
@@ -57,7 +57,7 @@ Item {
             Reply {
                 visible: model.replyTo
                 modelData: chat.model.getDump(model.replyTo, model.id)
-                userColor: TimelineManager.userColor(modelData.userId, colors.base)
+                userColor: TimelineManager.userColor(modelData.userId, Nheko.colors.base)
             }
 
             // actual message content
@@ -101,7 +101,7 @@ Item {
             width: 16
             sourceSize.width: 16
             sourceSize.height: 16
-            source: "image://colorimage/:/icons/icons/ui/edit.png?" + ((model.id == chat.model.edit) ? colors.highlight : colors.buttonText)
+            source: "image://colorimage/:/icons/icons/ui/edit.png?" + ((model.id == chat.model.edit) ? Nheko.colors.highlight : Nheko.colors.buttonText)
             ToolTip.visible: editHovered.hovered
             ToolTip.text: qsTr("Edited")
 
@@ -115,7 +115,7 @@ Item {
             Layout.alignment: Qt.AlignRight | Qt.AlignTop
             text: model.timestamp.toLocaleTimeString(Locale.ShortFormat)
             width: Math.max(implicitWidth, text.length * fontMetrics.maximumCharacterWidth)
-            color: inactiveColors.text
+            color: Nheko.inactiveColors.text
             ToolTip.visible: ma.hovered
             ToolTip.text: Qt.formatDateTime(model.timestamp, Qt.DefaultLocaleLongDate)
 
diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml
index 6750b427..52847db0 100644
--- a/resources/qml/TimelineView.qml
+++ b/resources/qml/TimelineView.qml
@@ -18,15 +18,13 @@ import im.nheko.EmojiModel 1.0
 Page {
     id: timelineRoot
 
-    property var colors: currentActivePalette
     property var systemInactive
-    property var inactiveColors: currentInactivePalette ? currentInactivePalette : systemInactive
     readonly property int avatarSize: 40
-    property real highlightHue: colors.highlight.hslHue
-    property real highlightSat: colors.highlight.hslSaturation
-    property real highlightLight: colors.highlight.hslLightness
+    property real highlightHue: Nheko.colors.highlight.hslHue
+    property real highlightSat: Nheko.colors.highlight.hslSaturation
+    property real highlightLight: Nheko.colors.highlight.hslLightness
 
-    palette: colors
+    palette: Nheko.colors
 
     FontMetrics {
         id: fontMetrics
@@ -219,7 +217,7 @@ Page {
 
     Rectangle {
         anchors.fill: parent
-        color: colors.window
+        color: Nheko.colors.window
 
         Component {
             id: deviceVerificationDialog
@@ -270,7 +268,7 @@ Page {
             anchors.centerIn: parent
             text: qsTr("No room open")
             font.pointSize: 24
-            color: colors.text
+            color: Nheko.colors.text
         }
 
         BusyIndicator {
@@ -296,7 +294,7 @@ Page {
                 Layout.fillWidth: true
                 height: 1
                 z: 3
-                color: colors.mid
+                color: Nheko.colors.mid
             }
 
             Rectangle {
@@ -304,7 +302,7 @@ Page {
 
                 Layout.fillWidth: true
                 Layout.fillHeight: true
-                color: colors.base
+                color: Nheko.colors.base
 
                 ColumnLayout {
                     anchors.fill: parent
@@ -358,7 +356,7 @@ Page {
                 Layout.fillWidth: true
                 z: 3
                 height: 1
-                color: colors.mid
+                color: Nheko.colors.mid
             }
 
             ReplyPopup {
@@ -383,8 +381,4 @@ Page {
         timelineRoot: timelineLayout
     }
 
-    systemInactive: SystemPalette {
-        colorGroup: SystemPalette.Disabled
-    }
-
 }
diff --git a/resources/qml/TopBar.qml b/resources/qml/TopBar.qml
index 0b943ed1..4de126b6 100644
--- a/resources/qml/TopBar.qml
+++ b/resources/qml/TopBar.qml
@@ -16,7 +16,7 @@ Rectangle {
     Layout.fillWidth: true
     implicitHeight: topLayout.height + 16
     z: 3
-    color: colors.window
+    color: Nheko.colors.window
 
     TapHandler {
         onSingleTapped: {
@@ -68,7 +68,7 @@ Rectangle {
             Layout.fillWidth: true
             Layout.column: 2
             Layout.row: 0
-            color: colors.text
+            color: Nheko.colors.text
             font.pointSize: fontMetrics.font.pointSize * 1.1
             text: room ? room.roomName : qsTr("No room selected")
             maximumLineCount: 1
diff --git a/resources/qml/TypingIndicator.qml b/resources/qml/TypingIndicator.qml
index ffe88fb6..783a9ebc 100644
--- a/resources/qml/TypingIndicator.qml
+++ b/resources/qml/TypingIndicator.qml
@@ -17,7 +17,7 @@ Item {
         id: typingRect
 
         visible: (room && room.typingUsers.length > 0)
-        color: colors.base
+        color: Nheko.colors.base
         anchors.fill: parent
         z: 3
 
@@ -29,8 +29,8 @@ Item {
             anchors.right: parent.right
             anchors.rightMargin: 10
             anchors.bottom: parent.bottom
-            color: colors.text
-            text: room ? room.formatTypingUsers(room.typingUsers, colors.base) : ""
+            color: Nheko.colors.text
+            text: room ? room.formatTypingUsers(room.typingUsers, Nheko.colors.base) : ""
             textFormat: Text.RichText
         }
 
diff --git a/resources/qml/UserProfile.qml b/resources/qml/UserProfile.qml
index 21c44793..4e5e64dc 100644
--- a/resources/qml/UserProfile.qml
+++ b/resources/qml/UserProfile.qml
@@ -19,8 +19,8 @@ ApplicationWindow {
     height: 650
     width: 420
     minimumHeight: 420
-    palette: colors
-    color: colors.window
+    palette: Nheko.colors
+    color: Nheko.colors.window
     title: profile.isGlobalUserProfile ? qsTr("Global User Profile") : qsTr("Room User Profile")
     modality: Qt.WindowModal
     flags: Qt.Dialog
@@ -97,7 +97,7 @@ ApplicationWindow {
             readOnly: !isUsernameEditingAllowed
             text: profile.displayName
             font.pixelSize: 20
-            color: TimelineManager.userColor(profile.userid, colors.window)
+            color: TimelineManager.userColor(profile.userid, Nheko.colors.window)
             font.bold: true
             Layout.alignment: Qt.AlignHCenter
             selectByMouse: true
@@ -145,7 +145,7 @@ ApplicationWindow {
         Image {
             Layout.preferredHeight: 16
             Layout.preferredWidth: 16
-	    source: "image://colorimage/:/icons/icons/ui/lock.png?" + ((profile.userVerified == Crypto.Verified) ?  "green" : colors.buttonText)
+            source: "image://colorimage/:/icons/icons/ui/lock.png?" + ((profile.userVerified == Crypto.Verified) ? "green" : Nheko.colors.buttonText)
             visible: profile.userVerified != Crypto.Unverified
             Layout.alignment: Qt.AlignHCenter
         }
@@ -218,7 +218,7 @@ ApplicationWindow {
                         Layout.alignment: Qt.AlignLeft
                         elide: Text.ElideRight
                         font.bold: true
-                        color: colors.text
+                        color: Nheko.colors.text
                         text: model.deviceId
                     }
 
@@ -226,7 +226,7 @@ ApplicationWindow {
                         Layout.fillWidth: true
                         Layout.alignment: Qt.AlignRight
                         elide: Text.ElideRight
-                        color: colors.text
+                        color: Nheko.colors.text
                         text: model.deviceName
                     }
 
diff --git a/resources/qml/delegates/FileMessage.qml b/resources/qml/delegates/FileMessage.qml
index e883ddbb..2e5f33c2 100644
--- a/resources/qml/delegates/FileMessage.qml
+++ b/resources/qml/delegates/FileMessage.qml
@@ -20,7 +20,7 @@ Item {
         Rectangle {
             id: button
 
-            color: colors.light
+            color: Nheko.colors.light
             radius: 22
             height: 44
             width: 44
@@ -55,7 +55,7 @@ Item {
                 text: model.data.filename
                 textFormat: Text.PlainText
                 elide: Text.ElideRight
-                color: colors.text
+                color: Nheko.colors.text
             }
 
             Text {
@@ -65,7 +65,7 @@ Item {
                 text: model.data.filesize
                 textFormat: Text.PlainText
                 elide: Text.ElideRight
-                color: colors.text
+                color: Nheko.colors.text
             }
 
         }
@@ -73,7 +73,7 @@ Item {
     }
 
     Rectangle {
-        color: colors.alternateBase
+        color: Nheko.colors.alternateBase
         z: -1
         radius: 10
         height: row.height + 24
diff --git a/resources/qml/delegates/ImageMessage.qml b/resources/qml/delegates/ImageMessage.qml
index 8fcf3f82..704af3fe 100644
--- a/resources/qml/delegates/ImageMessage.qml
+++ b/resources/qml/delegates/ImageMessage.qml
@@ -19,7 +19,7 @@ Item {
 
         anchors.fill: parent
         visible: img.status != Image.Ready
-        source: model.data.blurhash ? ("image://blurhash/" + model.data.blurhash) : ("image://colorimage/:/icons/icons/ui/do-not-disturb-rounded-sign@2x.png?" + colors.buttonText)
+        source: model.data.blurhash ? ("image://blurhash/" + model.data.blurhash) : ("image://colorimage/:/icons/icons/ui/do-not-disturb-rounded-sign@2x.png?" + Nheko.colors.buttonText)
         asynchronous: true
         fillMode: Image.PreserveAspectFit
         sourceSize.width: parent.width
@@ -61,7 +61,7 @@ Item {
                 width: parent.width
                 implicitHeight: imgcaption.implicitHeight
                 anchors.bottom: overlay.bottom
-                color: colors.window
+                color: Nheko.colors.window
                 opacity: 0.75
             }
 
@@ -74,7 +74,7 @@ Item {
                 verticalAlignment: Text.AlignVCenter
                 // See this MSC: https://github.com/matrix-org/matrix-doc/pull/2530
                 text: model.data.filename ? model.data.filename : model.data.body
-                color: colors.text
+                color: Nheko.colors.text
             }
 
         }
diff --git a/resources/qml/delegates/MessageDelegate.qml b/resources/qml/delegates/MessageDelegate.qml
index d278a586..4e6a73fe 100644
--- a/resources/qml/delegates/MessageDelegate.qml
+++ b/resources/qml/delegates/MessageDelegate.qml
@@ -58,7 +58,7 @@ Item {
 
             NoticeMessage {
                 formatted: TimelineManager.escapeEmoji(modelData.userName) + " " + model.data.formattedBody
-                color: TimelineManager.userColor(modelData.userId, colors.window)
+                color: TimelineManager.userColor(modelData.userId, Nheko.colors.window)
             }
 
         }
diff --git a/resources/qml/delegates/NoticeMessage.qml b/resources/qml/delegates/NoticeMessage.qml
index 4f8fbfd2..2af41bb2 100644
--- a/resources/qml/delegates/NoticeMessage.qml
+++ b/resources/qml/delegates/NoticeMessage.qml
@@ -2,7 +2,9 @@
 //
 // SPDX-License-Identifier: GPL-3.0-or-later
 
+import im.nheko 1.0
+
 TextMessage {
     font.italic: true
-    color: colors.buttonText
+    color: Nheko.colors.buttonText
 }
diff --git a/resources/qml/delegates/Pill.qml b/resources/qml/delegates/Pill.qml
index a3fa0d9e..fef226a7 100644
--- a/resources/qml/delegates/Pill.qml
+++ b/resources/qml/delegates/Pill.qml
@@ -6,14 +6,14 @@ import QtQuick 2.5
 import QtQuick.Controls 2.1
 
 Label {
-    color: colors.brightText
+    color: Nheko.colors.brightText
     horizontalAlignment: Text.AlignHCenter
     height: contentHeight * 1.2
     width: contentWidth * 1.2
 
     background: Rectangle {
         radius: parent.height / 2
-        color: colors.alternateBase
+        color: Nheko.colors.alternateBase
     }
 
 }
diff --git a/resources/qml/delegates/Placeholder.qml b/resources/qml/delegates/Placeholder.qml
index addbc7e7..c4fc6cc3 100644
--- a/resources/qml/delegates/Placeholder.qml
+++ b/resources/qml/delegates/Placeholder.qml
@@ -3,9 +3,10 @@
 // SPDX-License-Identifier: GPL-3.0-or-later
 
 import ".."
+import im.nheko 1.0
 
 MatrixText {
     text: qsTr("unimplemented event: ") + model.data.typeString
     width: parent ? parent.width : undefined
-    color: inactiveColors.text
+    color: Nheko.inactiveColors.text
 }
diff --git a/resources/qml/delegates/PlayableMediaMessage.qml b/resources/qml/delegates/PlayableMediaMessage.qml
index b62c90df..223c2a34 100644
--- a/resources/qml/delegates/PlayableMediaMessage.qml
+++ b/resources/qml/delegates/PlayableMediaMessage.qml
@@ -13,7 +13,7 @@ Rectangle {
     id: bg
 
     radius: 10
-    color: colors.alternateBase
+    color: Nheko.colors.alternateBase
     height: Math.round(content.height + 24)
     width: parent ? parent.width : undefined
 
@@ -58,7 +58,7 @@ Rectangle {
                 id: positionText
 
                 text: "--:--:--"
-                color: colors.text
+                color: Nheko.colors.text
             }
 
             Slider {
@@ -92,14 +92,14 @@ Rectangle {
                 to: media.duration
                 onMoved: media.seek(value)
                 onValueChanged: updatePositionTexts()
-                palette: colors
+                palette: Nheko.colors
             }
 
             Text {
                 id: durationText
 
                 text: "--:--:--"
-                color: colors.text
+                color: Nheko.colors.text
             }
 
         }
@@ -112,7 +112,7 @@ Rectangle {
                 id: button
 
                 Layout.alignment: Qt.AlignVCenter
-                //color: colors.window
+                //color: Nheko.colors.window
                 //radius: 22
                 height: 32
                 width: 32
@@ -194,7 +194,7 @@ Rectangle {
                     Layout.fillWidth: true
                     text: model.data.body
                     elide: Text.ElideRight
-                    color: colors.text
+                    color: Nheko.colors.text
                 }
 
                 Text {
@@ -202,7 +202,7 @@ Rectangle {
                     text: model.data.filesize
                     textFormat: Text.PlainText
                     elide: Text.ElideRight
-                    color: colors.text
+                    color: Nheko.colors.text
                 }
 
             }
diff --git a/resources/qml/delegates/Reply.qml b/resources/qml/delegates/Reply.qml
index 603d0cf6..b8c33539 100644
--- a/resources/qml/delegates/Reply.qml
+++ b/resources/qml/delegates/Reply.qml
@@ -33,7 +33,7 @@ Item {
         anchors.top: replyContainer.top
         anchors.bottom: replyContainer.bottom
         width: 4
-        color: TimelineManager.userColor(reply.modelData.userId, colors.window)
+        color: TimelineManager.userColor(reply.modelData.userId, Nheko.colors.window)
     }
 
     Column {
diff --git a/resources/qml/delegates/TextMessage.qml b/resources/qml/delegates/TextMessage.qml
index f44165b4..810ee3d4 100644
--- a/resources/qml/delegates/TextMessage.qml
+++ b/resources/qml/delegates/TextMessage.qml
@@ -9,7 +9,7 @@ MatrixText {
     property string formatted: model.data.formattedBody
     property string copyText: selectedText ? getText(selectionStart, selectionEnd) : model.data.body
 
-    text: "<style type=\"text/css\">a { color:" + colors.link + ";}\ncode { background-color: " + colors.alternateBase + ";}</style>" + formatted.replace("<pre>", "<pre style='white-space: pre-wrap; background-color: " + colors.alternateBase + "'>")
+    text: "<style type=\"text/css\">a { color:" + Nheko.colors.link + ";}\ncode { background-color: " + Nheko.colors.alternateBase + ";}</style>" + formatted.replace("<pre>", "<pre style='white-space: pre-wrap; background-color: " + Nheko.colors.alternateBase + "'>")
     width: parent ? parent.width : undefined
     height: isReply ? Math.round(Math.min(timelineRoot.height / 8, implicitHeight)) : undefined
     clip: isReply
diff --git a/resources/qml/device-verification/AwaitingVerificationConfirmation.qml b/resources/qml/device-verification/AwaitingVerificationConfirmation.qml
index ae62c334..a6a7f027 100644
--- a/resources/qml/device-verification/AwaitingVerificationConfirmation.qml
+++ b/resources/qml/device-verification/AwaitingVerificationConfirmation.qml
@@ -21,7 +21,7 @@ Pane {
             Layout.fillWidth: true
             wrapMode: Text.Wrap
             text: qsTr("Waiting for other side to complete verification.")
-            color: colors.text
+            color: Nheko.colors.text
             verticalAlignment: Text.AlignVCenter
         }
 
diff --git a/resources/qml/device-verification/DeviceVerification.qml b/resources/qml/device-verification/DeviceVerification.qml
index 41ed8d57..6d0be204 100644
--- a/resources/qml/device-verification/DeviceVerification.qml
+++ b/resources/qml/device-verification/DeviceVerification.qml
@@ -16,7 +16,7 @@ ApplicationWindow {
     title: stack.currentItem.title
     flags: Qt.Dialog
     modality: Qt.WindowModal
-    palette: colors
+    palette: Nheko.colors
     height: stack.implicitHeight
     width: stack.implicitWidth
     x: MainWindow.x + (MainWindow.width / 2) - (width / 2)
diff --git a/resources/qml/device-verification/DigitVerification.qml b/resources/qml/device-verification/DigitVerification.qml
index a387756d..aafdc043 100644
--- a/resources/qml/device-verification/DigitVerification.qml
+++ b/resources/qml/device-verification/DigitVerification.qml
@@ -19,7 +19,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: colors.text
+            color: Nheko.colors.text
             verticalAlignment: Text.AlignVCenter
         }
 
@@ -29,19 +29,19 @@ Pane {
             Label {
                 font.pixelSize: Qt.application.font.pixelSize * 2
                 text: flow.sasList[0]
-                color: colors.text
+                color: Nheko.colors.text
             }
 
             Label {
                 font.pixelSize: Qt.application.font.pixelSize * 2
                 text: flow.sasList[1]
-                color: colors.text
+                color: Nheko.colors.text
             }
 
             Label {
                 font.pixelSize: Qt.application.font.pixelSize * 2
                 text: flow.sasList[2]
-                color: colors.text
+                color: Nheko.colors.text
             }
 
         }
diff --git a/resources/qml/device-verification/EmojiVerification.qml b/resources/qml/device-verification/EmojiVerification.qml
index be9e3938..b6e8484f 100644
--- a/resources/qml/device-verification/EmojiVerification.qml
+++ b/resources/qml/device-verification/EmojiVerification.qml
@@ -19,7 +19,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: colors.text
+            color: Nheko.colors.text
             verticalAlignment: Text.AlignVCenter
         }
 
@@ -374,13 +374,13 @@ Pane {
                             text: col.emoji.emoji
                             font.pixelSize: Qt.application.font.pixelSize * 2
                             font.family: Settings.emojiFont
-                            color: colors.text
+                            color: Nheko.colors.text
                         }
 
                         Label {
                             Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
                             text: col.emoji.description
-                            color: colors.text
+                            color: Nheko.colors.text
                         }
 
                     }
diff --git a/resources/qml/device-verification/Failed.qml b/resources/qml/device-verification/Failed.qml
index 5c71b02e..71ef8b9b 100644
--- a/resources/qml/device-verification/Failed.qml
+++ b/resources/qml/device-verification/Failed.qml
@@ -38,7 +38,7 @@ Pane {
                     return "Unknown verification error.";
                 }
             }
-            color: colors.text
+            color: Nheko.colors.text
             verticalAlignment: Text.AlignVCenter
         }
 
diff --git a/resources/qml/device-verification/NewVerificationRequest.qml b/resources/qml/device-verification/NewVerificationRequest.qml
index e8589cf7..5ae2d25b 100644
--- a/resources/qml/device-verification/NewVerificationRequest.qml
+++ b/resources/qml/device-verification/NewVerificationRequest.qml
@@ -35,7 +35,7 @@ Pane {
                         return qsTr("Your device (%1) has requested to be verified.").arg(flow.deviceId);
                 }
             }
-            color: colors.text
+            color: Nheko.colors.text
             verticalAlignment: Text.AlignVCenter
         }
 
diff --git a/resources/qml/device-verification/Success.qml b/resources/qml/device-verification/Success.qml
index f2657b12..b858a1a1 100644
--- a/resources/qml/device-verification/Success.qml
+++ b/resources/qml/device-verification/Success.qml
@@ -20,7 +20,7 @@ Pane {
             Layout.fillWidth: true
             wrapMode: Text.Wrap
             text: qsTr("Verification successful! Both sides verified their devices!")
-            color: colors.text
+            color: Nheko.colors.text
             verticalAlignment: Text.AlignVCenter
         }
 
diff --git a/resources/qml/device-verification/Waiting.qml b/resources/qml/device-verification/Waiting.qml
index 3bfa153d..c521503b 100644
--- a/resources/qml/device-verification/Waiting.qml
+++ b/resources/qml/device-verification/Waiting.qml
@@ -30,13 +30,13 @@ Pane {
                     return qsTr("Waiting for other side to complete the verification process.");
                 }
             }
-            color: colors.text
+            color: Nheko.colors.text
             verticalAlignment: Text.AlignVCenter
         }
 
         BusyIndicator {
             Layout.alignment: Qt.AlignHCenter
-            palette: colors
+            palette: Nheko.colors
         }
 
         RowLayout {
diff --git a/resources/qml/emoji/EmojiPicker.qml b/resources/qml/emoji/EmojiPicker.qml
index 4aad832d..efcdc2cf 100644
--- a/resources/qml/emoji/EmojiPicker.qml
+++ b/resources/qml/emoji/EmojiPicker.qml
@@ -18,9 +18,9 @@ Menu {
     property alias model: gridView.model
     property var textArea
     property string emojiCategory: "people"
-    property real highlightHue: colors.highlight.hslHue
-    property real highlightSat: colors.highlight.hslSaturation
-    property real highlightLight: colors.highlight.hslLightness
+    property real highlightHue: Nheko.colors.highlight.hslHue
+    property real highlightSat: Nheko.colors.highlight.hslSaturation
+    property real highlightLight: Nheko.colors.highlight.hslLightness
 
     function show(showAt, callback) {
         console.debug("Showing emojiPicker");
@@ -80,7 +80,7 @@ Menu {
                 id: clearSearch
 
                 visible: emojiSearch.text !== ''
-                icon.source: "image://colorimage/:/icons/icons/ui/round-remove-button.png?" + (clearSearch.hovered ? colors.highlight : colors.buttonText)
+                icon.source: "image://colorimage/:/icons/icons/ui/round-remove-button.png?" + (clearSearch.hovered ? Nheko.colors.highlight : Nheko.colors.buttonText)
                 focusPolicy: Qt.NoFocus
                 onClicked: emojiSearch.clear()
 
@@ -146,7 +146,7 @@ Menu {
 
                 background: Rectangle {
                     anchors.fill: parent
-                    color: hovered ? colors.highlight : 'transparent'
+                    color: hovered ? Nheko.colors.highlight : 'transparent'
                     radius: 5
                 }
 
@@ -163,7 +163,7 @@ Menu {
             visible: emojiSearch.text === ''
             Layout.fillWidth: true
             Layout.preferredHeight: 1
-            color: emojiPopup.colors.alternateBase
+            color: emojiPopup.Nheko.colors.alternateBase
         }
 
         // Category picker row
@@ -265,14 +265,14 @@ Menu {
                         fillMode: Image.Pad
                         sourceSize.width: 32
                         sourceSize.height: 32
-                        source: "image://colorimage/" + model.image + "?" + (hovered ? colors.highlight : colors.buttonText)
+                        source: "image://colorimage/" + model.image + "?" + (hovered ? Nheko.colors.highlight : Nheko.colors.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 ? colors.highlight : 'transparent'
+                        border.color: emojiPopup.model.category === model.category ? Nheko.colors.highlight : 'transparent'
                     }
 
                 }
diff --git a/resources/qml/voip/CallDevices.qml b/resources/qml/voip/CallDevices.qml
index 11644797..824bb2e0 100644
--- a/resources/qml/voip/CallDevices.qml
+++ b/resources/qml/voip/CallDevices.qml
@@ -9,7 +9,7 @@ import im.nheko 1.0
 
 Popup {
     modal: true
-    palette: colors
+    palette: Nheko.colors
     // 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: {
@@ -31,7 +31,7 @@ Popup {
                 Image {
                     Layout.preferredWidth: 22
                     Layout.preferredHeight: 22
-                    source: "image://colorimage/:/icons/icons/ui/microphone-unmute.png?" + colors.windowText
+                    source: "image://colorimage/:/icons/icons/ui/microphone-unmute.png?" + Nheko.colors.windowText
                 }
 
                 ComboBox {
@@ -49,7 +49,7 @@ Popup {
                 Image {
                     Layout.preferredWidth: 22
                     Layout.preferredHeight: 22
-                    source: "image://colorimage/:/icons/icons/ui/video-call.png?" + colors.windowText
+                    source: "image://colorimage/:/icons/icons/ui/video-call.png?" + Nheko.colors.windowText
                 }
 
                 ComboBox {
@@ -81,8 +81,8 @@ Popup {
     }
 
     background: Rectangle {
-        color: colors.window
-        border.color: colors.windowText
+        color: Nheko.colors.window
+        border.color: Nheko.colors.windowText
     }
 
 }
diff --git a/resources/qml/voip/CallInvite.qml b/resources/qml/voip/CallInvite.qml
index 15d987e7..1b57976d 100644
--- a/resources/qml/voip/CallInvite.qml
+++ b/resources/qml/voip/CallInvite.qml
@@ -12,7 +12,7 @@ Popup {
     closePolicy: Popup.NoAutoClose
     width: parent.width
     height: parent.height
-    palette: colors
+    palette: Nheko.colors
 
     Component {
         id: deviceError
@@ -41,7 +41,7 @@ Popup {
             Layout.topMargin: msgView.height / 25
             text: CallManager.callParty
             font.pointSize: fontMetrics.font.pointSize * 2
-            color: colors.windowText
+            color: Nheko.colors.windowText
         }
 
         Avatar {
@@ -62,14 +62,14 @@ Popup {
                 Layout.alignment: Qt.AlignCenter
                 Layout.preferredWidth: msgView.height / 10
                 Layout.preferredHeight: msgView.height / 10
-                source: "image://colorimage/" + image + "?" + colors.windowText
+                source: "image://colorimage/" + image + "?" + Nheko.colors.windowText
             }
 
             Label {
                 Layout.alignment: Qt.AlignCenter
                 text: CallManager.callType == CallType.VIDEO ? qsTr("Video Call") : qsTr("Voice Call")
                 font.pointSize: fontMetrics.font.pointSize * 2
-                color: colors.windowText
+                color: Nheko.colors.windowText
             }
 
         }
@@ -88,7 +88,7 @@ Popup {
                 Image {
                     Layout.preferredWidth: deviceCombos.imageSize
                     Layout.preferredHeight: deviceCombos.imageSize
-                    source: "image://colorimage/:/icons/icons/ui/microphone-unmute.png?" + colors.windowText
+                    source: "image://colorimage/:/icons/icons/ui/microphone-unmute.png?" + Nheko.colors.windowText
                 }
 
                 ComboBox {
@@ -107,7 +107,7 @@ Popup {
                 Image {
                     Layout.preferredWidth: deviceCombos.imageSize
                     Layout.preferredHeight: deviceCombos.imageSize
-                    source: "image://colorimage/:/icons/icons/ui/video-call.png?" + colors.windowText
+                    source: "image://colorimage/:/icons/icons/ui/video-call.png?" + Nheko.colors.windowText
                 }
 
                 ComboBox {
@@ -194,8 +194,8 @@ Popup {
     }
 
     background: Rectangle {
-        color: colors.window
-        border.color: colors.windowText
+        color: Nheko.colors.window
+        border.color: Nheko.colors.windowText
     }
 
 }
diff --git a/resources/qml/voip/CallInviteBar.qml b/resources/qml/voip/CallInviteBar.qml
index fe3f791f..c20e4fff 100644
--- a/resources/qml/voip/CallInviteBar.qml
+++ b/resources/qml/voip/CallInviteBar.qml
@@ -88,7 +88,7 @@ Rectangle {
             Layout.rightMargin: 4
             icon.source: CallManager.callType == CallType.VIDEO ? "qrc:/icons/icons/ui/video-call.png" : "qrc:/icons/icons/ui/place-call.png"
             text: qsTr("Accept")
-            palette: colors
+            palette: Nheko.colors
             onClicked: {
                 if (CallManager.mics.length == 0) {
                     var dialog = deviceError.createObject(timelineRoot, {
@@ -121,7 +121,7 @@ Rectangle {
             Layout.rightMargin: 16
             icon.source: "qrc:/icons/icons/ui/end-call.png"
             text: qsTr("Decline")
-            palette: colors
+            palette: Nheko.colors
             onClicked: {
                 CallManager.hangUp();
             }
diff --git a/resources/qml/voip/DeviceError.qml b/resources/qml/voip/DeviceError.qml
index 05cfd409..47ded50a 100644
--- a/resources/qml/voip/DeviceError.qml
+++ b/resources/qml/voip/DeviceError.qml
@@ -24,19 +24,19 @@ Popup {
         Image {
             Layout.preferredWidth: 16
             Layout.preferredHeight: 16
-            source: "image://colorimage/" + image + "?" + colors.windowText
+            source: "image://colorimage/" + image + "?" + Nheko.colors.windowText
         }
 
         Label {
             text: errorString
-            color: colors.windowText
+            color: Nheko.colors.windowText
         }
 
     }
 
     background: Rectangle {
-        color: colors.window
-        border.color: colors.windowText
+        color: Nheko.colors.window
+        border.color: Nheko.colors.windowText
     }
 
 }
diff --git a/resources/qml/voip/PlaceCall.qml b/resources/qml/voip/PlaceCall.qml
index c9aa8ea1..d3306099 100644
--- a/resources/qml/voip/PlaceCall.qml
+++ b/resources/qml/voip/PlaceCall.qml
@@ -17,7 +17,7 @@ Popup {
             anchors.centerIn = parent;
 
     }
-    palette: colors
+    palette: Nheko.colors
 
     Component {
         id: deviceError
@@ -46,7 +46,7 @@ Popup {
 
             Label {
                 text: qsTr("Place a call to %1?").arg(TimelineManager.timeline.roomName)
-                color: colors.windowText
+                color: Nheko.colors.windowText
             }
 
             Item {
@@ -139,7 +139,7 @@ Popup {
                 Image {
                     Layout.preferredWidth: 22
                     Layout.preferredHeight: 22
-                    source: "image://colorimage/:/icons/icons/ui/microphone-unmute.png?" + colors.windowText
+                    source: "image://colorimage/:/icons/icons/ui/microphone-unmute.png?" + Nheko.colors.windowText
                 }
 
                 ComboBox {
@@ -160,7 +160,7 @@ Popup {
                 Image {
                     Layout.preferredWidth: 22
                     Layout.preferredHeight: 22
-                    source: "image://colorimage/:/icons/icons/ui/video-call.png?" + colors.windowText
+                    source: "image://colorimage/:/icons/icons/ui/video-call.png?" + Nheko.colors.windowText
                 }
 
                 ComboBox {
@@ -177,8 +177,8 @@ Popup {
     }
 
     background: Rectangle {
-        color: colors.window
-        border.color: colors.windowText
+        color: Nheko.colors.window
+        border.color: Nheko.colors.windowText
     }
 
 }
diff --git a/resources/qml/voip/ScreenShare.qml b/resources/qml/voip/ScreenShare.qml
index af473c04..258ac9b0 100644
--- a/resources/qml/voip/ScreenShare.qml
+++ b/resources/qml/voip/ScreenShare.qml
@@ -18,7 +18,7 @@ Popup {
 
         frameRateCombo.currentIndex = frameRateCombo.find(Settings.screenShareFrameRate);
     }
-    palette: colors
+    palette: Nheko.colors
 
     ColumnLayout {
         Label {
@@ -28,7 +28,7 @@ Popup {
             Layout.rightMargin: 8
             Layout.alignment: Qt.AlignLeft
             text: qsTr("Share desktop with %1?").arg(TimelineManager.timeline.roomName)
-            color: colors.windowText
+            color: Nheko.colors.windowText
         }
 
         RowLayout {
@@ -39,7 +39,7 @@ Popup {
             Label {
                 Layout.alignment: Qt.AlignLeft
                 text: qsTr("Window:")
-                color: colors.windowText
+                color: Nheko.colors.windowText
             }
 
             ComboBox {
@@ -59,7 +59,7 @@ Popup {
             Label {
                 Layout.alignment: Qt.AlignLeft
                 text: qsTr("Frame rate:")
-                color: colors.windowText
+                color: Nheko.colors.windowText
             }
 
             ComboBox {
@@ -161,8 +161,8 @@ Popup {
     }
 
     background: Rectangle {
-        color: colors.window
-        border.color: colors.windowText
+        color: Nheko.colors.window
+        border.color: Nheko.colors.windowText
     }
 
 }
diff --git a/src/timeline/TimelineViewManager.cpp b/src/timeline/TimelineViewManager.cpp
index 628f3c31..94cef1a7 100644
--- a/src/timeline/TimelineViewManager.cpp
+++ b/src/timeline/TimelineViewManager.cpp
@@ -32,6 +32,7 @@
 #include "emoji/Provider.h"
 #include "ui/NhekoCursorShape.h"
 #include "ui/NhekoDropArea.h"
+#include "ui/NhekoGlobalObject.h"
 
 Q_DECLARE_METATYPE(mtx::events::collections::TimelineEvents)
 Q_DECLARE_METATYPE(std::vector<DeviceInfo>)
@@ -221,6 +222,10 @@ TimelineViewManager::TimelineViewManager(CallManager *callManager, ChatPage *par
           "im.nheko", 1, 0, "Clipboard", [](QQmlEngine *, QJSEngine *) -> QObject * {
                   return new Clipboard();
           });
+        qmlRegisterSingletonType<Nheko>(
+          "im.nheko", 1, 0, "Nheko", [](QQmlEngine *, QJSEngine *) -> QObject * {
+                  return new Nheko();
+          });
 
         qRegisterMetaType<mtx::events::collections::TimelineEvents>();
         qRegisterMetaType<std::vector<DeviceInfo>>();
diff --git a/src/ui/NhekoGlobalObject.cpp b/src/ui/NhekoGlobalObject.cpp
new file mode 100644
index 00000000..5a2b9788
--- /dev/null
+++ b/src/ui/NhekoGlobalObject.cpp
@@ -0,0 +1,27 @@
+// SPDX-FileCopyrightText: 2021 Nheko Contributors
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "NhekoGlobalObject.h"
+
+#include "UserSettingsPage.h"
+
+Nheko::Nheko()
+{
+        connect(
+          UserSettings::instance().get(), &UserSettings::themeChanged, this, &Nheko::colorsChanged);
+}
+
+QPalette
+Nheko::colors() const
+{
+        return QPalette();
+}
+
+QPalette
+Nheko::inactiveColors() const
+{
+        QPalette p;
+        p.setCurrentColorGroup(QPalette::ColorGroup::Inactive);
+        return p;
+}
diff --git a/src/ui/NhekoGlobalObject.h b/src/ui/NhekoGlobalObject.h
new file mode 100644
index 00000000..76186828
--- /dev/null
+++ b/src/ui/NhekoGlobalObject.h
@@ -0,0 +1,25 @@
+// SPDX-FileCopyrightText: 2021 Nheko Contributors
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#pragma once
+
+#include <QObject>
+#include <QPalette>
+
+class Nheko : public QObject
+{
+        Q_OBJECT
+
+        Q_PROPERTY(QPalette colors READ colors NOTIFY colorsChanged)
+        Q_PROPERTY(QPalette inactiveColors READ inactiveColors NOTIFY colorsChanged)
+
+public:
+        Nheko();
+
+        QPalette colors() const;
+        QPalette inactiveColors() const;
+
+signals:
+        void colorsChanged();
+};