137 lines
5.0 KiB
QML
137 lines
5.0 KiB
QML
// Bluetooth, at page size.
|
|
//
|
|
// Paired devices first, because reconnecting to something you already own is
|
|
// what you are here for nine times out of ten; discovered devices follow.
|
|
// Battery is shown where BlueZ reports it, which is the one thing people
|
|
// routinely open a terminal for.
|
|
|
|
import QtQuick
|
|
import Quickshell
|
|
import Quickshell.Bluetooth
|
|
import qs.config
|
|
import qs.services
|
|
|
|
Column {
|
|
id: root
|
|
|
|
spacing: 0
|
|
|
|
// Connected and paired devices always render (they lead the sort, so the
|
|
// slice keeps them); unpaired strangers fill up to the cap and the rest
|
|
// wait behind the "nearby devices" row. Discovery in a busy room finds
|
|
// dozens of phones and TVs that are not yours.
|
|
property bool showAll: false
|
|
readonly property int visibleCap: 5
|
|
readonly property var shown: {
|
|
const list = Connectivity.bluetoothDevices;
|
|
if (root.showAll || list.length <= root.visibleCap)
|
|
return list;
|
|
const pinned = list.filter(device => device.connected || device.paired).length;
|
|
return list.slice(0, Math.max(root.visibleCap, pinned));
|
|
}
|
|
readonly property int hiddenCount: Connectivity.bluetoothDevices.length - root.shown.length
|
|
|
|
function primaryAction(device: var): void {
|
|
if (device.connected) {
|
|
device.disconnect();
|
|
return;
|
|
}
|
|
if (device.paired) {
|
|
device.connect();
|
|
return;
|
|
}
|
|
device.pair();
|
|
}
|
|
|
|
function stateLabel(device: var): string {
|
|
if (device.pairing)
|
|
return "Pairing…";
|
|
if (device.connected)
|
|
return device.batteryAvailable
|
|
? `Connected · ${Math.round(device.battery * 100)}% battery`
|
|
: "Connected";
|
|
if (device.paired)
|
|
return "Paired";
|
|
return device.address || "Not paired";
|
|
}
|
|
|
|
Repeater {
|
|
model: root.shown
|
|
|
|
SettingRow {
|
|
id: entry
|
|
|
|
required property var modelData
|
|
required property int index
|
|
|
|
width: parent.width
|
|
label: entry.modelData.name || entry.modelData.address || "Unknown device"
|
|
// Armed, the detail names what Forget costs. "Forget" reads like
|
|
// "hide from this list"; it is the pairing itself that goes, and
|
|
// the device has to be put back into pairing mode to return.
|
|
detail: forgetConfirm.armed
|
|
? "Drops the pairing — the device must be put back into pairing mode to return"
|
|
: root.stateLabel(entry.modelData)
|
|
divider: entry.index < root.shown.length - 1
|
|
|| root.hiddenCount > 0 || root.showAll
|
|
// Room for Keep and the confirming press while the row is armed.
|
|
controlWidth: forgetConfirm.armed ? 290 : 200
|
|
activatable: !entry.modelData.pairing
|
|
onActivated: root.primaryAction(entry.modelData)
|
|
|
|
Row {
|
|
anchors.right: parent.right
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
spacing: 7
|
|
|
|
SettingsButton {
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
enabled: !entry.modelData.pairing
|
|
text: entry.modelData.connected
|
|
? "Disconnect"
|
|
: (entry.modelData.paired ? "Connect" : "Pair")
|
|
onClicked: root.primaryAction(entry.modelData)
|
|
}
|
|
|
|
ConfirmAction {
|
|
id: forgetConfirm
|
|
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
visible: entry.modelData.paired
|
|
actionId: "bluetooth-forget:"
|
|
+ (entry.modelData.address || entry.modelData.name || "")
|
|
armText: "Forget…"
|
|
confirmText: "Forget it"
|
|
enabled: !entry.modelData.pairing
|
|
onConfirmed: entry.modelData.forget()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
SettingRow {
|
|
width: parent.width
|
|
visible: root.hiddenCount > 0
|
|
|| (root.showAll && Connectivity.bluetoothDevices.length > root.visibleCap)
|
|
label: root.showAll
|
|
? "Show fewer devices"
|
|
: root.hiddenCount + (root.hiddenCount === 1 ? " more nearby device" : " more nearby devices")
|
|
detail: root.showAll ? "" : "Unpaired devices in range, folded to keep the list short"
|
|
activatable: true
|
|
onActivated: root.showAll = !root.showAll
|
|
divider: false
|
|
}
|
|
|
|
SettingRow {
|
|
width: parent.width
|
|
visible: Connectivity.bluetoothDevices.length === 0
|
|
label: !Connectivity.adapter
|
|
? "No Bluetooth adapter"
|
|
: (Connectivity.adapter.enabled ? "Looking for devices…" : "Bluetooth is off")
|
|
detail: Connectivity.adapter && !Connectivity.adapter.enabled
|
|
? "Turn it on above to discover devices"
|
|
: "Put the device into pairing mode to make it appear"
|
|
divider: false
|
|
}
|
|
}
|