Regenerated

This commit is contained in:
2026-04-13 11:02:25 +02:00
parent 55dd1433d6
commit 28ba7e8342
4 changed files with 768 additions and 411 deletions
+478 -359
View File
File diff suppressed because it is too large Load Diff
+145 -26
View File
@@ -2656,15 +2656,19 @@ ShellRoot {
// State
QtObject {
id: media
property string artist: ""
property string title: ""
property string album: ""
property string artUrl: ""
property string status: ""
property string device: ""
property real progress: 0.0
property real duration: 0.0
property real position: 0.0
property string artist: ""
property string title: ""
property string album: ""
property string artUrl: ""
property string status: ""
property string device: ""
property string player: ""
property real progress: 0.0
property real duration: 0.0
property real position: 0.0
// 0 = no shuffle, 1 = shuffle, 2 = smart shuffle
property int shuffleMode: 0
readonly property bool isSpotify: player.indexOf("spotify") !== -1
}
// Poll playerctl every second
@@ -2673,13 +2677,34 @@ ShellRoot {
running: true
repeat: true
onTriggered: {
artistProc.running = true
titleProc.running = true
albumProc.running = true
artProc.running = true
statusProc.running = true
playerProc.running = true
artistProc.running = true
titleProc.running = true
albumProc.running = true
artProc.running = true
statusProc.running = true
positionProc.running = true
lengthProc.running = true
lengthProc.running = true
if (media.isSpotify)
shuffleProc.running = true
}
}
// Detect active player — prefers spotify
Process {
id: playerProc
command: ["playerctl", "-l"]
stdout: StdioCollector {
onStreamFinished: {
var lines = text.trim().split("\n")
for (var i = 0; i < lines.length; i++) {
if (lines[i].indexOf("spotify") !== -1) {
media.player = lines[i].trim()
return
}
}
media.player = lines[0] ? lines[0].trim() : ""
}
}
}
@@ -2729,10 +2754,48 @@ ShellRoot {
}
}
// Read shuffle state from playerctl
Process {
id: shuffleProc
command: ["playerctl", "--player=" + media.player, "shuffle"]
stdout: StdioCollector {
onStreamFinished: {
if (media.shuffleMode !== 2)
media.shuffleMode = (text.trim() === "On") ? 1 : 0
}
}
}
Process { id: shuffleOnProc; command: ["playerctl", "--player=" + media.player, "shuffle", "on"] }
Process { id: shuffleOffProc; command: ["playerctl", "--player=" + media.player, "shuffle", "off"] }
function cycleShuffleMode() {
var next = (media.shuffleMode + 1) % 3
media.shuffleMode = next
if (next === 0)
shuffleOffProc.running = true
else
shuffleOnProc.running = true
}
// Focus / open the active player app
Process {
id: focusProc
property string cmd: ""
command: ["bash", "-c", cmd]
}
function focusPlayer() {
var cls = media.isSpotify ? "Spotify" : media.player.split(".")[0]
var bin = cls.toLowerCase()
focusProc.cmd = "hyprctl dispatch focuswindow class:^(" + cls + ")$ 2>/dev/null || " + bin + " &"
focusProc.running = true
}
// Playback controls
Process { id: prevProc; command: ["playerctl", "previous"] }
Process { id: playProc; command: ["playerctl", "play-pause"] }
Process { id: nextProc; command: ["playerctl", "next"] }
Process { id: prevProc; command: ["playerctl", "previous"] }
Process { id: playProc; command: ["playerctl", "play-pause"] }
Process { id: nextProc; command: ["playerctl", "next"] }
FloatingWindow {
id: root
@@ -2747,7 +2810,7 @@ ShellRoot {
onActivated: Qt.quit()
}
// Gradient border
// Gradient border — hidden when window has focus
Rectangle {
anchors.fill: parent
anchors.margins: -2
@@ -2755,13 +2818,13 @@ ShellRoot {
z: -1
opacity: root.active ? 0 : 1
Behavior on opacity {
NumberAnimation { duration: 150 }
}
NumberAnimation { duration: 150 }
}
gradient: Gradient {
orientation: Gradient.Horizontal
GradientStop { position: 0.0; color: colors.blue }
GradientStop { position: 1.0; color: colors.green }
}
}
}
Rectangle {
@@ -2776,7 +2839,7 @@ ShellRoot {
}
spacing: 12
// Album art
// Album art — click to focus player
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 200
@@ -2791,7 +2854,6 @@ ShellRoot {
visible: media.artUrl !== ""
}
// Placeholder when no art
Text {
anchors.centerIn: parent
text: "󰝚"
@@ -2799,6 +2861,12 @@ ShellRoot {
color: colors.surface2
visible: media.artUrl === ""
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: focusPlayer()
}
}
// Artist
@@ -2885,11 +2953,46 @@ ShellRoot {
}
}
// Playback controls
// Playback controls + shuffle
RowLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
spacing: 24
spacing: 20
// Shuffle button (Spotify only)
Item {
visible: media.isSpotify
width: 28
height: 28
Text {
anchors.centerIn: parent
text: "󰒟"
font.pixelSize: 18
color: media.shuffleMode === 0 ? colors.surface2
: media.shuffleMode === 1 ? colors.blue
: colors.mauve
// "S" badge for smart shuffle
Text {
anchors.bottom: parent.bottom
anchors.right: parent.right
anchors.bottomMargin: -2
anchors.rightMargin: -4
text: "S"
font.pixelSize: 7
font.bold: true
color: colors.mauve
visible: media.shuffleMode === 2
}
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: cycleShuffleMode()
}
}
Text {
text: "󰒮"
@@ -2899,6 +3002,7 @@ ShellRoot {
id: prevHover
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: prevProc.running = true
}
}
@@ -2911,6 +3015,7 @@ ShellRoot {
id: playHover
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: playProc.running = true
}
}
@@ -2923,10 +3028,22 @@ ShellRoot {
id: nextHover
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: nextProc.running = true
}
}
}
// Shuffle mode label
Text {
Layout.alignment: Qt.AlignHCenter
text: media.shuffleMode === 1 ? "Shuffle"
: media.shuffleMode === 2 ? "Smart Shuffle"
: ""
color: media.shuffleMode === 2 ? colors.mauve : colors.blue
font.pixelSize: 10
visible: media.isSpotify && media.shuffleMode !== 0
}
}
}
}
@@ -3076,6 +3193,8 @@ ShellRoot {
** =generated/.config/scripts/media.sh=
Providing an media
#+BEGIN_SRC sh :tangle generated/.config/scripts/media.sh :shebang "#!/usr/bin/env bash" :noweb yes :mkdirp yes :eval never
#!/usr/bin/env bash
# Player selection — prefer actively playing player
player=$(playerctl -l 2>/dev/null | while read -r p; do
st=$(playerctl --player="$p" status 2>/dev/null)
@@ -27,15 +27,19 @@ ShellRoot {
// State
QtObject {
id: media
property string artist: ""
property string title: ""
property string album: ""
property string artUrl: ""
property string status: ""
property string device: ""
property real progress: 0.0
property real duration: 0.0
property real position: 0.0
property string artist: ""
property string title: ""
property string album: ""
property string artUrl: ""
property string status: ""
property string device: ""
property string player: ""
property real progress: 0.0
property real duration: 0.0
property real position: 0.0
// 0 = no shuffle, 1 = shuffle, 2 = smart shuffle
property int shuffleMode: 0
readonly property bool isSpotify: player.indexOf("spotify") !== -1
}
// Poll playerctl every second
@@ -44,13 +48,34 @@ ShellRoot {
running: true
repeat: true
onTriggered: {
artistProc.running = true
titleProc.running = true
albumProc.running = true
artProc.running = true
statusProc.running = true
playerProc.running = true
artistProc.running = true
titleProc.running = true
albumProc.running = true
artProc.running = true
statusProc.running = true
positionProc.running = true
lengthProc.running = true
lengthProc.running = true
if (media.isSpotify)
shuffleProc.running = true
}
}
// Detect active player — prefers spotify
Process {
id: playerProc
command: ["playerctl", "-l"]
stdout: StdioCollector {
onStreamFinished: {
var lines = text.trim().split("\n")
for (var i = 0; i < lines.length; i++) {
if (lines[i].indexOf("spotify") !== -1) {
media.player = lines[i].trim()
return
}
}
media.player = lines[0] ? lines[0].trim() : ""
}
}
}
@@ -100,10 +125,48 @@ ShellRoot {
}
}
// Read shuffle state from playerctl
Process {
id: shuffleProc
command: ["playerctl", "--player=" + media.player, "shuffle"]
stdout: StdioCollector {
onStreamFinished: {
if (media.shuffleMode !== 2)
media.shuffleMode = (text.trim() === "On") ? 1 : 0
}
}
}
Process { id: shuffleOnProc; command: ["playerctl", "--player=" + media.player, "shuffle", "on"] }
Process { id: shuffleOffProc; command: ["playerctl", "--player=" + media.player, "shuffle", "off"] }
function cycleShuffleMode() {
var next = (media.shuffleMode + 1) % 3
media.shuffleMode = next
if (next === 0)
shuffleOffProc.running = true
else
shuffleOnProc.running = true
}
// Focus / open the active player app
Process {
id: focusProc
property string cmd: ""
command: ["bash", "-c", cmd]
}
function focusPlayer() {
var cls = media.isSpotify ? "Spotify" : media.player.split(".")[0]
var bin = cls.toLowerCase()
focusProc.cmd = "hyprctl dispatch focuswindow class:^(" + cls + ")$ 2>/dev/null || " + bin + " &"
focusProc.running = true
}
// Playback controls
Process { id: prevProc; command: ["playerctl", "previous"] }
Process { id: playProc; command: ["playerctl", "play-pause"] }
Process { id: nextProc; command: ["playerctl", "next"] }
Process { id: prevProc; command: ["playerctl", "previous"] }
Process { id: playProc; command: ["playerctl", "play-pause"] }
Process { id: nextProc; command: ["playerctl", "next"] }
FloatingWindow {
id: root
@@ -118,7 +181,7 @@ ShellRoot {
onActivated: Qt.quit()
}
// Gradient border
// Gradient border — hidden when window has focus
Rectangle {
anchors.fill: parent
anchors.margins: -2
@@ -126,13 +189,13 @@ ShellRoot {
z: -1
opacity: root.active ? 0 : 1
Behavior on opacity {
NumberAnimation { duration: 150 }
}
NumberAnimation { duration: 150 }
}
gradient: Gradient {
orientation: Gradient.Horizontal
GradientStop { position: 0.0; color: colors.blue }
GradientStop { position: 1.0; color: colors.green }
}
}
}
Rectangle {
@@ -147,7 +210,7 @@ ShellRoot {
}
spacing: 12
// Album art
// Album art — click to focus player
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 200
@@ -162,7 +225,6 @@ ShellRoot {
visible: media.artUrl !== ""
}
// Placeholder when no art
Text {
anchors.centerIn: parent
text: "󰝚"
@@ -170,6 +232,12 @@ ShellRoot {
color: colors.surface2
visible: media.artUrl === ""
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: focusPlayer()
}
}
// Artist
@@ -256,11 +324,46 @@ ShellRoot {
}
}
// Playback controls
// Playback controls + shuffle
RowLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
spacing: 24
spacing: 20
// Shuffle button (Spotify only)
Item {
visible: media.isSpotify
width: 28
height: 28
Text {
anchors.centerIn: parent
text: "󰒟"
font.pixelSize: 18
color: media.shuffleMode === 0 ? colors.surface2
: media.shuffleMode === 1 ? colors.blue
: colors.mauve
// "S" badge for smart shuffle
Text {
anchors.bottom: parent.bottom
anchors.right: parent.right
anchors.bottomMargin: -2
anchors.rightMargin: -4
text: "S"
font.pixelSize: 7
font.bold: true
color: colors.mauve
visible: media.shuffleMode === 2
}
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: cycleShuffleMode()
}
}
Text {
text: "󰒮"
@@ -270,6 +373,7 @@ ShellRoot {
id: prevHover
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: prevProc.running = true
}
}
@@ -282,6 +386,7 @@ ShellRoot {
id: playHover
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: playProc.running = true
}
}
@@ -294,10 +399,22 @@ ShellRoot {
id: nextHover
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: nextProc.running = true
}
}
}
// Shuffle mode label
Text {
Layout.alignment: Qt.AlignHCenter
text: media.shuffleMode === 1 ? "Shuffle"
: media.shuffleMode === 2 ? "Smart Shuffle"
: ""
color: media.shuffleMode === 2 ? colors.mauve : colors.blue
font.pixelSize: 10
visible: media.isSpotify && media.shuffleMode !== 0
}
}
}
}
@@ -1,5 +1,7 @@
#!/usr/bin/env bash
# --- This file has been auto-generated. For permanent changes alter the appropriate block in the README.org. ---
#!/usr/bin/env bash
# Player selection — prefer actively playing player
player=$(playerctl -l 2>/dev/null | while read -r p; do
st=$(playerctl --player="$p" status 2>/dev/null)