import QtQuick import Quickshell.Services.Mpris import "." as M M.PopupPanel { id: menuWindow panelWidth: 280 required property MprisPlayer player function _fmtTime(ms) { const s = Math.floor(ms / 1000); const m = Math.floor(s / 60); return m + ":" + String(s % 60).padStart(2, "0"); } Item { width: menuWindow.panelWidth height: _artImg.status === Image.Ready ? 140 : 60 clip: true Rectangle { anchors.fill: parent color: M.Theme.base02 } Image { id: _artImg anchors.fill: parent source: menuWindow.player?.trackArtUrl ?? "" fillMode: Image.PreserveAspectCrop visible: status === Image.Ready } Rectangle { anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom height: 40 visible: _artImg.visible gradient: Gradient { GradientStop { position: 0; color: "transparent" } GradientStop { position: 1; color: M.Theme.base01 } } } Text { anchors.centerIn: parent text: "\uF001" color: M.Theme.base04 font.pixelSize: 28 font.family: M.Theme.iconFontFamily visible: _artImg.status !== Image.Ready } } Item { width: menuWindow.panelWidth height: titleCol.implicitHeight + 8 Column { id: titleCol anchors.left: parent.left anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter anchors.leftMargin: 12 anchors.rightMargin: 12 spacing: 2 Text { width: parent.width text: menuWindow.player?.trackTitle || "No track" color: M.Theme.base05 font.pixelSize: M.Theme.fontSize + 1 font.family: M.Theme.fontFamily font.bold: true elide: Text.ElideRight } Text { width: parent.width text: { const p = menuWindow.player; if (!p) return ""; const artist = Array.isArray(p.trackArtists) ? p.trackArtists.join(", ") : (p.trackArtists || ""); return [artist, p.trackAlbum].filter(s => s).join(" \u2014 "); } color: M.Theme.base04 font.pixelSize: M.Theme.fontSize - 1 font.family: M.Theme.fontFamily elide: Text.ElideRight visible: text !== "" } } } Item { width: menuWindow.panelWidth height: 20 readonly property real pos: menuWindow.player?.position ?? 0 readonly property real dur: menuWindow.player?.length ?? 0 readonly property real frac: dur > 0 ? pos / dur : 0 Text { anchors.left: parent.left anchors.leftMargin: 12 anchors.verticalCenter: parent.verticalCenter text: menuWindow._fmtTime(parent.pos) color: M.Theme.base04 font.pixelSize: M.Theme.fontSize - 2 font.family: M.Theme.fontFamily } Text { anchors.right: parent.right anchors.rightMargin: 12 anchors.verticalCenter: parent.verticalCenter text: menuWindow._fmtTime(parent.dur) color: M.Theme.base04 font.pixelSize: M.Theme.fontSize - 2 font.family: M.Theme.fontFamily } Item { anchors.horizontalCenter: parent.horizontalCenter anchors.verticalCenter: parent.verticalCenter width: parent.width - 80 height: 4 Rectangle { anchors.fill: parent color: M.Theme.base02 radius: 2 } Rectangle { width: parent.width * Math.min(1, Math.max(0, parent.parent.frac)) height: parent.height color: M.Theme.base0E radius: 2 } } } Item { width: menuWindow.panelWidth height: 36 Row { anchors.centerIn: parent spacing: 24 Text { text: "\uF048" color: menuWindow.player?.canGoPrevious ? M.Theme.base05 : M.Theme.base03 font.pixelSize: M.Theme.fontSize + 4 font.family: M.Theme.iconFontFamily anchors.verticalCenter: parent.verticalCenter MouseArea { anchors.fill: parent cursorShape: Qt.PointingHandCursor enabled: menuWindow.player?.canGoPrevious ?? false onClicked: menuWindow.player.previous() } } Text { text: menuWindow.player?.playbackState === MprisPlaybackState.Playing ? "\uF04C" : "\uF04B" color: M.Theme.base0E font.pixelSize: M.Theme.fontSize + 8 font.family: M.Theme.iconFontFamily anchors.verticalCenter: parent.verticalCenter MouseArea { anchors.fill: parent cursorShape: Qt.PointingHandCursor onClicked: menuWindow.player?.togglePlaying() } } Text { text: "\uF051" color: menuWindow.player?.canGoNext ? M.Theme.base05 : M.Theme.base03 font.pixelSize: M.Theme.fontSize + 4 font.family: M.Theme.iconFontFamily anchors.verticalCenter: parent.verticalCenter MouseArea { anchors.fill: parent cursorShape: Qt.PointingHandCursor enabled: menuWindow.player?.canGoNext ?? false onClicked: menuWindow.player.next() } } } } Item { width: menuWindow.panelWidth height: 20 Text { anchors.centerIn: parent text: menuWindow.player?.identity ?? "" color: M.Theme.base03 font.pixelSize: M.Theme.fontSize - 2 font.family: M.Theme.fontFamily } } }