nosignal-shell/modules/bar/popouts/Audio.qml
Laurens Duin 9ada66a78e
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>
2025-08-05 16:04:53 +10:00

139 lines
3.7 KiB
QML

pragma ComponentBehavior: Bound
import qs.components
import qs.components.controls
import qs.services
import qs.config
import Quickshell
import Quickshell.Services.Pipewire
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls
Item {
id: root
required property var wrapper
implicitWidth: layout.implicitWidth + Appearance.padding.normal * 2
implicitHeight: layout.implicitHeight + Appearance.padding.normal * 2
ButtonGroup {
id: sinks
}
ButtonGroup {
id: sources
}
ColumnLayout {
id: layout
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
spacing: 0
StyledText {
Layout.bottomMargin: Appearance.spacing.small / 2
text: qsTr("Output")
font.weight: 500
}
Repeater {
model: Audio.sinks
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
}
Repeater {
model: Audio.sources
StyledRadioButton {
required property PwNode modelData
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
}
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
}
}
}
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
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
}
}
}
}
}