feat(qt): the Releases list shows each release's label, and album menus open it

Library feed album items carry the catalog label id next to its name.
Library > Releases (list) gains a LABEL column between the item and its
quality — a link to the label page when the id is known, muted text
otherwise — hidden on the label page itself and on narrow kiosk rows.
AlbumListRow and AlbumCard menus gain "View label" (the card only where its
host passes the id: the library grid does). The library's release-wide
availability helper is shared with the playlist rows for the next change.

cc
This commit is contained in:
vicrodh committed 2026-09-13 20:26:11 -06:00
1 parent 22e064f340
commit 81c8d3908e
6 files changed
+64 -4

No files matched your search

@@ -27,6 +27,10 @@ Rectangle {
// AlbumListCols: art 52, quality 150, year 64, overflow 36, gap 12.
readonly property int colArt: 52
/// The release's label, between the item and its quality (2026-09-13);
/// off on the label page itself, where every row would repeat the same.
property bool showLabel: true
readonly property int colLabel: showLabel ? 150 : 0
readonly property int colQuality: 150
readonly property int colYear: 64
readonly property int colOverflow: 36
@@ -56,10 +60,16 @@ Rectangle {
ColLabel {
width: parent.width - root.colArt - root.colQuality - root.colYear
- root.colOverflow - 4 * root.colGap
- (root.showLabel ? root.colLabel + root.colGap : 0)
- (root.selectMode ? 18 + root.colGap : 0)
text: QbzSession.tr("ITEM", QbzSession.trRev)
elide: Text.ElideRight
}
ColLabel {
visible: root.showLabel
width: root.colLabel
text: QbzSession.tr("LABEL", QbzSession.trRev)
}
ColLabel {
width: root.colQuality
text: QbzSession.tr("QUALITY", QbzSession.trRev)
+36 -2
View File
@@ -76,6 +76,9 @@ Rectangle {
// Same columns (and widths) as AlbumListHeader.qml.
readonly property int colArt: 52
/// See AlbumListHeader.showLabel.
property bool showLabel: true
readonly property int colLabel: (!root.showLabel || (root.kioskHost && width < 500)) ? 0 : 150
readonly property int colQuality: root.kioskHost && width < 500 ? 0 : 150
readonly property int colYear: root.kioskHost && width < 500 ? 0 : 64
readonly property int colOverflow: root.kioskHost ? 44 : 36
@@ -107,7 +110,7 @@ Rectangle {
return
}
if (root.selectMode) root.toggleSelect(mouse.modifiers)
else if (!root.pulledDead) QbzAlbum.openAlbum(root.item.id || "")
else if (!root.pulledDead) QbzAlbum.openAlbumFrom(root.item.id || "", root.item.title || "", root.item.artist || "")
}
// Touch has no right button. Desktop-inert: `pressAndHold` never
// fires for a mouse press that is released normally, and the guard
@@ -160,13 +163,17 @@ Rectangle {
}
if (!root.pulledDead && root.catalogRow)
m.push({ "label": t("Block this album", r), "icon": "blind-eye", "action": "block" })
// The label page outlives a pulled release, so this one stays.
if ((root.item.labelId || "") !== "")
m.push({ "label": t("View label", r), "icon": "tags", "action": "view-label" })
return m
}
function menuAction(a) {
var id = root.item.id || ""
if (id === "") return
if (a === "view-label") { QbzHome.openLabel(root.item.labelId || ""); return }
if (root.pulledDead) return
if (a === "open") QbzAlbum.openAlbum(id)
if (a === "open") QbzAlbum.openAlbumFrom(id, root.item.title || "", root.item.artist || "")
else if (a === "play") QbzPlayer.playAlbum(id)
// `artUrl`, never `artPath`: the store keeps a denormalized cover url
// and a file:// cache path is dead on any other machine.
@@ -274,6 +281,7 @@ Rectangle {
// multi-select is switched on.
width: parent.width - root.colArt - root.colQuality - root.colYear
- root.colOverflow - 4 * root.colGap
- (root.colLabel > 0 ? root.colLabel + root.colGap : 0)
- (root.selectMode ? 18 + root.colGap : 0)
anchors.verticalCenter: parent.verticalCenter
spacing: 2
@@ -305,6 +313,32 @@ Rectangle {
}
}
// LABEL — the release's label, a link to its page when the feed
// carries the id (2026-09-13). Zero-width (and skipped by the Row)
// where the column is off.
Item {
visible: root.colLabel > 0
width: root.colLabel
height: parent.height
Text {
id: labelText
width: parent.width
anchors.verticalCenter: parent.verticalCenter
text: root.item.label || ""
color: labelArea.containsMouse && labelArea.enabled ? theme.accent : theme.textMuted
font.pixelSize: 12
elide: Text.ElideRight
MouseArea {
id: labelArea
anchors.fill: parent
enabled: (root.item.labelId || "") !== ""
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: QbzHome.openLabel(root.item.labelId)
}
}
}
// QUALITY — the SAME badge the album page shows (tier label over the
// exact bit-depth / sample-rate line).
Item {
+1 -1
View File
@@ -213,7 +213,7 @@ Rectangle {
height: root.kioskHost && (cr.kind === "album" || cr.kind === "playlist") ? 64 : 246
KioskCoverSource { id: cellArt; remote: root.kioskHost ? (crCell.modelData.artUrl || "") : ""; local: crCell.modelData.artPath || ""; edge: 44 }
Component { id: crKioskAlbum; AlbumListRow { kioskHost: true; item: crCell.modelData; artSource: root.kioskHost ? cellArt.source : (crCell.modelData.artPath || "") } }
Component { id: crKioskAlbum; AlbumListRow { kioskHost: true; showLabel: false; item: crCell.modelData; artSource: root.kioskHost ? cellArt.source : (crCell.modelData.artPath || "") } }
Component { id: crKioskPlaylist; PlaylistListRow { kioskHost: true; item: crCell.modelData; artSource: root.kioskHost ? cellArt.source : (crCell.modelData.artPath || "") } }
Component {
id: crAlbum
@@ -88,6 +88,7 @@ Item {
title: cell.item.title
artist: cell.item.artist
artistId: cell.item.artistId
labelId: cell.item.labelId || ""
genre: cell.item.genre
year: cell.item.year
qualityTier: cell.item.qualityTier