diff options
| author | 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> | 2025-08-03 18:43:25 +1000 |
|---|---|---|
| committer | 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> | 2025-08-03 18:43:25 +1000 |
| commit | 365b993221fe82c7e15ec79c7528799e6ea45cfc (patch) | |
| tree | d19b72ef83af7786b7a3dc634bea1215ac567012 | |
| parent | dcontent: add info to bt settings (diff) | |
| download | caelestia-shell-365b993221fe82c7e15ec79c7528799e6ea45cfc.tar.gz caelestia-shell-365b993221fe82c7e15ec79c7528799e6ea45cfc.tar.bz2 caelestia-shell-365b993221fe82c7e15ec79c7528799e6ea45cfc.zip | |
dcontent: impl bt device details
| -rw-r--r-- | modules/detachedcontent/Session.qml | 1 | ||||
| -rw-r--r-- | modules/detachedcontent/bluetooth/BtPane.qml | 3 | ||||
| -rw-r--r-- | modules/detachedcontent/bluetooth/Details.qml | 328 | ||||
| -rw-r--r-- | widgets/Elevation.qml | 22 |
4 files changed, 348 insertions, 6 deletions
diff --git a/modules/detachedcontent/Session.qml b/modules/detachedcontent/Session.qml index 4b27617..136454d 100644 --- a/modules/detachedcontent/Session.qml +++ b/modules/detachedcontent/Session.qml @@ -16,5 +16,6 @@ QtObject { property BluetoothDevice active property BluetoothAdapter currentAdapter: Bluetooth.defaultAdapter property bool editingAdapterName + property bool fabMenuOpen } } diff --git a/modules/detachedcontent/bluetooth/BtPane.qml b/modules/detachedcontent/bluetooth/BtPane.qml index ff2cc0a..1428540 100644 --- a/modules/detachedcontent/bluetooth/BtPane.qml +++ b/modules/detachedcontent/bluetooth/BtPane.qml @@ -72,9 +72,6 @@ RowLayout { id: details Details { - anchors.margins: Appearance.padding.normal - anchors.leftMargin: Appearance.padding.normal / 2 - session: root.session } } diff --git a/modules/detachedcontent/bluetooth/Details.qml b/modules/detachedcontent/bluetooth/Details.qml index b3f7e2a..6ca611e 100644 --- a/modules/detachedcontent/bluetooth/Details.qml +++ b/modules/detachedcontent/bluetooth/Details.qml @@ -1,15 +1,337 @@ +pragma ComponentBehavior: Bound + import ".." import qs.widgets import qs.services import qs.config -import Quickshell +import qs.utils import Quickshell.Bluetooth +import QtQuick import QtQuick.Layouts +import QtQuick.Effects -ColumnLayout { +Item { id: root required property Session session + readonly property BluetoothDevice device: session.bt.active + + StyledFlickable { + anchors.fill: parent + + flickableDirection: Flickable.VerticalFlick + contentHeight: layout.height + + ColumnLayout { + id: layout + + anchors.left: parent.left + anchors.right: parent.right + spacing: Appearance.spacing.normal + + MaterialIcon { + Layout.alignment: Qt.AlignHCenter + text: Icons.getBluetoothIcon(root.device.icon) + font.pointSize: Appearance.font.size.extraLarge * 3 + font.bold: true + } + + StyledText { + Layout.alignment: Qt.AlignHCenter + text: root.device.name + font.pointSize: Appearance.font.size.large + font.bold: true + } + + StyledText { + Layout.topMargin: Appearance.spacing.large + text: qsTr("Connection status") + font.pointSize: Appearance.font.size.larger + font.weight: 500 + } + + StyledText { + text: qsTr("Connection settings for this device") + color: Colours.palette.m3outline + } + + StyledRect { + Layout.fillWidth: true + implicitHeight: adapterStatus.implicitHeight + Appearance.padding.large * 2 + + radius: Appearance.rounding.normal + color: Colours.palette.m3surfaceContainer + + ColumnLayout { + id: adapterStatus + + anchors.left: parent.left + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + anchors.margins: Appearance.padding.large + + spacing: Appearance.spacing.larger + + Toggle { + label: qsTr("Connected") + checked: root.device.connected + toggle.onToggled: root.device.connected = checked + } + + Toggle { + label: qsTr("Paired") + checked: root.device.paired + toggle.onToggled: { + if (root.device.paired) + root.device.forget(); + else + root.device.pair(); + } + } + + Toggle { + label: qsTr("Blocked") + checked: root.device.blocked + toggle.onToggled: root.device.blocked = checked + } + } + } + } + } + + ColumnLayout { + anchors.right: fabRoot.right + anchors.bottom: fabRoot.top + anchors.bottomMargin: Appearance.padding.normal + + Repeater { + id: fabMenu + + model: [ + { + icon: "handshake", + label: root.device.trusted ? qsTr("Untrust") : qsTr("Trust"), + onClicked: () => root.device.trusted = !root.device.trusted + }, + { + icon: "block", + label: root.device.blocked ? qsTr("Unblock") : qsTr("Block"), + onClicked: () => root.device.blocked = !root.device.blocked + }, + { + icon: "missing_controller", + label: root.device.paired ? qsTr("Unpair") : qsTr("Pair"), + onClicked: () => { + if (root.device.paired) + root.device.forget(); + else + root.device.pair(); + } + }, + { + icon: "bluetooth_connected", + label: root.device.connected ? qsTr("Disconnect") : qsTr("Connect"), + onClicked: () => root.device.connected = !root.device.connected + } + ] + + StyledClippingRect { + id: fabMenuItem + + required property var modelData + required property int index + + Layout.alignment: Qt.AlignRight + + implicitHeight: fabMenuItemInner.implicitHeight + Appearance.padding.larger * 2 + + radius: Appearance.rounding.full + color: Colours.palette.m3primaryContainer + + opacity: 0 + + states: State { + name: "visible" + when: root.session.bt.fabMenuOpen + + PropertyChanges { + fabMenuItem.implicitWidth: fabMenuItemInner.implicitWidth + Appearance.padding.large * 2 + fabMenuItem.opacity: 1 + fabMenuItemInner.opacity: 1 + } + } + + transitions: [ + Transition { + to: "visible" + + SequentialAnimation { + PauseAnimation { + duration: (fabMenu.count - 1 - fabMenuItem.index) * Appearance.anim.durations.small / 8 + } + ParallelAnimation { + Anim { + property: "implicitWidth" + duration: Appearance.anim.durations.expressiveFastSpatial + easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial + } + Anim { + property: "opacity" + duration: Appearance.anim.durations.small + } + } + } + }, + Transition { + from: "visible" + + SequentialAnimation { + PauseAnimation { + duration: fabMenuItem.index * Appearance.anim.durations.small / 8 + } + ParallelAnimation { + Anim { + property: "implicitWidth" + duration: Appearance.anim.durations.expressiveFastSpatial + easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial + } + Anim { + property: "opacity" + duration: Appearance.anim.durations.small + } + } + } + } + ] + + StateLayer { + function onClicked(): void { + root.session.bt.fabMenuOpen = false; + fabMenuItem.modelData.onClicked(); + } + } + + RowLayout { + id: fabMenuItemInner + + anchors.centerIn: parent + spacing: Appearance.spacing.normal + opacity: 0 + + MaterialIcon { + text: fabMenuItem.modelData.icon + color: Colours.palette.m3onPrimaryContainer + fill: 1 + } + + StyledText { + text: fabMenuItem.modelData.label + color: Colours.palette.m3onPrimaryContainer + } + } + } + } + } + + Item { + id: fabRoot + + anchors.right: parent.right + anchors.bottom: parent.bottom + + implicitWidth: 64 + implicitHeight: 64 + + StyledRect { + id: fabBg + + anchors.right: parent.right + anchors.top: parent.top + + implicitWidth: 64 + implicitHeight: 64 + + radius: Appearance.rounding.normal + color: root.session.bt.fabMenuOpen ? Colours.palette.m3primary : Colours.palette.m3primaryContainer + + states: State { + name: "expanded" + when: root.session.bt.fabMenuOpen + + PropertyChanges { + fabBg.implicitWidth: 48 + fabBg.implicitHeight: 48 + fabBg.radius: 48 / 2 + fab.font.pointSize: Appearance.font.size.larger + } + } + + transitions: Transition { + Anim { + properties: "implicitWidth,implicitHeight" + duration: Appearance.anim.durations.expressiveFastSpatial + easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial + } + Anim { + properties: "radius,font.pointSize" + } + } + + Elevation { + anchors.fill: parent + radius: parent.radius + z: -1 + level: fabState.containsMouse && !fabState.pressed ? 4 : 3 + } + + StateLayer { + id: fabState + + color: root.session.bt.fabMenuOpen ? Colours.palette.m3onPrimary : Colours.palette.m3onPrimaryContainer + + function onClicked(): void { + root.session.bt.fabMenuOpen = !root.session.bt.fabMenuOpen; + } + } + + MaterialIcon { + id: fab + + anchors.centerIn: parent + animate: true + text: root.session.bt.fabMenuOpen ? "close" : "settings" + color: root.session.bt.fabMenuOpen ? Colours.palette.m3onPrimary : Colours.palette.m3onPrimaryContainer + font.pointSize: Appearance.font.size.large + fill: 1 + } + + Behavior on radius { + Anim {} + } + } + } + + component Toggle: RowLayout { + required property string label + property alias checked: toggle.checked + property alias toggle: toggle + + Layout.fillWidth: true + spacing: Appearance.spacing.normal + + StyledText { + Layout.fillWidth: true + text: parent.label + } + + StyledSwitch { + id: toggle + } + } - spacing: Appearance.spacing.normal + component Anim: NumberAnimation { + duration: Appearance.anim.durations.normal + easing.type: Easing.BezierSpline + easing.bezierCurve: Appearance.anim.curves.standard + } } diff --git a/widgets/Elevation.qml b/widgets/Elevation.qml new file mode 100644 index 0000000..999b199 --- /dev/null +++ b/widgets/Elevation.qml @@ -0,0 +1,22 @@ +import qs.services +import qs.config +import QtQuick +import QtQuick.Effects + +RectangularShadow { + property int level + property real dp: [0, 1, 3, 6, 8, 12][level] + + color: Qt.alpha(Colours.palette.m3shadow, 0.7) + blur: (dp * 5) ** 0.7 + spread: -dp * 0.3 + (dp * 0.1) ** 2 + offset.y: dp / 2 + + Behavior on dp { + NumberAnimation { + duration: Appearance.anim.durations.normal + easing.type: Easing.BezierSpline + easing.bezierCurve: Appearance.anim.curves.standard + } + } +} |