mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-24 21:42:51 -05:00
integrate light/dark mode and profile image with desktop portal
This commit is contained in:
@@ -22,7 +22,6 @@ Singleton {
|
|||||||
property bool use24HourClock: true
|
property bool use24HourClock: true
|
||||||
property bool useFahrenheit: false
|
property bool useFahrenheit: false
|
||||||
property bool nightModeEnabled: false
|
property bool nightModeEnabled: false
|
||||||
property string profileImage: ""
|
|
||||||
property string weatherLocation: "New York, NY"
|
property string weatherLocation: "New York, NY"
|
||||||
property string weatherCoordinates: "40.7128,-74.0060"
|
property string weatherCoordinates: "40.7128,-74.0060"
|
||||||
property bool useAutoLocation: false
|
property bool useAutoLocation: false
|
||||||
@@ -147,7 +146,6 @@ Singleton {
|
|||||||
use24HourClock = settings.use24HourClock !== undefined ? settings.use24HourClock : true;
|
use24HourClock = settings.use24HourClock !== undefined ? settings.use24HourClock : true;
|
||||||
useFahrenheit = settings.useFahrenheit !== undefined ? settings.useFahrenheit : false;
|
useFahrenheit = settings.useFahrenheit !== undefined ? settings.useFahrenheit : false;
|
||||||
nightModeEnabled = settings.nightModeEnabled !== undefined ? settings.nightModeEnabled : false;
|
nightModeEnabled = settings.nightModeEnabled !== undefined ? settings.nightModeEnabled : false;
|
||||||
profileImage = settings.profileImage !== undefined ? settings.profileImage : "";
|
|
||||||
weatherLocation = settings.weatherLocation !== undefined ? settings.weatherLocation : "New York, NY";
|
weatherLocation = settings.weatherLocation !== undefined ? settings.weatherLocation : "New York, NY";
|
||||||
weatherCoordinates = settings.weatherCoordinates !== undefined ? settings.weatherCoordinates : "40.7128,-74.0060";
|
weatherCoordinates = settings.weatherCoordinates !== undefined ? settings.weatherCoordinates : "40.7128,-74.0060";
|
||||||
useAutoLocation = settings.useAutoLocation !== undefined ? settings.useAutoLocation : false;
|
useAutoLocation = settings.useAutoLocation !== undefined ? settings.useAutoLocation : false;
|
||||||
@@ -229,7 +227,6 @@ Singleton {
|
|||||||
"use24HourClock": use24HourClock,
|
"use24HourClock": use24HourClock,
|
||||||
"useFahrenheit": useFahrenheit,
|
"useFahrenheit": useFahrenheit,
|
||||||
"nightModeEnabled": nightModeEnabled,
|
"nightModeEnabled": nightModeEnabled,
|
||||||
"profileImage": profileImage,
|
|
||||||
"weatherLocation": weatherLocation,
|
"weatherLocation": weatherLocation,
|
||||||
"weatherCoordinates": weatherCoordinates,
|
"weatherCoordinates": weatherCoordinates,
|
||||||
"useAutoLocation": useAutoLocation,
|
"useAutoLocation": useAutoLocation,
|
||||||
@@ -421,10 +418,6 @@ Singleton {
|
|||||||
saveSettings();
|
saveSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
function setProfileImage(imageUrl) {
|
|
||||||
profileImage = imageUrl;
|
|
||||||
saveSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Widget visibility setters
|
// Widget visibility setters
|
||||||
function setShowLauncherButton(enabled) {
|
function setShowLauncherButton(enabled) {
|
||||||
|
|||||||
@@ -151,13 +151,13 @@ PanelWindow {
|
|||||||
id: profileImageLoader
|
id: profileImageLoader
|
||||||
|
|
||||||
source: {
|
source: {
|
||||||
if (Prefs.profileImage === "")
|
if (PortalService.profileImage === "")
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
if (Prefs.profileImage.startsWith("/"))
|
if (PortalService.profileImage.startsWith("/"))
|
||||||
return "file://" + Prefs.profileImage;
|
return "file://" + PortalService.profileImage;
|
||||||
|
|
||||||
return Prefs.profileImage;
|
return PortalService.profileImage;
|
||||||
}
|
}
|
||||||
smooth: true
|
smooth: true
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
@@ -215,7 +215,7 @@ PanelWindow {
|
|||||||
name: "warning"
|
name: "warning"
|
||||||
size: Theme.iconSize + 8
|
size: Theme.iconSize + 8
|
||||||
color: Theme.primaryText
|
color: Theme.primaryText
|
||||||
visible: Prefs.profileImage !== "" && profileImageLoader.status === Image.Error
|
visible: PortalService.profileImage !== "" && profileImageLoader.status === Image.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -743,8 +743,7 @@ PanelWindow {
|
|||||||
description: "Use light theme instead of dark theme"
|
description: "Use light theme instead of dark theme"
|
||||||
checked: Prefs.isLightMode
|
checked: Prefs.isLightMode
|
||||||
onToggled: (checked) => {
|
onToggled: (checked) => {
|
||||||
Prefs.setLightMode(checked);
|
PortalService.setLightMode(checked);
|
||||||
Theme.isLightMode = checked;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -167,11 +167,11 @@ Item {
|
|||||||
Image {
|
Image {
|
||||||
id: profileImageLoader
|
id: profileImageLoader
|
||||||
source: {
|
source: {
|
||||||
if (Prefs.profileImage === "")
|
if (PortalService.profileImage === "")
|
||||||
return ""
|
return ""
|
||||||
if (Prefs.profileImage.startsWith("/"))
|
if (PortalService.profileImage.startsWith("/"))
|
||||||
return "file://" + Prefs.profileImage
|
return "file://" + PortalService.profileImage
|
||||||
return Prefs.profileImage
|
return PortalService.profileImage
|
||||||
}
|
}
|
||||||
smooth: true
|
smooth: true
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
@@ -226,7 +226,7 @@ Item {
|
|||||||
name: "warning"
|
name: "warning"
|
||||||
size: Theme.iconSize + 4
|
size: Theme.iconSize + 4
|
||||||
color: Theme.primaryText
|
color: Theme.primaryText
|
||||||
visible: Prefs.profileImage !== "" && profileImageLoader.status === Image.Error
|
visible: PortalService.profileImage !== "" && profileImageLoader.status === Image.Error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -76,8 +76,7 @@ ScrollView {
|
|||||||
description: "Use light theme instead of dark theme"
|
description: "Use light theme instead of dark theme"
|
||||||
checked: Prefs.isLightMode
|
checked: Prefs.isLightMode
|
||||||
onToggled: (checked) => {
|
onToggled: (checked) => {
|
||||||
Prefs.setLightMode(checked);
|
PortalService.setLightMode(checked);
|
||||||
Theme.isLightMode = checked;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -83,13 +83,13 @@ ScrollView {
|
|||||||
id: avatarImageSource
|
id: avatarImageSource
|
||||||
|
|
||||||
source: {
|
source: {
|
||||||
if (Prefs.profileImage === "")
|
if (PortalService.profileImage === "")
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
if (Prefs.profileImage.startsWith("/"))
|
if (PortalService.profileImage.startsWith("/"))
|
||||||
return "file://" + Prefs.profileImage;
|
return "file://" + PortalService.profileImage;
|
||||||
|
|
||||||
return Prefs.profileImage;
|
return PortalService.profileImage;
|
||||||
}
|
}
|
||||||
smooth: true
|
smooth: true
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
@@ -147,7 +147,7 @@ ScrollView {
|
|||||||
name: "warning"
|
name: "warning"
|
||||||
size: Theme.iconSizeLarge
|
size: Theme.iconSizeLarge
|
||||||
color: Theme.error
|
color: Theme.error
|
||||||
visible: Prefs.profileImage !== "" && avatarImageSource.status === Image.Error
|
visible: PortalService.profileImage !== "" && avatarImageSource.status === Image.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -158,7 +158,7 @@ ScrollView {
|
|||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: Prefs.profileImage ? Prefs.profileImage.split('/').pop() : "No profile image selected"
|
text: PortalService.profileImage ? PortalService.profileImage.split('/').pop() : "No profile image selected"
|
||||||
font.pixelSize: Theme.fontSizeLarge
|
font.pixelSize: Theme.fontSizeLarge
|
||||||
color: Theme.surfaceText
|
color: Theme.surfaceText
|
||||||
elide: Text.ElideMiddle
|
elide: Text.ElideMiddle
|
||||||
@@ -166,12 +166,32 @@ ScrollView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
text: Prefs.profileImage ? Prefs.profileImage : ""
|
text: PortalService.profileImage ? PortalService.profileImage : ""
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.surfaceVariantText
|
color: Theme.surfaceVariantText
|
||||||
elide: Text.ElideMiddle
|
elide: Text.ElideMiddle
|
||||||
width: parent.width
|
width: parent.width
|
||||||
visible: Prefs.profileImage !== ""
|
visible: PortalService.profileImage !== ""
|
||||||
|
}
|
||||||
|
|
||||||
|
Row {
|
||||||
|
spacing: Theme.spacingXS
|
||||||
|
visible: !PortalService.accountsServiceAvailable
|
||||||
|
|
||||||
|
DankIcon {
|
||||||
|
name: "error"
|
||||||
|
size: Theme.iconSizeSmall
|
||||||
|
color: Theme.error
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: "xdg-desktop-portal-gtk missing"
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.error
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
@@ -214,12 +234,13 @@ ScrollView {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
StyledRect {
|
StyledRect {
|
||||||
width: 80
|
width: 80
|
||||||
height: 32
|
height: 32
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
color: Theme.surfaceVariant
|
color: Theme.surfaceVariant
|
||||||
opacity: Prefs.profileImage !== "" ? 1 : 0.5
|
opacity: PortalService.profileImage !== "" ? 1 : 0.5
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
@@ -243,10 +264,10 @@ ScrollView {
|
|||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
enabled: Prefs.profileImage !== ""
|
enabled: PortalService.profileImage !== ""
|
||||||
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||||
onClicked: {
|
onClicked: {
|
||||||
Prefs.setProfileImage("");
|
PortalService.setProfileImage("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -551,7 +572,7 @@ ScrollView {
|
|||||||
browserType: "profile"
|
browserType: "profile"
|
||||||
fileExtensions: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp"]
|
fileExtensions: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp"]
|
||||||
onFileSelected: (path) => {
|
onFileSelected: (path) => {
|
||||||
Prefs.setProfileImage(path);
|
PortalService.setProfileImage(path);
|
||||||
visible = false;
|
visible = false;
|
||||||
}
|
}
|
||||||
onDialogClosed: {}
|
onDialogClosed: {}
|
||||||
|
|||||||
186
Services/PortalService.qml
Normal file
186
Services/PortalService.qml
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
pragma Singleton
|
||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Io
|
||||||
|
|
||||||
|
Singleton {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property bool accountsServiceAvailable: false
|
||||||
|
property string systemProfileImage: ""
|
||||||
|
property string profileImage: ""
|
||||||
|
property bool settingsPortalAvailable: false
|
||||||
|
property int systemColorScheme: 0 // 0=default, 1=prefer-dark, 2=prefer-light
|
||||||
|
|
||||||
|
function getSystemProfileImage() {
|
||||||
|
systemProfileCheckProcess.running = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function setProfileImage(imagePath) {
|
||||||
|
profileImage = imagePath
|
||||||
|
if (accountsServiceAvailable && imagePath) {
|
||||||
|
setSystemProfileImage(imagePath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSystemColorScheme() {
|
||||||
|
systemColorSchemeCheckProcess.running = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function setLightMode(isLightMode) {
|
||||||
|
if (typeof Theme !== "undefined") {
|
||||||
|
Theme.isLightMode = isLightMode
|
||||||
|
}
|
||||||
|
if (typeof Prefs !== "undefined") {
|
||||||
|
Prefs.setLightMode(isLightMode)
|
||||||
|
}
|
||||||
|
if (settingsPortalAvailable) {
|
||||||
|
setSystemColorScheme(isLightMode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setSystemColorScheme(isLightMode) {
|
||||||
|
if (!settingsPortalAvailable) return
|
||||||
|
|
||||||
|
var colorScheme = isLightMode ? "prefer-light" : "prefer-dark"
|
||||||
|
var script = "gsettings set org.gnome.desktop.interface color-scheme '" + colorScheme + "'"
|
||||||
|
|
||||||
|
systemColorSchemeSetProcess.command = ["bash", "-c", script]
|
||||||
|
systemColorSchemeSetProcess.running = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function setSystemProfileImage(imagePath) {
|
||||||
|
if (!accountsServiceAvailable || !imagePath) return
|
||||||
|
|
||||||
|
var script = [
|
||||||
|
"dbus-send --system --print-reply --dest=org.freedesktop.Accounts",
|
||||||
|
"/org/freedesktop/Accounts/User$(id -u)",
|
||||||
|
"org.freedesktop.Accounts.User.SetIconFile",
|
||||||
|
"string:'" + imagePath + "'"
|
||||||
|
].join(" ")
|
||||||
|
|
||||||
|
systemProfileSetProcess.command = ["bash", "-c", script]
|
||||||
|
systemProfileSetProcess.running = true
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
checkAccountsService()
|
||||||
|
checkSettingsPortal()
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkAccountsService() {
|
||||||
|
accountsServiceCheckProcess.running = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkSettingsPortal() {
|
||||||
|
settingsPortalCheckProcess.running = true
|
||||||
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: accountsServiceCheckProcess
|
||||||
|
command: ["bash", "-c", "dbus-send --system --print-reply --dest=org.freedesktop.Accounts /org/freedesktop/Accounts org.freedesktop.Accounts.FindUserByName string:\"$USER\""]
|
||||||
|
running: false
|
||||||
|
|
||||||
|
onExited: (exitCode) => {
|
||||||
|
root.accountsServiceAvailable = (exitCode === 0)
|
||||||
|
if (root.accountsServiceAvailable) {
|
||||||
|
root.getSystemProfileImage()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: systemProfileCheckProcess
|
||||||
|
command: ["bash", "-c", "dbus-send --system --print-reply --dest=org.freedesktop.Accounts /org/freedesktop/Accounts/User$(id -u) org.freedesktop.DBus.Properties.Get string:org.freedesktop.Accounts.User string:IconFile"]
|
||||||
|
running: false
|
||||||
|
|
||||||
|
stdout: StdioCollector {
|
||||||
|
onStreamFinished: {
|
||||||
|
var match = text.match(/string\s+"([^"]+)"/)
|
||||||
|
if (match && match[1] && match[1] !== "" && match[1] !== "/var/lib/AccountsService/icons/") {
|
||||||
|
root.systemProfileImage = match[1]
|
||||||
|
|
||||||
|
if (!root.profileImage || root.profileImage === "") {
|
||||||
|
root.profileImage = root.systemProfileImage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onExited: (exitCode) => {
|
||||||
|
if (exitCode !== 0) {
|
||||||
|
root.systemProfileImage = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: systemProfileSetProcess
|
||||||
|
running: false
|
||||||
|
|
||||||
|
onExited: (exitCode) => {
|
||||||
|
if (exitCode === 0) {
|
||||||
|
root.getSystemProfileImage()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: settingsPortalCheckProcess
|
||||||
|
command: ["gdbus", "call", "--session", "--dest", "org.freedesktop.portal.Desktop", "--object-path", "/org/freedesktop/portal/desktop", "--method", "org.freedesktop.portal.Settings.ReadOne", "org.freedesktop.appearance", "color-scheme"]
|
||||||
|
running: false
|
||||||
|
|
||||||
|
onExited: (exitCode) => {
|
||||||
|
root.settingsPortalAvailable = (exitCode === 0)
|
||||||
|
if (root.settingsPortalAvailable) {
|
||||||
|
root.getSystemColorScheme()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: systemColorSchemeCheckProcess
|
||||||
|
command: ["gdbus", "call", "--session", "--dest", "org.freedesktop.portal.Desktop", "--object-path", "/org/freedesktop/portal/desktop", "--method", "org.freedesktop.portal.Settings.ReadOne", "org.freedesktop.appearance", "color-scheme"]
|
||||||
|
running: false
|
||||||
|
|
||||||
|
stdout: StdioCollector {
|
||||||
|
onStreamFinished: {
|
||||||
|
var match = text.match(/uint32 (\d+)/)
|
||||||
|
if (match && match[1]) {
|
||||||
|
root.systemColorScheme = parseInt(match[1])
|
||||||
|
|
||||||
|
if (typeof Theme !== "undefined") {
|
||||||
|
var shouldBeLightMode = (root.systemColorScheme === 2)
|
||||||
|
if (Theme.isLightMode !== shouldBeLightMode) {
|
||||||
|
Theme.isLightMode = shouldBeLightMode
|
||||||
|
if (typeof Prefs !== "undefined") {
|
||||||
|
Prefs.setLightMode(shouldBeLightMode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onExited: (exitCode) => {
|
||||||
|
if (exitCode !== 0) {
|
||||||
|
root.systemColorScheme = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: systemColorSchemeSetProcess
|
||||||
|
running: false
|
||||||
|
|
||||||
|
onExited: (exitCode) => {
|
||||||
|
if (exitCode === 0) {
|
||||||
|
Qt.callLater(() => {
|
||||||
|
root.getSystemColorScheme()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user