Files
deepdrft/DeepDrftPublic.Client/Clients/ReleaseClient.cs
T
daniel-c-harvey af724ce570 Phase 9 Wave 4: ARCHIVE nav + Cuts/Sessions/Mixes pages + MixWaveformVisualizer
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).
2026-06-12 23:05:25 -04:00

102 lines
3.9 KiB
C#

using DeepDrftModels.DTOs;
using Models.Common;
using NetBlocks.Models;
using System.Text.Json;
using Microsoft.AspNetCore.Http;
namespace DeepDrftPublic.Client.Clients;
/// <summary>
/// HTTP client for the release read surface (Phase 9). Uses the named <c>"DeepDrft.API"</c>
/// client like <see cref="TrackClient"/>: on WASM it points at the public host and proxies
/// through <c>ReleaseProxyController</c>; on SSR prerender it points directly at DeepDrftAPI.
/// All routes are unauthenticated reads. Responses deserialize as bare DTOs (no ApiResultDto
/// envelope), matching the API's <c>Ok(value)</c> shape.
/// </summary>
public class ReleaseClient
{
private static readonly JsonSerializerOptions JsonOptions = new() { PropertyNameCaseInsensitive = true };
private readonly HttpClient _http;
public ReleaseClient(IHttpClientFactory httpClientFactory)
{
_http = httpClientFactory.CreateClient("DeepDrft.API");
}
public async Task<ApiResult<PagedResult<ReleaseDto>>> GetPaged(
string? medium,
int page,
int pageSize,
string? sortColumn = null,
bool sortDescending = false)
{
var queryArgs = new Dictionary<string, string?>
{
["page"] = page.ToString(),
["pageSize"] = pageSize.ToString()
};
if (!string.IsNullOrEmpty(medium))
queryArgs["medium"] = medium;
if (!string.IsNullOrEmpty(sortColumn))
queryArgs["sortColumn"] = sortColumn;
if (sortDescending)
queryArgs["sortDescending"] = "true";
string query = QueryString.Create(queryArgs).ToString();
var response = await _http.GetAsync($"api/release{query}");
if (!response.IsSuccessStatusCode)
return ApiResult<PagedResult<ReleaseDto>>.CreateFailResult($"HTTP {(int)response.StatusCode}");
var json = await response.Content.ReadAsStringAsync();
var paged = JsonSerializer.Deserialize<PagedResult<ReleaseDto>>(json, JsonOptions);
return paged is not null
? ApiResult<PagedResult<ReleaseDto>>.CreatePassResult(paged)
: ApiResult<PagedResult<ReleaseDto>>.CreateFailResult("Failed to deserialize response");
}
public async Task<ApiResult<ReleaseDto>> GetById(long id)
{
var response = await _http.GetAsync($"api/release/{id}");
if (!response.IsSuccessStatusCode)
return ApiResult<ReleaseDto>.CreateFailResult($"HTTP {(int)response.StatusCode}");
var json = await response.Content.ReadAsStringAsync();
var release = JsonSerializer.Deserialize<ReleaseDto>(json, JsonOptions);
return release is not null
? ApiResult<ReleaseDto>.CreatePassResult(release)
: ApiResult<ReleaseDto>.CreateFailResult("Failed to deserialize response");
}
/// <summary>
/// Fetches the high-res waveform datum for a Mix release. A 404 means no datum is stored
/// (not yet generated, or not a Mix) — a valid state, so it returns a pass result with a
/// null value. Any other non-success status is a genuine failure.
/// </summary>
public async Task<ApiResult<WaveformProfileDto?>> GetMixWaveform(long id)
{
var response = await _http.GetAsync($"api/release/{id}/mix/waveform");
if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
return ApiResult<WaveformProfileDto?>.CreatePassResult(null);
if (!response.IsSuccessStatusCode)
return ApiResult<WaveformProfileDto?>.CreateFailResult($"HTTP {(int)response.StatusCode}");
var json = await response.Content.ReadAsStringAsync();
var profile = JsonSerializer.Deserialize<WaveformProfileDto>(json, JsonOptions);
return profile is not null
? ApiResult<WaveformProfileDto?>.CreatePassResult(profile)
: ApiResult<WaveformProfileDto?>.CreateFailResult("Failed to deserialize response");
}
}