From 87952b543c0e4735f0c2b3af3c6930d540ed3cb6 Mon Sep 17 00:00:00 2001 From: Damocles Date: Wed, 22 Apr 2026 21:33:53 +0200 Subject: [PATCH] bluetooth menu: show connecting/disconnecting state with pulse feedback --- shell/modules/BluetoothMenu.qml | 43 ++++++++++++++++++++++------- shell/services/BluetoothService.qml | 10 +++++-- 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/shell/modules/BluetoothMenu.qml b/shell/modules/BluetoothMenu.qml index f348e90..9bbb6a4 100644 --- a/shell/modules/BluetoothMenu.qml +++ b/shell/modules/BluetoothMenu.qml @@ -50,6 +50,8 @@ M.HoverPanel { required property var modelData required property int index + readonly property bool _pending: S.BluetoothService.pendingMac === entry.modelData.mac + width: menuWindow.contentWidth height: 32 @@ -67,7 +69,7 @@ M.HoverPanel { anchors.leftMargin: 12 anchors.verticalCenter: parent.verticalCenter text: "\uF294" - color: entry.modelData.connected ? menuWindow.accentColor : S.Theme.base04 + color: entry._pending ? menuWindow.accentColor : entry.modelData.connected ? menuWindow.accentColor : S.Theme.base04 font.pixelSize: S.Theme.fontSize + 1 font.family: S.Theme.iconFontFamily } @@ -75,27 +77,46 @@ M.HoverPanel { Text { anchors.left: btIcon.right anchors.leftMargin: 8 - anchors.right: batLabel.left + anchors.right: _statusLabel.left anchors.rightMargin: 4 anchors.verticalCenter: parent.verticalCenter text: entry.modelData.name - color: entry.modelData.connected ? menuWindow.accentColor : S.Theme.base05 + color: entry._pending ? menuWindow.accentColor : entry.modelData.connected ? menuWindow.accentColor : S.Theme.base05 font.pixelSize: S.Theme.fontSize font.family: S.Theme.fontFamily - font.bold: entry.modelData.connected + font.bold: entry.modelData.connected || entry._pending elide: Text.ElideRight } Text { - id: batLabel + id: _statusLabel anchors.right: parent.right anchors.rightMargin: 12 anchors.verticalCenter: parent.verticalCenter - text: entry.modelData.battery >= 0 ? entry.modelData.battery + "%" : "" - color: S.Theme.base04 + text: entry._pending ? (entry.modelData.connected ? "disconnecting..." : "connecting...") : (entry.modelData.battery >= 0 ? entry.modelData.battery + "%" : "") + color: entry._pending ? S.Theme.base04 : S.Theme.base04 font.pixelSize: S.Theme.fontSize - 1 font.family: S.Theme.fontFamily - width: entry.modelData.battery >= 0 ? implicitWidth : 0 + font.italic: entry._pending + width: text ? implicitWidth : 0 + } + + // Pulse animation while pending + SequentialAnimation on opacity { + loops: Animation.Infinite + running: entry._pending + NumberAnimation { + to: 0.5 + duration: 400 + easing.type: Easing.InOutQuad + } + NumberAnimation { + to: 1 + duration: 400 + easing.type: Easing.InOutQuad + } + onRunningChanged: if (!running) + entry.opacity = 1 } HoverHandler { @@ -104,8 +125,10 @@ M.HoverPanel { } TapHandler { onTapped: { - S.BluetoothService.toggleDevice(entry.modelData.mac, !entry.modelData.connected); - menuWindow.keepOpen(500); + if (!entry._pending) { + S.BluetoothService.toggleDevice(entry.modelData.mac, !entry.modelData.connected); + menuWindow.keepOpen(500); + } } } } diff --git a/shell/services/BluetoothService.qml b/shell/services/BluetoothService.qml index e648538..608f1c6 100644 --- a/shell/services/BluetoothService.qml +++ b/shell/services/BluetoothService.qml @@ -26,7 +26,11 @@ QtObject { _powerProc.running = true; } + // MAC address of device currently connecting/disconnecting + property string pendingMac: "" + function toggleDevice(mac, connect) { + pendingMac = mac; _toggleProc._action = connect ? "connect" : "disconnect"; _toggleProc._mac = mac; _toggleProc.running = true; @@ -120,7 +124,9 @@ QtObject { property string _action: "" property string _mac: "" command: ["bluetoothctl", _action, _mac] - onRunningChanged: if (!running) - root.refresh() + onRunningChanged: if (!running) { + root.pendingMac = ""; + root.refresh(); + } } }