mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-24 21:42:51 -05:00
api: unify dms API clients
- Single subscribe socket - Single req/callback socket - Remove PrepareForSleep handling - Dependency on dms API version enforcement - Remove gdbus from portal and session
This commit is contained in:
@@ -67,12 +67,26 @@ Item {
|
|||||||
onToggled: checked => SettingsData.setLockScreenShowPowerActions(checked)
|
onToggled: checked => SettingsData.setLockScreenShowPowerActions(checked)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
text: I18n.tr("loginctl not available - lock integration requires DMS socket connection")
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.warning
|
||||||
|
visible: !SessionService.loginctlAvailable
|
||||||
|
width: parent.width
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
}
|
||||||
|
|
||||||
DankToggle {
|
DankToggle {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
text: I18n.tr("Enable loginctl lock integration")
|
text: I18n.tr("Enable loginctl lock integration")
|
||||||
description: "Bind lock screen to dbus signals from loginctl. Disable if using an external lock screen."
|
description: "Bind lock screen to dbus signals from loginctl. Disable if using an external lock screen."
|
||||||
checked: SessionData.loginctlLockIntegration
|
checked: SessionService.loginctlAvailable && SessionData.loginctlLockIntegration
|
||||||
onToggled: checked => SessionData.setLoginctlLockIntegration(checked)
|
enabled: SessionService.loginctlAvailable
|
||||||
|
onToggled: checked => {
|
||||||
|
if (SessionService.loginctlAvailable) {
|
||||||
|
SessionData.setLoginctlLockIntegration(checked)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DankToggle {
|
DankToggle {
|
||||||
@@ -80,7 +94,7 @@ Item {
|
|||||||
text: I18n.tr("Lock before suspend")
|
text: I18n.tr("Lock before suspend")
|
||||||
description: "Automatically lock the screen when the system prepares to suspend"
|
description: "Automatically lock the screen when the system prepares to suspend"
|
||||||
checked: SessionData.lockBeforeSuspend
|
checked: SessionData.lockBeforeSuspend
|
||||||
visible: SessionData.loginctlLockIntegration
|
visible: SessionService.loginctlAvailable && SessionData.loginctlLockIntegration
|
||||||
onToggled: checked => SessionData.setLockBeforeSuspend(checked)
|
onToggled: checked => SessionData.setLockBeforeSuspend(checked)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ PanelWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
width: Math.min(900, messageText.implicitWidth + statusIcon.width + Theme.spacingM + (ToastService.hasDetails ? (expandButton.width + closeButton.width + 4) : 0) + Theme.spacingL * 2 + Theme.spacingM * 2)
|
width: shouldBeVisible ? Math.min(900, messageText.implicitWidth + statusIcon.width + Theme.spacingM + (ToastService.hasDetails ? (expandButton.width + closeButton.width + 4) : 0) + Theme.spacingL * 2 + Theme.spacingM * 2) : frozenWidth
|
||||||
height: toastContent.height + Theme.spacingL * 2
|
height: toastContent.height + Theme.spacingL * 2
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
y: Theme.barHeight - 4 + SettingsData.dankBarSpacing + 2
|
y: Theme.barHeight - 4 + SettingsData.dankBarSpacing + 2
|
||||||
@@ -206,84 +206,121 @@ PanelWindow {
|
|||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: detailsText.height + Theme.spacingS * 2
|
height: detailsColumn.height + Theme.spacingS * 2
|
||||||
color: Qt.rgba(0, 0, 0, 0.2)
|
color: Qt.rgba(0, 0, 0, 0.2)
|
||||||
radius: Theme.cornerRadius / 2
|
radius: Theme.cornerRadius / 2
|
||||||
visible: toast.expanded && ToastService.hasDetails
|
visible: toast.expanded && ToastService.hasDetails
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
|
||||||
StyledText {
|
Column {
|
||||||
id: detailsText
|
id: detailsColumn
|
||||||
text: ToastService.currentDetails
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
color: {
|
|
||||||
switch (ToastService.currentLevel) {
|
|
||||||
case ToastService.levelError:
|
|
||||||
case ToastService.levelWarn:
|
|
||||||
return SessionData.isLightMode ? Theme.surfaceText : Theme.background
|
|
||||||
default:
|
|
||||||
return Theme.surfaceText
|
|
||||||
}
|
|
||||||
}
|
|
||||||
isMonospace: true
|
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: copyButton.left
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
anchors.margins: Theme.spacingS
|
|
||||||
anchors.rightMargin: Theme.spacingS
|
|
||||||
wrapMode: Text.Wrap
|
|
||||||
}
|
|
||||||
|
|
||||||
DankActionButton {
|
|
||||||
id: copyButton
|
|
||||||
iconName: "content_copy"
|
|
||||||
iconSize: Theme.iconSizeSmall
|
|
||||||
iconColor: {
|
|
||||||
switch (ToastService.currentLevel) {
|
|
||||||
case ToastService.levelError:
|
|
||||||
case ToastService.levelWarn:
|
|
||||||
return SessionData.isLightMode ? Theme.surfaceText : Theme.background
|
|
||||||
default:
|
|
||||||
return Theme.surfaceText
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buttonSize: Theme.iconSizeSmall + 8
|
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.rightMargin: Theme.spacingS
|
anchors.margins: Theme.spacingS
|
||||||
|
spacing: Theme.spacingS
|
||||||
|
|
||||||
property bool showTooltip: false
|
StyledText {
|
||||||
|
id: detailsText
|
||||||
onClicked: {
|
text: ToastService.currentDetails
|
||||||
Quickshell.execDetached(
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
["wl-copy", ToastService.currentDetails])
|
color: {
|
||||||
showTooltip = true
|
switch (ToastService.currentLevel) {
|
||||||
tooltipTimer.start()
|
case ToastService.levelError:
|
||||||
}
|
case ToastService.levelWarn:
|
||||||
|
return SessionData.isLightMode ? Theme.surfaceText : Theme.background
|
||||||
Timer {
|
default:
|
||||||
id: tooltipTimer
|
return Theme.surfaceText
|
||||||
interval: 1500
|
}
|
||||||
onTriggered: copyButton.showTooltip = false
|
}
|
||||||
|
visible: ToastService.currentDetails.length > 0
|
||||||
|
width: parent.width - Theme.spacingS * 2
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
wrapMode: Text.Wrap
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
visible: copyButton.showTooltip
|
width: parent.width - Theme.spacingS * 2
|
||||||
width: tooltipLabel.implicitWidth + 16
|
height: commandText.height + Theme.spacingS
|
||||||
height: tooltipLabel.implicitHeight + 8
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
color: Theme.surfaceContainer
|
color: Qt.rgba(0, 0, 0, 0.3)
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius / 2
|
||||||
border.width: 1
|
visible: ToastService.currentCommand.length > 0
|
||||||
border.color: Theme.outlineMedium
|
|
||||||
y: -height - 4
|
|
||||||
x: -width / 2 + copyButton.width / 2
|
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
id: tooltipLabel
|
id: commandText
|
||||||
anchors.centerIn: parent
|
text: ToastService.currentCommand
|
||||||
text: root.copiedText
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
color: Theme.surfaceText
|
color: {
|
||||||
|
switch (ToastService.currentLevel) {
|
||||||
|
case ToastService.levelError:
|
||||||
|
case ToastService.levelWarn:
|
||||||
|
return SessionData.isLightMode ? Theme.surfaceText : Theme.background
|
||||||
|
default:
|
||||||
|
return Theme.surfaceText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isMonospace: true
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: copyButton.visible ? copyButton.left : parent.right
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.margins: Theme.spacingS / 2
|
||||||
|
anchors.rightMargin: Theme.spacingS / 2
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
}
|
||||||
|
|
||||||
|
DankActionButton {
|
||||||
|
id: copyButton
|
||||||
|
iconName: "content_copy"
|
||||||
|
iconSize: Theme.iconSizeSmall
|
||||||
|
iconColor: {
|
||||||
|
switch (ToastService.currentLevel) {
|
||||||
|
case ToastService.levelError:
|
||||||
|
case ToastService.levelWarn:
|
||||||
|
return SessionData.isLightMode ? Theme.surfaceText : Theme.background
|
||||||
|
default:
|
||||||
|
return Theme.surfaceText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buttonSize: Theme.iconSizeSmall + 8
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.rightMargin: Theme.spacingS / 2
|
||||||
|
visible: ToastService.currentCommand.length > 0
|
||||||
|
|
||||||
|
property bool showTooltip: false
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
Quickshell.execDetached(["wl-copy", ToastService.currentCommand])
|
||||||
|
showTooltip = true
|
||||||
|
tooltipTimer.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
id: tooltipTimer
|
||||||
|
interval: 1500
|
||||||
|
onTriggered: copyButton.showTooltip = false
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
visible: copyButton.showTooltip
|
||||||
|
width: tooltipLabel.implicitWidth + 16
|
||||||
|
height: tooltipLabel.implicitHeight + 8
|
||||||
|
color: Theme.surfaceContainer
|
||||||
|
radius: Theme.cornerRadius
|
||||||
|
border.width: 1
|
||||||
|
border.color: Theme.outlineMedium
|
||||||
|
y: -height - 4
|
||||||
|
x: -width / 2 + copyButton.width / 2
|
||||||
|
|
||||||
|
StyledText {
|
||||||
|
id: tooltipLabel
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: root.copiedText
|
||||||
|
font.pixelSize: Theme.fontSizeSmall
|
||||||
|
color: Theme.surfaceText
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,15 +13,22 @@ Singleton {
|
|||||||
|
|
||||||
property bool dmsAvailable: false
|
property bool dmsAvailable: false
|
||||||
property var capabilities: []
|
property var capabilities: []
|
||||||
|
property int apiVersion: 0
|
||||||
|
readonly property int expectedApiVersion: 1
|
||||||
property var availablePlugins: []
|
property var availablePlugins: []
|
||||||
property var installedPlugins: []
|
property var installedPlugins: []
|
||||||
property bool isConnected: false
|
property bool isConnected: false
|
||||||
property bool isConnecting: false
|
property bool isConnecting: false
|
||||||
|
property bool subscribeConnected: false
|
||||||
|
|
||||||
readonly property string socketPath: Quickshell.env("DMS_SOCKET")
|
readonly property string socketPath: Quickshell.env("DMS_SOCKET")
|
||||||
|
readonly property bool verboseLogs: Quickshell.env("DMS_VERBOSE_LOGS") === "1"
|
||||||
|
|
||||||
property var pendingRequests: ({})
|
property var pendingRequests: ({})
|
||||||
property int requestIdCounter: 0
|
property int requestIdCounter: 0
|
||||||
|
property bool shownOutdatedError: false
|
||||||
|
property string updateCommand: "dms update"
|
||||||
|
property bool checkingUpdateCommand: false
|
||||||
|
|
||||||
signal pluginsListReceived(var plugins)
|
signal pluginsListReceived(var plugins)
|
||||||
signal installedPluginsReceived(var plugins)
|
signal installedPluginsReceived(var plugins)
|
||||||
@@ -30,12 +37,87 @@ Singleton {
|
|||||||
signal operationError(string error)
|
signal operationError(string error)
|
||||||
signal connectionStateChanged()
|
signal connectionStateChanged()
|
||||||
|
|
||||||
|
signal networkStateUpdate(var data)
|
||||||
|
signal loginctlStateUpdate(var data)
|
||||||
|
signal loginctlEvent(var event)
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
|
if (socketPath && socketPath.length > 0) {
|
||||||
|
detectUpdateCommand()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function detectUpdateCommand() {
|
||||||
|
checkingUpdateCommand = true
|
||||||
|
checkAurHelper.running = true
|
||||||
|
}
|
||||||
|
|
||||||
|
function startSocketConnection() {
|
||||||
if (socketPath && socketPath.length > 0) {
|
if (socketPath && socketPath.length > 0) {
|
||||||
testProcess.running = true
|
testProcess.running = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: checkAurHelper
|
||||||
|
command: ["sh", "-c", "command -v paru || command -v yay"]
|
||||||
|
running: false
|
||||||
|
|
||||||
|
stdout: StdioCollector {
|
||||||
|
onStreamFinished: {
|
||||||
|
const helper = text.trim()
|
||||||
|
if (helper.includes("paru")) {
|
||||||
|
checkDmsPackage.helper = "paru"
|
||||||
|
checkDmsPackage.running = true
|
||||||
|
} else if (helper.includes("yay")) {
|
||||||
|
checkDmsPackage.helper = "yay"
|
||||||
|
checkDmsPackage.running = true
|
||||||
|
} else {
|
||||||
|
updateCommand = "dms update"
|
||||||
|
checkingUpdateCommand = false
|
||||||
|
startSocketConnection()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onExited: exitCode => {
|
||||||
|
if (exitCode !== 0) {
|
||||||
|
updateCommand = "dms update"
|
||||||
|
checkingUpdateCommand = false
|
||||||
|
startSocketConnection()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Process {
|
||||||
|
id: checkDmsPackage
|
||||||
|
property string helper: ""
|
||||||
|
command: ["sh", "-c", "pacman -Qi dms-shell-git 2>/dev/null || pacman -Qi dms-shell-bin 2>/dev/null"]
|
||||||
|
running: false
|
||||||
|
|
||||||
|
stdout: StdioCollector {
|
||||||
|
onStreamFinished: {
|
||||||
|
if (text.includes("dms-shell-git")) {
|
||||||
|
updateCommand = checkDmsPackage.helper + " -S dms-shell-git"
|
||||||
|
} else if (text.includes("dms-shell-bin")) {
|
||||||
|
updateCommand = checkDmsPackage.helper + " -S dms-shell-bin"
|
||||||
|
} else {
|
||||||
|
updateCommand = "dms update"
|
||||||
|
}
|
||||||
|
checkingUpdateCommand = false
|
||||||
|
startSocketConnection()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onExited: exitCode => {
|
||||||
|
if (exitCode !== 0) {
|
||||||
|
updateCommand = "dms update"
|
||||||
|
checkingUpdateCommand = false
|
||||||
|
startSocketConnection()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Process {
|
Process {
|
||||||
id: testProcess
|
id: testProcess
|
||||||
command: ["test", "-S", root.socketPath]
|
command: ["test", "-S", root.socketPath]
|
||||||
@@ -56,11 +138,11 @@ Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isConnecting = true
|
isConnecting = true
|
||||||
socket.connected = true
|
requestSocket.connected = true
|
||||||
}
|
}
|
||||||
|
|
||||||
DankSocket {
|
DankSocket {
|
||||||
id: socket
|
id: requestSocket
|
||||||
path: root.socketPath
|
path: root.socketPath
|
||||||
connected: false
|
connected: false
|
||||||
|
|
||||||
@@ -69,9 +151,12 @@ Singleton {
|
|||||||
root.isConnected = true
|
root.isConnected = true
|
||||||
root.isConnecting = false
|
root.isConnecting = false
|
||||||
root.connectionStateChanged()
|
root.connectionStateChanged()
|
||||||
|
subscribeSocket.connected = true
|
||||||
} else {
|
} else {
|
||||||
root.isConnected = false
|
root.isConnected = false
|
||||||
root.isConnecting = false
|
root.isConnecting = false
|
||||||
|
root.apiVersion = 0
|
||||||
|
root.capabilities = []
|
||||||
root.connectionStateChanged()
|
root.connectionStateChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,28 +167,112 @@ Singleton {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (root.verboseLogs) {
|
||||||
|
console.log("DMSService: Request socket <<", line)
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = JSON.parse(line)
|
const response = JSON.parse(line)
|
||||||
|
|
||||||
if (response.capabilities) {
|
|
||||||
root.capabilities = response.capabilities
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
handleResponse(response)
|
handleResponse(response)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn("DMSService: Failed to parse response:", line, e)
|
console.warn("DMSService: Failed to parse request response:", line, e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DankSocket {
|
||||||
|
id: subscribeSocket
|
||||||
|
path: root.socketPath
|
||||||
|
connected: false
|
||||||
|
|
||||||
|
onConnectionStateChanged: {
|
||||||
|
root.subscribeConnected = connected
|
||||||
|
if (connected) {
|
||||||
|
sendSubscribeRequest()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parser: SplitParser {
|
||||||
|
onRead: line => {
|
||||||
|
if (!line || line.length === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (root.verboseLogs) {
|
||||||
|
console.log("DMSService: Subscribe socket <<", line)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = JSON.parse(line)
|
||||||
|
handleSubscriptionEvent(response)
|
||||||
|
} catch (e) {
|
||||||
|
console.warn("DMSService: Failed to parse subscription event:", line, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendSubscribeRequest() {
|
||||||
|
const request = {
|
||||||
|
"method": "subscribe"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verboseLogs) {
|
||||||
|
console.log("DMSService: Subscribing to all services")
|
||||||
|
}
|
||||||
|
subscribeSocket.send(request)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSubscriptionEvent(response) {
|
||||||
|
if (response.error) {
|
||||||
|
if (response.error.includes("unknown method") && response.error.includes("subscribe")) {
|
||||||
|
if (!shownOutdatedError) {
|
||||||
|
console.error("DMSService: Server does not support subscribe method")
|
||||||
|
ToastService.showError(
|
||||||
|
I18n.tr("DMS out of date"),
|
||||||
|
I18n.tr("To update, run the following command:"),
|
||||||
|
updateCommand
|
||||||
|
)
|
||||||
|
shownOutdatedError = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!response.result) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const service = response.result.service
|
||||||
|
const data = response.result.data
|
||||||
|
|
||||||
|
if (service === "server") {
|
||||||
|
apiVersion = data.apiVersion || 0
|
||||||
|
capabilities = data.capabilities || []
|
||||||
|
|
||||||
|
console.log("DMSService: Connected (API v" + apiVersion + ") -", JSON.stringify(capabilities))
|
||||||
|
|
||||||
|
if (apiVersion < expectedApiVersion) {
|
||||||
|
ToastService.showError("DMS server is outdated (API v" + apiVersion + ", expected v" + expectedApiVersion + ")")
|
||||||
|
}
|
||||||
|
} else if (service === "network") {
|
||||||
|
networkStateUpdate(data)
|
||||||
|
} else if (service === "loginctl") {
|
||||||
|
if (data.event) {
|
||||||
|
loginctlEvent(data)
|
||||||
|
} else {
|
||||||
|
loginctlStateUpdate(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function sendRequest(method, params, callback) {
|
function sendRequest(method, params, callback) {
|
||||||
if (!isConnected) {
|
if (!isConnected) {
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback({
|
callback({
|
||||||
"error": "not connected to DMS socket"
|
"error": "not connected to DMS socket"
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -123,21 +292,10 @@ Singleton {
|
|||||||
pendingRequests[id] = callback
|
pendingRequests[id] = callback
|
||||||
}
|
}
|
||||||
|
|
||||||
socket.send(request)
|
requestSocket.send(request)
|
||||||
}
|
}
|
||||||
|
|
||||||
property var networkUpdateCallback: null
|
|
||||||
|
|
||||||
function handleResponse(response) {
|
function handleResponse(response) {
|
||||||
if (response.id === undefined && response.result) {
|
|
||||||
if (response.result.type === "state_changed" && response.result.data) {
|
|
||||||
if (networkUpdateCallback) {
|
|
||||||
networkUpdateCallback(response.result.data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const callback = pendingRequests[response.id]
|
const callback = pendingRequests[response.id]
|
||||||
|
|
||||||
if (callback) {
|
if (callback) {
|
||||||
|
|||||||
@@ -76,8 +76,6 @@ Singleton {
|
|||||||
signal networksUpdated
|
signal networksUpdated
|
||||||
signal connectionChanged
|
signal connectionChanged
|
||||||
|
|
||||||
property bool subscriptionConnected: false
|
|
||||||
|
|
||||||
readonly property string socketPath: Quickshell.env("DMS_SOCKET")
|
readonly property string socketPath: Quickshell.env("DMS_SOCKET")
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
@@ -87,51 +85,16 @@ Singleton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DankSocket {
|
Connections {
|
||||||
id: subscriptionSocket
|
target: DMSService
|
||||||
path: root.socketPath
|
|
||||||
connected: networkAvailable
|
|
||||||
|
|
||||||
onConnectionStateChanged: {
|
function onNetworkStateUpdate(data) {
|
||||||
root.subscriptionConnected = connected
|
if (DMSService.verboseLogs) {
|
||||||
if (connected) {
|
const networksCount = data.wifiNetworks?.length ?? "null"
|
||||||
console.log("NetworkManagerService: Subscription socket connected")
|
console.log("NetworkManagerService: Subscription update received, networks:", networksCount)
|
||||||
}
|
}
|
||||||
|
updateState(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
parser: SplitParser {
|
|
||||||
onRead: line => {
|
|
||||||
if (!line || line.length === 0) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = JSON.parse(line)
|
|
||||||
|
|
||||||
if (response.capabilities) {
|
|
||||||
console.log("NetworkManagerService: Subscription socket received capabilities")
|
|
||||||
Qt.callLater(() => sendSubscribeRequest())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.result && response.result.type === "state_changed" && response.result.data) {
|
|
||||||
const networksCount = response.result.data.wifiNetworks?.length ?? "null"
|
|
||||||
console.log("NetworkManagerService: Subscription update received, networks:", networksCount)
|
|
||||||
updateState(response.result.data)
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.warn("NetworkManagerService: Failed to parse subscription response:", line, e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function sendSubscribeRequest() {
|
|
||||||
subscriptionSocket.send({
|
|
||||||
"id": 1,
|
|
||||||
"method": "network.subscribe"
|
|
||||||
})
|
|
||||||
console.log("NetworkManagerService: Sent network.subscribe request")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
@@ -162,15 +125,15 @@ Singleton {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("NetworkManagerService: Capabilities:", JSON.stringify(DMSService.capabilities))
|
|
||||||
networkAvailable = DMSService.capabilities.includes("network")
|
networkAvailable = DMSService.capabilities.includes("network")
|
||||||
console.log("NetworkManagerService: Network available:", networkAvailable)
|
|
||||||
|
if (DMSService.verboseLogs) {
|
||||||
|
console.log("NetworkManagerService: Network available:", networkAvailable)
|
||||||
|
}
|
||||||
|
|
||||||
if (networkAvailable && !stateInitialized) {
|
if (networkAvailable && !stateInitialized) {
|
||||||
console.log("NetworkManagerService: Requesting network state and starting subscription socket...")
|
|
||||||
stateInitialized = true
|
stateInitialized = true
|
||||||
getState()
|
getState()
|
||||||
subscriptionSocket.connected = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,7 +160,9 @@ Singleton {
|
|||||||
if (response.result) {
|
if (response.result) {
|
||||||
updateState(response.result)
|
updateState(response.result)
|
||||||
if (!initialStateFetched && response.result.wifiEnabled && (!response.result.wifiNetworks || response.result.wifiNetworks.length === 0)) {
|
if (!initialStateFetched && response.result.wifiEnabled && (!response.result.wifiNetworks || response.result.wifiNetworks.length === 0)) {
|
||||||
console.log("NetworkManagerService: Initial state has no networks, triggering scan")
|
if (DMSService.verboseLogs) {
|
||||||
|
console.log("NetworkManagerService: Initial state has no networks, triggering scan")
|
||||||
|
}
|
||||||
initialStateFetched = true
|
initialStateFetched = true
|
||||||
Qt.callLater(() => scanWifi())
|
Qt.callLater(() => scanWifi())
|
||||||
}
|
}
|
||||||
@@ -258,14 +223,18 @@ Singleton {
|
|||||||
function scanWifi() {
|
function scanWifi() {
|
||||||
if (!networkAvailable || isScanning || !wifiEnabled) return
|
if (!networkAvailable || isScanning || !wifiEnabled) return
|
||||||
|
|
||||||
console.log("NetworkManagerService: Starting WiFi scan...")
|
if (DMSService.verboseLogs) {
|
||||||
|
console.log("NetworkManagerService: Starting WiFi scan...")
|
||||||
|
}
|
||||||
isScanning = true
|
isScanning = true
|
||||||
DMSService.sendRequest("network.wifi.scan", null, response => {
|
DMSService.sendRequest("network.wifi.scan", null, response => {
|
||||||
isScanning = false
|
isScanning = false
|
||||||
if (response.error) {
|
if (response.error) {
|
||||||
console.warn("NetworkManagerService: WiFi scan failed:", response.error)
|
console.warn("NetworkManagerService: WiFi scan failed:", response.error)
|
||||||
} else {
|
} else {
|
||||||
console.log("NetworkManagerService: Scan completed, requesting fresh state...")
|
if (DMSService.verboseLogs) {
|
||||||
|
console.log("NetworkManagerService: Scan completed")
|
||||||
|
}
|
||||||
Qt.callLater(() => getState())
|
Qt.callLater(() => getState())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -424,7 +424,7 @@ Singleton {
|
|||||||
validateProcess.running = true
|
validateProcess.running = true
|
||||||
} else {
|
} else {
|
||||||
configValidationOutput = ""
|
configValidationOutput = ""
|
||||||
if (ToastService.toastVisible && ToastService.currentLevel === ToastService.levelError) {
|
if (ToastService.toastVisible && ToastService.currentLevel === ToastService.levelError && ToastService.currentMessage.startsWith("niri:")) {
|
||||||
ToastService.hideToast()
|
ToastService.hideToast()
|
||||||
}
|
}
|
||||||
fetchOutputs()
|
fetchOutputs()
|
||||||
|
|||||||
@@ -22,24 +22,22 @@ Singleton {
|
|||||||
function init() {}
|
function init() {}
|
||||||
|
|
||||||
function getSystemProfileImage() {
|
function getSystemProfileImage() {
|
||||||
if (freedeskAvailable) {
|
if (!freedeskAvailable) return
|
||||||
const username = Quickshell.env("USER")
|
|
||||||
if (!username) return
|
|
||||||
|
|
||||||
DMSService.sendRequest("freedesktop.accounts.getUserIconFile", { username: username }, response => {
|
const username = Quickshell.env("USER")
|
||||||
if (response.result && response.result.success) {
|
if (!username) return
|
||||||
const iconFile = response.result.value || ""
|
|
||||||
if (iconFile && iconFile !== "" && iconFile !== "/var/lib/AccountsService/icons/") {
|
DMSService.sendRequest("freedesktop.accounts.getUserIconFile", { username: username }, response => {
|
||||||
systemProfileImage = iconFile
|
if (response.result && response.result.success) {
|
||||||
if (!profileImage || profileImage === "") {
|
const iconFile = response.result.value || ""
|
||||||
profileImage = iconFile
|
if (iconFile && iconFile !== "" && iconFile !== "/var/lib/AccountsService/icons/") {
|
||||||
}
|
systemProfileImage = iconFile
|
||||||
|
if (!profileImage || profileImage === "") {
|
||||||
|
profileImage = iconFile
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
} else {
|
})
|
||||||
systemProfileCheckProcess.running = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getUserProfileImage(username) {
|
function getUserProfileImage(username) {
|
||||||
@@ -52,26 +50,23 @@ Singleton {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (freedeskAvailable) {
|
if (!freedeskAvailable) {
|
||||||
DMSService.sendRequest("freedesktop.accounts.getUserIconFile", { username: username }, response => {
|
profileImage = ""
|
||||||
if (response.result && response.result.success) {
|
return
|
||||||
const icon = response.result.value || ""
|
}
|
||||||
if (icon && icon !== "" && icon !== "/var/lib/AccountsService/icons/") {
|
|
||||||
profileImage = icon
|
DMSService.sendRequest("freedesktop.accounts.getUserIconFile", { username: username }, response => {
|
||||||
} else {
|
if (response.result && response.result.success) {
|
||||||
profileImage = ""
|
const icon = response.result.value || ""
|
||||||
}
|
if (icon && icon !== "" && icon !== "/var/lib/AccountsService/icons/") {
|
||||||
|
profileImage = icon
|
||||||
} else {
|
} else {
|
||||||
profileImage = ""
|
profileImage = ""
|
||||||
}
|
}
|
||||||
})
|
} else {
|
||||||
} else {
|
profileImage = ""
|
||||||
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) {
|
function setProfileImage(imagePath) {
|
||||||
@@ -86,25 +81,23 @@ Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getSystemColorScheme() {
|
function getSystemColorScheme() {
|
||||||
if (freedeskAvailable) {
|
if (!freedeskAvailable) return
|
||||||
DMSService.sendRequest("freedesktop.settings.getColorScheme", null, response => {
|
|
||||||
if (response.result) {
|
|
||||||
systemColorScheme = response.result.value || 0
|
|
||||||
|
|
||||||
if (typeof Theme !== "undefined") {
|
DMSService.sendRequest("freedesktop.settings.getColorScheme", null, response => {
|
||||||
const shouldBeLightMode = (systemColorScheme === 2)
|
if (response.result) {
|
||||||
if (Theme.isLightMode !== shouldBeLightMode) {
|
systemColorScheme = response.result.value || 0
|
||||||
Theme.isLightMode = shouldBeLightMode
|
|
||||||
if (typeof SessionData !== "undefined") {
|
if (typeof Theme !== "undefined") {
|
||||||
SessionData.setLightMode(shouldBeLightMode)
|
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) {
|
function setLightMode(isLightMode) {
|
||||||
@@ -114,49 +107,32 @@ Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setSystemColorScheme(isLightMode) {
|
function setSystemColorScheme(isLightMode) {
|
||||||
if (!settingsPortalAvailable) return
|
if (!settingsPortalAvailable || !freedeskAvailable) return
|
||||||
|
|
||||||
const colorScheme = isLightMode ? "default" : "prefer-dark"
|
DMSService.sendRequest("freedesktop.settings.setColorScheme", { preferDark: !isLightMode }, response => {
|
||||||
colorSchemeSetProcess.command = ["gsettings", "set", "org.gnome.desktop.interface", "color-scheme", colorScheme]
|
if (!response.error) {
|
||||||
colorSchemeSetProcess.running = true
|
|
||||||
}
|
|
||||||
|
|
||||||
Process {
|
|
||||||
id: colorSchemeSetProcess
|
|
||||||
running: false
|
|
||||||
|
|
||||||
onExited: exitCode => {
|
|
||||||
if (exitCode === 0) {
|
|
||||||
Qt.callLater(() => getSystemColorScheme())
|
Qt.callLater(() => getSystemColorScheme())
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function setSystemProfileImage(imagePath) {
|
function setSystemProfileImage(imagePath) {
|
||||||
if (!accountsServiceAvailable) return
|
if (!accountsServiceAvailable || !freedeskAvailable) return
|
||||||
|
|
||||||
if (freedeskAvailable) {
|
DMSService.sendRequest("freedesktop.accounts.setIconFile", { path: imagePath || "" }, response => {
|
||||||
DMSService.sendRequest("freedesktop.accounts.setIconFile", { path: imagePath || "" }, response => {
|
if (response.error) {
|
||||||
if (response.error) {
|
console.warn("PortalService: Failed to set icon file:", response.error)
|
||||||
console.warn("PortalService: Failed to set icon file:", response.error)
|
} else {
|
||||||
} else {
|
Qt.callLater(() => getSystemProfileImage())
|
||||||
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: {
|
Component.onCompleted: {
|
||||||
if (socketPath && socketPath.length > 0) {
|
if (socketPath && socketPath.length > 0) {
|
||||||
checkDMSCapabilities()
|
checkDMSCapabilities()
|
||||||
} else {
|
} else {
|
||||||
console.log("PortalService: DMS_SOCKET not set, using fallback methods")
|
console.log("PortalService: DMS_SOCKET not set")
|
||||||
checkAccountsServiceFallback()
|
|
||||||
checkSettingsPortalFallback()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,9 +169,7 @@ Singleton {
|
|||||||
checkAccountsService()
|
checkAccountsService()
|
||||||
checkSettingsPortal()
|
checkSettingsPortal()
|
||||||
} else {
|
} else {
|
||||||
console.log("PortalService: freedesktop capability not available in DMS, using fallback methods")
|
console.log("PortalService: freedesktop capability not available in DMS")
|
||||||
checkAccountsServiceFallback()
|
|
||||||
checkSettingsPortalFallback()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,14 +199,6 @@ Singleton {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkAccountsServiceFallback() {
|
|
||||||
accountsServiceCheckProcess.running = true
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkSettingsPortalFallback() {
|
|
||||||
settingsPortalCheckProcess.running = true
|
|
||||||
}
|
|
||||||
|
|
||||||
function getGreeterUserProfileImage(username) {
|
function getGreeterUserProfileImage(username) {
|
||||||
if (!username) {
|
if (!username) {
|
||||||
profileImage = ""
|
profileImage = ""
|
||||||
@@ -245,54 +211,6 @@ Singleton {
|
|||||||
userProfileCheckProcess.running = true
|
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 {
|
Process {
|
||||||
id: userProfileCheckProcess
|
id: userProfileCheckProcess
|
||||||
command: []
|
command: []
|
||||||
@@ -316,50 +234,6 @@ Singleton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
IpcHandler {
|
||||||
target: "profile"
|
target: "profile"
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ Singleton {
|
|||||||
signal prepareForSleep()
|
signal prepareForSleep()
|
||||||
signal loginctlStateChanged()
|
signal loginctlStateChanged()
|
||||||
|
|
||||||
property bool subscriptionConnected: false
|
|
||||||
property bool stateInitialized: false
|
property bool stateInitialized: false
|
||||||
|
|
||||||
readonly property string socketPath: Quickshell.env("DMS_SOCKET")
|
readonly property string socketPath: Quickshell.env("DMS_SOCKET")
|
||||||
@@ -68,8 +67,7 @@ Singleton {
|
|||||||
if (socketPath && socketPath.length > 0) {
|
if (socketPath && socketPath.length > 0) {
|
||||||
checkDMSCapabilities()
|
checkDMSCapabilities()
|
||||||
} else {
|
} else {
|
||||||
console.log("SessionService: DMS_SOCKET not set, using fallback")
|
console.log("SessionService: DMS_SOCKET not set")
|
||||||
initFallbackLoginctl()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -300,60 +298,36 @@ Singleton {
|
|||||||
|
|
||||||
function onLoginctlLockIntegrationChanged() {
|
function onLoginctlLockIntegrationChanged() {
|
||||||
if (SessionData.loginctlLockIntegration) {
|
if (SessionData.loginctlLockIntegration) {
|
||||||
if (socketPath && socketPath.length > 0) {
|
if (socketPath && socketPath.length > 0 && loginctlAvailable) {
|
||||||
checkDMSCapabilities()
|
if (!stateInitialized) {
|
||||||
} else {
|
stateInitialized = true
|
||||||
initFallbackLoginctl()
|
getLoginctlState()
|
||||||
|
syncLockBeforeSuspend()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
subscriptionSocket.connected = false
|
|
||||||
lockStateMonitorFallback.running = false
|
|
||||||
loginctlAvailable = false
|
|
||||||
stateInitialized = false
|
stateInitialized = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
DankSocket {
|
function onLockBeforeSuspendChanged() {
|
||||||
id: subscriptionSocket
|
if (SessionData.loginctlLockIntegration) {
|
||||||
path: root.socketPath
|
syncLockBeforeSuspend()
|
||||||
connected: loginctlAvailable && SessionData.loginctlLockIntegration
|
|
||||||
|
|
||||||
onConnectionStateChanged: {
|
|
||||||
root.subscriptionConnected = connected
|
|
||||||
}
|
|
||||||
|
|
||||||
parser: SplitParser {
|
|
||||||
onRead: line => {
|
|
||||||
if (!line || line.length === 0) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = JSON.parse(line)
|
|
||||||
|
|
||||||
if (response.capabilities) {
|
|
||||||
Qt.callLater(() => sendSubscribeRequest())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.result && response.result.type === "loginctl_event") {
|
|
||||||
handleLoginctlEvent(response.result)
|
|
||||||
} else if (response.result && response.result.type === "state_changed" && response.result.data) {
|
|
||||||
updateLoginctlState(response.result.data)
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.warn("SessionService: Failed to parse subscription response:", line, e)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendSubscribeRequest() {
|
Connections {
|
||||||
subscriptionSocket.send({
|
target: DMSService
|
||||||
"id": 2,
|
enabled: SessionData.loginctlLockIntegration
|
||||||
"method": "loginctl.subscribe"
|
|
||||||
})
|
function onLoginctlStateUpdate(data) {
|
||||||
|
updateLoginctlState(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
function onLoginctlEvent(event) {
|
||||||
|
handleLoginctlEvent(event)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkDMSCapabilities() {
|
function checkDMSCapabilities() {
|
||||||
@@ -365,20 +339,16 @@ Singleton {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SessionData.loginctlLockIntegration) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DMSService.capabilities.includes("loginctl")) {
|
if (DMSService.capabilities.includes("loginctl")) {
|
||||||
loginctlAvailable = true
|
loginctlAvailable = true
|
||||||
if (!stateInitialized) {
|
if (SessionData.loginctlLockIntegration && !stateInitialized) {
|
||||||
stateInitialized = true
|
stateInitialized = true
|
||||||
getLoginctlState()
|
getLoginctlState()
|
||||||
subscriptionSocket.connected = true
|
syncLockBeforeSuspend()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log("SessionService: loginctl capability not available in DMS, using fallback")
|
loginctlAvailable = false
|
||||||
initFallbackLoginctl()
|
console.log("SessionService: loginctl capability not available in DMS")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -392,6 +362,20 @@ Singleton {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function syncLockBeforeSuspend() {
|
||||||
|
if (!loginctlAvailable) return
|
||||||
|
|
||||||
|
DMSService.sendRequest("loginctl.setLockBeforeSuspend", {
|
||||||
|
enabled: SessionData.lockBeforeSuspend
|
||||||
|
}, response => {
|
||||||
|
if (response.error) {
|
||||||
|
console.warn("SessionService: Failed to sync lock before suspend:", response.error)
|
||||||
|
} else {
|
||||||
|
console.log("SessionService: Synced lock before suspend:", SessionData.lockBeforeSuspend)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function updateLoginctlState(state) {
|
function updateLoginctlState(state) {
|
||||||
const wasLocked = locked
|
const wasLocked = locked
|
||||||
|
|
||||||
@@ -406,13 +390,6 @@ Singleton {
|
|||||||
seat = state.seat || ""
|
seat = state.seat || ""
|
||||||
display = state.display || ""
|
display = state.display || ""
|
||||||
|
|
||||||
const wasPreparing = preparingForSleep
|
|
||||||
preparingForSleep = state.preparingForSleep || false
|
|
||||||
|
|
||||||
if (preparingForSleep && !wasPreparing) {
|
|
||||||
prepareForSleep()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (locked && !wasLocked) {
|
if (locked && !wasLocked) {
|
||||||
sessionLocked()
|
sessionLocked()
|
||||||
} else if (!locked && wasLocked) {
|
} else if (!locked && wasLocked) {
|
||||||
@@ -431,90 +408,6 @@ Singleton {
|
|||||||
locked = false
|
locked = false
|
||||||
lockedHint = false
|
lockedHint = false
|
||||||
sessionUnlocked()
|
sessionUnlocked()
|
||||||
} else if (event.event === "PrepareForSleep") {
|
|
||||||
preparingForSleep = event.data?.sleeping || false
|
|
||||||
if (preparingForSleep) {
|
|
||||||
prepareForSleep()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function initFallbackLoginctl() {
|
|
||||||
getSessionPathFallback.running = true
|
|
||||||
}
|
|
||||||
|
|
||||||
Process {
|
|
||||||
id: getSessionPathFallback
|
|
||||||
command: ["gdbus", "call", "--system", "--dest", "org.freedesktop.login1", "--object-path", "/org/freedesktop/login1", "--method", "org.freedesktop.login1.Manager.GetSession", Quickshell.env("XDG_SESSION_ID") || "self"]
|
|
||||||
running: false
|
|
||||||
|
|
||||||
stdout: StdioCollector {
|
|
||||||
onStreamFinished: {
|
|
||||||
const match = text.match(/objectpath '([^']+)'/)
|
|
||||||
if (match) {
|
|
||||||
sessionPath = match[1]
|
|
||||||
console.log("SessionService: Found session path (fallback):", sessionPath)
|
|
||||||
checkCurrentLockStateFallback.running = true
|
|
||||||
lockStateMonitorFallback.running = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Process {
|
|
||||||
id: checkCurrentLockStateFallback
|
|
||||||
command: sessionPath ? ["gdbus", "call", "--system", "--dest", "org.freedesktop.login1", "--object-path", sessionPath, "--method", "org.freedesktop.DBus.Properties.Get", "org.freedesktop.login1.Session", "LockedHint"] : []
|
|
||||||
running: false
|
|
||||||
|
|
||||||
stdout: StdioCollector {
|
|
||||||
onStreamFinished: {
|
|
||||||
if (text.includes("true")) {
|
|
||||||
locked = true
|
|
||||||
lockedHint = true
|
|
||||||
sessionLocked()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Process {
|
|
||||||
id: lockStateMonitorFallback
|
|
||||||
command: sessionPath ? ["gdbus", "monitor", "--system", "--dest", "org.freedesktop.login1"] : []
|
|
||||||
running: false
|
|
||||||
|
|
||||||
stdout: SplitParser {
|
|
||||||
splitMarker: "\n"
|
|
||||||
onRead: line => {
|
|
||||||
if (sessionPath && line.includes(sessionPath)) {
|
|
||||||
if (line.includes("org.freedesktop.login1.Session.Lock")) {
|
|
||||||
locked = true
|
|
||||||
lockedHint = true
|
|
||||||
sessionLocked()
|
|
||||||
} else if (line.includes("org.freedesktop.login1.Session.Unlock")) {
|
|
||||||
locked = false
|
|
||||||
lockedHint = false
|
|
||||||
sessionUnlocked()
|
|
||||||
} else if (line.includes("LockedHint") && line.includes("true")) {
|
|
||||||
locked = true
|
|
||||||
lockedHint = true
|
|
||||||
loginctlStateChanged()
|
|
||||||
} else if (line.includes("LockedHint") && line.includes("false")) {
|
|
||||||
locked = false
|
|
||||||
lockedHint = false
|
|
||||||
loginctlStateChanged()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (line.includes("PrepareForSleep") && line.includes("true") && SessionData.lockBeforeSuspend) {
|
|
||||||
preparingForSleep = true
|
|
||||||
prepareForSleep()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onExited: exitCode => {
|
|
||||||
if (exitCode !== 0) {
|
|
||||||
console.warn("SessionService: gdbus monitor fallback failed, exit code:", exitCode)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,36 +16,39 @@ Singleton {
|
|||||||
property bool toastVisible: false
|
property bool toastVisible: false
|
||||||
property var toastQueue: []
|
property var toastQueue: []
|
||||||
property string currentDetails: ""
|
property string currentDetails: ""
|
||||||
|
property string currentCommand: ""
|
||||||
property bool hasDetails: false
|
property bool hasDetails: false
|
||||||
property string wallpaperErrorStatus: ""
|
property string wallpaperErrorStatus: ""
|
||||||
|
|
||||||
function showToast(message, level = levelInfo, details = "") {
|
function showToast(message, level = levelInfo, details = "", command = "") {
|
||||||
toastQueue.push({
|
toastQueue.push({
|
||||||
"message": message,
|
"message": message,
|
||||||
"level": level,
|
"level": level,
|
||||||
"details": details
|
"details": details,
|
||||||
|
"command": command
|
||||||
})
|
})
|
||||||
if (!toastVisible) {
|
if (!toastVisible) {
|
||||||
processQueue()
|
processQueue()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function showInfo(message, details = "") {
|
function showInfo(message, details = "", command = "") {
|
||||||
showToast(message, levelInfo, details)
|
showToast(message, levelInfo, details, command)
|
||||||
}
|
}
|
||||||
|
|
||||||
function showWarning(message, details = "") {
|
function showWarning(message, details = "", command = "") {
|
||||||
showToast(message, levelWarn, details)
|
showToast(message, levelWarn, details, command)
|
||||||
}
|
}
|
||||||
|
|
||||||
function showError(message, details = "") {
|
function showError(message, details = "", command = "") {
|
||||||
showToast(message, levelError, details)
|
showToast(message, levelError, details, command)
|
||||||
}
|
}
|
||||||
|
|
||||||
function hideToast() {
|
function hideToast() {
|
||||||
toastVisible = false
|
toastVisible = false
|
||||||
currentMessage = ""
|
currentMessage = ""
|
||||||
currentDetails = ""
|
currentDetails = ""
|
||||||
|
currentCommand = ""
|
||||||
hasDetails = false
|
hasDetails = false
|
||||||
currentLevel = levelInfo
|
currentLevel = levelInfo
|
||||||
toastTimer.stop()
|
toastTimer.stop()
|
||||||
@@ -64,7 +67,8 @@ Singleton {
|
|||||||
currentMessage = toast.message
|
currentMessage = toast.message
|
||||||
currentLevel = toast.level
|
currentLevel = toast.level
|
||||||
currentDetails = toast.details || ""
|
currentDetails = toast.details || ""
|
||||||
hasDetails = currentDetails.length > 0
|
currentCommand = toast.command || ""
|
||||||
|
hasDetails = currentDetails.length > 0 || currentCommand.length > 0
|
||||||
toastVisible = true
|
toastVisible = true
|
||||||
resetToastState()
|
resetToastState()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user