refactor(qbz-qt): split QbzAlbum and QbzArtist out of the God-object

Two singletons rather than one merged object, per the owner: each maps to the
view it backs. Registering them and deleting the duplicates from bridge.rs is
one change, because wiring one without removing the other compiles fine and
leaves two independent states with the view frozen and nothing in the log.

view_param_id goes with them. It had no consumer in QML, verified, and none in
Rust once the two opens stopped writing it — so it is deleted rather than
carried into a new bridge for symmetry's sake.

bridge.rs is down to three domains: settings, search and playlist.

cc
This commit is contained in:
vicrodh committed 2026-07-28 15:24:38 -06:00
1 parent e8a821dd9e
commit ade156a72a
14 files changed
+273 -104

No files matched your search

+6 -6
View File
@@ -34,7 +34,7 @@ Rectangle {
QbzTheme { id: theme }
// The view's album + url-keyed cover map (artwork pipeline).
readonly property var album: JSON.parse(QbzBridge.albumJson)
readonly property var album: JSON.parse(QbzAlbum.albumJson)
readonly property var header: album.header || ({})
readonly property var tracks: album.tracks || []
readonly property var awards: album.awards || []
@@ -234,7 +234,7 @@ Rectangle {
enabled: modelData[1] !== ""
hoverEnabled: true
cursorShape: modelData[1] !== "" ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: QbzBridge.openArtist(modelData[1])
onClicked: QbzArtist.openArtist(modelData[1])
}
}
Text {
@@ -384,7 +384,7 @@ Rectangle {
// Loading.
Item {
visible: QbzBridge.albumLoading && tracks.length === 0
visible: QbzAlbum.albumLoading && tracks.length === 0
width: parent.width
height: 280
Column {
@@ -402,7 +402,7 @@ Rectangle {
// Toolbar — quality badge + track search (+ inert select).
Row {
visible: !QbzBridge.albumLoading
visible: !QbzAlbum.albumLoading
width: parent.width
height: 52
spacing: 16
@@ -494,7 +494,7 @@ Rectangle {
// Column header.
Row {
visible: !QbzBridge.albumLoading
visible: !QbzAlbum.albumLoading
width: parent.width
height: 40
leftPadding: 12
@@ -567,7 +567,7 @@ Rectangle {
enabled: modelData.workComposerId !== ""
hoverEnabled: true
cursorShape: modelData.workComposerId !== "" ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: QbzBridge.openArtist(modelData.workComposerId)
onClicked: QbzArtist.openArtist(modelData.workComposerId)
}
}
Text {
+11 -11
View File
@@ -35,7 +35,7 @@ Rectangle {
QbzTheme { id: theme }
readonly property var artist: JSON.parse(QbzBridge.artistJson)
readonly property var artist: JSON.parse(QbzArtist.artistJson)
readonly property var topTracks: artist.topTracks || []
readonly property var appearsOn: artist.appearsOn || []
readonly property var releaseSections: artist.releaseSections || []
@@ -67,7 +67,7 @@ Rectangle {
}
// Two blocks, not one: artwork is QbzLibrary's signal and the releases
// pager is still QbzBridge's. Retargeting a mixed block wholesale would
// pager is QbzArtist's. Retargeting a mixed block wholesale would
// silently orphan the other half — QML resolves handlers lazily, so the
// discography would just stop loading with nothing in the log.
Connections {
@@ -80,7 +80,7 @@ Rectangle {
}
Connections {
target: QbzBridge
target: QbzArtist
function onReleaseSectionReady(releaseType, cardsJson, hasMore) {
var cards = JSON.parse(cardsJson)
var sections = root.releaseSections
@@ -273,7 +273,7 @@ Rectangle {
enabled: row.albumId !== ""
hoverEnabled: true
cursorShape: row.albumId !== "" ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: QbzBridge.openAlbum(row.albumId)
onClicked: QbzAlbum.openAlbum(row.albumId)
}
}
Text {
@@ -501,7 +501,7 @@ Rectangle {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: QbzBridge.loadReleaseSection(artist.id, section.releaseType, section.cards.length)
onClicked: QbzArtist.loadReleaseSection(artist.id, section.releaseType, section.cards.length)
}
}
Item { width: (parent.width - loadMoreBtn.width) / 2; height: 1 }
@@ -740,7 +740,7 @@ Rectangle {
// --- Loading -------------------------------------------------
Item {
visible: QbzBridge.artistLoading && topTracks.length === 0
visible: QbzArtist.artistLoading && topTracks.length === 0
width: parent.width - 64
height: 280
Column {
@@ -759,7 +759,7 @@ Rectangle {
// ================= Catalog tab ================================
Column {
id: sectionAnchors
visible: root.artistTab === "catalog" && !QbzBridge.artistLoading
visible: root.artistTab === "catalog" && !QbzArtist.artistLoading
width: parent.width - 64
spacing: 0
@@ -1050,7 +1050,7 @@ Rectangle {
// ================= In library tab =============================
Column {
id: libraryTab
visible: root.artistTab === "library" && !QbzBridge.artistLoading
visible: root.artistTab === "library" && !QbzArtist.artistLoading
width: parent.width - 64
spacing: 0
readonly property var libItems: {
@@ -1265,7 +1265,7 @@ Rectangle {
}
// SIMILAR ARTISTS.
Column {
visible: similarArtists.length > 0 || QbzBridge.artistLoading
visible: similarArtists.length > 0 || QbzArtist.artistLoading
width: parent.width
leftPadding: 14
rightPadding: 14
@@ -1280,7 +1280,7 @@ Rectangle {
font.letterSpacing: 0.5
}
Text {
visible: similarArtists.length === 0 && QbzBridge.artistLoading
visible: similarArtists.length === 0 && QbzArtist.artistLoading
text: QbzSession.tr("Loading…", QbzSession.trRev)
color: theme.textMuted
font.pixelSize: 12
@@ -1290,7 +1290,7 @@ Rectangle {
delegate: SidebarLink {
label: modelData.name
iconName: "user"
onClicked: QbzBridge.openArtist(modelData.id)
onClicked: QbzArtist.openArtist(modelData.id)
}
}
}
+9 -9
View File
@@ -311,8 +311,8 @@ Rectangle {
else if (a === "next") QbzPlayer.enqueueTrack(item.id, "next")
else if (a === "later") QbzPlayer.enqueueTrack(item.id, "later")
else if (a === "queue") QbzPlayer.enqueueTrack(item.id, "queue")
else if (a === "go-artist") QbzBridge.openArtist(item.artistId)
else if (a === "go-album") QbzBridge.openAlbum(item.albumId)
else if (a === "go-artist") QbzArtist.openArtist(item.artistId)
else if (a === "go-album") QbzAlbum.openAlbum(item.albumId)
else if (a === "favorite") {
item.isFavorite = !item.isFavorite
QbzLibrary.libraryToggleFavorite("track", item.id)
@@ -335,8 +335,8 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (item.kind === "track") QbzPlayer.playTrack(item.id)
else if (item.kind === "album") QbzBridge.openAlbum(item.id)
else if (item.kind === "artist") QbzBridge.openArtist(item.id)
else if (item.kind === "album") QbzAlbum.openAlbum(item.id)
else if (item.kind === "artist") QbzArtist.openArtist(item.id)
// playlist/label pages: out of scope (POC-NOTE).
}
}
@@ -418,8 +418,8 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onClicked: {
if (item.kind === "track") QbzPlayer.playTrack(item.id)
else if (item.kind === "album") QbzBridge.openAlbum(item.id)
else if (item.kind === "artist") QbzBridge.openArtist(item.id)
else if (item.kind === "album") QbzAlbum.openAlbum(item.id)
else if (item.kind === "artist") QbzArtist.openArtist(item.id)
}
}
}
@@ -439,7 +439,7 @@ Rectangle {
hoverEnabled: true
cursorShape: (item.artistId !== "" && (item.kind === "track" || item.kind === "album"))
? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: if (item.artistId !== "") QbzBridge.openArtist(item.artistId)
onClicked: if (item.artistId !== "") QbzArtist.openArtist(item.artistId)
}
}
}
@@ -549,12 +549,12 @@ Rectangle {
onPicked: function (a) {
if (item.kind === "track") { root.trackAction(item, a); return }
if (a === "open") {
if (item.kind === "album") QbzBridge.openAlbum(item.id)
if (item.kind === "album") QbzAlbum.openAlbum(item.id)
// playlist/label pages: out of scope (POC-NOTE).
} else if (a === "play") {
if (item.kind === "album") QbzPlayer.playAlbum(item.id)
} else if (a === "go-artist") {
QbzBridge.openArtist(item.id)
QbzArtist.openArtist(item.id)
} else if (a === "favorite") {
item.isFavorite = !item.isFavorite
QbzLibrary.libraryToggleFavorite(item.kind, item.id)