fix(player): make song info responsive
cx
This commit is contained in:
4 files changed
+77
-22
No files matched your search
@@ -27,8 +27,11 @@ ApplicationWindow {
|
||||
// This was the title-truncation bug: at the old hardcoded 1280 the
|
||||
// now-playing bar sat one responsive tier below the Slint build on the same
|
||||
// machine (1280 < 1366 -> side fraction 0.39 instead of 0.30), so the
|
||||
// Classic song card capped at ~446px instead of 560 and elided titles ~114px
|
||||
// early. The tier thresholds were right; the window was the wrong size.
|
||||
// Classic song card received ~446px instead of the larger mid-tier runway
|
||||
// and elided titles early. The tier thresholds were right; the window was
|
||||
// the wrong size. The card now also measures its live neighbouring controls,
|
||||
// so restored geometry and in-bar allocation solve different parts of the
|
||||
// same problem rather than relying on a fixed card cap.
|
||||
//
|
||||
// These stay plain bindings so the size is correct before the window maps.
|
||||
// The WM's own resizes write `width`/`height` from C++ — that does not
|
||||
|
||||
@@ -272,15 +272,23 @@ Rectangle {
|
||||
|
||||
// === B. CONTROLS ROW — symmetric 3 columns =======================
|
||||
Item {
|
||||
id: controlsLayout
|
||||
width: parent.width
|
||||
height: parent.height - 3
|
||||
|
||||
// Intrinsic boundary of the centred transport. The metadata/time
|
||||
// group may use every pixel before it, regardless of how wide the
|
||||
// nominal centre zone is at this window size.
|
||||
readonly property real transportLeft:
|
||||
centreZone.x + centreTransport.x
|
||||
|
||||
// ---- LEFT column: SongCard + Sep + time column --------------
|
||||
Item {
|
||||
id: leftZone
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
width: (root.width - 6) * root.sideFrac
|
||||
width: Math.max(0, controlsLayout.transportLeft - 8)
|
||||
// No clip: the Row sums to exactly this column (width-59 + 19
|
||||
// + 40, spacing 0) and the two time Texts above are now
|
||||
// bounded, which was the only escape path.
|
||||
@@ -311,7 +319,8 @@ Rectangle {
|
||||
// a 74px card would push the 37px cover off-centre.
|
||||
SongCard {
|
||||
height: parent.height
|
||||
width: parent.width - (QbzPlayer.npHasTrack ? 59 : 0)
|
||||
width: Math.max(0,
|
||||
parent.width - (QbzPlayer.npHasTrack ? 59 : 0))
|
||||
artSize: 37
|
||||
artBorderWidth: 3
|
||||
artBorderColor: theme.surfaceCard
|
||||
@@ -365,6 +374,7 @@ Rectangle {
|
||||
|
||||
// ---- CENTER column: transport, window-centred --------------
|
||||
Item {
|
||||
id: centreZone
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: (root.width - 6) * root.sideFrac
|
||||
anchors.top: parent.top
|
||||
@@ -376,6 +386,7 @@ Rectangle {
|
||||
// Small bar's own copy was a byte-for-byte twin of the full
|
||||
// bar's at playCircle:false / classicActions:false.
|
||||
TransportControls {
|
||||
id: centreTransport
|
||||
anchors.centerIn: parent
|
||||
height: 34
|
||||
playCircle: false
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// Classic uses a fixed 32.4/35.2/32.4 split (col-side 0.324).
|
||||
//
|
||||
// New (0): LEFT SongCard · CENTER transport (filled disc) · RIGHT cluster
|
||||
// Classic (1): LEFT transport · CENTER glass SongCard (<=560px) · RIGHT cluster
|
||||
// Classic (1): LEFT transport · elastic glass SongCard · RIGHT cluster
|
||||
// Large (3): LEFT SongCard WITHOUT the cover (it lives in the sidebar
|
||||
// dock, shifted right to clear it) · CENTER transport ·
|
||||
// RIGHT inline AudioStamp + cluster.
|
||||
@@ -394,23 +394,40 @@ Rectangle {
|
||||
|
||||
// --- Controls: the responsive symmetric zones -----------------------
|
||||
Item {
|
||||
id: controlsLayout
|
||||
width: parent.width
|
||||
height: parent.height - 38
|
||||
|
||||
// The three zones keep PLAY centred and the right cluster pinned,
|
||||
// but the SongCard is sized against the controls themselves, not
|
||||
// against an arbitrary zone edge. This lets metadata consume the
|
||||
// centre column's empty runway without ever crossing transport.
|
||||
readonly property real transportLeft:
|
||||
centreZone.x + centreTransport.x
|
||||
readonly property real classicTransportRight: Math.min(
|
||||
leftZone.x + leftZone.width,
|
||||
leftZone.x + classicTransport.x + classicTransport.width)
|
||||
readonly property real rightControlsLeft:
|
||||
rightZone.x + Math.max(0, rightControls.x)
|
||||
|
||||
// LEFT column.
|
||||
Item {
|
||||
id: leftZone
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 6
|
||||
width: (parent.width - 12) * root.colSide
|
||||
height: parent.height
|
||||
clip: true
|
||||
|
||||
// New (0) AND Large (3): the song card (Large drops the cover
|
||||
// — it lives in the dock — and shifts right to clear it).
|
||||
// — it lives in the dock — and shifts right to clear it). Its
|
||||
// right edge follows the ACTUAL transport bounds; subtracting
|
||||
// the 240px dock from this zone was the old Large-mode bug that
|
||||
// left long titles only ~260px on a 1700px window.
|
||||
SongCard {
|
||||
visible: !root.isClassic
|
||||
x: root.largeActive ? root.dockWidth + 8 : 0
|
||||
width: parent.width - x
|
||||
width: Math.max(0,
|
||||
controlsLayout.transportLeft - 10 - leftZone.x - x)
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
showArt: !root.largeActive
|
||||
showBadges: !root.largeActive
|
||||
@@ -419,6 +436,7 @@ Rectangle {
|
||||
// Classic: transport cluster hugging the left edge (plain
|
||||
// play glyph + inline favorite, the Tauri arrangement).
|
||||
TransportControls {
|
||||
id: classicTransport
|
||||
visible: root.isClassic
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
@@ -433,6 +451,7 @@ Rectangle {
|
||||
|
||||
// CENTRE column.
|
||||
Item {
|
||||
id: centreZone
|
||||
x: 6 + (parent.width - 12) * root.colSide
|
||||
width: (parent.width - 12) * root.colCentre
|
||||
height: parent.height
|
||||
@@ -441,6 +460,7 @@ Rectangle {
|
||||
// New (0) AND Large (3): centred transport, PLAY on the
|
||||
// window centre.
|
||||
TransportControls {
|
||||
id: centreTransport
|
||||
visible: !root.isClassic
|
||||
anchors.centerIn: parent
|
||||
playCircle: true
|
||||
@@ -448,20 +468,12 @@ Rectangle {
|
||||
onAddRequested: function (anchorItem) { addMenu.openBelowRight(anchorItem) }
|
||||
onTrackInfoRequested: root.openTrackInfo()
|
||||
}
|
||||
// Classic: the contained glass song card (<=560px cap).
|
||||
SongCard {
|
||||
visible: root.isClassic
|
||||
glass: true
|
||||
width: Math.min(parent.width, 560)
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
onTrackInfoRequested: root.openTrackInfo()
|
||||
}
|
||||
}
|
||||
|
||||
// RIGHT column — secondary actions + volume, clustered at the
|
||||
// right wall.
|
||||
Item {
|
||||
id: rightZone
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 6
|
||||
width: (parent.width - 12) * root.colSide
|
||||
@@ -469,6 +481,7 @@ Rectangle {
|
||||
clip: true
|
||||
|
||||
Row {
|
||||
id: rightControls
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: 1
|
||||
@@ -638,6 +651,25 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Classic lives between the REAL left transport and right action
|
||||
// cluster. It may use at most 90% of that live gap, centred: the
|
||||
// remaining 5% on each side keeps both the cover edge and the
|
||||
// in-card AudioStamp visibly detached from their neighbour controls.
|
||||
// Unlike the old fixed 560px cap this still scales with volume
|
||||
// steppers, remote state and the actual window width.
|
||||
SongCard {
|
||||
visible: root.isClassic
|
||||
glass: true
|
||||
readonly property real availableWidth: Math.max(0,
|
||||
controlsLayout.rightControlsLeft
|
||||
- controlsLayout.classicTransportRight)
|
||||
width: availableWidth * 0.90
|
||||
x: controlsLayout.classicTransportRight
|
||||
+ (availableWidth - width) / 2
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
onTrackInfoRequested: root.openTrackInfo()
|
||||
}
|
||||
}
|
||||
|
||||
Item { width: 1; height: 6 }
|
||||
|
||||
@@ -46,6 +46,14 @@ Rectangle {
|
||||
// full-height, space-distributed column.
|
||||
property bool textCenter: false
|
||||
|
||||
// Furniture is admitted by intrinsic fit, not by a window breakpoint.
|
||||
// When a host becomes genuinely narrow, metadata keeps the runway and the
|
||||
// cover/stamp yield before either can sit on top of text.
|
||||
readonly property bool stampFits: root.width >= stamp.width + 24
|
||||
readonly property bool effectiveShowArt: root.showArt
|
||||
&& root.width >= root.artSize + root.artTextGap
|
||||
+ (stamp.visible ? stamp.width + 4 : 0)
|
||||
|
||||
/// Title clicked — the host opens the Track Info modal.
|
||||
signal trackInfoRequested()
|
||||
|
||||
@@ -116,8 +124,8 @@ Rectangle {
|
||||
spacing: 0
|
||||
|
||||
Item {
|
||||
visible: root.showArt
|
||||
width: root.showArt ? root.artSize : 0
|
||||
visible: root.effectiveShowArt
|
||||
width: root.effectiveShowArt ? root.artSize : 0
|
||||
height: parent.height
|
||||
Rectangle {
|
||||
width: root.artSize
|
||||
@@ -186,10 +194,11 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
Item { width: root.showArt ? root.artTextGap : 0; height: 1 }
|
||||
Item { width: root.effectiveShowArt ? root.artTextGap : 0; height: 1 }
|
||||
|
||||
Column {
|
||||
width: parent.width - (root.showArt ? root.artSize + root.artTextGap : 0)
|
||||
width: Math.max(0, parent.width
|
||||
- (root.effectiveShowArt ? root.artSize + root.artTextGap : 0))
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
// textCenter tightens the inter-line gap to 1px so the two lines
|
||||
// read as one block beside the small cover (SongCard.slint:333);
|
||||
@@ -350,7 +359,7 @@ Rectangle {
|
||||
|
||||
SongCardStamp {
|
||||
id: stamp
|
||||
visible: root.showBadges && QbzPlayer.npHasTrack
|
||||
visible: root.showBadges && root.stampFits && QbzPlayer.npHasTrack
|
||||
anchors.right: parent.right
|
||||
// Classic (glass) insets the stamp by pad + stamp-right-margin
|
||||
// (2px each) so it clears the visible card border.
|
||||
|
||||
Reference in new issue
Block a user