diff --git a/screenlocker/images/dark/media-playback-pause-symbolic.svg b/screenlocker/images/dark/media-playback-pause-symbolic.svg
new file mode 100644
index 0000000..63c10bf
--- /dev/null
+++ b/screenlocker/images/dark/media-playback-pause-symbolic.svg
@@ -0,0 +1,6 @@
+
diff --git a/screenlocker/images/dark/media-playback-start-symbolic.svg b/screenlocker/images/dark/media-playback-start-symbolic.svg
new file mode 100644
index 0000000..d9fd388
--- /dev/null
+++ b/screenlocker/images/dark/media-playback-start-symbolic.svg
@@ -0,0 +1,3 @@
+
diff --git a/screenlocker/images/dark/media-skip-backward-symbolic.svg b/screenlocker/images/dark/media-skip-backward-symbolic.svg
new file mode 100644
index 0000000..e35c9d5
--- /dev/null
+++ b/screenlocker/images/dark/media-skip-backward-symbolic.svg
@@ -0,0 +1,4 @@
+
diff --git a/screenlocker/images/dark/media-skip-forward-symbolic.svg b/screenlocker/images/dark/media-skip-forward-symbolic.svg
new file mode 100644
index 0000000..a2c94d7
--- /dev/null
+++ b/screenlocker/images/dark/media-skip-forward-symbolic.svg
@@ -0,0 +1,4 @@
+
diff --git a/screenlocker/images/light/media-playback-pause-symbolic.svg b/screenlocker/images/light/media-playback-pause-symbolic.svg
new file mode 100644
index 0000000..7929a93
--- /dev/null
+++ b/screenlocker/images/light/media-playback-pause-symbolic.svg
@@ -0,0 +1,6 @@
+
diff --git a/screenlocker/images/light/media-playback-start-symbolic.svg b/screenlocker/images/light/media-playback-start-symbolic.svg
new file mode 100644
index 0000000..551081f
--- /dev/null
+++ b/screenlocker/images/light/media-playback-start-symbolic.svg
@@ -0,0 +1,3 @@
+
diff --git a/screenlocker/images/light/media-skip-backward-symbolic.svg b/screenlocker/images/light/media-skip-backward-symbolic.svg
new file mode 100644
index 0000000..1b85972
--- /dev/null
+++ b/screenlocker/images/light/media-skip-backward-symbolic.svg
@@ -0,0 +1,4 @@
+
diff --git a/screenlocker/images/light/media-skip-forward-symbolic.svg b/screenlocker/images/light/media-skip-forward-symbolic.svg
new file mode 100644
index 0000000..1193e44
--- /dev/null
+++ b/screenlocker/images/light/media-skip-forward-symbolic.svg
@@ -0,0 +1,4 @@
+
diff --git a/screenlocker/images/media-cover.svg b/screenlocker/images/media-cover.svg
new file mode 100644
index 0000000..c4542b5
--- /dev/null
+++ b/screenlocker/images/media-cover.svg
@@ -0,0 +1,4 @@
+
diff --git a/screenlocker/qml.qrc b/screenlocker/qml.qrc
index 81370ca..e2cfe9c 100644
--- a/screenlocker/qml.qrc
+++ b/screenlocker/qml.qrc
@@ -5,5 +5,16 @@
qml/LoginButton.qml
images/screensaver-unlock-symbolic.svg
images/system-lock-screen-symbolic.svg
+ qml/MprisItem.qml
+ images/media-cover.svg
+ images/light/media-playback-pause-symbolic.svg
+ images/light/media-playback-start-symbolic.svg
+ images/light/media-skip-backward-symbolic.svg
+ images/light/media-skip-forward-symbolic.svg
+ images/dark/media-playback-pause-symbolic.svg
+ images/dark/media-playback-start-symbolic.svg
+ images/dark/media-skip-backward-symbolic.svg
+ images/dark/media-skip-forward-symbolic.svg
+ qml/IconButton.qml
diff --git a/screenlocker/qml/IconButton.qml b/screenlocker/qml/IconButton.qml
new file mode 100644
index 0000000..010e066
--- /dev/null
+++ b/screenlocker/qml/IconButton.qml
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2021 CutefishOS Team.
+ *
+ * Author: Reion Wong
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+import QtQuick 2.12
+import QtQuick.Controls 2.12
+import QtQuick.Layouts 1.12
+import FishUI 1.0 as FishUI
+
+Item {
+ id: control
+
+ property url source
+ property real size: 24
+ property string popupText
+
+ signal leftButtonClicked
+ signal rightButtonClicked
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+ hoverEnabled: control.visible ? true : false
+
+ onClicked: {
+ if (mouse.button === Qt.LeftButton)
+ control.leftButtonClicked()
+ else if (mouse.button === Qt.RightButton)
+ control.rightButtonClicked()
+ }
+ }
+
+ Rectangle {
+ anchors.fill: parent
+ anchors.margins: 1
+ // radius: parent.height * 0.2
+ radius: parent.height / 2
+
+ color: {
+ if (mouseArea.containsMouse) {
+ if (mouseArea.containsPress)
+ return (FishUI.Theme.darkMode) ? Qt.rgba(255, 255, 255, 0.3) : Qt.rgba(0, 0, 0, 0.2)
+ else
+ return (FishUI.Theme.darkMode) ? Qt.rgba(255, 255, 255, 0.2) : Qt.rgba(0, 0, 0, 0.1)
+ }
+
+ return "transparent"
+ }
+ }
+
+ Image {
+ id: iconImage
+ anchors.centerIn: parent
+ width: parent.height * 0.8
+ height: width
+ sourceSize.width: width
+ sourceSize.height: height
+ source: control.source
+ asynchronous: true
+ antialiasing: true
+ smooth: false
+ }
+}
diff --git a/screenlocker/qml/LockScreen.qml b/screenlocker/qml/LockScreen.qml
index 2571893..c9c360f 100644
--- a/screenlocker/qml/LockScreen.qml
+++ b/screenlocker/qml/LockScreen.qml
@@ -171,7 +171,7 @@ Item {
Item {
id: _mainItem
anchors.centerIn: parent
- width: 260 + FishUI.Units.largeSpacing * 3
+ width: 280 + FishUI.Units.largeSpacing * 3
height: _mainLayout.implicitHeight + FishUI.Units.largeSpacing * 4
Layout.alignment: Qt.AlignHCenter
@@ -312,6 +312,21 @@ Item {
visible: true
}
+ Item {
+ // anchors.top: message.bottom
+ // anchors.topMargin: FishUI.Units.largeSpacing
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: root.height * 0.05 //FishUI.Units.largeSpacing
+ anchors.horizontalCenter: parent.horizontalCenter
+
+ width: 280 + FishUI.Units.largeSpacing * 3
+ height: 70
+
+ MprisItem {
+ anchors.fill: parent
+ }
+ }
+
function tryUnlock() {
if (!password.text) {
notificationResetTimer.start()
diff --git a/screenlocker/qml/LoginButton.qml b/screenlocker/qml/LoginButton.qml
index 446bde4..70dfcb2 100644
--- a/screenlocker/qml/LoginButton.qml
+++ b/screenlocker/qml/LoginButton.qml
@@ -54,7 +54,6 @@ Item {
id: mouseArea
anchors.fill: parent
hoverEnabled: true
-
onClicked: control.clicked()
}
diff --git a/screenlocker/qml/MprisItem.qml b/screenlocker/qml/MprisItem.qml
new file mode 100644
index 0000000..9c0c8d8
--- /dev/null
+++ b/screenlocker/qml/MprisItem.qml
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2021 CutefishOS Team.
+ *
+ * Author: Reion Wong
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+import QtQuick 2.12
+import QtQuick.Layouts 1.12
+import QtQuick.Controls 2.12
+import QtGraphicalEffects 1.0
+import FishUI 1.0 as FishUI
+import Cutefish.Mpris 1.0
+
+Item {
+ id: control
+
+ property bool available: mprisManager.availableServices.length > 0
+ property bool isPlaying: currentService && mprisManager.playbackStatus === Mpris.Playing
+ property alias currentService: mprisManager.currentService
+ property var artUrlTag: Mpris.metadataToString(Mpris.ArtUrl)
+ property var titleTag: Mpris.metadataToString(Mpris.Title)
+ property var artistTag: Mpris.metadataToString(Mpris.Artist)
+
+ MprisManager {
+ id: mprisManager
+
+ onCurrentServiceChanged: {
+ control.updateInfo()
+ }
+
+ onMetadataChanged: {
+ control.updateInfo()
+ }
+ }
+
+ Component.onCompleted: { control.updateInfo() }
+
+ function updateInfo() {
+ var titleAvailable = (titleTag in mprisManager.metadata) ? mprisManager.metadata[titleTag].toString() !== "" : false
+ var artistAvailable = (artistTag in mprisManager.metadata) ? mprisManager.metadata[artistTag].toString() !== "" : false
+
+ control.visible = titleAvailable || artistAvailable
+ _songLabel.text = titleAvailable ? mprisManager.metadata[titleTag].toString() : ""
+ _artistLabel.text = artistAvailable ? mprisManager.metadata[artistTag].toString() : ""
+ artImage.source = (artUrlTag in mprisManager.metadata) ? mprisManager.metadata[artUrlTag].toString() : ""
+ }
+
+ Rectangle {
+ anchors.fill: parent
+ radius: FishUI.Theme.bigRadius + 2
+ color: FishUI.Theme.darkMode ? "#424242" : "white"
+ opacity: 0.5
+ }
+
+ RowLayout {
+ id: _mainLayout
+ anchors.fill: parent
+ anchors.margins: FishUI.Units.largeSpacing
+ spacing: FishUI.Units.largeSpacing
+
+ Image {
+ id: defaultImage
+ width: _mainLayout.height
+ height: width
+ source: "qrc:/images/media-cover.svg"
+ sourceSize: Qt.size(width, height)
+ visible: !artImage.visible
+
+ layer.enabled: true
+ layer.effect: OpacityMask {
+ maskSource: Item {
+ width: defaultImage.width
+ height: defaultImage.height
+
+ Rectangle {
+ anchors.fill: parent
+ radius: FishUI.Theme.smallRadius
+ }
+ }
+ }
+ }
+
+ Image {
+ id: artImage
+ Layout.preferredHeight: _mainLayout.height
+ Layout.preferredWidth: _mainLayout.height
+ visible: status === Image.Ready
+ // sourceSize: Qt.size(width, height)
+ fillMode: Image.PreserveAspectFit
+
+ layer.enabled: true
+ layer.effect: OpacityMask {
+ maskSource: Item {
+ width: artImage.width
+ height: artImage.height
+
+ Rectangle {
+ anchors.fill: parent
+ radius: FishUI.Theme.smallRadius
+ }
+ }
+ }
+ }
+
+ Item {
+ Layout.fillHeight: true
+ Layout.fillWidth: true
+
+ ColumnLayout {
+ anchors.fill: parent
+
+ Item {
+ Layout.fillHeight: true
+ }
+
+ Label {
+ id: _songLabel
+ Layout.fillWidth: true
+ visible: _songLabel.text !== ""
+ elide: Text.ElideRight
+ }
+
+ Label {
+ id: _artistLabel
+ Layout.fillWidth: true
+ visible: _artistLabel.text !== ""
+ elide: Text.ElideRight
+ }
+
+ Item {
+ Layout.fillHeight: true
+ }
+ }
+ }
+
+ Item {
+ id: _buttons
+ Layout.fillHeight: true
+ Layout.preferredWidth: _buttonsLayout.implicitWidth
+
+ RowLayout {
+ id: _buttonsLayout
+ anchors.fill: parent
+ spacing: FishUI.Units.smallSpacing
+
+ IconButton {
+ width: 30
+ height: 30
+ source: "qrc:/images/" + (FishUI.Theme.darkMode ? "dark" : "light") + "/media-skip-backward-symbolic.svg"
+ onLeftButtonClicked: if (mprisManager.canGoPrevious) mprisManager.previous()
+ visible: mprisManager.canGoPrevious
+ Layout.alignment: Qt.AlignRight
+ }
+
+ IconButton {
+ width: 30
+ height: 30
+ source: control.isPlaying ? "qrc:/images/" + (FishUI.Theme.darkMode ? "dark" : "light") + "/media-playback-pause-symbolic.svg"
+ : "qrc:/images/" + (FishUI.Theme.darkMode ? "dark" : "light") + "/media-playback-start-symbolic.svg"
+ Layout.alignment: Qt.AlignRight
+ visible: mprisManager.canPause || mprisManager.canPlay
+ onLeftButtonClicked:
+ if ((control.isPlaying && mprisManager.canPause) || (!control.isPlaying && mprisManager.canPlay)) {
+ mprisManager.playPause()
+ }
+ }
+
+ IconButton {
+ width: 30
+ height: 30
+ source: "qrc:/images/" + (FishUI.Theme.darkMode ? "dark" : "light") + "/media-skip-forward-symbolic.svg"
+ Layout.alignment: Qt.AlignRight
+ visible: mprisManager.canGoNext
+ onLeftButtonClicked: if (mprisManager.canGoNext) mprisManager.next()
+ }
+ }
+ }
+ }
+}