Replace MudSlider seekbar with WaveformSeeker loudness-waveform control

DOM bar chart with clip-overlay progress split; pointer-capture drag;
WaveformProfile fetched on load (fire-and-forget, cancellable); flat
fallback when no profile; small lazily-loaded waveformSeeker.js for
getBoundingClientRect and setPointerCapture.
This commit is contained in:
daniel-c-harvey
2026-06-05 17:35:11 -04:00
parent 7c89220667
commit 8de7342352
12 changed files with 516 additions and 56 deletions
@@ -3,48 +3,17 @@ using Microsoft.AspNetCore.Components;
namespace DeepDrftPublic.Client.Controls.AudioPlayerBar;
/// <summary>
/// Centre zone of the player: seek slider over the spectrum visualizer.
/// Owns the pointer-gesture seek logic (drag-to-seek) in one place so it is no
/// longer duplicated inline between the desktop and mobile branches of the parent.
/// Centre zone of the player: the <see cref="WaveformSeeker"/> over a timestamp label.
/// The seeker owns the pointer-gesture seek logic and reads playback state off the cascaded
/// player service directly; this zone just forwards the seek callbacks up to
/// <see cref="AudioPlayerBar"/> (whose wiring is unchanged) and renders the timestamp.
/// </summary>
public partial class PlayerSeekZone : ComponentBase
{
private double _seekPosition;
private bool _isSeeking = false;
[Parameter] public double DisplayTime { get; set; }
[Parameter] public double? Duration { get; set; }
[Parameter] public bool CanSeek { get; set; }
[Parameter] public EventCallback OnSeekStart { get; set; }
[Parameter] public EventCallback<double> OnSeekEnd { get; set; }
[Parameter] public EventCallback<double> OnSeekChange { get; set; }
[Parameter] public string? Class { get; set; }
private async Task HandlePointerDown()
{
_isSeeking = true;
_seekPosition = DisplayTime;
await OnSeekStart.InvokeAsync();
}
private async Task HandlePointerUp()
{
_isSeeking = false;
await OnSeekEnd.InvokeAsync(_seekPosition);
}
private async Task HandlePointerLeave()
{
if (_isSeeking)
{
_isSeeking = false;
await OnSeekEnd.InvokeAsync(_seekPosition);
}
}
private async Task HandleValueChanged(double value)
{
_seekPosition = value;
await OnSeekChange.InvokeAsync(value);
}
}