fix(media): tighten MediaMini panel layout for album art and height

This commit is contained in:
Lysec
2026-03-27 15:02:45 +01:00
parent 9b64e21bea
commit 4d31d05248
+105 -65
View File
@@ -14,7 +14,8 @@ SmartPanel {
id: root id: root
preferredWidth: Math.round((root.isSideBySide ? 480 : 360) * Style.uiScaleRatio) preferredWidth: Math.round((root.isSideBySide ? 480 : 360) * Style.uiScaleRatio)
preferredHeight: Math.round((root.compactMode ? 240 : (root.showAlbumArt ? 560 : 300)) * Style.uiScaleRatio) // Fallback only; SmartPanel uses panelContent.contentPreferredHeight when set.
preferredHeight: Math.round((root.compactMode ? 240 : 400) * Style.uiScaleRatio)
property var mediaMiniSettings: { property var mediaMiniSettings: {
const widget = BarService.lookupWidget("MediaMini", screen?.name); const widget = BarService.lookupWidget("MediaMini", screen?.name);
@@ -73,9 +74,16 @@ SmartPanel {
id: playerContent id: playerContent
anchors.fill: parent anchors.fill: parent
readonly property real contentPreferredHeight: (root.compactMode ? 240 : (root.showAlbumArt ? 560 : 300)) * Style.uiScaleRatio // implicitHeight + mainLayout vertical anchors.margins (each Style.marginL).
readonly property real contentPreferredHeight: {
// Old loader removed from here const m = mainLayout.implicitHeight + 2 * Style.marginL;
const scale = Style.uiScaleRatio;
if (root.compactMode)
return Math.max(m, 240 * scale);
if (!root.showAlbumArt)
return Math.max(m, 300 * scale);
return Math.max(m, 260 * scale);
}
property Component visualizerSource: { property Component visualizerSource: {
switch (root.visualizerType) { switch (root.visualizerType) {
@@ -90,7 +98,6 @@ SmartPanel {
} }
} }
// Layout
ColumnLayout { ColumnLayout {
id: mainLayout id: mainLayout
anchors.fill: parent anchors.fill: parent
@@ -229,10 +236,9 @@ SmartPanel {
} }
} }
// Adaptive Content Area
NBox { NBox {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.preferredHeight: mediaContentGrid.implicitHeight + Style.marginM + Style.marginM
// Visualizer background for content area // Visualizer background for content area
Loader { Loader {
@@ -243,7 +249,10 @@ SmartPanel {
} }
GridLayout { GridLayout {
anchors.fill: parent id: mediaContentGrid
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.leftMargin: root.compactMode ? Style.marginL : Style.marginM anchors.leftMargin: root.compactMode ? Style.marginL : Style.marginM
anchors.rightMargin: root.compactMode ? Style.marginL : Style.marginM anchors.rightMargin: root.compactMode ? Style.marginL : Style.marginM
anchors.topMargin: Style.marginM anchors.topMargin: Style.marginM
@@ -255,21 +264,35 @@ SmartPanel {
// Album Art (Vertical in normal, Horizontal in compact) // Album Art (Vertical in normal, Horizontal in compact)
Item { Item {
id: albumArtItem id: albumArtItem
Layout.preferredWidth: { readonly property real compactArtSize: Math.round(110 * Style.uiScaleRatio)
if (root.compactMode) readonly property bool artSizeKnown: artSizeProbe.status === Image.Ready && artSizeProbe.sourceSize.width > 0 && artSizeProbe.sourceSize.height > 0
return Math.round(110 * Style.uiScaleRatio); readonly property real artAspectRatio: artSizeKnown ? artSizeProbe.sourceSize.width / artSizeProbe.sourceSize.height : 1
return Math.min(parent.width, parent.height - controlsLayout.implicitHeight - parent.rowSpacing); // Non-compact: height from width÷aspect so grid implicit height does not depend on panel height (no layout loop).
} readonly property real artBoxW: root.compactMode ? compactArtSize : Math.max(parent.width, 1)
Layout.preferredHeight: Layout.preferredWidth readonly property real artBoxH: root.compactMode ? compactArtSize : (artBoxW / Math.max(artAspectRatio, 0.001))
readonly property real fitArtW: artBoxW / artBoxH > artAspectRatio ? artBoxH * artAspectRatio : artBoxW
readonly property real fitArtH: artBoxW / artBoxH > artAspectRatio ? artBoxH : artBoxW / artAspectRatio
Layout.preferredWidth: fitArtW
Layout.preferredHeight: fitArtH
Layout.minimumWidth: fitArtW
Layout.maximumWidth: fitArtW
Layout.minimumHeight: fitArtH
Layout.maximumHeight: fitArtH
Layout.fillWidth: false Layout.fillWidth: false
Layout.fillHeight: false Layout.fillHeight: false
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
visible: root.showAlbumArt visible: root.showAlbumArt
Image {
id: artSizeProbe
visible: false
asynchronous: true
source: MediaService.trackArtUrl
}
NImageRounded { NImageRounded {
anchors.centerIn: parent anchors.fill: parent
width: Math.min(parent.width, parent.height)
height: width
radius: root.compactMode ? Style.radiusM : Style.radiusL radius: root.compactMode ? Style.radiusM : Style.radiusL
imagePath: MediaService.trackArtUrl imagePath: MediaService.trackArtUrl
imageFillMode: Image.PreserveAspectCrop imageFillMode: Image.PreserveAspectCrop
@@ -279,9 +302,7 @@ SmartPanel {
} }
Loader { Loader {
anchors.centerIn: parent anchors.fill: parent
width: Math.min(parent.width, parent.height)
height: width
anchors.margins: Style.marginS anchors.margins: Style.marginS
z: 2 z: 2
active: !!(root.needsSpectrum && root.showAlbumArt) active: !!(root.needsSpectrum && root.showAlbumArt)
@@ -367,7 +388,7 @@ SmartPanel {
id: progressWrapper id: progressWrapper
visible: (MediaService.currentPlayer && MediaService.trackLength > 0) visible: (MediaService.currentPlayer && MediaService.trackLength > 0)
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: root.compactMode ? (Style.baseWidgetSize * 0.4) : (Style.baseWidgetSize * 0.5) Layout.preferredHeight: progressColumn.implicitHeight
property real localSeekRatio: -1 property real localSeekRatio: -1
property real lastSentSeekRatio: -1 property real lastSentSeekRatio: -1
@@ -396,55 +417,74 @@ SmartPanel {
} }
} }
NSlider { ColumnLayout {
id: progressSlider id: progressColumn
anchors.fill: parent anchors.left: parent.left
from: 0 anchors.right: parent.right
to: 1 anchors.top: parent.top
stepSize: 0 spacing: 2
snapAlways: false
enabled: MediaService.trackLength > 0 && MediaService.canSeek
heightRatio: 0.4
value: (!MediaService.isSeeking) ? progressWrapper.progressRatio : (progressWrapper.localSeekRatio >= 0 ? progressWrapper.localSeekRatio : 0) Item {
Layout.fillWidth: true
Layout.preferredHeight: root.compactMode ? (Style.baseWidgetSize * 0.4) : (Style.baseWidgetSize * 0.5)
onMoved: { NSlider {
progressWrapper.localSeekRatio = value; id: progressSlider
seekDebounce.restart(); anchors.fill: parent
} from: 0
onPressedChanged: { to: 1
if (pressed) { stepSize: 0
MediaService.isSeeking = true; snapAlways: false
progressWrapper.localSeekRatio = value; enabled: MediaService.trackLength > 0 && MediaService.canSeek
MediaService.seekByRatio(value); heightRatio: 0.4
progressWrapper.lastSentSeekRatio = value;
} else { value: (!MediaService.isSeeking) ? progressWrapper.progressRatio : (progressWrapper.localSeekRatio >= 0 ? progressWrapper.localSeekRatio : 0)
seekDebounce.stop();
MediaService.seekByRatio(value); onMoved: {
MediaService.isSeeking = false; progressWrapper.localSeekRatio = value;
progressWrapper.localSeekRatio = -1; seekDebounce.restart();
progressWrapper.lastSentSeekRatio = -1; }
onPressedChanged: {
if (pressed) {
MediaService.isSeeking = true;
progressWrapper.localSeekRatio = value;
MediaService.seekByRatio(value);
progressWrapper.lastSentSeekRatio = value;
} else {
seekDebounce.stop();
MediaService.seekByRatio(value);
MediaService.isSeeking = false;
progressWrapper.localSeekRatio = -1;
progressWrapper.lastSentSeekRatio = -1;
}
}
} }
} }
}
NText { RowLayout {
anchors.left: parent.left Layout.fillWidth: true
anchors.top: parent.bottom spacing: 0
anchors.topMargin: 2 // Small gap for side-by-side mode
text: MediaService.positionString || "0:00" NText {
pointSize: Style.fontSizeXS text: MediaService.positionString || "0:00"
color: Color.mOnSurfaceVariant pointSize: Style.fontSizeXS
visible: parent.visible color: Color.mOnSurfaceVariant
} visible: progressWrapper.visible
NText { }
anchors.right: parent.right
anchors.top: parent.bottom Item {
anchors.topMargin: 2 Layout.fillWidth: true
text: MediaService.lengthString || "0:00" Layout.minimumWidth: 0
pointSize: Style.fontSizeXS }
color: Color.mOnSurfaceVariant
visible: parent.visible NText {
text: MediaService.lengthString || "0:00"
pointSize: Style.fontSizeXS
color: Color.mOnSurfaceVariant
horizontalAlignment: Text.AlignRight
visible: progressWrapper.visible
}
}
} }
} }