From 1c2da6975fead84cf3e8e23356d9e364c08ee467 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Mon, 14 Sep 2026 19:42:14 +0200 Subject: fix(desktop): queue KDE Connect actions instead of interrupting A second action while one was in flight killed the first process, whose onExited then fired under the new label and raised a false failure notification. Actions are now queued and launched on exit, so each exit reports under its own label. Also correct two comments that contradicted the code: the pairing banner is only noticed on the on-open poll, and the laptop glyph keys off the daemon's desktop type. --- desktop/modules/kdeconnect/KdeConnectModule.qml | 23 ++++++++++++++++++++--- desktop/modules/kdeconnect/KdeConnectPage.qml | 5 +++-- desktop/modules/kdeconnect/KdeConnectRow.qml | 6 +++--- 3 files changed, 26 insertions(+), 8 deletions(-) (limited to 'desktop') diff --git a/desktop/modules/kdeconnect/KdeConnectModule.qml b/desktop/modules/kdeconnect/KdeConnectModule.qml index b7392b0..fa4fb52 100644 --- a/desktop/modules/kdeconnect/KdeConnectModule.qml +++ b/desktop/modules/kdeconnect/KdeConnectModule.qml @@ -103,12 +103,24 @@ Module { property Process notifyProc: Process {} - // One reusable action process. Actions are serialized; a second click - // while one runs replaces it rather than racing. A failure notifies. + // One reusable action process. Actions never interrupt one another: a + // second action while one runs is queued until the first exits, so each + // exit is reported under the label it was started with. Killing an + // in-flight process to start a new one would fire onExited with the new + // label and raise a false failure. + property var queuedAction: null + function run(label, cmd) { + if (actProc.running) { + queuedAction = { label: label, cmd: cmd }; + return; + } + launch(label, cmd); + } + + function launch(label, cmd) { actProc.label = label; actProc.command = cmd; - actProc.running = false; actProc.running = true; } @@ -120,6 +132,11 @@ Module { mod.notify(actProc.label + " failed", actErr.text.trim() || ("exited " + code)); mod.refresh(); + if (mod.queuedAction !== null) { + const q = mod.queuedAction; + mod.queuedAction = null; + mod.launch(q.label, q.cmd); + } } } diff --git a/desktop/modules/kdeconnect/KdeConnectPage.qml b/desktop/modules/kdeconnect/KdeConnectPage.qml index 89df597..d570125 100644 --- a/desktop/modules/kdeconnect/KdeConnectPage.qml +++ b/desktop/modules/kdeconnect/KdeConnectPage.qml @@ -38,8 +38,9 @@ Column { color: Theme.red } - // Incoming pairing requests. The property persists while the drawer is - // closed, so a request raised then is still here when it opens. + // Incoming pairing requests. The poll runs only while the drawer is open, + // so a request raised while it was closed is not noticed until it opens; + // the daemon keeps the request, so it is here then. Repeater { model: page.kc.requests diff --git a/desktop/modules/kdeconnect/KdeConnectRow.qml b/desktop/modules/kdeconnect/KdeConnectRow.qml index 0b45fb7..e4d4d93 100644 --- a/desktop/modules/kdeconnect/KdeConnectRow.qml +++ b/desktop/modules/kdeconnect/KdeConnectRow.qml @@ -12,9 +12,9 @@ import QtQuick import "../.." -// One KDE Connect device. The type glyph is the phone for anything that is -// not a laptop or desktop, since the daemon's type strings are not a closed -// set. +// One KDE Connect device. The type glyph is a laptop only for a device the +// daemon reports as "desktop" (which is how it reports laptops too), and a +// phone for anything else, since the type strings are not a closed set. Rectangle { id: row -- cgit v1.2.3