Restored queues and recently_played carried whatever variant the building surface picked — 50px JPEGs measured in the wild — into the now-playing bar, MPRIS, Discord and the immersive big slots. The np feed rewrites sized Qobuz covers up to 600px; big slots (immersive panels, split, preview overlay) resolve per size bucket through npArtworkPathLarge with one re-resolve per tier crossed and never on shrink. Registry-miss arm (restored sessions carry no ImageSet): rewrite to the FULL requested bucket with a session negative cache, so a pre-mega album pays one 404 per session instead of one per track change. And the mega tier's wire suffix is the literal _max.jpg, not _3000 (404 measured against the live CDN) — qobuz_cover_at_px now accepts and emits _max. Local covers gain an on-demand 1600px tier (never upscaled); Plex big slots tokenize at 1024. km
78 lines
3.1 KiB
QML
78 lines
3.1 KiB
QML
// Global floating album-art preview — a 220x220 cover that floats ABOVE the
|
|
// now-playing bar's small cover while the pointer hovers it. 1:1 port of
|
|
// ArtPreviewOverlay.slint.
|
|
//
|
|
// Two properties of the original are load-bearing and kept exactly:
|
|
//
|
|
// 1. It is mounted LAST in AppShell and fills the window, so it paints over
|
|
// every surface without needing a z fight.
|
|
// 2. It is NON-INTERACTIVE — no MouseArea anywhere. The Slint tried a
|
|
// PopupWindow first and it STOLE THE HOVER from the trigger (the cover's
|
|
// has-hover flipped the moment the popup appeared, which closed it, which
|
|
// restored the hover…), so the preview flickered. An overlay that cannot
|
|
// receive events cannot do that; clicks also pass straight through to
|
|
// whatever is underneath.
|
|
//
|
|
// The state (anchor + visibility) rides QbzShell, like the drag ghost in the
|
|
// same file — the trigger is inside the bar and the overlay is a sibling of
|
|
// the whole shell, so they cannot see each other's ids.
|
|
|
|
import QtQuick
|
|
import com.blitzfc.qbz
|
|
import "../theme"
|
|
|
|
Item {
|
|
id: root
|
|
anchors.fill: parent
|
|
visible: QbzShell.artPreviewShow && QbzPlayer.npHasTrack
|
|
|
|
QbzTheme { id: theme }
|
|
|
|
// 232 = the 220 image plus a 6px frame on each side (ArtPreviewOverlay
|
|
// .slint:16 `card`).
|
|
readonly property int card: 232
|
|
|
|
Rectangle {
|
|
width: root.card
|
|
height: root.card
|
|
// Centred on the cover, clamped 8px inside the window, floating with
|
|
// its bottom edge 8px above the cover's top.
|
|
x: Math.max(8, Math.min(QbzShell.artPreviewX - width / 2,
|
|
Math.max(8, root.width - width - 8)))
|
|
y: QbzShell.artPreviewY - height - 8
|
|
radius: 8
|
|
color: theme.surfaceCard
|
|
border.width: 1
|
|
border.color: theme.borderSubtle
|
|
clip: true
|
|
|
|
// The .slint carries a 16px drop shadow; QtQuick's DropShadow is a
|
|
// shader effect and shader effects render NOTHING on this port's
|
|
// software path (the phase-2 finding that also killed ColorOverlay in
|
|
// QbzIcon), so the depth cue is a border instead of a fake blurred
|
|
// rectangle that would be wrong on both paths.
|
|
|
|
Image {
|
|
x: 6
|
|
y: 6
|
|
width: 220
|
|
height: 220
|
|
fillMode: Image.PreserveAspectFit
|
|
// D2 (contract 04 §4): the small feed is now the thumbnail
|
|
// variant (150px), too small for a 220px preview — prefer the
|
|
// size-resolved large feed, fall back to the small one. The
|
|
// request below asks with 2x DPR headroom (440 -> the 600
|
|
// bucket).
|
|
source: QbzPlayer.npArtworkPathLarge !== ""
|
|
? QbzPlayer.npArtworkPathLarge : QbzPlayer.npArtworkPath
|
|
asynchronous: true
|
|
smooth: true
|
|
mipmap: true
|
|
}
|
|
}
|
|
|
|
// Ask for the large feed while the preview is up (bucketed in Rust —
|
|
// repeated shows of the same track at the same size are no-ops).
|
|
onVisibleChanged: if (visible) QbzPlayer.requestNpArtworkSize(440)
|
|
}
|