diff options
| author | Leander Scherer <leander@schererleander.de> | 2026-05-18 21:48:24 +0200 |
|---|---|---|
| committer | Leander Scherer <leander@schererleander.de> | 2026-05-28 22:42:07 +0200 |
| commit | 9a7cf1242d296dbdb9c03df48ab09054960295aa (patch) | |
| tree | f1a2d5c77ef6bdb049c995afcc4c663c1ffd1373 /modules/system/quickshell/Media.qml | |
| parent | 3ef8b4973bcae26445f99467d50ad75730d204b5 (diff) | |
feat(quickshell): basic bar, tray, notification
Diffstat (limited to 'modules/system/quickshell/Media.qml')
| -rw-r--r-- | modules/system/quickshell/Media.qml | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/modules/system/quickshell/Media.qml b/modules/system/quickshell/Media.qml new file mode 100644 index 0000000..ee5bf42 --- /dev/null +++ b/modules/system/quickshell/Media.qml @@ -0,0 +1,119 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell +import Quickshell.Services.Mpris + +Item { + id: root + + property QtObject manualExpandedPlayer: null + + readonly property var activePlayers: Mpris.players?.values || [] + + readonly property var expandedPlayer: { + if (root.manualExpandedPlayer !== null && root.activePlayers.includes(root.manualExpandedPlayer)) { + return root.manualExpandedPlayer; + } + for (const player of root.activePlayers) { + if (player.playbackState === MprisPlaybackState.Playing) { + return player; + } + } + if (root.activePlayers.length > 0) { + return root.activePlayers[0]; + } + return null; + } + + width: childrenRect.width + height: parent.height + + Row { + anchors.verticalCenter: parent.verticalCenter + + MusicVisualizer { + active: root.expandedPlayer?.playbackState === MprisPlaybackState.Playing + anchors.verticalCenter: parent.verticalCenter + } + } + + MouseArea { + anchors.fill: parent + onClicked: GlobalState.toggle("Media") + } + + PopupWindow { + id: popup + visible: GlobalState.activePopup === "Media" + grabFocus: true + implicitWidth: card.width + implicitHeight: card.height + + anchor { + window: barWindow + item: root + edges: Edges.Bottom + gravity: Edges.Bottom + margins.top: Theme.popupGap + } + + color: Theme.transparent + + PopupCard { + id: card + width: 320 + + ColumnLayout { + Layout.fillWidth: true + spacing: 0 + Layout.margins: 8 + + Repeater { + model: root.activePlayers.length > 0 ? root.activePlayers : [null] + + delegate: Item { + id: playerDelegate + Layout.fillWidth: true + implicitHeight: mediaCard.implicitHeight + (separator.visible ? separator.height + 16 : 0) + + required property var modelData + required property int index + + readonly property bool isEmpty: modelData === null + readonly property bool isExpanded: root.expandedPlayer === modelData && !isEmpty + + ColumnLayout { + anchors.fill: parent + spacing: 16 + + MediaCard { + id: mediaCard + Layout.fillWidth: true + player: playerDelegate.modelData + isExpanded: playerDelegate.isExpanded + + onClicked: { + if (!playerDelegate.isEmpty) { + root.manualExpandedPlayer = playerDelegate.modelData; + } else { + Quickshell.execDetached(["spotify"]); + } + } + } + + Rectangle { + id: separator + Layout.fillWidth: true + height: 1 + color: Theme.border + opacity: 0.3 + visible: !playerDelegate.isEmpty && playerDelegate.index < root.activePlayers.length - 1 + Layout.topMargin: 4 + } + } + } + } + } + } + } +} |
