Un-following a Qobuz playlist left it in the sidebar and in My Library. toggle_follow called unsubscribe_playlist and settled the ownership snapshot and stopped there, so the row only left at the next full refetch. Both surfaces are patched directly now, in both directions: following from a card buys the metadata with one get_playlist rather than re-reading getUserPlaylists, which lags the write. The un-follow collapses a hearted-and-followed playlist to the one row the next load will actually produce instead of dropping it, because the local heart is a library.db flag that survives the unsubscribe — removing every row made it vanish and come back, which is the original complaint wearing the other shoe. The Plex mark on album cards was a hard-drive glyph tinted accent — a blue hard drive — and the three Qobuz kinds drew no badge at all. The badge now ports discover/AlbumCard.slint:326-354 exactly: 24x24 at radius 4 pinned bottom-right with a 6px inset, plex-logo untinted at 16, qobuz-logo at 18 (22 for a download), the purchase arm gold on its amber chip, hard-drive white at 14 for local only. The brand marks are plain Images: routing them through QbzIcon floods every pixel with the tint and flattens a logo to a silhouette. SourceIcon moves to controls/ since it is no longer local-only, and every other surface drawing a hard-drive was audited against its .slint. The local album detail loses the two nav chevrons above the art. They are a Tauri-era leftover from before the app had global navigation. My QBZ used a bespoke card in the grid. MyQbzDetailCard is deleted and the standard cards/AlbumCard is mounted with its overlay. localMode bundled four separate things — action routing, the heart, the pin and Block this album — so a multi-source container had to switch all four off together; it is split, and the catalog affordances now follow the ITEM. On a Qobuz cell the heart works through the shared favourite seam; on a track, playlist, local or Plex cell it is absent rather than dead. Row covers carry two rungs: the list keeps _50, the grid gets _600. Not the _230 that would merely cover a 200px card — the complaint was that the cover reads softer than a normal AlbumCard, and a normal AlbumCard is fed image.large, which IS _600. _200 is not a rung the CDN serves at all (it answers 404). The My QBZ grid sets reuseItems, and AlbumCard assigns to its own isFavorite and isPinned when toggled, which destroys the binding that fed them. A recycled delegate therefore showed the previous row's heart and the click added the new album while the glyph said remove. Restored with the Qt.binding idiom this port already uses on TrackCard, PlaylistCard and TrackRow. The details view no longer force-opens every row on entry, and the per-row open state persists. Library > Artists showed placeholders for nearly every portrait. The side panel never reported its artwork window — the one caller of libraryArtworkWindow is LibraryView.reportWindow, and the panel had no report call at all, so no key ever reached the resolver and artMap stayed empty for its rows. The rail now reports through that same path, with the section-header sentinel reportWindow already skips. Note the reference has no portrait fallback either: an artist Qobuz serves no image for is a placeholder on both sides. cc
119 lines
3.9 KiB
QML
119 lines
3.9 KiB
QML
// Local album version picker (album/LocalAlbumView.slint:41 VersionPicker) —
|
|
// shown only when an album has several PHYSICAL copies (distinct source
|
|
// folders), so two copies never merge into a duplicated track list.
|
|
//
|
|
// Sized like QbzSelect `sm` (30px, radius 6, 10px left pad) so it reads as
|
|
// one of the small selects rather than towering over them: source icon +
|
|
// label + chevron, with a 280px dropdown that repeats the icon and ticks the
|
|
// current entry.
|
|
|
|
import QtQuick
|
|
import com.blitzfc.qbz
|
|
import "../../controls"
|
|
import "../../theme"
|
|
|
|
Rectangle {
|
|
id: root
|
|
|
|
/// [{ label, source }]
|
|
property var versions: []
|
|
property int current: 0
|
|
signal picked(int index)
|
|
|
|
QbzTheme { id: theme }
|
|
|
|
readonly property var currentVersion: versions[current] || ({})
|
|
|
|
height: 30
|
|
width: row.width
|
|
radius: 6
|
|
color: pickArea.containsMouse ? theme.surfaceHover : theme.surfaceElevated
|
|
|
|
Row {
|
|
id: row
|
|
height: parent.height
|
|
leftPadding: 10
|
|
rightPadding: 8
|
|
spacing: 7
|
|
SourceIcon {
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
kind: root.currentVersion.source || "local"
|
|
// No size overrides on purpose: LocalAlbumView.slint:24-26 draws
|
|
// ALL THREE kinds at a flat 14px here, which is SourceIcon's
|
|
// default (the row glyphs are the ones that grow the marks).
|
|
}
|
|
Text {
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
text: root.currentVersion.label || ""
|
|
color: theme.textSecondary
|
|
font.pixelSize: theme.fontLegal
|
|
}
|
|
QbzIcon {
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
name: "chevron-down"
|
|
width: 12
|
|
height: 12
|
|
tintName: "muted"
|
|
}
|
|
}
|
|
MouseArea {
|
|
id: pickArea
|
|
anchors.fill: parent
|
|
hoverEnabled: true
|
|
cursorShape: Qt.PointingHandCursor
|
|
onClicked: menu.openBelowRight(pickArea)
|
|
}
|
|
|
|
QbzContextMenu {
|
|
id: menu
|
|
menuWidth: 280
|
|
Repeater {
|
|
model: root.versions
|
|
delegate: Rectangle {
|
|
id: opt
|
|
required property var modelData
|
|
required property int index
|
|
width: parent ? parent.width : 0
|
|
height: 30
|
|
radius: 6
|
|
color: index === root.current ? theme.surfaceElevated
|
|
: optArea.containsMouse ? theme.surfaceHover : "transparent"
|
|
Row {
|
|
anchors.fill: parent
|
|
anchors.leftMargin: 8
|
|
anchors.rightMargin: 8
|
|
spacing: 8
|
|
SourceIcon {
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
kind: opt.modelData.source || "local"
|
|
}
|
|
Text {
|
|
width: parent.width - 22 - (opt.index === root.current ? 20 : 0)
|
|
height: parent.height
|
|
text: opt.modelData.label || ""
|
|
color: theme.textPrimary
|
|
font.pixelSize: theme.fontLegal
|
|
verticalAlignment: Text.AlignVCenter
|
|
elide: Text.ElideRight
|
|
}
|
|
QbzIcon {
|
|
visible: opt.index === root.current
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
name: "check"
|
|
width: 12
|
|
height: 12
|
|
tintName: "accent"
|
|
}
|
|
}
|
|
MouseArea {
|
|
id: optArea
|
|
anchors.fill: parent
|
|
hoverEnabled: true
|
|
cursorShape: Qt.PointingHandCursor
|
|
onClicked: { menu.close(); root.picked(opt.index) }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|