mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-10-18 09:14:01 -04:00
254 lines
8.9 KiB
QML
254 lines
8.9 KiB
QML
pragma ComponentBehavior: Bound
|
|
|
|
import QtQuick
|
|
import Quickshell
|
|
import qs.Common
|
|
import qs.Modules.DBar.Widgets
|
|
import qs.Services
|
|
import qs.DCommon.Widgets
|
|
import qs.Widgets
|
|
|
|
Item {
|
|
id: root
|
|
|
|
required property var mediaModel
|
|
|
|
property bool dense: false
|
|
property real contentScale: 1
|
|
property bool isVertical: false
|
|
property real artworkSize: Theme.iconSizeLarge
|
|
readonly property real textGutter: Theme.spacingXS
|
|
readonly property real cavaWidth: 20
|
|
readonly property real minTextWidth: 48
|
|
readonly property real clockLeadPad: Theme.spacingXS / 2
|
|
readonly property real clockTrailPad: Theme.spacingS
|
|
readonly property real clockPillHeight: root.dense ? Math.max(22, root.artworkSize - Theme.spacingXS) : 32
|
|
// A fully rounded side strip crowds square content, so the vertical face insets on both axes.
|
|
readonly property real verticalPad: Theme.spacingS
|
|
readonly property real verticalArtworkSize: Math.max(12, Math.min(root.artworkSize, root.width - root.verticalPad * 2))
|
|
readonly property string timeText: systemClock.date.toLocaleTimeString(I18n.locale(), SettingsData.getEffectiveTimeFormat())
|
|
readonly property string hourText: {
|
|
const hours = systemClock.date.getHours();
|
|
if (SettingsData.use24HourClock)
|
|
return String(hours).padStart(2, "0");
|
|
return String(hours === 0 ? 12 : (hours > 12 ? hours - 12 : hours)).padStart(2, "0");
|
|
}
|
|
readonly property string minuteText: String(systemClock.date.getMinutes()).padStart(2, "0")
|
|
property bool clockVisible: false
|
|
readonly property real naturalTextWidth: Math.max(root.minTextWidth, titleMetrics.width, root.dense ? 0 : artistMetrics.width) + root.textGutter * 2
|
|
readonly property real measuredWidth: {
|
|
let width = Theme.spacingS + root.artworkSize + Theme.spacingXS + root.cavaWidth + Theme.spacingXS + root.naturalTextWidth + Theme.spacingXS;
|
|
if (root.clockVisible)
|
|
width += clockText.width + Theme.spacingXS * 2 + Theme.spacingS;
|
|
return width;
|
|
}
|
|
|
|
implicitWidth: isVertical ? artworkSize + verticalPad * 2 : measuredWidth
|
|
implicitHeight: isVertical ? verticalFace.implicitHeight + verticalPad * 2 : artworkSize
|
|
readonly property bool clockHovered: enabled && visible && ((clockArea.visible && clockArea.containsMouse) || (verticalClockArea.visible && verticalClockArea.containsMouse))
|
|
signal clockClicked
|
|
|
|
StyledTextMetrics {
|
|
id: titleMetrics
|
|
|
|
font.pixelSize: Theme.fontSizeSmall * root.contentScale
|
|
font.weight: Theme.fontWeightMedium
|
|
text: root.mediaModel.title
|
|
}
|
|
|
|
StyledTextMetrics {
|
|
id: artistMetrics
|
|
|
|
font.pixelSize: Math.max(9, Theme.fontSizeSmall - 2) * root.contentScale
|
|
text: root.dense ? "" : root.mediaModel.artist
|
|
}
|
|
|
|
SystemClock {
|
|
id: systemClock
|
|
|
|
enabled: root.enabled && root.visible && root.clockVisible
|
|
precision: SettingsData.showSeconds ? SystemClock.Seconds : SystemClock.Minutes
|
|
}
|
|
|
|
MediaArtwork {
|
|
id: artwork
|
|
|
|
anchors {
|
|
left: parent.left
|
|
leftMargin: Theme.spacingS
|
|
verticalCenter: parent.verticalCenter
|
|
}
|
|
visible: !root.isVertical
|
|
width: root.artworkSize
|
|
height: width
|
|
artUrl: root.mediaModel.artUrl
|
|
}
|
|
|
|
Row {
|
|
visible: !root.isVertical
|
|
anchors {
|
|
left: artwork.right
|
|
leftMargin: Theme.spacingXS
|
|
right: root.clockVisible ? rightActivity.left : parent.right
|
|
rightMargin: Theme.spacingXS
|
|
verticalCenter: parent.verticalCenter
|
|
}
|
|
height: root.artworkSize
|
|
spacing: Theme.spacingXS
|
|
|
|
AudioVisualization {
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
width: root.cavaWidth
|
|
height: parent.height
|
|
maxBarHeight: Math.max(3, height - 2)
|
|
idleIconName: "graphic_eq"
|
|
}
|
|
|
|
Column {
|
|
width: parent.width - root.cavaWidth - parent.spacing
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
spacing: 0
|
|
|
|
ScrollingText {
|
|
x: root.textGutter
|
|
width: parent.width - root.textGutter * 2
|
|
text: root.mediaModel.title
|
|
color: Theme.surfaceText
|
|
font.pixelSize: Theme.fontSizeSmall * root.contentScale
|
|
font.weight: Theme.fontWeightMedium
|
|
active: root.enabled && root.mediaModel.playing
|
|
holdStartMs: 1600
|
|
holdEndMs: 1200
|
|
pxPerMs: 1 / 62.5
|
|
overscroll: root.textGutter
|
|
}
|
|
|
|
StyledText {
|
|
x: root.textGutter
|
|
width: parent.width - root.textGutter * 2
|
|
visible: !root.dense
|
|
text: root.mediaModel.artist
|
|
color: Theme.surfaceTextSecondary
|
|
font.pixelSize: Math.max(9, Theme.fontSizeSmall - 2) * root.contentScale
|
|
wrapMode: Text.NoWrap
|
|
elide: Text.ElideRight
|
|
}
|
|
}
|
|
}
|
|
|
|
Item {
|
|
id: rightActivity
|
|
|
|
anchors {
|
|
right: parent.right
|
|
rightMargin: Theme.spacingS
|
|
verticalCenter: parent.verticalCenter
|
|
}
|
|
width: root.clockVisible ? (clockText.width + Theme.spacingXS * 2) : 0
|
|
height: root.clockPillHeight
|
|
visible: root.clockVisible && !root.isVertical
|
|
|
|
Rectangle {
|
|
anchors.fill: parent
|
|
radius: Math.min(Theme.cornerRadiusFull, height / 2)
|
|
color: clockArea.containsMouse ? Theme.surfaceTextHover : "transparent"
|
|
|
|
NumericText {
|
|
id: clockText
|
|
|
|
anchors.centerIn: parent
|
|
isMonospace: false
|
|
text: root.timeText
|
|
reserveText: root.timeText.replace(/\d/g, "0")
|
|
width: Math.ceil(Math.max(implicitWidth, reservedWidth))
|
|
horizontalAlignment: Text.AlignHCenter
|
|
color: Theme.surfaceText
|
|
font.pixelSize: Theme.fontSizeSmall * root.contentScale
|
|
font.weight: Theme.fontWeightMedium
|
|
}
|
|
|
|
MouseArea {
|
|
id: clockArea
|
|
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
x: -root.clockLeadPad
|
|
width: parent.width + root.clockLeadPad + root.clockTrailPad
|
|
height: root.height
|
|
hoverEnabled: true
|
|
cursorShape: Qt.PointingHandCursor
|
|
onClicked: root.clockClicked()
|
|
}
|
|
}
|
|
}
|
|
|
|
// A side strip has no room for track text, so the vertical face is artwork over the meter.
|
|
Column {
|
|
id: verticalFace
|
|
|
|
anchors.centerIn: parent
|
|
visible: root.isVertical
|
|
spacing: Theme.spacingXS
|
|
|
|
MediaArtwork {
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
width: root.verticalArtworkSize
|
|
height: width
|
|
artUrl: root.mediaModel.artUrl
|
|
}
|
|
|
|
AudioVisualization {
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
width: root.verticalArtworkSize
|
|
height: root.cavaWidth
|
|
maxBarHeight: Math.max(3, height - 2)
|
|
idleIconName: "graphic_eq"
|
|
}
|
|
|
|
Item {
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
visible: root.clockVisible
|
|
width: verticalClock.width
|
|
height: verticalClock.height
|
|
|
|
// A side strip cannot fit "10:42 PM" on one line, so the hour sits over the minute.
|
|
Column {
|
|
id: verticalClock
|
|
|
|
spacing: 0
|
|
|
|
NumericText {
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
isMonospace: false
|
|
text: root.hourText
|
|
reserveText: "00"
|
|
horizontalAlignment: Text.AlignHCenter
|
|
color: Theme.surfaceText
|
|
font.pixelSize: Theme.fontSizeSmall * root.contentScale
|
|
font.weight: Theme.fontWeightMedium
|
|
}
|
|
|
|
NumericText {
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
isMonospace: false
|
|
text: root.minuteText
|
|
reserveText: "00"
|
|
horizontalAlignment: Text.AlignHCenter
|
|
color: Theme.surfaceTextMedium
|
|
font.pixelSize: Theme.fontSizeSmall * root.contentScale
|
|
font.weight: Theme.fontWeightMedium
|
|
}
|
|
}
|
|
|
|
MouseArea {
|
|
id: verticalClockArea
|
|
anchors.centerIn: parent
|
|
width: root.width
|
|
height: parent.height + Theme.spacingXS
|
|
hoverEnabled: true
|
|
cursorShape: Qt.PointingHandCursor
|
|
onClicked: root.clockClicked()
|
|
}
|
|
}
|
|
}
|
|
}
|