pragma Singleton // Transition-only device monitoring. Resting state is intentionally silent. import Quickshell import Quickshell.Bluetooth import Quickshell.Io import Quickshell.Services.Pipewire import QtQuick Singleton { id: root property bool outputInitialized: false property bool bluetoothInitialized: false property bool kdeInitialized: false property string previousOutput: "" property string previousBluetooth: "" property string previousKde: "" PwObjectTracker { objects: [Pipewire.defaultAudioSink] } readonly property string outputName: { const sink = Pipewire.defaultAudioSink; return sink?.description || sink?.nickname || sink?.name || ""; } readonly property string bluetoothNames: { const devices = Bluetooth.devices?.values ?? []; return devices.filter(device => device.connected) .map(device => device.name || device.address) .sort() .join("\u001f"); } onOutputNameChanged: { if (!root.outputInitialized) { root.previousOutput = root.outputName; return; } if (root.outputInitialized && root.outputName && root.outputName !== root.previousOutput) { StatusEvents.publish({ key: "device-output", glyph: "\u{F07E7}", title: root.outputName, detail: "Audio output selected", priority: StatusEvents.ambientPriority }); } root.previousOutput = root.outputName; } onBluetoothNamesChanged: { if (!root.bluetoothInitialized) { root.previousBluetooth = root.bluetoothNames; return; } if (root.bluetoothInitialized && root.bluetoothNames !== root.previousBluetooth) { const current = root.bluetoothNames ? root.bluetoothNames.split("\u001f") : []; const previous = root.previousBluetooth ? root.previousBluetooth.split("\u001f") : []; const connected = current.find(name => !previous.includes(name)); const disconnected = previous.find(name => !current.includes(name)); StatusEvents.publish({ key: "device-bluetooth", glyph: "\u{F00B1}", title: connected || disconnected || "Bluetooth device", detail: connected ? "Connected" : "Disconnected", tone: connected ? "accent" : "warn", priority: StatusEvents.ambientPriority }); } root.previousBluetooth = root.bluetoothNames; } Timer { id: discoverySettle interval: 1800 onTriggered: { root.previousOutput = root.outputName; root.previousBluetooth = root.bluetoothNames; root.outputInitialized = true; root.bluetoothInitialized = true; } } Timer { interval: 15000 repeat: true running: true triggeredOnStart: true onTriggered: { if (!kdeProbe.running) kdeProbe.running = true; } } Process { id: kdeProbe command: ["kdeconnect-cli", "-a", "--name-only"] stdout: StdioCollector { onStreamFinished: { const names = this.text.split("\n") .map(line => line.trim()) .filter(line => line && !/^\d+ devices? found$/.test(line)) .sort() .join("\u001f"); if (root.kdeInitialized && names !== root.previousKde) { const current = names ? names.split("\u001f") : []; const previous = root.previousKde ? root.previousKde.split("\u001f") : []; const connected = current.find(name => !previous.includes(name)); const disconnected = previous.find(name => !current.includes(name)); StatusEvents.publish({ key: "device-kdeconnect", glyph: "\u{F03F2}", title: connected || disconnected || "Phone", detail: connected ? "KDE Connect available" : "KDE Connect disconnected", tone: connected ? "accent" : "warn", priority: StatusEvents.ambientPriority }); } root.previousKde = names; root.kdeInitialized = true; } } } Component.onCompleted: { root.previousOutput = root.outputName; root.previousBluetooth = root.bluetoothNames; discoverySettle.start(); } }