feat: artist/page endpoint, multi-disc fix, playlist ownership, UX improvements
- Switch artist view to artist/page API (proper sections: Albums, Singles & EPs, Live, Compilations; version in titles like "Deluxe") - Fix artist sections categorization using releases[].type from artist/page - Add getUser() backend call; fetch on session restore when userId=0 to fix playlist ownership (Remove from playlist / Delete playlist were missing) - Fix multi-disc double-click / Play Now queue start index (disc headers were counted in row index but excluded from currentTracksJson) - Hide redundant Album column when viewing an album - Make artist name in context header clickable (navigates to artist page) - Fix gap between title and artist name in context header (addStretch) - Fix queue panel track titles to include version field - Fix album list to show version in title column Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -35,24 +35,32 @@ Tracks::Tracks(QobuzBackend *backend, PlayQueue *queue, QWidget *parent)
|
||||
this, &Tracks::onDoubleClicked);
|
||||
connect(this, &QTreeView::customContextMenuRequested,
|
||||
this, &Tracks::onContextMenu);
|
||||
connect(m_model, &QAbstractItemModel::modelReset, this, [this] {
|
||||
for (int row : m_model->discHeaderRows())
|
||||
setFirstColumnSpanned(row, {}, true);
|
||||
setSortingEnabled(!m_model->hasMultipleDiscs());
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
void Tracks::loadTracks(const QJsonArray &tracks)
|
||||
{
|
||||
setPlaylistContext(0);
|
||||
setColumnHidden(TrackListModel::ColAlbum, false);
|
||||
m_model->setTracks(tracks, false, /*useSequential=*/true);
|
||||
}
|
||||
|
||||
void Tracks::loadAlbum(const QJsonObject &album)
|
||||
{
|
||||
setPlaylistContext(0);
|
||||
setColumnHidden(TrackListModel::ColAlbum, true);
|
||||
const QJsonArray items = album["tracks"].toObject()["items"].toArray();
|
||||
m_model->setTracks(items); // album: use track_number
|
||||
}
|
||||
|
||||
void Tracks::loadPlaylist(const QJsonObject &playlist)
|
||||
{
|
||||
setColumnHidden(TrackListModel::ColAlbum, false);
|
||||
const qint64 id = static_cast<qint64>(playlist["id"].toDouble());
|
||||
const qint64 ownId = static_cast<qint64>(playlist["owner"].toObject()["id"].toDouble());
|
||||
const qint64 myId = AppSettings::instance().userId();
|
||||
@@ -65,6 +73,7 @@ void Tracks::loadPlaylist(const QJsonObject &playlist)
|
||||
void Tracks::loadSearchTracks(const QJsonArray &tracks)
|
||||
{
|
||||
setPlaylistContext(0);
|
||||
setColumnHidden(TrackListModel::ColAlbum, false);
|
||||
m_model->setTracks(tracks, false, /*useSequential=*/true);
|
||||
}
|
||||
|
||||
@@ -118,7 +127,11 @@ void Tracks::onDoubleClicked(const QModelIndex &index)
|
||||
{
|
||||
const qint64 id = m_model->data(index, TrackListModel::TrackIdRole).toLongLong();
|
||||
if (id > 0) {
|
||||
m_queue->setContext(m_model->currentTracksJson(), index.row());
|
||||
// Compute filtered row (disc headers excluded from currentTracksJson)
|
||||
int filteredRow = 0;
|
||||
for (int r = 0; r < index.row(); ++r)
|
||||
if (!m_model->trackAt(r).isDiscHeader) ++filteredRow;
|
||||
m_queue->setContext(m_model->currentTracksJson(), filteredRow);
|
||||
emit playTrackRequested(id);
|
||||
}
|
||||
}
|
||||
@@ -129,6 +142,7 @@ void Tracks::onContextMenu(const QPoint &pos)
|
||||
if (!index.isValid()) return;
|
||||
|
||||
const qint64 id = m_model->data(index, TrackListModel::TrackIdRole).toLongLong();
|
||||
if (id <= 0) return; // disc header row
|
||||
const QJsonObject trackJson = m_model->data(index, TrackListModel::TrackJsonRole).toJsonObject();
|
||||
|
||||
QMenu menu(this);
|
||||
@@ -153,9 +167,12 @@ void Tracks::onContextMenu(const QPoint &pos)
|
||||
});
|
||||
}
|
||||
|
||||
const int row = index.row();
|
||||
connect(playNow, &QAction::triggered, this, [this, id, row] {
|
||||
m_queue->setContext(m_model->currentTracksJson(), row);
|
||||
// Compute filtered row for multi-disc albums (disc headers excluded from currentTracksJson)
|
||||
int filteredRow = 0;
|
||||
for (int r = 0; r < index.row(); ++r)
|
||||
if (!m_model->trackAt(r).isDiscHeader) ++filteredRow;
|
||||
connect(playNow, &QAction::triggered, this, [this, id, filteredRow] {
|
||||
m_queue->setContext(m_model->currentTracksJson(), filteredRow);
|
||||
emit playTrackRequested(id);
|
||||
});
|
||||
connect(playNext, &QAction::triggered, this, [this, trackJson] {
|
||||
|
||||
Reference in New Issue
Block a user