feat(release): front int PK with app-minted GUID EntryKey on the public addressing surface (P11 W5, 11.H)

This commit is contained in:
daniel-c-harvey
2026-06-16 17:11:55 -04:00
parent fe28573b68
commit f07d29cdcf
37 changed files with 627 additions and 160 deletions
@@ -9,7 +9,7 @@ namespace DeepDrftPublic.Client.Controls;
/// <summary>
/// Full-page scrolling Mix waveform background. Standalone and reusable: give it a
/// <see cref="ReleaseId"/> and it fetches its own loudness datum. The rendering itself — a windowed,
/// <see cref="ReleaseEntryKey"/> and it fetches its own loudness datum. The rendering itself — a windowed,
/// bottom-to-top, playback-coupled scroll with a glassy theme-aware gradient — lives in the
/// MixVisualizer.ts interop module; this component is the bridge that feeds it datum, playback
/// position, zoom, and theme, and owns the module lifecycle.
@@ -36,8 +36,8 @@ public partial class MixWaveformVisualizer : ComponentBase, IAsyncDisposable
// us, and OnAfterRender pushes fresh palette colours into the module.
[CascadingParameter] public DarkModeSettings? DarkMode { get; set; }
/// <summary>The Mix release whose waveform datum to fetch and render.</summary>
[Parameter] public required long ReleaseId { get; set; }
/// <summary>The opaque public EntryKey of the Mix release whose waveform datum to fetch and render.</summary>
[Parameter] public required string ReleaseEntryKey { get; set; }
/// <summary>
/// The id of this mix's playable track. Used to gate the cascaded player as the live source: we
@@ -75,7 +75,7 @@ public partial class MixWaveformVisualizer : ComponentBase, IAsyncDisposable
private IStreamingPlayerService? _subscribedService;
private WaveformProfileDto? _profile;
private long? _loadedReleaseId;
private string? _loadedReleaseKey;
// Whether we are subscribed to the shared control state's Changed event. The controls row (a
// sibling component) mutates ControlState and raises Changed; we push the affected uniforms.
@@ -114,21 +114,21 @@ public partial class MixWaveformVisualizer : ComponentBase, IAsyncDisposable
_subscribedService.StateChanged -= OnPlayerStateChanged;
PlayerService.StateChanged += OnPlayerStateChanged;
_subscribedService = PlayerService;
DebugLog($"subscribed to player StateChanged. ReleaseId={ReleaseId}, TrackId={TrackId?.ToString() ?? "null"}.");
DebugLog($"subscribed to player StateChanged. ReleaseEntryKey={ReleaseEntryKey}, TrackId={TrackId?.ToString() ?? "null"}.");
}
else if (PlayerService is null)
{
DebugLog($"NO player cascade — playback will never couple. ReleaseId={ReleaseId}, TrackId={TrackId?.ToString() ?? "null"}.");
DebugLog($"NO player cascade — playback will never couple. ReleaseEntryKey={ReleaseEntryKey}, TrackId={TrackId?.ToString() ?? "null"}.");
}
// ReleaseId is the only fetch input; fetch once per id. Position/zoom/theme changes re-render
// but must not refetch, and a release with no datum must not refetch either — so the guard
// keys on the fetched id, not on whether a profile came back.
if (_loadedReleaseId == ReleaseId) return;
_loadedReleaseId = ReleaseId;
// ReleaseEntryKey is the only fetch input; fetch once per key. Position/zoom/theme changes
// re-render but must not refetch, and a release with no datum must not refetch either — so the
// guard keys on the fetched key, not on whether a profile came back.
if (_loadedReleaseKey == ReleaseEntryKey) return;
_loadedReleaseKey = ReleaseEntryKey;
DebugLog($"fetching mix waveform datum for ReleaseId={ReleaseId}…");
var result = await ReleaseData.GetMixWaveform(ReleaseId);
DebugLog($"fetching mix waveform datum for ReleaseEntryKey={ReleaseEntryKey}…");
var result = await ReleaseData.GetMixWaveform(ReleaseEntryKey);
if (result is { Success: true, Value: { } profile } && profile.BucketCount > 0 && profile.Data.Length > 0)
{
_profile = profile;
@@ -140,7 +140,7 @@ public partial class MixWaveformVisualizer : ComponentBase, IAsyncDisposable
// renders its content over a plain background.
_profile = null;
DebugLog(result.Success
? $"datum fetch returned EMPTY/absent (no stored datum for ReleaseId={ReleaseId}) — backdrop stays blank."
? $"datum fetch returned EMPTY/absent (no stored datum for ReleaseEntryKey={ReleaseEntryKey}) — backdrop stays blank."
: $"datum fetch FAILED ({result.GetMessage() ?? "unknown error"}) — backdrop stays blank.");
}