1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-04-14 01:32:29 -04:00

Add adaptive media width setting. (#2165)

This commit is contained in:
Ron Harel
2026-04-07 18:07:36 +03:00
committed by GitHub
parent f6e590a518
commit 13e8130858
4 changed files with 119 additions and 45 deletions

View File

@@ -301,6 +301,7 @@ Singleton {
property var workspaceNameIcons: ({}) property var workspaceNameIcons: ({})
property bool waveProgressEnabled: true property bool waveProgressEnabled: true
property bool scrollTitleEnabled: true property bool scrollTitleEnabled: true
property bool mediaAdaptiveWidthEnabled: true
property bool audioVisualizerEnabled: true property bool audioVisualizerEnabled: true
property string audioScrollMode: "volume" property string audioScrollMode: "volume"
property int audioWheelScrollAmount: 5 property int audioWheelScrollAmount: 5

View File

@@ -140,6 +140,7 @@ var SPEC = {
workspaceNameIcons: { def: {} }, workspaceNameIcons: { def: {} },
waveProgressEnabled: { def: true }, waveProgressEnabled: { def: true },
scrollTitleEnabled: { def: true }, scrollTitleEnabled: { def: true },
mediaAdaptiveWidthEnabled: { def: true },
audioVisualizerEnabled: { def: true }, audioVisualizerEnabled: { def: true },
audioScrollMode: { def: "volume" }, audioScrollMode: { def: "volume" },
audioWheelScrollAmount: { def: 5 }, audioWheelScrollAmount: { def: 5 },

View File

@@ -19,7 +19,8 @@ BasePill {
readonly property bool usePlayerVolume: activePlayer && activePlayer.volumeSupported && !__isChromeBrowser readonly property bool usePlayerVolume: activePlayer && activePlayer.volumeSupported && !__isChromeBrowser
property bool compactMode: false property bool compactMode: false
property var widgetData: null property var widgetData: null
readonly property int textWidth: { readonly property bool adaptiveWidthEnabled: SettingsData.mediaAdaptiveWidthEnabled
readonly property int maxTextWidth: {
const size = widgetData?.mediaSize !== undefined ? widgetData.mediaSize : SettingsData.mediaSize; const size = widgetData?.mediaSize !== undefined ? widgetData.mediaSize : SettingsData.mediaSize;
switch (size) { switch (size) {
case 0: case 0:
@@ -36,10 +37,7 @@ BasePill {
if (isVerticalOrientation) { if (isVerticalOrientation) {
return widgetThickness - horizontalPadding * 2; return widgetThickness - horizontalPadding * 2;
} }
const controlsWidth = 20 + Theme.spacingXS + 24 + Theme.spacingXS + 20; return 0;
const audioVizWidth = 20;
const contentWidth = audioVizWidth + Theme.spacingXS + controlsWidth;
return contentWidth + (textWidth > 0 ? textWidth + Theme.spacingXS : 0);
} }
readonly property int currentContentHeight: { readonly property int currentContentHeight: {
if (!isVerticalOrientation) { if (!isVerticalOrientation) {
@@ -119,7 +117,28 @@ BasePill {
content: Component { content: Component {
Item { Item {
implicitWidth: root.playerAvailable ? root.currentContentWidth : 0 id: contentRoot
readonly property real measuredTextWidth: {
if (!root.playerAvailable || root.maxTextWidth <= 0 || !textContainer.visible)
return 0;
// Preserve the fixed-width text slot even if metadata is briefly empty.
if (!root.adaptiveWidthEnabled)
return root.maxTextWidth;
if (textContainer.displayText.length === 0)
return 0;
const rawWidth = mediaText.contentWidth;
if (!isFinite(rawWidth) || rawWidth <= 0)
return 0;
return Math.min(root.maxTextWidth, Math.ceil(rawWidth));
}
readonly property int horizontalContentWidth: {
const controlsWidth = 20 + Theme.spacingXS + 24 + Theme.spacingXS + 20;
const audioVizWidth = 20;
const baseWidth = audioVizWidth + Theme.spacingXS + controlsWidth;
return baseWidth + (measuredTextWidth > 0 ? measuredTextWidth + Theme.spacingXS : 0);
}
implicitWidth: root.playerAvailable ? (root.isVerticalOrientation ? root.currentContentWidth : horizontalContentWidth) : 0
implicitHeight: root.playerAvailable ? root.currentContentHeight : 0 implicitHeight: root.playerAvailable ? root.currentContentHeight : 0
opacity: root.playerAvailable ? 1 : 0 opacity: root.playerAvailable ? 1 : 0
@@ -132,8 +151,9 @@ BasePill {
Behavior on implicitWidth { Behavior on implicitWidth {
NumberAnimation { NumberAnimation {
duration: Theme.shortDuration duration: Theme.mediumDuration
easing.type: Theme.standardEasing easing.type: Easing.BezierSpline
easing.bezierCurve: Theme.expressiveCurves.emphasizedDecel
} }
} }
@@ -269,7 +289,7 @@ BasePill {
} }
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
width: textWidth width: contentRoot.measuredTextWidth
height: root.widgetThickness height: root.widgetThickness
visible: { visible: {
const size = widgetData?.mediaSize !== undefined ? widgetData.mediaSize : SettingsData.mediaSize; const size = widgetData?.mediaSize !== undefined ? widgetData.mediaSize : SettingsData.mediaSize;
@@ -278,50 +298,95 @@ BasePill {
clip: true clip: true
color: "transparent" color: "transparent"
StyledText { Behavior on width {
id: mediaText NumberAnimation {
property bool needsScrolling: implicitWidth > textContainer.width && SettingsData.scrollTitleEnabled duration: Theme.mediumDuration
property real scrollOffset: 0 easing.type: Easing.BezierSpline
easing.bezierCurve: Theme.expressiveCurves.emphasizedDecel
anchors.verticalCenter: parent.verticalCenter
text: textContainer.displayText
font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText)
color: Theme.widgetTextColor
wrapMode: Text.NoWrap
x: needsScrolling ? -scrollOffset : 0
onTextChanged: {
scrollOffset = 0;
scrollAnimation.restart();
} }
}
SequentialAnimation { Item {
id: scrollAnimation id: textClip
running: mediaText.needsScrolling && textContainer.visible anchors.fill: parent
loops: Animation.Infinite clip: true
PauseAnimation { StyledText {
duration: 2000 id: mediaText
property bool needsScrolling: implicitWidth > textContainer.width && SettingsData.scrollTitleEnabled
property real scrollOffset: 0
property real textShift: 0
anchors.verticalCenter: parent.verticalCenter
text: textContainer.displayText
font.pixelSize: Theme.barTextSize(root.barThickness, root.barConfig?.fontScale, root.barConfig?.maximizeWidgetText)
color: Theme.widgetTextColor
wrapMode: Text.NoWrap
x: (needsScrolling ? -scrollOffset : 0) + textShift
opacity: 1
onTextChanged: {
scrollOffset = 0;
textShift = 0;
scrollAnimation.restart();
textChangeAnimation.restart();
} }
NumberAnimation { SequentialAnimation {
target: mediaText id: scrollAnimation
property: "scrollOffset" running: mediaText.needsScrolling && textContainer.visible
from: 0 loops: Animation.Infinite
to: mediaText.implicitWidth - textContainer.width + 5
duration: Math.max(1000, (mediaText.implicitWidth - textContainer.width + 5) * 60) PauseAnimation {
easing.type: Easing.Linear duration: 2000
}
NumberAnimation {
target: mediaText
property: "scrollOffset"
from: 0
to: mediaText.implicitWidth - textContainer.width + 5
duration: Math.max(1000, (mediaText.implicitWidth - textContainer.width + 5) * 60)
easing.type: Easing.Linear
}
PauseAnimation {
duration: 2000
}
NumberAnimation {
target: mediaText
property: "scrollOffset"
to: 0
duration: Math.max(1000, (mediaText.implicitWidth - textContainer.width + 5) * 60)
easing.type: Easing.Linear
}
} }
PauseAnimation { SequentialAnimation {
duration: 2000 id: textChangeAnimation
}
NumberAnimation { ParallelAnimation {
target: mediaText NumberAnimation {
property: "scrollOffset" target: mediaText
to: 0 property: "opacity"
duration: Math.max(1000, (mediaText.implicitWidth - textContainer.width + 5) * 60) from: 0.7
easing.type: Easing.Linear to: 1
duration: Theme.shortDuration
easing.type: Easing.BezierSpline
easing.bezierCurve: Theme.expressiveCurves.emphasizedDecel
}
NumberAnimation {
target: mediaText
property: "textShift"
from: 4
to: 0
duration: Theme.shortDuration
easing.type: Easing.BezierSpline
easing.bezierCurve: Theme.expressiveCurves.emphasizedDecel
}
}
} }
} }
} }

View File

@@ -46,6 +46,13 @@ Item {
onToggled: checked => SettingsData.set("audioVisualizerEnabled", checked) onToggled: checked => SettingsData.set("audioVisualizerEnabled", checked)
} }
SettingsToggleRow {
text: I18n.tr("Adaptive Media Width")
description: I18n.tr("Shrink the media widget to fit shorter song titles while still respecting the configured maximum size")
checked: SettingsData.mediaAdaptiveWidthEnabled
onToggled: checked => SettingsData.set("mediaAdaptiveWidthEnabled", checked)
}
SettingsDropdownRow { SettingsDropdownRow {
property var scrollOptsInternal: ["volume", "song", "nothing"] property var scrollOptsInternal: ["volume", "song", "nothing"]
property var scrollOptsDisplay: [I18n.tr("Change Volume", "media scroll wheel option"), I18n.tr("Change Song", "media scroll wheel option"), I18n.tr("Nothing", "media scroll wheel option")] property var scrollOptsDisplay: [I18n.tr("Change Volume", "media scroll wheel option"), I18n.tr("Change Song", "media scroll wheel option"), I18n.tr("Nothing", "media scroll wheel option")]