feature: Embed Frame Player

This commit is contained in:
daniel-c-harvey
2026-06-06 15:43:09 -04:00
parent d96c41eafb
commit c83b132522
22 changed files with 308 additions and 29 deletions
@@ -62,4 +62,13 @@ public interface IStreamingPlayerService : IPlayerService
// Streaming control methods
Task SelectTrackStreaming(TrackDto track);
/// <summary>
/// Stages a track as the current track without touching the audio context or starting the
/// stream. Used by the embed player, where there is no user gesture on initial load: the track
/// is shown as ready, and the first play click (a genuine gesture) calls
/// <see cref="SelectTrackStreaming"/> so the browser allows the AudioContext to start. Sets
/// <see cref="IPlayerService.CurrentTrack"/> and notifies; performs no JS interop.
/// </summary>
Task StageTrack(TrackDto track);
}
@@ -18,4 +18,6 @@ public interface ITrackDataService
int pageSize,
string? sortColumn = null,
bool sortDescending = false);
Task<ApiResult<TrackDto>> GetTrack(string trackId);
}
@@ -59,6 +59,17 @@ public class StreamingAudioPlayerService : AudioPlayerService, IStreamingPlayerS
await NotifyStateChanged();
}
/// <inheritdoc />
public async Task StageTrack(TrackDto track)
{
// Pure state: expose the track as current so the bar shows it ready, but do NOT
// initialize the player, resume the AudioContext, or start streaming. Those steps
// require a user gesture and run on the first play click via SelectTrackStreaming.
CurrentTrack = track;
ErrorMessage = null;
await NotifyStateChanged();
}
private async Task LoadTrackStreaming(TrackDto track)
{
// Always reset to clean state before loading new track. ResetToIdle
@@ -25,4 +25,7 @@ public class TrackClientDataService : ITrackDataService
string? sortColumn = null,
bool sortDescending = false)
=> _trackClient.GetPage(pageNumber, pageSize, sortColumn, sortDescending);
public Task<ApiResult<TrackDto>> GetTrack(string trackId)
=> _trackClient.GetTrack(trackId);
}