using DeepDrftModels.DTOs;
namespace DeepDrftManager.Services;
/// The browse dimensions for the /tracks page.
public enum BrowseMode
{
Tracks,
/// The release view — hosts the medium tab strip (ALL · CUTS · SESSIONS · MIXES, §8.A).
Albums,
Genres,
}
///
/// Holds the /tracks browser's current mode plus the album- and genre-mode datasets. Scoped per
/// circuit. Album and genre lists are fetched lazily on first switch into their mode and cached for
/// the circuit's lifetime; Track mode owns its own paging inside CmsTrackGrid and needs no
/// state here.
///
public class CmsTrackBrowserViewModel
{
private readonly ICmsTrackService _trackService;
public CmsTrackBrowserViewModel(ICmsTrackService trackService)
{
_trackService = trackService;
}
public BrowseMode Mode { get; private set; } = BrowseMode.Tracks;
// Genre mode.
public IReadOnlyList Genres { get; private set; } = Array.Empty();
public bool GenresLoading { get; private set; }
public string? ExpandedGenre { get; private set; }
///
/// 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 CmsAllReleasesGrid) — so no fetch happens for
/// either here.
///
public async Task SwitchModeAsync(BrowseMode mode)
{
Mode = mode;
ExpandedGenre = null; // collapse on mode switch
if (mode == BrowseMode.Genres && Genres.Count == 0 && !GenresLoading)
{
GenresLoading = true;
var result = await _trackService.GetGenreSummariesAsync();
Genres = result.Success && result.Value is not null
? result.Value
: Array.Empty();
GenresLoading = false;
}
}
/// Toggle the expanded genre row. Selecting the already-expanded genre collapses it.
public void SetExpandedGenre(string? genre)
{
ExpandedGenre = ExpandedGenre == genre ? null : genre;
}
///
/// Drop the cached genre dataset so the next 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.
///
public void Invalidate()
{
Genres = Array.Empty();
}
}