feat(cms): extract all-releases grid as embeddable ALL-tab component (9.8.B)

CmsAllReleasesGrid self-loads the cross-medium release list so 8.A can host it as the ALL tab with no VM plumbing; TrackList's Albums mode renders it now. Preserves sort/delete/expand/edit and the 8.D Type chip.
This commit is contained in:
daniel-c-harvey
2026-06-13 21:26:43 -04:00
parent 2991d9ec5d
commit e78a61c3b1
4 changed files with 77 additions and 30 deletions
@@ -28,34 +28,23 @@ public class CmsTrackBrowserViewModel
public BrowseMode Mode { get; private set; } = BrowseMode.Tracks;
// Album mode.
public IReadOnlyList<ReleaseDto> Albums { get; private set; } = Array.Empty<ReleaseDto>();
public bool AlbumsLoading { get; private set; }
// Genre mode.
public IReadOnlyList<GenreSummaryDto> Genres { get; private set; } = Array.Empty<GenreSummaryDto>();
public bool GenresLoading { get; private set; }
public string? ExpandedGenre { get; private set; }
/// <summary>
/// Switch the active mode, lazily loading the album or genre dataset on first entry. Collapses
/// any expanded genre row. The grid in Track mode owns its own data, so no fetch happens there.
/// Switch the active mode, lazily loading the genre dataset on first entry into Genre mode and
/// collapsing any expanded genre row. Track mode and the all-releases grid (Albums mode) each own
/// their own data — the grid loads itself (see <c>CmsAllReleasesGrid</c>) — so no fetch happens for
/// either here.
/// </summary>
public async Task SwitchModeAsync(BrowseMode mode)
{
Mode = mode;
ExpandedGenre = null; // collapse on mode switch
if (mode == BrowseMode.Albums && Albums.Count == 0 && !AlbumsLoading)
{
AlbumsLoading = true;
var result = await _trackService.GetReleasesAsync();
Albums = result.Success && result.Value is not null
? result.Value
: Array.Empty<ReleaseDto>();
AlbumsLoading = false;
}
else if (mode == BrowseMode.Genres && Genres.Count == 0 && !GenresLoading)
if (mode == BrowseMode.Genres && Genres.Count == 0 && !GenresLoading)
{
GenresLoading = true;
var result = await _trackService.GetGenreSummariesAsync();
@@ -73,13 +62,13 @@ public class CmsTrackBrowserViewModel
}
/// <summary>
/// Drop the cached album and genre datasets so the next <see cref="SwitchModeAsync"/> into
/// either mode re-fetches from the API. Call after a track or release mutation (edit, delete)
/// since both datasets are derived from the catalogue and go stale on any such change.
/// Drop the cached genre dataset so the next <see cref="SwitchModeAsync"/> into Genre mode
/// re-fetches from the API. Call after a track or release mutation (edit, delete) since the genre
/// summaries are derived from the catalogue and go stale on any such change. The all-releases grid
/// owns and refreshes its own data, so it needs no invalidation here.
/// </summary>
public void Invalidate()
{
Albums = Array.Empty<ReleaseDto>();
Genres = Array.Empty<GenreSummaryDto>();
}
}