Files
dms-gamebar/widgets/BluetoothWidget.qml

193 lines
6.4 KiB
QML

import QtQuick
import Quickshell
import Quickshell.Bluetooth
import qs.Common
import qs.Services
import qs.Widgets
Item {
id: widget
readonly property var adapter: BluetoothService.adapter
readonly property bool adapterEnabled: BluetoothService.enabled
readonly property var devices: BluetoothService.pairedDevices || []
function batteryText(device) {
if (device && device.batteryAvailable && device.battery > 0)
return Math.round(device.battery * 100) + "%";
return "";
}
Row {
id: header
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
height: 34
spacing: Theme.spacingS
DankIcon {
anchors.verticalCenter: parent.verticalCenter
name: widget.adapterEnabled ? "bluetooth" : "bluetooth_disabled"
size: Theme.iconSize - 6
color: widget.adapterEnabled ? Theme.primary : Theme.surfaceVariantText
}
StyledText {
anchors.verticalCenter: parent.verticalCenter
width: parent.width - Theme.iconSize - scanButton.width - toggle.width - parent.spacing * 3
text: widget.adapter ? (widget.adapterEnabled ? "On" : "Off") : "No adapter"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
elide: Text.ElideRight
}
DankActionButton {
id: scanButton
anchors.verticalCenter: parent.verticalCenter
iconName: "search"
buttonSize: 30
iconSize: 17
iconColor: BluetoothService.discovering ? Theme.primary : Theme.surfaceText
enabled: widget.adapterEnabled
onClicked: {
if (widget.adapter)
widget.adapter.discovering = !widget.adapter.discovering;
}
}
DankToggle {
id: toggle
anchors.verticalCenter: parent.verticalCenter
hideText: true
checked: widget.adapterEnabled
enabled: widget.adapter !== null
onToggled: isChecked => {
if (widget.adapter)
widget.adapter.enabled = isChecked;
}
}
}
DankListView {
id: deviceList
anchors.top: header.bottom
anchors.topMargin: Theme.spacingXS
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
clip: true
spacing: Theme.spacingXS
visible: widget.adapterEnabled && widget.devices.length > 0
model: widget.devices
delegate: Rectangle {
id: deviceItem
required property var modelData
readonly property bool isConnected: modelData.connected
readonly property bool isBusy: BluetoothService.isDeviceBusy(modelData)
width: deviceList.width
height: 46
radius: Theme.cornerRadius
color: isConnected ? Theme.primarySelected : (deviceArea.containsMouse ? Theme.surfaceHover : Theme.withAlpha(Theme.surfaceLight, Theme.popupTransparency))
border.color: isConnected ? Theme.primary : Theme.outlineLight
border.width: isConnected ? 1 : Theme.layerOutlineWidth
DankIcon {
id: deviceIcon
anchors.left: parent.left
anchors.leftMargin: Theme.spacingM
anchors.verticalCenter: parent.verticalCenter
name: BluetoothService.getDeviceIcon(deviceItem.modelData)
size: Theme.iconSize - 6
color: deviceItem.isConnected ? Theme.primary : Theme.surfaceText
}
Column {
anchors.left: deviceIcon.right
anchors.leftMargin: Theme.spacingS
anchors.right: busyIndicator.left
anchors.rightMargin: Theme.spacingS
anchors.verticalCenter: parent.verticalCenter
spacing: 0
StyledText {
width: parent.width
text: deviceItem.modelData.name || deviceItem.modelData.address
font.pixelSize: Theme.fontSizeMedium
font.weight: deviceItem.isConnected ? Font.Medium : Font.Normal
color: Theme.surfaceText
elide: Text.ElideRight
}
StyledText {
width: parent.width
text: {
const battery = widget.batteryText(deviceItem.modelData);
const state = deviceItem.isBusy ? "Working…" : (deviceItem.isConnected ? "Connected" : "Disconnected");
return battery !== "" ? state + " · " + battery : state;
}
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
elide: Text.ElideRight
}
}
DankSpinner {
id: busyIndicator
anchors.right: parent.right
anchors.rightMargin: Theme.spacingM
anchors.verticalCenter: parent.verticalCenter
size: 18
running: deviceItem.isBusy
visible: deviceItem.isBusy
}
MouseArea {
id: deviceArea
anchors.fill: parent
hoverEnabled: true
enabled: !deviceItem.isBusy
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: {
if (deviceItem.isConnected)
deviceItem.modelData.disconnect();
else
BluetoothService.connectDeviceWithTrust(deviceItem.modelData);
}
}
}
}
Column {
anchors.centerIn: parent
spacing: Theme.spacingS
visible: !deviceList.visible
DankIcon {
anchors.horizontalCenter: parent.horizontalCenter
name: "bluetooth_disabled"
size: Theme.iconSizeLarge
color: Theme.surfaceVariantText
}
StyledText {
anchors.horizontalCenter: parent.horizontalCenter
text: widget.adapterEnabled ? "No paired devices" : "Bluetooth is off"
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
}
}
}