af724ce570
Replaces flat RELEASES/SESSIONS/MIXES nav with ARCHIVE dropdown (PageRoute.Children,
one-level cap, dual-role node). Adds /archive overview, /cuts (AlbumsView + medium
filter; /albums redirects), /sessions + /sessions/{id} (hero-dominant), /mixes +
/mixes/{id} (MixWaveformVisualizer full-page background). Extracts ReleaseDetailScaffold
from TrackDetail (invariant trio). PersistentComponentState bridge on all new pages.
Click-to-seek seam designed on MixWaveformVisualizer (inert until wired).
70 lines
2.4 KiB
C#
70 lines
2.4 KiB
C#
using DeepDrftModels.DTOs;
|
|
using DeepDrftPublic.Client.Services;
|
|
|
|
namespace DeepDrftPublic.Client.ViewModels;
|
|
|
|
/// <summary>
|
|
/// 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 album title — for
|
|
/// Session/Mix that yields the single track. Scoped; reset every flag per <see cref="Load"/> so a
|
|
/// reused instance never bleeds across navigations (mirrors TrackDetailViewModel).
|
|
/// </summary>
|
|
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;
|
|
}
|
|
|
|
/// <summary>Seed state directly from a bridged prerender payload — no fetch.</summary>
|
|
public void Restore(ReleaseDto release, TrackDto? track)
|
|
{
|
|
Release = release;
|
|
Track = track;
|
|
NotFound = false;
|
|
IsLoading = false;
|
|
}
|
|
|
|
public async Task Load(long releaseId)
|
|
{
|
|
IsLoading = true;
|
|
NotFound = false;
|
|
Release = null;
|
|
Track = null;
|
|
|
|
try
|
|
{
|
|
var releaseResult = await _releaseData.GetById(releaseId);
|
|
if (releaseResult is not { Success: true, Value: { } release })
|
|
{
|
|
NotFound = true;
|
|
return;
|
|
}
|
|
|
|
Release = release;
|
|
|
|
// Resolve the playable track via the album-filtered track page. 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, album: release.Title);
|
|
if (trackResult is { Success: true, Value: { Items: { } items } })
|
|
Track = items.FirstOrDefault();
|
|
}
|
|
finally
|
|
{
|
|
IsLoading = false;
|
|
}
|
|
}
|
|
}
|