feat: full artist release list via artist/getReleasesList

Instead of relying on the limited preview in artist/page, fire a
separate artist/getReleasesList request per release type (album,
epSingle, live, compilation) in parallel when loading an artist.
Each result updates its section independently as it arrives, so the
page populates progressively without a single large request.

Also fixes the artist name in the status bar (was reading wrong field).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
joren
2026-03-25 13:53:57 +01:00
parent 6f11b364aa
commit 5ae18afa08
10 changed files with 107 additions and 27 deletions

View File

@@ -61,6 +61,12 @@ void QobuzBackend::getArtist(qint64 artistId)
qobuz_backend_get_artist(m_backend, artistId);
}
void QobuzBackend::getArtistReleases(qint64 artistId, const QString &releaseType, quint32 limit, quint32 offset)
{
qobuz_backend_get_artist_releases(m_backend, artistId,
releaseType.toUtf8().constData(), limit, offset);
}
void QobuzBackend::getPlaylist(qint64 playlistId, quint32 offset, quint32 limit)
{
qobuz_backend_get_playlist(m_backend, playlistId, offset, limit);
@@ -242,6 +248,9 @@ void QobuzBackend::onEvent(int eventType, const QString &json)
case EV_ARTIST_OK:
emit artistLoaded(obj);
break;
case 24: // EV_ARTIST_RELEASES_OK
emit artistReleasesLoaded(obj["release_type"].toString(), obj["items"].toArray());
break;
case EV_ARTIST_ERR:
emit error(obj["error"].toString());
break;

View File

@@ -4,6 +4,7 @@
#include <QObject>
#include <QString>
#include <QJsonArray>
#include <QJsonObject>
#include <QTimer>
@@ -29,6 +30,7 @@ public:
void search(const QString &query, quint32 offset = 0, quint32 limit = 20);
void getAlbum(const QString &albumId);
void getArtist(qint64 artistId);
void getArtistReleases(qint64 artistId, const QString &releaseType, quint32 limit = 500, quint32 offset = 0);
void getPlaylist(qint64 playlistId, quint32 offset = 0, quint32 limit = 500);
// --- favorites ---
@@ -83,6 +85,7 @@ signals:
void searchResult(const QJsonObject &result);
void albumLoaded(const QJsonObject &album);
void artistLoaded(const QJsonObject &artist);
void artistReleasesLoaded(const QString &releaseType, const QJsonArray &items);
void playlistLoaded(const QJsonObject &playlist);
void playlistCreated(const QJsonObject &playlist);
void playlistDeleted(const QJsonObject &result);

View File

@@ -84,6 +84,8 @@ MainWindow::MainWindow(QobuzBackend *backend, QWidget *parent)
connect(m_backend, &QobuzBackend::favArtistsLoaded, this, &MainWindow::onFavArtistsLoaded);
connect(m_backend, &QobuzBackend::albumLoaded, this, &MainWindow::onAlbumLoaded);
connect(m_backend, &QobuzBackend::artistLoaded, this, &MainWindow::onArtistLoaded);
connect(m_backend, &QobuzBackend::artistReleasesLoaded,
m_content, &MainContent::updateArtistReleases);
connect(m_backend, &QobuzBackend::playlistLoaded, this, &MainWindow::onPlaylistLoaded);
connect(m_backend, &QobuzBackend::playlistCreated, this, &MainWindow::onPlaylistCreated);
connect(m_backend, &QobuzBackend::playlistDeleted, this, [this](const QJsonObject &) {
@@ -334,7 +336,7 @@ void MainWindow::onArtistLoaded(const QJsonObject &artist)
{
m_content->showArtist(artist);
statusBar()->showMessage(
tr("Artist: %1").arg(artist["name"].toString()), 4000);
tr("Artist: %1").arg(artist["name"].toObject()["display"].toString()), 4000);
}
void MainWindow::onPlaylistLoaded(const QJsonObject &playlist)
@@ -358,6 +360,9 @@ void MainWindow::onSearchAlbumSelected(const QString &albumId)
void MainWindow::onSearchArtistSelected(qint64 artistId)
{
m_backend->getArtist(artistId);
// Fire release-type requests in parallel — each updates its section when it arrives
for (const char *type : {"album", "epSingle", "live", "compilation"})
m_backend->getArtistReleases(artistId, QString::fromLatin1(type));
statusBar()->showMessage(tr("Loading artist…"));
}

View File

@@ -195,32 +195,29 @@ void ArtistView::setArtist(const QJsonObject &artist)
m_topTracks->loadTracks(topTracks);
m_topTracksSection->setVisible(!topTracks.isEmpty());
// releases is an array of {type, has_more, items[]}
const QJsonArray releases = artist["releases"].toArray();
QJsonArray albums, eps, live, compilations;
for (const QJsonValue &rv : releases) {
const QJsonObject rg = rv.toObject();
const QString type = rg["type"].toString();
const QJsonArray items = rg["items"].toArray();
if (type == QStringLiteral("album"))
albums = items;
else if (type == QStringLiteral("epSingle"))
eps = items;
else if (type == QStringLiteral("live"))
live = items;
else if (type == QStringLiteral("compilation"))
compilations = items;
}
m_secAlbums->setAlbums(albums);
m_secEps->setAlbums(eps);
m_secLive->setAlbums(live);
m_secCompilations->setAlbums(compilations);
// Release sections are populated asynchronously via setReleases().
// Clear them now so stale data from a previous artist isn't shown.
m_secAlbums->setAlbums({});
m_secEps->setAlbums({});
m_secLive->setAlbums({});
m_secCompilations->setAlbums({});
m_secOther->setAlbums({});
m_secAlbums->setVisible(!m_secAlbums->isEmpty());
m_secEps->setVisible(!m_secEps->isEmpty());
m_secLive->setVisible(!m_secLive->isEmpty());
m_secCompilations->setVisible(!m_secCompilations->isEmpty());
m_secAlbums->setVisible(false);
m_secEps->setVisible(false);
m_secLive->setVisible(false);
m_secCompilations->setVisible(false);
m_secOther->setVisible(false);
}
void ArtistView::setReleases(const QString &releaseType, const QJsonArray &items)
{
ArtistSection *sec = nullptr;
if (releaseType == QStringLiteral("album")) sec = m_secAlbums;
else if (releaseType == QStringLiteral("epSingle")) sec = m_secEps;
else if (releaseType == QStringLiteral("live")) sec = m_secLive;
else if (releaseType == QStringLiteral("compilation")) sec = m_secCompilations;
else sec = m_secOther;
sec->setAlbums(items);
sec->setVisible(!sec->isEmpty());
}

View File

@@ -45,6 +45,8 @@ public:
explicit ArtistView(QobuzBackend *backend, PlayQueue *queue, QWidget *parent = nullptr);
void setArtist(const QJsonObject &artist);
/// Update a specific release section when getReleasesList responds.
void setReleases(const QString &releaseType, const QJsonArray &items);
signals:
void albumSelected(const QString &albumId);

View File

@@ -107,3 +107,8 @@ void MainContent::showArtist(const QJsonObject &artist)
m_artistView->setArtist(artist);
m_stack->setCurrentIndex(4);
}
void MainContent::updateArtistReleases(const QString &releaseType, const QJsonArray &items)
{
m_artistView->setReleases(releaseType, items);
}

View File

@@ -31,6 +31,7 @@ public:
void showFavAlbums(const QJsonObject &result);
void showFavArtists(const QJsonObject &result);
void showArtist(const QJsonObject &artist);
void updateArtistReleases(const QString &releaseType, const QJsonArray &items);
signals:
void albumRequested(const QString &albumId);