using DeepDrftModels.DTOs; using DeepDrftPublic.Client.Services; namespace DeepDrftPublic.Client.ViewModels; /// /// State for a single-release detail page (Session, Mix). Loads the release and resolves its /// playable track. The release read surface exposes no track entry directly, so the playable track /// is resolved through the existing track gallery filtered by the release's id (an exact join) — for /// Session/Mix that yields the single track. Scoped; reset every flag per so a /// reused instance never bleeds across navigations. /// public class ReleaseDetailViewModel { private readonly IReleaseDataService _releaseData; private readonly ITrackDataService _trackData; public ReleaseDto? Release { get; private set; } public TrackDto? Track { get; private set; } public bool IsLoading { get; private set; } = true; public bool NotFound { get; private set; } public ReleaseDetailViewModel(IReleaseDataService releaseData, ITrackDataService trackData) { _releaseData = releaseData; _trackData = trackData; } /// Seed state directly from a bridged prerender payload — no fetch. public void Restore(ReleaseDto release, TrackDto? track) { Release = release; Track = track; NotFound = false; IsLoading = false; } public async Task Load(string entryKey) { IsLoading = true; NotFound = false; Release = null; Track = null; try { var releaseResult = await _releaseData.GetByEntryKey(entryKey); if (releaseResult is not { Success: true, Value: { } release }) { NotFound = true; return; } Release = release; // Resolve the playable track via the releaseId-filtered track page — an exact join, not a // title string (which collides across same-titled releases and breaks on rename). The public // page addresses the release by EntryKey; the track→release join stays on the internal int // FK (Phase 11 §3e leaves internal joins on the int PK), so use the resolved release.Id here. // Session/Mix releases carry a single track; take the first. A release with no streamable // track simply leaves Track null (the detail page hides the play affordance). var trackResult = await _trackData.GetPage( pageNumber: 1, pageSize: 1, releaseId: release.Id); if (trackResult is { Success: true, Value: { Items: { } items } }) Track = items.FirstOrDefault(); } finally { IsLoading = false; } } }