feat(qt): queue and Listen list row menus offer Go to album and Go to artist

Both queue surfaces (the sidebar panel and the Listen list view) gain the
two entries, routed by source the way the local rows already do: a
catalog row opens the album through its catalog id, with its title and
artist riding along as the unavailable-page hint, and the artist by id; a
local row (file, Plex, Jellyfin, Subsonic) opens the album through the
queue's navigation key — the key local_playback stamps so it opens the
same page the card does — and the artist by name through the Local
Library Artists tab. A row without the key or the name shows no entry.

cc
This commit is contained in:
vicrodh committed 2026-09-14 00:39:47 -06:00
1 parent fed0816e9b
commit 2e984e14cd
2 files changed
+86

No files matched your search

+41
View File
@@ -316,6 +316,41 @@ Rectangle {
// Row action icon button (the panel's small IconButton).
// Go to album / Go to artist, by SOURCE (2026-09-14). A catalog row routes
// through its catalog ids (title and artist ride along as the
// unavailable-page hint); a local row — file, Plex, Jellyfin, Subsonic —
// through the queue's NAVIGATION KEY (local_playback.rs stamps the album
// key the card itself opens, prefixed for media servers) and the artist
// NAME into the Local Library Artists tab, the local surfaces' own routes
// (local/LocalTrackRow.qml). A row without the key or the name shows no
// entry.
function rowCanGoAlbum(row) {
return (row.albumId || "") !== ""
}
function rowCanGoArtist(row) {
return row.isLocal === true ? (row.artist || "") !== "" : (row.artistId || "") !== ""
}
function goToAlbum(row) {
if (!rowCanGoAlbum(row))
return
if (row.isLocal === true) {
QbzLocal.openAlbum(row.albumId)
QbzShell.navigateTo("localalbum")
} else {
QbzAlbum.openAlbumFrom(row.albumId, row.album || "", row.artist || "")
}
}
function goToArtist(row) {
if (!rowCanGoArtist(row))
return
if (row.isLocal === true) {
QbzLocal.openArtistByName(row.artist)
QbzShell.navigateTo("local")
} else {
QbzArtist.openArtist(row.artistId)
}
}
// One UP NEXT / History row (QueueRow.slint).
component QueueRow: Rectangle {
id: qrRoot
@@ -556,6 +591,10 @@ Rectangle {
: QbzSession.tr("Stop after this", QbzSession.trRev), "icon": "circle-stop", "action": "stop-after" },
{ "label": QbzSession.tr("Remove all after", QbzSession.trRev), "icon": "list-x", "action": "remove-after" },
]
if (root.rowCanGoAlbum(row))
items.push({ "label": QbzSession.tr("Go to album", QbzSession.trRev), "icon": "disc-3", "action": "go-album" })
if (root.rowCanGoArtist(row))
items.push({ "label": QbzSession.tr("Go to artist", QbzSession.trRev), "icon": "user", "action": "go-artist" })
if (row.isEphemeral !== true) {
// LOCAL/Plex rows drop it too: the queue's
// `add_to_playlist` refuses them
@@ -609,6 +648,8 @@ Rectangle {
else if (a === "add-to-playlist") QbzQueue.queueAddToPlaylist(rowIndex)
else if (a === "track-info") qrRoot.openTrackInfo()
else if (a === "favorite") root.toggleFav(row)
else if (a === "go-album") root.goToAlbum(row)
else if (a === "go-artist") root.goToArtist(row)
}
}
}
+45
View File
@@ -258,6 +258,41 @@ Rectangle {
return ""
}
// Go to album / Go to artist, by SOURCE (2026-09-14). A catalog row routes
// through its catalog ids (title and artist ride along as the
// unavailable-page hint); a local row — file, Plex, Jellyfin, Subsonic —
// through the queue's NAVIGATION KEY (local_playback.rs stamps the album
// key the card itself opens, prefixed for media servers) and the artist
// NAME into the Local Library Artists tab, the local surfaces' own routes
// (local/LocalTrackRow.qml). A row without the key or the name shows no
// entry.
function rowCanGoAlbum(row) {
return (row.albumId || "") !== ""
}
function rowCanGoArtist(row) {
return row.isLocal === true ? (row.artist || "") !== "" : (row.artistId || "") !== ""
}
function goToAlbum(row) {
if (!rowCanGoAlbum(row))
return
if (row.isLocal === true) {
QbzLocal.openAlbum(row.albumId)
QbzShell.navigateTo("localalbum")
} else {
QbzAlbum.openAlbumFrom(row.albumId, row.album || "", row.artist || "")
}
}
function goToArtist(row) {
if (!rowCanGoArtist(row))
return
if (row.isLocal === true) {
QbzLocal.openArtistByName(row.artist)
QbzShell.navigateTo("local")
} else {
QbzArtist.openArtist(row.artistId)
}
}
function queueMenu(row) {
var t = QbzSession.tr
var r = QbzSession.trRev
@@ -277,6 +312,12 @@ Rectangle {
? t("Cancel stop after this", r) : t("Stop after this", r),
"icon": "circle-stop", "action": "stop-after", "external": true })
}
if (root.rowCanGoAlbum(row))
items.push({ "label": t("Go to album", r), "icon": "disc-3",
"action": "go-album", "external": true })
if (root.rowCanGoArtist(row))
items.push({ "label": t("Go to artist", r), "icon": "user",
"action": "go-artist", "external": true })
if (row.isEphemeral !== true) {
if (row.isLocal !== true)
items.push({ "label": t("Add to playlist", r), "icon": "list-plus",
@@ -315,6 +356,10 @@ Rectangle {
QbzQueue.queueToggleStopAfter(row.id)
else if (action === "add-to-playlist")
QbzPlaylistPicker.openForTrack(row.id)
else if (action === "go-album")
root.goToAlbum(row)
else if (action === "go-artist")
root.goToArtist(row)
}
function historyVisualIndex(row) {