me like nix
1import QtQuick
2import QtQuick.Layouts
3import Quickshell
4import Quickshell.Wayland
5import Quickshell.Io
6import "../../../config" as Config
7import "../../../components"
8import "../../../services" as Services
9
10PopupWindow {
11 id: audioPopout
12
13 property bool show: false
14 property var parentWindow
15 property real anchorY: 0
16 signal close()
17
18 visible: show || contentRect.opacity > 0
19 anchor.window: parentWindow
20 anchor.onAnchoring: {
21 anchor.rect.x = parentWindow.width + 8
22 anchor.rect.y = Math.max(0, anchorY - implicitHeight / 2)
23 }
24
25 implicitWidth: 220
26 implicitHeight: audioContent.implicitHeight + 32
27 color: "transparent"
28
29 onShowChanged: {
30 if (show) { contentRect._opening = true; fadeIn.start() }
31 else { fadeIn.stop(); contentRect._opening = false; contentRect.opacity = 0 }
32 }
33 Timer { id: fadeIn; interval: 16; onTriggered: contentRect.opacity = 1 }
34
35 Rectangle {
36 id: contentRect
37 anchors.fill: parent
38 color: Config.Colours.base
39 radius: Config.Appearance.rounding.large
40 border.width: 1
41 border.color: Config.Colours.surface0
42 opacity: 0
43 property bool _opening: false
44 Behavior on opacity {
45 Anim {
46 duration: contentRect._opening ? Config.Appearance.anim.durations.normal : Config.Appearance.anim.durations.small
47 easing.bezierCurve: contentRect._opening ? Config.Appearance.anim.curves.standardDecel : Config.Appearance.anim.curves.standardAccel
48 }
49 }
50
51 ColumnLayout {
52 id: audioContent
53 anchors.fill: parent
54 anchors.margins: 16
55 spacing: 12
56
57 Text {
58 color: Config.Colours.text
59 font.family: Config.Appearance.font.family
60 font.pixelSize: Config.Appearance.font.size.normal
61 font.bold: true
62 text: "Volume"
63 }
64
65 RowLayout {
66 Layout.fillWidth: true
67 spacing: 8
68 Text { color: Config.Colours.maroon; font.family: Config.Appearance.font.family; font.pixelSize: 20; text: Services.Audio.muted ? "\uf026" : "\uf028" }
69 Text { color: Config.Colours.text; font.family: Config.Appearance.font.family; font.pixelSize: Config.Appearance.font.size.large; font.bold: true; text: Services.Audio.muted ? "Muted" : Services.Audio.volume + "%" }
70 }
71
72 Item {
73 Layout.fillWidth: true
74 height: 6
75 property real animatedPct: Services.Audio.volume
76 Behavior on animatedPct { Anim { duration: Config.Appearance.anim.durations.large } }
77 Rectangle { anchors.fill: parent; radius: 3; color: Config.Colours.surface1 }
78 Rectangle { width: parent.width * (parent.animatedPct / 100); height: parent.height; radius: 3; color: Config.Colours.maroon }
79 }
80
81 Rectangle {
82 Layout.fillWidth: true
83 height: 32
84 radius: Config.Appearance.rounding.normal
85 color: muteMouse.containsMouse ? Config.Colours.surface1 : Config.Colours.surface0
86 Behavior on color { CAnim {} }
87 Text { anchors.centerIn: parent; color: Config.Colours.subtext0; font.family: Config.Appearance.font.family; font.pixelSize: Config.Appearance.font.size.small; text: Services.Audio.muted ? "Unmute" : "Mute" }
88 MouseArea { id: muteMouse; anchors.fill: parent; hoverEnabled: true; cursorShape: Qt.PointingHandCursor; onClicked: muteProc.running = true }
89 }
90
91 Process { id: muteProc; command: ["wpctl", "set-mute", "@DEFAULT_AUDIO_SINK@", "toggle"] }
92 }
93
94 Keys.onEscapePressed: audioPopout.close()
95 }
96
97 MouseArea { anchors.fill: parent; z: -1; onClicked: audioPopout.close() }
98}