fix: restore waveform status coherence, drop dead GetGenreSummaries, restore track info tooltip

This commit is contained in:
daniel-c-harvey
2026-06-17 14:13:34 -04:00
parent 30999726e5
commit 13fbcc2d43
8 changed files with 159 additions and 74 deletions
@@ -73,14 +73,23 @@
<MudTabs Elevation="0" Rounded="true" ApplyEffectsToContainer="true" PanelClass="pt-4"
@bind-ActivePanelIndex="_activeTabIndex">
<MudTabPanel Text="ALL">
<CmsAllReleasesGrid />
<CmsAllReleasesGrid @ref="_allGrid"
OnWaveformGenerated="RefreshWaveformStatusAsync" />
</MudTabPanel>
<MudTabPanel Text="@MediumTabLabels[ReleaseMedium.Cut]">
<CmsCutBrowser @ref="_cutBrowser"
OnWaveformGenerated="RefreshWaveformStatusAsync" />
</MudTabPanel>
<MudTabPanel Text="@MediumTabLabels[ReleaseMedium.Session]">
<CmsSessionBrowser @ref="_sessionBrowser"
Embedded="true"
OnWaveformGenerated="RefreshWaveformStatusAsync" />
</MudTabPanel>
<MudTabPanel Text="@MediumTabLabels[ReleaseMedium.Mix]">
<CmsMixBrowser @ref="_mixBrowser"
Embedded="true"
OnWaveformGenerated="RefreshWaveformStatusAsync" />
</MudTabPanel>
@foreach (var medium in Enum.GetValues<ReleaseMedium>())
{
<MudTabPanel Text="@MediumTabLabels[medium]">
@MediumGrid(medium)
</MudTabPanel>
}
</MudTabs>
</MudContainer>
@@ -104,9 +113,8 @@
private static string AddTrackHref(ReleaseMedium medium) =>
$"/tracks/upload?medium={medium.ToString().ToLowerInvariant()}";
// Medium → tab label. The one place medium display text lives for the tab strip; a future medium adds
// one entry here and surfaces a tab automatically. The ALL tab is rendered separately (it is not a
// medium).
// Medium → tab label. The one place medium display text lives for the tab strip. The ALL tab is
// rendered separately (it is not a medium). Tabs are explicit markup so @ref captures work.
private static readonly IReadOnlyDictionary<ReleaseMedium, string> MediumTabLabels =
new Dictionary<ReleaseMedium, string>
{
@@ -115,17 +123,14 @@
[ReleaseMedium.Mix] = "MIXES",
};
// Medium → embedded grid. Each medium's grid is its own component (Cut has no per-row action; Session
// carries hero upload; Mix carries waveform generation), so the content dispatch is a per-medium
// mapping by nature — but it is a single switch returning a fragment, not a markup fork. The browsers
// render Embedded so their standalone page chrome (container, title, back button) is suppressed here.
private RenderFragment MediumGrid(ReleaseMedium medium) => medium switch
{
ReleaseMedium.Cut => @<CmsCutBrowser />,
ReleaseMedium.Session => @<CmsSessionBrowser Embedded="true" />,
ReleaseMedium.Mix => @<CmsMixBrowser Embedded="true" />,
_ => @<MudText Typo="Typo.body1" Class="mt-4">No grid for this medium.</MudText>
};
// @ref handles for the per-tab grids. Used to (a) invalidate their cached per-track waveform status
// after a page-level bulk run, and (b) to wire OnWaveformGenerated so per-row generates bubble up
// and refresh the page-level missing-count badges. Tabs are now explicit markup rather than the
// former enum-driven MediumGrid() switch so @ref captures are possible.
private CmsAllReleasesGrid? _allGrid;
private CmsCutBrowser? _cutBrowser;
private CmsSessionBrowser? _sessionBrowser;
private CmsMixBrowser? _mixBrowser;
// EntryKey → HasProfile / HasHighRes, loaded once on init so the bulk buttons can show accurate missing
// counts without depending on any rendered grid. Re-fetched after each bulk run so the counts settle.
@@ -167,6 +172,21 @@
StateHasChanged();
}
// Invalidates the cached per-track waveform status on all embedded grids so the next row expand
// re-fetches fresh data. Called after each catalogue-wide bulk run so already-expanded rows
// reflect the new waveform state on the next expand interaction.
private async Task InvalidateAllGridsAsync()
{
var tasks = new[]
{
_allGrid?.InvalidateWaveformStatusAsync() ?? Task.CompletedTask,
_cutBrowser?.InvalidateWaveformStatusAsync() ?? Task.CompletedTask,
_sessionBrowser?.InvalidateWaveformStatusAsync() ?? Task.CompletedTask,
_mixBrowser?.InvalidateWaveformStatusAsync() ?? Task.CompletedTask,
};
await Task.WhenAll(tasks);
}
/// <summary>
/// Backfill every track missing a waveform profile, one request at a time so a large backfill does not
/// flood the API with concurrent WAV decodes. On completion, re-reads the status map so the missing
@@ -206,6 +226,7 @@
_bulkRunning = false;
await RefreshWaveformStatusAsync();
await InvalidateAllGridsAsync();
var succeeded = missing.Count - failures;
if (failures == 0)
@@ -257,6 +278,7 @@
_highResBulkRunning = false;
await RefreshWaveformStatusAsync();
await InvalidateAllGridsAsync();
var succeeded = missing.Count - failures;
if (failures == 0)