lock: add media
This commit is contained in:
parent
bf686b1c36
commit
92700bbd84
6 changed files with 380 additions and 1 deletions
|
|
@ -10,5 +10,9 @@ JsonObject {
|
|||
property int faceSize: 100
|
||||
property int weatherWidth: 400
|
||||
property int weatherHeight: 100
|
||||
property int mediaWidth: 600
|
||||
property int mediaHeight: 170
|
||||
property int mediaCoverSize: 150
|
||||
property int mediaCoverBorder: 3
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ Item {
|
|||
readonly property real inputTop: innerMask.anchors.margins + inputPath.height
|
||||
readonly property real weatherTop: innerMask.anchors.margins + weatherPath.height
|
||||
readonly property real weatherRight: innerMask.anchors.margins + weatherPath.width
|
||||
readonly property real mediaBottom: innerMask.anchors.margins + mediaPath.height
|
||||
readonly property real mediaRight: innerMask.anchors.margins + mediaPath.width
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
|
|
@ -261,6 +263,70 @@ Item {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
ShapePath {
|
||||
id: mediaPath
|
||||
|
||||
property int width: root.locked ? Config.lock.sizes.mediaWidth - Config.lock.sizes.border / 4 : 0
|
||||
property real height: root.locked ? Config.lock.sizes.mediaHeight : 0
|
||||
|
||||
readonly property real rounding: Appearance.rounding.large * 2
|
||||
readonly property real roundingX: width < rounding * 2 ? width / 2 : rounding
|
||||
readonly property real roundingY: height < rounding * 2 ? height / 2 : rounding
|
||||
|
||||
strokeWidth: -1
|
||||
fillColor: Config.border.colour
|
||||
|
||||
startY: height + roundingY
|
||||
|
||||
PathArc {
|
||||
relativeX: mediaPath.roundingX
|
||||
relativeY: -mediaPath.roundingY
|
||||
radiusX: Math.min(mediaPath.rounding, mediaPath.width)
|
||||
radiusY: Math.min(mediaPath.rounding, mediaPath.height)
|
||||
}
|
||||
PathLine {
|
||||
relativeX: mediaPath.width - mediaPath.roundingX * 2
|
||||
relativeY: 0
|
||||
}
|
||||
PathArc {
|
||||
relativeX: mediaPath.roundingX
|
||||
relativeY: -mediaPath.roundingY
|
||||
radiusX: Math.min(mediaPath.rounding, mediaPath.width)
|
||||
radiusY: Math.min(mediaPath.rounding, mediaPath.height)
|
||||
direction: PathArc.Counterclockwise
|
||||
}
|
||||
PathLine {
|
||||
relativeX: 0
|
||||
relativeY: -(mediaPath.height - mediaPath.roundingY * 2)
|
||||
}
|
||||
PathArc {
|
||||
relativeX: mediaPath.roundingX
|
||||
relativeY: -mediaPath.roundingY
|
||||
radiusX: Math.min(mediaPath.rounding, mediaPath.width)
|
||||
radiusY: Math.min(mediaPath.rounding, mediaPath.height)
|
||||
}
|
||||
PathLine {
|
||||
relativeX: -mediaPath.width - mediaPath.roundingX
|
||||
relativeY: 0
|
||||
}
|
||||
|
||||
Behavior on width {
|
||||
Anim {}
|
||||
}
|
||||
|
||||
Behavior on height {
|
||||
Anim {}
|
||||
}
|
||||
|
||||
Behavior on fillColor {
|
||||
ColorAnimation {
|
||||
duration: Appearance.anim.durations.normal
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Appearance.anim.curves.standard
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component Anim: NumberAnimation {
|
||||
|
|
|
|||
|
|
@ -79,6 +79,11 @@ ColumnLayout {
|
|||
radius: Appearance.rounding.small
|
||||
clip: true
|
||||
|
||||
onFocusChanged: {
|
||||
if (!focus)
|
||||
focus = true;
|
||||
}
|
||||
|
||||
Keys.onPressed: event => {
|
||||
if (pam.active)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ Scope {
|
|||
CustomShortcut {
|
||||
name: "unlock"
|
||||
description: "Unlock the current session"
|
||||
onPressed: lock.locked = false
|
||||
onPressed: loader.item.locked = false
|
||||
}
|
||||
|
||||
IpcHandler {
|
||||
|
|
|
|||
|
|
@ -99,6 +99,13 @@ WlSessionLockSurface {
|
|||
anchors.rightMargin: -backgrounds.weatherRight
|
||||
}
|
||||
|
||||
MediaPlaying {
|
||||
anchors.bottom: parent.top
|
||||
anchors.right: parent.left
|
||||
anchors.bottomMargin: -backgrounds.mediaBottom
|
||||
anchors.rightMargin: -backgrounds.mediaRight
|
||||
}
|
||||
|
||||
component Anim: NumberAnimation {
|
||||
duration: Appearance.anim.durations.large
|
||||
easing.type: Easing.BezierSpline
|
||||
|
|
|
|||
297
modules/lock/MediaPlaying.qml
Normal file
297
modules/lock/MediaPlaying.qml
Normal file
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue