diff options
| author | 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> | 2025-06-23 19:33:55 +1000 |
|---|---|---|
| committer | 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> | 2025-06-23 19:33:55 +1000 |
| commit | 92700bbd84511c0d2963d29c5346118322e67562 (patch) | |
| tree | a99f1eec415e32724ab7ac2f5357ffbf0a5467dd /modules/lock/MediaPlaying.qml | |
| parent | drawers: give back focus when close (diff) | |
| download | caelestia-shell-92700bbd84511c0d2963d29c5346118322e67562.tar.gz caelestia-shell-92700bbd84511c0d2963d29c5346118322e67562.tar.bz2 caelestia-shell-92700bbd84511c0d2963d29c5346118322e67562.zip | |
lock: add media
Diffstat (limited to 'modules/lock/MediaPlaying.qml')
| -rw-r--r-- | modules/lock/MediaPlaying.qml | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/modules/lock/MediaPlaying.qml b/modules/lock/MediaPlaying.qml new file mode 100644 index 0000000..c297694 --- /dev/null +++ b/modules/lock/MediaPlaying.qml @@ -0,0 +1,297 @@ +import "root:/widgets" +import "root:/services" +import "root:/config" +import Quickshell.Widgets +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls + +RowLayout { + id: root + + spacing: Appearance.spacing.large * 2 + width: Config.lock.sizes.mediaWidth + + property real playerProgress: { + const active = Players.active; + return active?.length ? active.position / active.length : 0; + } + + Behavior on playerProgress { + NumberAnimation { + duration: Appearance.anim.durations.large + easing.type: Easing.BezierSpline + easing.bezierCurve: Appearance.anim.curves.standard + } + } + + Timer { + running: Players.active?.isPlaying ?? false + interval: Config.dashboard.mediaUpdateInterval + triggeredOnStart: true + repeat: true + onTriggered: Players.active?.positionChanged() + } + + Item { + Layout.bottomMargin: Config.lock.sizes.border / 2 + + implicitWidth: Config.lock.sizes.mediaCoverSize + implicitHeight: Config.lock.sizes.mediaCoverSize + + ClippingWrapperRectangle { + anchors.fill: parent + + color: Colours.palette.m3surfaceContainerHigh + radius: Appearance.rounding.small + rotation: 9 + + Image { + anchors.fill: parent + + source: Players.active?.trackArtUrl ?? "" + asynchronous: true + fillMode: Image.PreserveAspectCrop + sourceSize.width: width + sourceSize.height: height + } + + Behavior on color { + ColorAnimation { + duration: Appearance.anim.durations.normal + easing.type: Easing.BezierSpline + easing.bezierCurve: Appearance.anim.curves.standard + } + } + } + + Rectangle { + anchors.fill: parent + anchors.margins: -1 + border.width: Config.lock.sizes.mediaCoverBorder + border.color: Colours.palette.m3primary + color: "transparent" + radius: Appearance.rounding.small + rotation: 9 + + Behavior on border.color { + ColorAnimation { + duration: Appearance.anim.durations.normal + easing.type: Easing.BezierSpline + easing.bezierCurve: Appearance.anim.curves.standard + } + } + } + + StyledClippingRect { + anchors.fill: parent + + color: Colours.palette.m3surfaceContainerHigh + radius: Appearance.rounding.small + + border.width: Config.lock.sizes.mediaCoverBorder + border.color: Colours.palette.m3primary + + MaterialIcon { + anchors.centerIn: parent + + text: "art_track" + color: Colours.palette.m3onSurfaceVariant + font.pointSize: Config.lock.sizes.mediaCoverSize * 0.4 + } + + Image { + anchors.fill: parent + + source: Players.active?.trackArtUrl ?? "" + asynchronous: true + fillMode: Image.PreserveAspectCrop + sourceSize.width: width + sourceSize.height: height + } + } + } + + ColumnLayout { + Layout.alignment: Qt.AlignVCenter + Layout.bottomMargin: Config.lock.sizes.border / 2 + Layout.rightMargin: Config.lock.sizes.border / 2 + Layout.fillWidth: true + + spacing: Appearance.spacing.small + + StyledText { + Layout.fillWidth: true + + animate: true + text: (Players.active?.trackTitle ?? qsTr("No media")) || qsTr("Unknown title") + color: Colours.palette.m3primary + font.pointSize: Appearance.font.size.large + elide: Text.ElideRight + } + + StyledText { + Layout.fillWidth: true + + animate: true + text: (Players.active?.trackAlbum ?? qsTr("No media")) || qsTr("Unknown album") + color: Colours.palette.m3outline + font.pointSize: Appearance.font.size.larger + elide: Text.ElideRight + } + + StyledText { + Layout.fillWidth: true + + animate: true + text: (Players.active?.trackArtist ?? qsTr("No media")) || qsTr("Unknown artist") + color: Colours.palette.m3secondary + font.pointSize: Appearance.font.size.larger + elide: Text.ElideRight + } + + RowLayout { + id: controls + + Layout.fillWidth: true + + spacing: Appearance.spacing.small + + Slider { + id: slider + + Layout.rightMargin: Appearance.spacing.small + Layout.fillWidth: true + implicitHeight: Appearance.padding.normal * 3 + + value: root.playerProgress + onMoved: { + const active = Players.active; + if (active?.canSeek && active?.positionSupported) + active.position = value * active.length; + } + + background: Item { + StyledRect { + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.topMargin: slider.implicitHeight / 3 + anchors.bottomMargin: slider.implicitHeight / 3 + + implicitWidth: slider.handle.x - slider.implicitHeight / 6 + + color: Colours.palette.m3primary + radius: Appearance.rounding.full + topRightRadius: slider.implicitHeight / 15 + bottomRightRadius: slider.implicitHeight / 15 + } + + StyledRect { + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.right: parent.right + anchors.topMargin: slider.implicitHeight / 3 + anchors.bottomMargin: slider.implicitHeight / 3 + + implicitWidth: parent.width - slider.handle.x - slider.handle.implicitWidth - slider.implicitHeight / 6 + + color: Colours.palette.m3surfaceContainer + radius: Appearance.rounding.full + topLeftRadius: slider.implicitHeight / 15 + bottomLeftRadius: slider.implicitHeight / 15 + } + } + + handle: StyledRect { + id: rect + + x: slider.visualPosition * slider.availableWidth + + implicitWidth: slider.implicitHeight / 4.5 + implicitHeight: slider.implicitHeight + + color: Colours.palette.m3primary + radius: Appearance.rounding.full + + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onPressed: event => event.accepted = false + } + } + } + + Control { + icon: "skip_previous" + canUse: Players.active?.canGoPrevious ?? false + + function onClicked(): void { + Players.active?.previous(); + } + } + + Control { + icon: Players.active?.isPlaying ? "pause" : "play_arrow" + canUse: Players.active?.canTogglePlaying ?? false + primary: true + + function onClicked(): void { + Players.active?.togglePlaying(); + } + } + + Control { + icon: "skip_next" + canUse: Players.active?.canGoNext ?? false + + function onClicked(): void { + Players.active?.next(); + } + } + } + } + + component Control: StyledRect { + id: control + + required property string icon + required property bool canUse + property int fontSize: Appearance.font.size.extraLarge + property int padding + property bool fill: true + property bool primary + function onClicked(): void { + } + + implicitWidth: Math.max(icon.implicitWidth, icon.implicitHeight) + padding * 2 + implicitHeight: implicitWidth + + radius: Appearance.rounding.full + color: primary && canUse ? Colours.palette.m3primary : "transparent" + + StateLayer { + disabled: !control.canUse + radius: parent.radius + color: control.primary ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface + + function onClicked(): void { + control.onClicked(); + } + } + + MaterialIcon { + id: icon + + anchors.centerIn: parent + anchors.horizontalCenterOffset: -font.pointSize * 0.02 + anchors.verticalCenterOffset: font.pointSize * 0.02 + + animate: true + fill: control.fill ? 1 : 0 + text: control.icon + color: control.canUse ? control.primary ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface : Colours.palette.m3outline + font.pointSize: control.fontSize + } + } +} |