mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-06 05:25:41 -05:00
397 lines
14 KiB
QML
397 lines
14 KiB
QML
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
|
|
|
|
property var dmsService: null
|
|
property bool freedeskAvailable: false
|
|
|
|
function init() {}
|
|
|
|
function getSystemProfileImage() {
|
|
if (freedeskAvailable && dmsService && dmsService.service) {
|
|
const username = Quickshell.env("USER")
|
|
if (!username) return
|
|
|
|
dmsService.service.sendRequest("freedesktop.accounts.getUserIconFile", { username: username }, response => {
|
|
if (response.result && response.result.success) {
|
|
const iconFile = response.result.value || ""
|
|
if (iconFile && iconFile !== "" && iconFile !== "/var/lib/AccountsService/icons/") {
|
|
systemProfileImage = iconFile
|
|
if (!profileImage || profileImage === "") {
|
|
profileImage = iconFile
|
|
}
|
|
}
|
|
}
|
|
})
|
|
} else {
|
|
systemProfileCheckProcess.running = true
|
|
}
|
|
}
|
|
|
|
function getUserProfileImage(username) {
|
|
if (!username) {
|
|
profileImage = ""
|
|
return
|
|
}
|
|
if (Quickshell.env("DMS_RUN_GREETER") === "1" || Quickshell.env("DMS_RUN_GREETER") === "true") {
|
|
profileImage = ""
|
|
return
|
|
}
|
|
|
|
if (freedeskAvailable && dmsService && dmsService.service) {
|
|
dmsService.service.sendRequest("freedesktop.accounts.getUserIconFile", { username: username }, response => {
|
|
if (response.result && response.result.success) {
|
|
const icon = response.result.value || ""
|
|
if (icon && icon !== "" && icon !== "/var/lib/AccountsService/icons/") {
|
|
profileImage = icon
|
|
} else {
|
|
profileImage = ""
|
|
}
|
|
} else {
|
|
profileImage = ""
|
|
}
|
|
})
|
|
} else {
|
|
userProfileCheckProcess.command = [
|
|
"bash", "-c",
|
|
`uid=$(id -u ${username} 2>/dev/null) && [ -n "$uid" ] && dbus-send --system --print-reply --dest=org.freedesktop.Accounts /org/freedesktop/Accounts/User$uid org.freedesktop.DBus.Properties.Get string:org.freedesktop.Accounts.User string:IconFile 2>/dev/null | grep -oP 'string "\\K[^"]+' || echo ""`
|
|
]
|
|
userProfileCheckProcess.running = true
|
|
}
|
|
}
|
|
|
|
function setProfileImage(imagePath) {
|
|
profileImage = imagePath
|
|
if (accountsServiceAvailable) {
|
|
if (imagePath) {
|
|
setSystemProfileImage(imagePath)
|
|
} else {
|
|
setSystemProfileImage("")
|
|
}
|
|
}
|
|
}
|
|
|
|
function getSystemColorScheme() {
|
|
if (freedeskAvailable && dmsService && dmsService.service) {
|
|
dmsService.service.sendRequest("freedesktop.settings.getColorScheme", null, response => {
|
|
if (response.result) {
|
|
systemColorScheme = response.result.value || 0
|
|
|
|
if (typeof Theme !== "undefined") {
|
|
const shouldBeLightMode = (systemColorScheme === 2)
|
|
if (Theme.isLightMode !== shouldBeLightMode) {
|
|
Theme.isLightMode = shouldBeLightMode
|
|
if (typeof SessionData !== "undefined") {
|
|
SessionData.setLightMode(shouldBeLightMode)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})
|
|
} else {
|
|
systemColorSchemeCheckProcess.running = true
|
|
}
|
|
}
|
|
|
|
function setLightMode(isLightMode) {
|
|
if (settingsPortalAvailable) {
|
|
setSystemColorScheme(isLightMode)
|
|
}
|
|
}
|
|
|
|
function setSystemColorScheme(isLightMode) {
|
|
if (!settingsPortalAvailable) return
|
|
|
|
const colorScheme = isLightMode ? "default" : "prefer-dark"
|
|
colorSchemeSetProcess.command = ["gsettings", "set", "org.gnome.desktop.interface", "color-scheme", colorScheme]
|
|
colorSchemeSetProcess.running = true
|
|
}
|
|
|
|
Process {
|
|
id: colorSchemeSetProcess
|
|
running: false
|
|
|
|
onExited: exitCode => {
|
|
if (exitCode === 0) {
|
|
Qt.callLater(() => getSystemColorScheme())
|
|
}
|
|
}
|
|
}
|
|
|
|
function setSystemProfileImage(imagePath) {
|
|
if (!accountsServiceAvailable) return
|
|
|
|
if (freedeskAvailable && dmsService && dmsService.service) {
|
|
dmsService.service.sendRequest("freedesktop.accounts.setIconFile", { path: imagePath || "" }, response => {
|
|
if (response.error) {
|
|
console.warn("PortalService: Failed to set icon file:", response.error)
|
|
} else {
|
|
Qt.callLater(() => getSystemProfileImage())
|
|
}
|
|
})
|
|
} else {
|
|
const path = imagePath || ""
|
|
systemProfileSetProcess.command = ["bash", "-c", `dbus-send --system --print-reply --dest=org.freedesktop.Accounts /org/freedesktop/Accounts/User$(id -u) org.freedesktop.Accounts.User.SetIconFile string:'${path}'`]
|
|
systemProfileSetProcess.running = true
|
|
}
|
|
}
|
|
|
|
Component.onCompleted: {
|
|
Qt.callLater(initializeDMSConnection)
|
|
}
|
|
|
|
function initializeDMSConnection() {
|
|
try {
|
|
dmsService = Qt.createQmlObject('import QtQuick; import qs.Services; QtObject { property var service: DMSService }', root)
|
|
if (dmsService && dmsService.service) {
|
|
dmsService.service.connectionStateChanged.connect(onDMSConnectionStateChanged)
|
|
dmsService.service.capabilitiesChanged.connect(onDMSCapabilitiesChanged)
|
|
if (dmsService.service.isConnected) {
|
|
onDMSConnected()
|
|
} else {
|
|
Qt.callLater(checkFallback)
|
|
}
|
|
} else {
|
|
Qt.callLater(checkFallback)
|
|
}
|
|
} catch (e) {
|
|
console.warn("PortalService: Failed to initialize DMS connection:", e)
|
|
Qt.callLater(checkFallback)
|
|
}
|
|
}
|
|
|
|
function checkFallback() {
|
|
if (!freedeskAvailable) {
|
|
console.log("PortalService: DMS not available, using fallback methods")
|
|
checkAccountsServiceFallback()
|
|
checkSettingsPortalFallback()
|
|
}
|
|
}
|
|
|
|
function onDMSConnectionStateChanged() {
|
|
if (dmsService && dmsService.service && dmsService.service.isConnected) {
|
|
onDMSConnected()
|
|
}
|
|
}
|
|
|
|
function onDMSCapabilitiesChanged() {
|
|
if (dmsService && dmsService.service && dmsService.service.capabilities.includes("freedesktop")) {
|
|
freedeskAvailable = true
|
|
checkAccountsService()
|
|
checkSettingsPortal()
|
|
}
|
|
}
|
|
|
|
function onDMSConnected() {
|
|
if (dmsService && dmsService.service && dmsService.service.capabilities && dmsService.service.capabilities.length > 0) {
|
|
freedeskAvailable = dmsService.service.capabilities.includes("freedesktop")
|
|
if (freedeskAvailable) {
|
|
checkAccountsService()
|
|
checkSettingsPortal()
|
|
}
|
|
}
|
|
}
|
|
|
|
function checkAccountsService() {
|
|
if (!freedeskAvailable || !dmsService || !dmsService.service) return
|
|
|
|
dmsService.service.sendRequest("freedesktop.getState", null, response => {
|
|
if (response.result && response.result.accounts) {
|
|
accountsServiceAvailable = response.result.accounts.available || false
|
|
if (accountsServiceAvailable) {
|
|
getSystemProfileImage()
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
function checkSettingsPortal() {
|
|
if (!freedeskAvailable || !dmsService || !dmsService.service) return
|
|
|
|
dmsService.service.sendRequest("freedesktop.getState", null, response => {
|
|
if (response.result && response.result.settings) {
|
|
settingsPortalAvailable = response.result.settings.available || false
|
|
if (settingsPortalAvailable) {
|
|
getSystemColorScheme()
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
function checkAccountsServiceFallback() {
|
|
accountsServiceCheckProcess.running = true
|
|
}
|
|
|
|
function checkSettingsPortalFallback() {
|
|
settingsPortalCheckProcess.running = true
|
|
}
|
|
|
|
function getGreeterUserProfileImage(username) {
|
|
if (!username) {
|
|
profileImage = ""
|
|
return
|
|
}
|
|
userProfileCheckProcess.command = [
|
|
"bash", "-c",
|
|
`uid=$(id -u ${username} 2>/dev/null) && [ -n "$uid" ] && dbus-send --system --print-reply --dest=org.freedesktop.Accounts /org/freedesktop/Accounts/User$uid org.freedesktop.DBus.Properties.Get string:org.freedesktop.Accounts.User string:IconFile 2>/dev/null | grep -oP 'string "\\K[^"]+' || echo ""`
|
|
]
|
|
userProfileCheckProcess.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 => {
|
|
accountsServiceAvailable = (exitCode === 0)
|
|
if (accountsServiceAvailable) {
|
|
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: {
|
|
const match = text.match(/string\s+"([^"]+)"/)
|
|
if (match && match[1] && match[1] !== "" && match[1] !== "/var/lib/AccountsService/icons/") {
|
|
systemProfileImage = match[1]
|
|
if (!profileImage || profileImage === "") {
|
|
profileImage = systemProfileImage
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
onExited: exitCode => {
|
|
if (exitCode !== 0) {
|
|
systemProfileImage = ""
|
|
}
|
|
}
|
|
}
|
|
|
|
Process {
|
|
id: systemProfileSetProcess
|
|
running: false
|
|
|
|
onExited: exitCode => {
|
|
if (exitCode === 0) {
|
|
getSystemProfileImage()
|
|
}
|
|
}
|
|
}
|
|
|
|
Process {
|
|
id: userProfileCheckProcess
|
|
command: []
|
|
running: false
|
|
|
|
stdout: StdioCollector {
|
|
onStreamFinished: {
|
|
const trimmed = text.trim()
|
|
if (trimmed && trimmed !== "" && !trimmed.includes("Error") && trimmed !== "/var/lib/AccountsService/icons/") {
|
|
root.profileImage = trimmed
|
|
} else {
|
|
root.profileImage = ""
|
|
}
|
|
}
|
|
}
|
|
|
|
onExited: exitCode => {
|
|
if (exitCode !== 0) {
|
|
root.profileImage = ""
|
|
}
|
|
}
|
|
}
|
|
|
|
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 => {
|
|
settingsPortalAvailable = (exitCode === 0)
|
|
if (settingsPortalAvailable) {
|
|
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: {
|
|
const match = text.match(/uint32 (\d+)/)
|
|
if (match && match[1]) {
|
|
systemColorScheme = parseInt(match[1])
|
|
|
|
if (typeof Theme !== "undefined") {
|
|
const shouldBeLightMode = (systemColorScheme === 2)
|
|
if (Theme.isLightMode !== shouldBeLightMode) {
|
|
Theme.isLightMode = shouldBeLightMode
|
|
if (typeof SessionData !== "undefined") {
|
|
SessionData.setLightMode(shouldBeLightMode)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
onExited: exitCode => {
|
|
if (exitCode !== 0) {
|
|
systemColorScheme = 0
|
|
}
|
|
}
|
|
}
|
|
|
|
IpcHandler {
|
|
target: "profile"
|
|
|
|
function getImage(): string {
|
|
return root.profileImage
|
|
}
|
|
|
|
function setImage(path: string): string {
|
|
if (!path) {
|
|
return "ERROR: No path provided"
|
|
}
|
|
|
|
const absolutePath = path.startsWith("/") ? path : `${StandardPaths.writableLocation(StandardPaths.HomeLocation)}/${path}`
|
|
|
|
try {
|
|
root.setProfileImage(absolutePath)
|
|
return "SUCCESS: Profile image set to " + absolutePath
|
|
} catch (e) {
|
|
return "ERROR: Failed to set profile image: " + e.toString()
|
|
}
|
|
}
|
|
|
|
function clearImage(): string {
|
|
root.setProfileImage("")
|
|
return "SUCCESS: Profile image cleared"
|
|
}
|
|
}
|
|
}
|