pragma ComponentBehavior: Bound import QtQuick import QtQuick.Layouts import Quickshell import Caelestia.Components import Caelestia.Config import qs.components import qs.components.controls import qs.components.effects import qs.services Item { id: root required property var lock anchors.left: parent.left anchors.right: parent.right implicitHeight: layout.implicitHeight Image { anchors.fill: parent source: Players.getArtUrl(Players.active) asynchronous: true fillMode: Image.PreserveAspectCrop sourceSize: { const dpr = (QsWindow.window as QsWindow)?.devicePixelRatio ?? 1; return Qt.size(width * dpr, height * dpr); } layer.enabled: true layer.effect: Mask { maskSource: mask } opacity: status === Image.Ready ? 1 : 0 Behavior on opacity { Anim { type: Anim.StandardExtraLarge } } } Rectangle { id: mask anchors.fill: parent layer.enabled: true visible: false gradient: Gradient { orientation: Gradient.Horizontal GradientStop { position: 0 color: Qt.rgba(0, 0, 0, 0.5) } GradientStop { position: 0.4 color: Qt.rgba(0, 0, 0, 0.2) } GradientStop { position: 0.8 color: Qt.rgba(0, 0, 0, 0) } } } ColumnLayout { id: layout anchors.left: parent.left anchors.right: parent.right anchors.margins: Tokens.padding.medium StyledText { Layout.topMargin: Tokens.padding.medium Layout.bottomMargin: Tokens.spacing.large text: qsTr("Now playing") color: Colours.palette.m3onSurfaceVariant font: Tokens.font.label.builders.medium.weight(Font.DemiBold).vaxis("slnt", -4).build() } StyledText { Layout.fillWidth: true animate: true text: Players.active?.trackArtist ?? qsTr("No media") color: Colours.palette.m3primary horizontalAlignment: Text.AlignHCenter font: Tokens.font.body.builders.large.weight(Font.DemiBold).build() elide: Text.ElideRight } StyledText { Layout.fillWidth: true animate: true text: Players.active?.trackTitle ?? qsTr("No media") horizontalAlignment: Text.AlignHCenter font: Tokens.font.title.medium elide: Text.ElideRight } ButtonRow { Layout.alignment: Qt.AlignHCenter Layout.topMargin: Tokens.spacing.medium Layout.bottomMargin: Tokens.padding.extraLarge spacing: Tokens.spacing.extraSmall IconButton { type: IconButton.Tonal icon: "skip_previous" isRound: true shapeMorph: true disabled: !Players.active?.canGoPrevious onClicked: Players.active?.previous() } IconButton { icon: Players.active?.isPlaying ? "pause" : "play_arrow" isRound: true shapeMorph: true checked: Players.active?.isPlaying ?? false disabled: !Players.active?.canTogglePlaying onClicked: Players.active?.togglePlaying() implicitWidth: implicitHeight + Tokens.padding.large * 2 } IconButton { type: IconButton.Tonal icon: "skip_next" isRound: true shapeMorph: true disabled: !Players.active?.canGoNext onClicked: Players.active?.next() } } } }