Files

153 lines
4.5 KiB
QML

// Compact media controls in the date menu: artwork, useful metadata, and the
// three controls people expect. It disappears completely without a track.
import QtQuick
import Quickshell.Services.Mpris
import qs.config
import qs.widgets
Rectangle {
id: root
readonly property bool compact: width < 360
readonly property MprisPlayer player: {
const players = Mpris.players ? Mpris.players.values : [];
return players.find(p => p.isPlaying) ?? players.find(p => p.trackTitle) ?? null;
}
visible: root.player !== null
implicitHeight: visible ? (compact ? 64 : 76) : 0
radius: Theme.cardRadius
border.width: 0
color: Theme.alpha(Theme.fg, 0.06)
clip: true
Rectangle {
id: artwork
anchors.left: parent.left
anchors.leftMargin: root.compact ? 8 : 10
anchors.verticalCenter: parent.verticalCenter
width: root.compact ? 46 : 56
height: width
radius: root.compact ? 9 : 10
border.width: 0
color: Theme.alpha(Theme.accentAlt, 0.16)
clip: true
Image {
anchors.fill: parent
source: root.player?.trackArtUrl ?? ""
asynchronous: true
cache: true
fillMode: Image.PreserveAspectCrop
visible: status === Image.Ready
}
ThemedIcon {
anchors.centerIn: parent
size: 24
icon: "audio-x-generic-symbolic"
iconFallback: "multimedia-player-symbolic"
tint: Theme.accentAlt
visible: !root.player?.trackArtUrl
}
}
Column {
anchors.left: artwork.right
anchors.leftMargin: root.compact ? 9 : 12
anchors.right: controls.left
anchors.rightMargin: root.compact ? 6 : 10
anchors.verticalCenter: parent.verticalCenter
spacing: 3
Text {
width: parent.width
text: root.player?.trackTitle || "Unknown track"
color: Theme.fg
elide: Text.ElideRight
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSize
font.weight: Font.DemiBold
}
Text {
width: parent.width
text: root.player?.trackArtist || root.player?.identity || "Media"
color: Theme.fgDim
elide: Text.ElideRight
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
}
}
Row {
id: controls
anchors.right: parent.right
anchors.rightMargin: root.compact ? 7 : 10
anchors.verticalCenter: parent.verticalCenter
spacing: 2
MediaButton {
icon: "media-skip-backward-symbolic"
enabled: root.player?.canGoPrevious ?? false
onClicked: root.player?.previous()
}
MediaButton {
icon: root.player?.isPlaying ? "media-playback-pause-symbolic" : "media-playback-start-symbolic"
enabled: root.player?.canTogglePlaying ?? false
emphasized: true
onClicked: root.player?.togglePlaying()
}
MediaButton {
icon: "media-skip-forward-symbolic"
enabled: root.player?.canGoNext ?? false
onClicked: root.player?.next()
}
}
component MediaButton: Rectangle {
id: button
required property string icon
property bool emphasized: false
signal clicked
width: root.compact ? (emphasized ? 30 : 27) : (emphasized ? 34 : 30)
height: width
radius: width / 2
border.width: 0
opacity: enabled ? 1 : 0.35
color: {
if (mouse.pressed)
return Theme.alpha(emphasized ? Theme.accent : Theme.fg, 0.34);
if (mouse.containsMouse)
return Theme.alpha(emphasized ? Theme.accent : Theme.fg, 0.22);
return emphasized ? Theme.alpha(Theme.accent, 0.14) : "transparent";
}
Behavior on color {
ColorAnimation { duration: Theme.durFast }
}
ThemedIcon {
anchors.centerIn: parent
size: 15
icon: button.icon
tint: button.emphasized ? Theme.accent : Theme.fg
}
MouseArea {
id: mouse
anchors.fill: parent
enabled: button.enabled
hoverEnabled: true
cursorShape: button.enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: button.clicked()
}
}
}