quickshell media player enchantments
This commit is contained in:
1
quickshell/assets/bar/MutedMic.svg
Normal file
1
quickshell/assets/bar/MutedMic.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#EA3323"><path d="m710-362-58-58q14-23 21-48t7-52h80q0 44-13 83.5T710-362ZM592-482 360-714v-46q0-50 35-85t85-35q50 0 85 35t35 85v240q0 11-2.5 20t-5.5 18ZM440-120v-124q-104-14-172-92.5T200-520h80q0 83 58.5 141.5T480-320q34 0 64.5-10.5T600-360l57 57q-29 23-63.5 38.5T520-244v124h-80Zm352 64L56-792l56-56 736 736-56 56Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 424 B |
1
quickshell/assets/bar/MutedSpeaker.svg
Normal file
1
quickshell/assets/bar/MutedSpeaker.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#EA3323"><path d="M792-56 671-177q-25 16-53 27.5T560-131v-82q14-5 27.5-10t25.5-12L480-368v208L280-360H120v-240h128L56-792l56-56 736 736-56 56Zm-8-232-58-58q17-31 25.5-65t8.5-70q0-94-55-168T560-749v-82q124 28 202 125.5T840-481q0 53-14.5 102T784-288ZM650-422l-90-90v-130q47 22 73.5 66t26.5 96q0 15-2.5 29.5T650-422ZM480-592 376-696l104-104v208Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 450 B |
@@ -8,6 +8,7 @@ import Quickshell.Widgets
|
|||||||
import "widgets" as Widgets
|
import "widgets" as Widgets
|
||||||
import "widgets/player" as Player
|
import "widgets/player" as Player
|
||||||
import "widgets/common" as Common
|
import "widgets/common" as Common
|
||||||
|
import "widgets/clock" as Clock
|
||||||
|
|
||||||
// Tako kindly threatened you to sort the naming schema and to put all the svg's in an asset folder, so please do that
|
// Tako kindly threatened you to sort the naming schema and to put all the svg's in an asset folder, so please do that
|
||||||
|
|
||||||
@@ -22,15 +23,20 @@ import "widgets/common" as Common
|
|||||||
right: true
|
right: true
|
||||||
}
|
}
|
||||||
|
|
||||||
implicitHeight: 30
|
implicitHeight: 32
|
||||||
RowLayout {
|
RowLayout {
|
||||||
|
height: 28
|
||||||
anchors {
|
anchors {
|
||||||
fill: parent
|
top: parent.top
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
// bottomMargin: 2
|
||||||
leftMargin: 10
|
leftMargin: 10
|
||||||
rightMargin: 10
|
rightMargin: 10
|
||||||
}
|
}
|
||||||
RowLayout { // Left
|
RowLayout { // Left
|
||||||
Layout.alignment: Qt.AlignLeft
|
Layout.alignment: Qt.AlignLeft
|
||||||
|
Clock.Date {}
|
||||||
}
|
}
|
||||||
RowLayout { // Center
|
RowLayout { // Center
|
||||||
// TODO: add icons of the active window per workspace in the workspace tab
|
// TODO: add icons of the active window per workspace in the workspace tab
|
||||||
@@ -50,13 +56,7 @@ import "widgets/common" as Common
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Common.VerticalSeprator {}
|
Common.VerticalSeprator {}
|
||||||
WrapperItem {
|
Clock.Clock {}
|
||||||
Text { // Date & Time
|
|
||||||
text: Widgets.Time.time
|
|
||||||
color: '#FFFFFF'
|
|
||||||
font.pointSize: 10.75
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Widgets.SystemTray {
|
Widgets.SystemTray {
|
||||||
id: systemTray
|
id: systemTray
|
||||||
}
|
}
|
||||||
@@ -68,7 +68,7 @@ import "widgets/common" as Common
|
|||||||
left: parent.left
|
left: parent.left
|
||||||
right: parent.right
|
right: parent.right
|
||||||
}
|
}
|
||||||
height: 2
|
height: 1
|
||||||
color: "#8d8d8d"
|
color: "#8d8d8d"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,30 +18,26 @@ Item {
|
|||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
id: row
|
id: row
|
||||||
|
Item {
|
||||||
|
implicitWidth: 28
|
||||||
|
implicitHeight: 28
|
||||||
|
Rectangle {
|
||||||
|
width: parent.width
|
||||||
|
height: parent.height
|
||||||
|
radius: 7
|
||||||
|
color: "black"
|
||||||
|
}
|
||||||
IconImage {
|
IconImage {
|
||||||
// anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
implicitSize: 27
|
implicitSize: 25
|
||||||
source: "root:/assets/bar/Speaker.svg"
|
source: root.speakerNode.audio.muted ? "root:/assets/bar/MutedSpeaker.svg" : "root:/assets/bar/Speaker.svg"
|
||||||
|
// source: "root:/assets/bar/Speaker.svg"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Text {
|
|
||||||
id: text
|
|
||||||
text: root.speakerNode.audio.muted ? "0%" : root.speakerNode.audio.volume * 100 + "%"
|
|
||||||
font.pointSize: 10.75
|
|
||||||
color: root.speakerNode.audio.muted ? "red" : "#FFFFFF"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IconImage {
|
IconImage {
|
||||||
implicitSize: 26
|
implicitSize: 25
|
||||||
source: "root:/assets/bar/Mic.svg"
|
source: root.microphoneNode.audio.muted ? "root:/assets/bar/MutedMic.svg" : "root:/assets/bar/Mic.svg"
|
||||||
}
|
// source: "root:/assets/bar/Mic.svg"
|
||||||
|
|
||||||
Text {
|
|
||||||
text: parseInt(root.microphoneNode.audio.muted ? "0" : root.microphoneNode.audio.volume * 100) + "%"
|
|
||||||
font.pointSize: 10.75
|
|
||||||
color: root.microphoneNode.audio.muted ? "red" : "#FFFFFF"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
pragma Singleton
|
|
||||||
|
|
||||||
import Quickshell
|
|
||||||
import Quickshell.Io
|
|
||||||
import QtQuick
|
|
||||||
|
|
||||||
Singleton {
|
|
||||||
id: root
|
|
||||||
readonly property string time: {
|
|
||||||
Qt.formatDateTime(clock.date, "ddd d MMM [hh:mm]")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
SystemClock {
|
|
||||||
id: clock
|
|
||||||
precision: SystemClock.Minutes
|
|
||||||
}
|
|
||||||
}
|
|
||||||
18
quickshell/bar/widgets/clock/Clock.qml
Normal file
18
quickshell/bar/widgets/clock/Clock.qml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import Quickshell
|
||||||
|
import Quickshell.Io
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
import "../common" as Common
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
width: text.width
|
||||||
|
height: text.height
|
||||||
|
Common.Container {}
|
||||||
|
Text {
|
||||||
|
id: text
|
||||||
|
text: ClockData.time
|
||||||
|
font.pointSize: 10.25
|
||||||
|
color: "white"
|
||||||
|
}
|
||||||
|
}
|
||||||
22
quickshell/bar/widgets/clock/ClockData.qml
Normal file
22
quickshell/bar/widgets/clock/ClockData.qml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
pragma Singleton
|
||||||
|
|
||||||
|
import Quickshell
|
||||||
|
import Quickshell.Io
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
Singleton {
|
||||||
|
id: root
|
||||||
|
readonly property string time: {
|
||||||
|
// Qt.formatDateTime(clock.date, "ddd d MMM [hh:mm]")
|
||||||
|
Qt.formatDateTime(clock.date, "hh:mm")
|
||||||
|
}
|
||||||
|
readonly property string date: {
|
||||||
|
Qt.formatDateTime(clock.date, "d MMM")
|
||||||
|
// Qt.formatDateTime(clock.date, "hh:mm")
|
||||||
|
}
|
||||||
|
|
||||||
|
SystemClock {
|
||||||
|
id: clock
|
||||||
|
precision: SystemClock.Minutes
|
||||||
|
}
|
||||||
|
}
|
||||||
19
quickshell/bar/widgets/clock/Date.qml
Normal file
19
quickshell/bar/widgets/clock/Date.qml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import Quickshell
|
||||||
|
import Quickshell.Io
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
import "../common" as Common
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
width: text.width + 15
|
||||||
|
height: text.height
|
||||||
|
Common.Container {}
|
||||||
|
Text {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
id: text
|
||||||
|
text: ClockData.date
|
||||||
|
font.pointSize: 10.25
|
||||||
|
color: "white"
|
||||||
|
}
|
||||||
|
}
|
||||||
13
quickshell/bar/widgets/common/Container.qml
Normal file
13
quickshell/bar/widgets/common/Container.qml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import Quickshell
|
||||||
|
import QtQuick
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
z: -1
|
||||||
|
color: "black"
|
||||||
|
anchors {
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
height: 25
|
||||||
|
width: parent.width
|
||||||
|
radius: 7
|
||||||
|
}
|
||||||
@@ -3,11 +3,16 @@ import QtQuick
|
|||||||
import Quickshell
|
import Quickshell
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
|
import Quickshell.Widgets
|
||||||
import Quickshell.Services.Mpris
|
import Quickshell.Services.Mpris
|
||||||
|
|
||||||
PopupWindow {
|
PopupWindow {
|
||||||
property PlayerControllerV2 player: PlayerControllerV2;
|
property PlayerControllerV2 player: PlayerControllerV2;
|
||||||
|
|
||||||
|
readonly property string elementBackgroundColor : "#323232"
|
||||||
|
readonly property string elementButtonBaseColor : "#515151"
|
||||||
|
readonly property string elementButtonHoverColor : "#737373"
|
||||||
|
|
||||||
id: audioPopup
|
id: audioPopup
|
||||||
anchor {
|
anchor {
|
||||||
item: root
|
item: root
|
||||||
@@ -16,6 +21,7 @@ PopupWindow {
|
|||||||
anchor.rect.y: root.height * 1.2
|
anchor.rect.y: root.height * 1.2
|
||||||
height: columnContainer.height + 5
|
height: columnContainer.height + 5
|
||||||
width: 425
|
width: 425
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
color: "#919191"
|
color: "#919191"
|
||||||
@@ -26,15 +32,15 @@ PopupWindow {
|
|||||||
model: player.mpris.players
|
model: player.mpris.players
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
width: 400
|
width: 375
|
||||||
height: 80
|
height: 110
|
||||||
required property MprisPlayer modelData
|
required property MprisPlayer modelData
|
||||||
property string trackPosition: PlayerControllerV2.trackPositionFormatter(root.modelData.position)
|
property string trackPosition: PlayerControllerV2.trackPositionFormatter(root.modelData.position)
|
||||||
property string trackLength: "0:00"
|
property string trackLength: "0:00"
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: background
|
id: background
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
color: "black"
|
color: audioPopup.elementBackgroundColor
|
||||||
radius: 7
|
radius: 7
|
||||||
}
|
}
|
||||||
MouseArea {
|
MouseArea {
|
||||||
@@ -48,21 +54,23 @@ PopupWindow {
|
|||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
Layout.alignment: Qt.AlignHCenter
|
Layout.alignment: Qt.AlignHCenter
|
||||||
width:380
|
width:root.width - 15
|
||||||
RowLayout {
|
RowLayout {
|
||||||
implicitWidth: 380
|
implicitWidth: root.width - 15
|
||||||
Item {
|
ClippingWrapperRectangle {
|
||||||
implicitWidth: 50
|
implicitWidth: 75
|
||||||
implicitHeight: 50
|
implicitHeight: 75
|
||||||
|
radius: 7
|
||||||
Image {
|
Image {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
mipmap: true
|
||||||
source: root.modelData.trackArtUrl
|
source: root.modelData.trackArtUrl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
spacing: 2
|
spacing: 2
|
||||||
ScrollView {
|
ScrollView {
|
||||||
implicitWidth: 230
|
implicitWidth: 180
|
||||||
height: parent.height
|
height: parent.height
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
@@ -75,7 +83,7 @@ PopupWindow {
|
|||||||
Text {
|
Text {
|
||||||
text: root.modelData.trackArtist
|
text: root.modelData.trackArtist
|
||||||
color: "white"
|
color: "white"
|
||||||
font.pointSize: 6
|
font.pointSize: 8
|
||||||
antialiasing: true
|
antialiasing: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -84,28 +92,41 @@ PopupWindow {
|
|||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
RowLayout {
|
RowLayout {
|
||||||
Layout.alignment: Qt.AlignRight
|
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
||||||
|
// Layout.
|
||||||
spacing: 0
|
spacing: 0
|
||||||
// buttons
|
// buttons
|
||||||
Item {
|
Item {
|
||||||
width: 30
|
implicitWidth: 30
|
||||||
height: 25
|
implicitHeight: 25
|
||||||
|
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
||||||
|
Item {
|
||||||
|
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: gobackButton
|
id: gobackButton
|
||||||
width: 30
|
width: 30
|
||||||
height: 25
|
height: 25
|
||||||
topLeftRadius: 7
|
topLeftRadius: 7
|
||||||
bottomLeftRadius: 7
|
bottomLeftRadius: 7
|
||||||
color: "white"
|
color: audioPopup.elementButtonBaseColor
|
||||||
|
}
|
||||||
|
IconImage {
|
||||||
|
Layout.alignment: Qt.AlignCenter
|
||||||
|
implicitSize: 25
|
||||||
|
source: "root:/assets/media_player/skip_previous.svg"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
onEntered: event => {
|
onEntered: event => {
|
||||||
gobackButton.color = "grey"
|
gobackButton.color = audioPopup.elementButtonHoverColor
|
||||||
}
|
}
|
||||||
onExited: event => {
|
onExited: event => {
|
||||||
gobackButton.color = "white"
|
gobackButton.color = audioPopup.elementButtonBaseColor
|
||||||
|
}
|
||||||
|
onClicked: event => {
|
||||||
|
root.modelData.previous();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -113,6 +134,7 @@ PopupWindow {
|
|||||||
width: 30
|
width: 30
|
||||||
height: 25
|
height: 25
|
||||||
Item {
|
Item {
|
||||||
|
Layout.alignment: Qt.AlignCenter
|
||||||
width: 30
|
width: 30
|
||||||
height: 25
|
height: 25
|
||||||
Rectangle {
|
Rectangle {
|
||||||
@@ -121,7 +143,13 @@ PopupWindow {
|
|||||||
height: 25
|
height: 25
|
||||||
// topLeftRadius: 7
|
// topLeftRadius: 7
|
||||||
// bottomLeftRadius: 7
|
// bottomLeftRadius: 7
|
||||||
color: "white"
|
color: audioPopup.elementButtonBaseColor
|
||||||
|
}
|
||||||
|
IconImage {
|
||||||
|
Layout.alignment: Qt.AlignCenter
|
||||||
|
anchors.centerIn: parent
|
||||||
|
implicitSize: 25
|
||||||
|
source: root.modelData.isPlaying ? "root:/assets/media_player/pausebutton.svg" : "root:/assets/media_player/playbutton.svg"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MouseArea {
|
MouseArea {
|
||||||
@@ -129,10 +157,10 @@ PopupWindow {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
onEntered: event => {
|
onEntered: event => {
|
||||||
pauseButton.color = "grey"
|
pauseButton.color = audioPopup.elementButtonHoverColor
|
||||||
}
|
}
|
||||||
onExited: event => {
|
onExited: event => {
|
||||||
pauseButton.color = "white"
|
pauseButton.color = audioPopup.elementButtonBaseColor
|
||||||
}
|
}
|
||||||
onClicked: event => {
|
onClicked: event => {
|
||||||
root.modelData.togglePlaying();
|
root.modelData.togglePlaying();
|
||||||
@@ -142,22 +170,33 @@ PopupWindow {
|
|||||||
Item {
|
Item {
|
||||||
width: 30
|
width: 30
|
||||||
height: 25
|
height: 25
|
||||||
|
Item {
|
||||||
|
Layout.alignment: Qt.AlignCenter
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: gonextButton
|
id: gonextButton
|
||||||
width: 30
|
width: 30
|
||||||
height: 25
|
height: 25
|
||||||
topRightRadius: 7
|
topRightRadius: 7
|
||||||
bottomRightRadius: 7
|
bottomRightRadius: 7
|
||||||
color: "white"
|
color: audioPopup.elementButtonBaseColor
|
||||||
|
}
|
||||||
|
IconImage {
|
||||||
|
Layout.alignment: Qt.AlignCenter
|
||||||
|
implicitSize: 25
|
||||||
|
source: "root:/assets/media_player/skip_next.svg"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
onEntered: event => {
|
onEntered: event => {
|
||||||
gonextButton.color = "grey"
|
gonextButton.color = audioPopup.elementButtonHoverColor
|
||||||
}
|
}
|
||||||
onExited: event => {
|
onExited: event => {
|
||||||
gonextButton.color = "white"
|
gonextButton.color = audioPopup.elementButtonBaseColor
|
||||||
|
}
|
||||||
|
onClicked: event => {
|
||||||
|
root.modelData.next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -170,15 +209,20 @@ PopupWindow {
|
|||||||
from: 0
|
from: 0
|
||||||
value: root.modelData.position
|
value: root.modelData.position
|
||||||
to: root.modelData.length
|
to: root.modelData.length
|
||||||
|
property double lastPosition;
|
||||||
|
property bool debounceValue: false;
|
||||||
onMoved: event => {
|
onMoved: event => {
|
||||||
root.modelData.position = slider.value
|
debounceValue = true; // there is insane lag if we put the move logic here, so its better to trigger a time with the logic instead
|
||||||
audioPopup.player.update(); // force values to update // causing ui to update with it
|
|
||||||
}
|
}
|
||||||
Timer {
|
Timer {
|
||||||
running: root.modelData.playbackState == MprisPlaybackState.Playing
|
running: slider.debounceValue
|
||||||
interval: 500
|
interval: 250
|
||||||
repeat: true
|
repeat: true
|
||||||
onTriggered: slider.value = root.modelData.position
|
onTriggered: {
|
||||||
|
root.modelData.position = slider.value
|
||||||
|
audioPopup.player.update(); // force values to update // causing ui to update with it
|
||||||
|
slider.debounceValue = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
@@ -190,12 +234,17 @@ PopupWindow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Timer {
|
Timer {
|
||||||
running: root.modelData.isPlaying
|
id: updateTimer
|
||||||
interval: 1000
|
property bool tempOneshot: false;
|
||||||
|
running: root.modelData.isPlaying || (root.modelData.position != slider.lastPosition)
|
||||||
|
interval: 750
|
||||||
repeat: true
|
repeat: true
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
trackPosition = PlayerControllerV2.trackPositionFormatter(root.modelData.position)
|
trackPosition = PlayerControllerV2.trackPositionFormatter(root.modelData.position)
|
||||||
trackLength = PlayerControllerV2.trackPositionFormatter(root.modelData.length)
|
trackLength = PlayerControllerV2.trackPositionFormatter(root.modelData.length)
|
||||||
|
updateTimer.tempOneshot = false;
|
||||||
|
slider.lastPosition = slider.value
|
||||||
|
slider.value = root.modelData.position
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user