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(); } }