fix(playback): harden idle queue and gapless transitions

cx
This commit is contained in:
vicrodh committed 2026-08-28 02:57:09 -06:00
1 parent 97f9b85d7f
commit 3d0ee66708
8 files changed
+178 -17

No files matched your search

@@ -70,6 +70,7 @@ Rectangle {
readonly property int timeFont: root.compactMode ? 10 : 11
readonly property bool hasTrack: QbzPlayer.npHasTrack
readonly property bool canPlay: root.hasTrack || QbzQueue.hasPlayTarget
// --- The pending-seek machine (:214-249) -------------------------------
// All three constants are load-bearing: the -1.0 SENTINEL (every test is
@@ -273,6 +274,7 @@ Rectangle {
icSkip: root.icSkip
icPlay: root.icPlay
btnEnabled: root.hasTrack
playEnabled: root.canPlay
}
// The capsule (:322-327): right-aligned, vertically centred
@@ -394,6 +396,7 @@ Rectangle {
icSkip: 9
icPlay: 9
btnEnabled: root.hasTrack
playEnabled: root.canPlay
}
}
@@ -28,6 +28,9 @@ Row {
property int gap: 18
/// Gated on `NowPlayingState.has-track` by the footer (:315).
property bool btnEnabled: true
/// Play additionally accepts an idle, populated queue. The other four
/// controls remain tied to a real current track.
property bool playEnabled: root.btnEnabled
spacing: root.gap
@@ -50,7 +53,7 @@ Row {
name: QbzPlayer.npPlaying ? "pause" : "play-fill"
iconSize: root.icPlay
btn: root.btn
btnEnabled: root.btnEnabled
btnEnabled: root.playEnabled
onClicked: QbzPlayer.togglePlay()
}
TBtn {
+1 -1
View File
@@ -577,7 +577,7 @@ Rectangle {
// (kiosk_nav_qt.rs:222-225).
if (QbzKioskNav.zone === "player") {
QbzKioskNav.markActive()
if (QbzPlayer.npHasTrack)
if (QbzPlayer.npHasTrack || QbzQueue.hasPlayTarget)
QbzPlayer.togglePlay()
} else if (QbzKioskNav.zone === "rail") {
QbzKioskNav.markActive()
@@ -73,6 +73,10 @@ Row {
// play. Not gated on `npHasTrack`: the first play of a session has no
// track yet, and that is exactly the case that felt dead.
readonly property bool loading: QbzPlayer.npLoading
// Clear-while-paused removes the NPB cursor by design. Rows added
// afterwards still make Play actionable: the backend promotes the first
// one without resurrecting the cleared paused stream.
readonly property bool playEnabled: QbzPlayer.npHasTrack || QbzQueue.hasPlayTarget
// Spin phase, advanced on the shared shell pulse (QbzShell.pulseMs).
property real spinPhase: 0
Connections {
@@ -94,10 +98,10 @@ Row {
height: tc.playCircle ? 38 : 34
radius: tc.playCircle ? width / 2 : theme.radiusSm
anchors.verticalCenter: parent.verticalCenter
opacity: QbzPlayer.npHasTrack ? 1.0 : 0.3
opacity: tc.playEnabled ? 1.0 : 0.3
color: tc.playCircle
? (playArea.containsMouse && QbzPlayer.npHasTrack ? theme.accentHover : theme.accent)
: ((playArea.containsMouse && QbzPlayer.npHasTrack) ? theme.surfaceHover : "transparent")
? (playArea.containsMouse && tc.playEnabled ? theme.accentHover : theme.accent)
: ((playArea.containsMouse && tc.playEnabled) ? theme.surfaceHover : "transparent")
QbzIcon {
// Hidden while loading — the ring below stands in for it, so the
// button never shows a play glyph for a track that is still being
@@ -145,8 +149,8 @@ Row {
id: playArea
anchors.fill: parent
hoverEnabled: true
cursorShape: QbzPlayer.npHasTrack ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: if (QbzPlayer.npHasTrack) QbzPlayer.togglePlay()
cursorShape: tc.playEnabled ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: if (tc.playEnabled) QbzPlayer.togglePlay()
}
}
QbzIconButton {