From 9ada66a78ea58d8b498f1dd26bf0783e1a442c51 Mon Sep 17 00:00:00 2001 From: Laurens Duin <85798751+Laurens256@users.noreply.github.com> Date: Tue, 5 Aug 2025 08:04:53 +0200 Subject: bar/popouts: add audio device switcher (#319) * feat: basic audio switcher * feat: replace VerticalSlider with StyledSlider * fix: styling * fix: formatting * chore: make sound icons consistent, change slider styling * feat: styled slider component variants * chore: cleanup * chore: cleanup * fix: pr fixes * fix: remove redundant code * chore: remove old code * fix: controls styling * fixes * more tweaks * radiobtn: add interaction stuff Anim slider --------- Co-authored-by: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> --- modules/bar/components/StatusIcons.qml | 2 +- modules/bar/popouts/Audio.qml | 145 +++++++++++++++++++++++++-------- modules/dashboard/Media.qml | 54 +----------- modules/lock/MediaPlaying.qml | 53 +----------- modules/osd/Content.qml | 15 +--- 5 files changed, 123 insertions(+), 146 deletions(-) (limited to 'modules') diff --git a/modules/bar/components/StatusIcons.qml b/modules/bar/components/StatusIcons.qml index ad8c35e..c364d6b 100644 --- a/modules/bar/components/StatusIcons.qml +++ b/modules/bar/components/StatusIcons.qml @@ -58,7 +58,7 @@ Item { sourceComponent: MaterialIcon { animate: true - text: Audio.muted ? "volume_off" : Audio.volume >= 0.66 ? "volume_up" : Audio.volume >= 0.33 ? "volume_down" : "volume_mute" + text: Icons.getVolumeIcon(Audio.volume, Audio.muted) color: root.colour } } diff --git a/modules/bar/popouts/Audio.qml b/modules/bar/popouts/Audio.qml index e6e5514..84378c9 100644 --- a/modules/bar/popouts/Audio.qml +++ b/modules/bar/popouts/Audio.qml @@ -1,58 +1,139 @@ +pragma ComponentBehavior: Bound + import qs.components import qs.components.controls import qs.services import qs.config -import QtQuick.Layouts import Quickshell +import Quickshell.Services.Pipewire +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls -ColumnLayout { +Item { id: root required property var wrapper - spacing: Appearance.spacing.normal + implicitWidth: layout.implicitWidth + Appearance.padding.normal * 2 + implicitHeight: layout.implicitHeight + Appearance.padding.normal * 2 + + ButtonGroup { + id: sinks + } + + ButtonGroup { + id: sources + } + + ColumnLayout { + id: layout - VerticalSlider { - id: volumeSlider + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + spacing: 0 - icon: { - if (Audio.muted) - return "no_sound"; - if (value >= 0.5) - return "volume_up"; - if (value > 0) - return "volume_down"; - return "volume_mute"; + StyledText { + Layout.bottomMargin: Appearance.spacing.small / 2 + text: qsTr("Output") + font.weight: 500 } - value: Audio.volume - onMoved: Audio.setVolume(value) + Repeater { + model: Audio.sinks - implicitWidth: Config.osd.sizes.sliderWidth - implicitHeight: Config.osd.sizes.sliderHeight - } + StyledRadioButton { + id: control + + required property PwNode modelData + + ButtonGroup.group: sinks + checked: Audio.sink?.id === modelData.id + onClicked: Audio.setAudioSink(modelData) + text: modelData.description + } + } + + StyledText { + Layout.topMargin: Appearance.spacing.small + Layout.bottomMargin: Appearance.spacing.small / 2 + text: qsTr("Input") + font.weight: 500 + } - StyledRect { - id: pavuButton + Repeater { + model: Audio.sources - implicitWidth: implicitHeight - implicitHeight: icon.implicitHeight + Appearance.padding.small * 2 + StyledRadioButton { + required property PwNode modelData - radius: Appearance.rounding.normal - color: Colours.palette.m3surfaceContainer + ButtonGroup.group: sources + checked: Audio.source?.id === modelData.id + onClicked: Audio.setAudioSource(modelData) + text: modelData.description + } + } + + StyledText { + Layout.topMargin: Appearance.spacing.small + Layout.bottomMargin: Appearance.spacing.small / 2 + text: qsTr("Volume") + font.weight: 500 + } - StateLayer { - function onClicked(): void { - root.wrapper.hasCurrent = false; - Quickshell.execDetached(["app2unit", "--", ...Config.general.apps.audio]); + StyledSlider { + Layout.fillWidth: true + implicitHeight: Appearance.padding.normal * 3 + + value: Audio.volume + onMoved: Audio.setVolume(value) + + Behavior on value { + NumberAnimation { + duration: Appearance.anim.durations.normal + easing.type: Easing.BezierSpline + easing.bezierCurve: Appearance.anim.curves.standard + } } } - MaterialIcon { - id: icon + StyledRect { + Layout.topMargin: Appearance.spacing.normal + visible: Config.general.apps.audio.length > 0 + + implicitWidth: expandBtn.implicitWidth + Appearance.padding.normal * 2 + implicitHeight: expandBtn.implicitHeight + Appearance.padding.small + + radius: Appearance.rounding.normal + color: Colours.palette.m3primaryContainer - anchors.centerIn: parent - text: "settings" + StateLayer { + color: Colours.palette.m3onPrimaryContainer + + function onClicked(): void { + root.wrapper.hasCurrent = false; + Quickshell.execDetached(["app2unit", "--", ...Config.general.apps.audio]); + } + } + + RowLayout { + id: expandBtn + + anchors.centerIn: parent + spacing: Appearance.spacing.small + + StyledText { + Layout.leftMargin: Appearance.padding.smaller + text: qsTr("Open settings") + color: Colours.palette.m3onPrimaryContainer + } + + MaterialIcon { + text: "chevron_right" + color: Colours.palette.m3onPrimaryContainer + font.pointSize: Appearance.font.size.large + } + } } } } diff --git a/modules/dashboard/Media.qml b/modules/dashboard/Media.qml index c12db22..edb09af 100644 --- a/modules/dashboard/Media.qml +++ b/modules/dashboard/Media.qml @@ -3,6 +3,7 @@ pragma ComponentBehavior: Bound import qs.components import qs.components.effects import qs.components.misc +import qs.components.controls import qs.services import qs.utils import qs.config @@ -279,9 +280,10 @@ Item { } } - Slider { + StyledSlider { id: slider + enabled: !!Players.active implicitWidth: controls.implicitWidth * 1.5 implicitHeight: Appearance.padding.normal * 3 @@ -291,56 +293,6 @@ Item { if (active?.canSeek && active?.positionSupported) active.position = value * active.length; } - - background: Item { - StyledRect { - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.topMargin: slider.implicitHeight / 3 - anchors.bottomMargin: slider.implicitHeight / 3 - - implicitWidth: slider.handle.x - slider.implicitHeight / 6 - - color: Colours.palette.m3primary - radius: Appearance.rounding.full - topRightRadius: slider.implicitHeight / 15 - bottomRightRadius: slider.implicitHeight / 15 - } - - StyledRect { - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.right: parent.right - anchors.topMargin: slider.implicitHeight / 3 - anchors.bottomMargin: slider.implicitHeight / 3 - - implicitWidth: parent.width - slider.handle.x - slider.handle.implicitWidth - slider.implicitHeight / 6 - - color: Colours.palette.m3surfaceContainer - radius: Appearance.rounding.full - topLeftRadius: slider.implicitHeight / 15 - bottomLeftRadius: slider.implicitHeight / 15 - } - } - - handle: StyledRect { - id: rect - - x: slider.visualPosition * slider.availableWidth - - implicitWidth: slider.implicitHeight / 4.5 - implicitHeight: slider.implicitHeight - - color: Colours.palette.m3primary - radius: Appearance.rounding.full - - MouseArea { - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - onPressed: event => event.accepted = false - } - } } Item { diff --git a/modules/lock/MediaPlaying.qml b/modules/lock/MediaPlaying.qml index 08f1490..2ebd177 100644 --- a/modules/lock/MediaPlaying.qml +++ b/modules/lock/MediaPlaying.qml @@ -1,4 +1,5 @@ import qs.components +import qs.components.controls import qs.services import qs.config import Quickshell.Widgets @@ -164,7 +165,7 @@ RowLayout { spacing: Appearance.spacing.small - Slider { + StyledSlider { id: slider Layout.rightMargin: root.isLarge ? Appearance.spacing.small : 0 @@ -177,56 +178,6 @@ RowLayout { if (active?.canSeek && active?.positionSupported) active.position = value * active.length; } - - background: Item { - StyledRect { - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.topMargin: slider.implicitHeight / 3 - anchors.bottomMargin: slider.implicitHeight / 3 - - implicitWidth: slider.handle.x - slider.implicitHeight / 6 - - color: Colours.palette.m3primary - radius: Appearance.rounding.full - topRightRadius: slider.implicitHeight / 15 - bottomRightRadius: slider.implicitHeight / 15 - } - - StyledRect { - anchors.top: parent.top - anchors.bottom: parent.bottom - anchors.right: parent.right - anchors.topMargin: slider.implicitHeight / 3 - anchors.bottomMargin: slider.implicitHeight / 3 - - implicitWidth: parent.width - slider.handle.x - slider.handle.implicitWidth - slider.implicitHeight / 6 - - color: Colours.palette.m3surfaceContainer - radius: Appearance.rounding.full - topLeftRadius: slider.implicitHeight / 15 - bottomLeftRadius: slider.implicitHeight / 15 - } - } - - handle: StyledRect { - id: rect - - x: slider.visualPosition * slider.availableWidth - - implicitWidth: slider.implicitHeight / 4.5 - implicitHeight: slider.implicitHeight - - color: Colours.palette.m3primary - radius: Appearance.rounding.full - - MouseArea { - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - onPressed: event => event.accepted = false - } - } } Control { diff --git a/modules/osd/Content.qml b/modules/osd/Content.qml index 3177ee9..29b1b39 100644 --- a/modules/osd/Content.qml +++ b/modules/osd/Content.qml @@ -1,6 +1,7 @@ import qs.components.controls import qs.services import qs.config +import qs.utils import QtQuick Column { @@ -26,18 +27,10 @@ Column { Audio.setVolume(Audio.volume - 0.1); } - VerticalSlider { + FilledSlider { anchors.fill: parent - icon: { - if (Audio.muted) - return "no_sound"; - if (value >= 0.5) - return "volume_up"; - if (value > 0) - return "volume_down"; - return "volume_mute"; - } + icon: Icons.getVolumeIcon(value, Audio.muted) value: Audio.volume onMoved: Audio.setVolume(value) } @@ -57,7 +50,7 @@ Column { monitor.setBrightness(monitor.brightness - 0.1); } - VerticalSlider { + FilledSlider { anchors.fill: parent icon: `brightness_${(Math.round(value * 6) + 1)}` -- cgit v1.2.3-freya