feat: refresh views on all playlist mutations

- Add EV_PLAYLIST_TRACK_ADDED (22) — emitted when a track is
  successfully added to a playlist
- If the currently-open playlist is the one modified, re-fetch it
  so the track appears in the list immediately
- After creating a playlist, open it automatically so the user
  lands in the new (empty) playlist view right away
- Sidebar already refreshes on create/delete; this ensures the
  track list view also stays in sync

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
joren
2026-03-24 11:23:45 +01:00
parent f30e2058c1
commit 75e2b623b8
6 changed files with 26 additions and 7 deletions

View File

@@ -33,6 +33,7 @@ enum QobuzEvent {
EV_GENERIC_ERR = 19, EV_GENERIC_ERR = 19,
EV_PLAYLIST_CREATED = 20, EV_PLAYLIST_CREATED = 20,
EV_PLAYLIST_DELETED = 21, EV_PLAYLIST_DELETED = 21,
EV_PLAYLIST_TRACK_ADDED = 22,
}; };
// Callback signature // Callback signature

View File

@@ -562,6 +562,7 @@ pub unsafe extern "C" fn qobuz_backend_remove_fav_album(ptr: *mut Backend, album
pub const EV_PLAYLIST_CREATED: c_int = 20; pub const EV_PLAYLIST_CREATED: c_int = 20;
pub const EV_PLAYLIST_DELETED: c_int = 21; pub const EV_PLAYLIST_DELETED: c_int = 21;
pub const EV_PLAYLIST_TRACK_ADDED: c_int = 22;
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn qobuz_backend_create_playlist(ptr: *mut Backend, name: *const c_char) { pub unsafe extern "C" fn qobuz_backend_create_playlist(ptr: *mut Backend, name: *const c_char) {
@@ -601,8 +602,10 @@ pub unsafe extern "C" fn qobuz_backend_add_track_to_playlist(
let client = inner.client.clone(); let client = inner.client.clone();
let cb = inner.cb; let ud = inner.ud; let cb = inner.cb; let ud = inner.ud;
spawn(inner, async move { spawn(inner, async move {
if let Err(e) = client.lock().await.add_track_to_playlist(playlist_id, track_id).await { match client.lock().await.add_track_to_playlist(playlist_id, track_id).await {
call_cb(cb, ud, EV_GENERIC_ERR, &err_json(&e.to_string())); Ok(()) => call_cb(cb, ud, EV_PLAYLIST_TRACK_ADDED,
&serde_json::json!({"playlist_id": playlist_id}).to_string()),
Err(e) => call_cb(cb, ud, EV_GENERIC_ERR, &err_json(&e.to_string())),
} }
}); });
} }

View File

@@ -241,6 +241,9 @@ void QobuzBackend::onEvent(int eventType, const QString &json)
case 21: // EV_PLAYLIST_DELETED case 21: // EV_PLAYLIST_DELETED
emit playlistDeleted(obj); emit playlistDeleted(obj);
break; break;
case 22: // EV_PLAYLIST_TRACK_ADDED
emit playlistTrackAdded(static_cast<qint64>(obj["playlist_id"].toDouble()));
break;
case EV_GENERIC_ERR: case EV_GENERIC_ERR:
case EV_TRACK_URL_ERR: case EV_TRACK_URL_ERR:
emit error(obj["error"].toString()); emit error(obj["error"].toString());

View File

@@ -78,6 +78,7 @@ signals:
void playlistLoaded(const QJsonObject &playlist); void playlistLoaded(const QJsonObject &playlist);
void playlistCreated(const QJsonObject &playlist); void playlistCreated(const QJsonObject &playlist);
void playlistDeleted(const QJsonObject &result); void playlistDeleted(const QJsonObject &result);
void playlistTrackAdded(qint64 playlistId);
// favorites // favorites
void favTracksLoaded(const QJsonObject &result); void favTracksLoaded(const QJsonObject &result);

View File

@@ -30,6 +30,7 @@ namespace List
/// Set which playlist is currently displayed (0 = none). /// Set which playlist is currently displayed (0 = none).
void setPlaylistContext(qint64 playlistId); void setPlaylistContext(qint64 playlistId);
qint64 playlistId() const { return m_playlistId; }
/// Provide the user's playlist list for the "Add to playlist" submenu. /// Provide the user's playlist list for the "Add to playlist" submenu.
void setUserPlaylists(const QVector<QPair<qint64, QString>> &playlists); void setUserPlaylists(const QVector<QPair<qint64, QString>> &playlists);

View File

@@ -80,7 +80,13 @@ MainWindow::MainWindow(QobuzBackend *backend, QWidget *parent)
connect(m_backend, &QobuzBackend::playlistLoaded, this, &MainWindow::onPlaylistLoaded); connect(m_backend, &QobuzBackend::playlistLoaded, this, &MainWindow::onPlaylistLoaded);
connect(m_backend, &QobuzBackend::playlistCreated, this, &MainWindow::onPlaylistCreated); connect(m_backend, &QobuzBackend::playlistCreated, this, &MainWindow::onPlaylistCreated);
connect(m_backend, &QobuzBackend::playlistDeleted, this, [this](const QJsonObject &) { connect(m_backend, &QobuzBackend::playlistDeleted, this, [this](const QJsonObject &) {
statusBar()->showMessage(tr("Playlist deleted"), 3000); // status bar message is also shown by library's openPlaylistDeleted handler
});
connect(m_backend, &QobuzBackend::playlistTrackAdded, this, [this](qint64 playlistId) {
// Refresh the currently shown playlist if a track was added to it
if (m_content->tracksList()->playlistId() == playlistId)
m_backend->getPlaylist(playlistId);
statusBar()->showMessage(tr("Track added to playlist"), 3000);
}); });
connect(m_backend, &QobuzBackend::trackChanged, this, &MainWindow::onTrackChanged); connect(m_backend, &QobuzBackend::trackChanged, this, &MainWindow::onTrackChanged);
connect(m_backend, &QobuzBackend::error, this, [this](const QString &msg) { connect(m_backend, &QobuzBackend::error, this, [this](const QString &msg) {
@@ -337,8 +343,12 @@ void MainWindow::onSearchToggled(bool visible)
void MainWindow::onPlaylistCreated(const QJsonObject &playlist) void MainWindow::onPlaylistCreated(const QJsonObject &playlist)
{ {
statusBar()->showMessage( const QString name = playlist["name"].toString();
tr("Playlist '%1' created").arg(playlist["name"].toString()), 4000); statusBar()->showMessage(tr("Playlist '%1' created").arg(name), 4000);
// Open the new playlist immediately
const qint64 id = static_cast<qint64>(playlist["id"].toDouble());
if (id > 0)
m_backend->getPlaylist(id);
} }
void MainWindow::onUserPlaylistsChanged(const QVector<QPair<qint64, QString>> &playlists) void MainWindow::onUserPlaylistsChanged(const QVector<QPair<qint64, QString>> &playlists)