feat(player): docked queue overlay with reorder, remove, jump, and clear-upcoming
Add a Queue toggle to the docked player bar opening a centered editable queue overlay. New additive QueueService.ClearUpcoming keeps the playing track while dropping the rest. Current track is non-removable.
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
@namespace DeepDrftPublic.Client.Controls
|
||||
@using DeepDrftModels.DTOs
|
||||
|
||||
@* The docked player's queue panel: a screen-centered, mostly-square modal hosting the editable
|
||||
QueueList (Phase 17 §3.2). The overlay shell, dismissal, and drag-safety are a direct lift of
|
||||
WaveformVisualizerControlPopover (Phase 15 §4):
|
||||
- MudOverlay (DarkBackground = mild tint, Modal = focus/scroll stay on the panel).
|
||||
- Scrim OnClick closes; the panel stops click propagation so an inside click is not a dismissal.
|
||||
- AutoClose left OFF; dismissal is the explicit scrim click only. A MudDropContainer drag that
|
||||
ends outside the panel does not synthesise a click on the scrim, so a reorder drag never
|
||||
dismisses (same drag-safety posture as the visualizer popover).
|
||||
This host owns NO queue state and NO JS interop — it renders Items/CurrentIndex and forwards
|
||||
QueueList's reorder/remove/jump callbacks plus a Clear action to the parent (AudioPlayerBar), which
|
||||
holds the cascaded IQueueService. Purely presentational; prerender-safe. *@
|
||||
|
||||
<MudOverlay Visible="@Visible"
|
||||
DarkBackground="true"
|
||||
Modal="true"
|
||||
OnClick="@OnClose"
|
||||
Class="deepdrft-queue-overlay">
|
||||
<div class="deepdrft-queue-modal" @onclick:stopPropagation="true">
|
||||
<div class="deepdrft-queue-modal-header">
|
||||
<span class="deepdrft-queue-modal-title">Up Next</span>
|
||||
<MudButton Variant="Variant.Text"
|
||||
Size="Size.Small"
|
||||
Color="Color.Primary"
|
||||
Disabled="@(!CanClear)"
|
||||
OnClick="@OnClear"
|
||||
Class="deepdrft-queue-clear">Clear</MudButton>
|
||||
</div>
|
||||
<div class="deepdrft-queue-modal-body">
|
||||
<QueueList Items="Items"
|
||||
CurrentIndex="CurrentIndex"
|
||||
Editable="true"
|
||||
OnReorder="OnReorder"
|
||||
OnRemove="OnRemove"
|
||||
OnJump="OnJump"/>
|
||||
</div>
|
||||
</div>
|
||||
</MudOverlay>
|
||||
|
||||
@code {
|
||||
/// <summary>Whether the overlay is shown. Owned by the parent (the Queue button toggles it).</summary>
|
||||
[Parameter] public bool Visible { get; set; }
|
||||
|
||||
/// <summary>The queue to render. Passed straight through to <see cref="QueueList"/>.</summary>
|
||||
[Parameter] public IReadOnlyList<TrackDto>? Items { get; set; }
|
||||
|
||||
/// <summary>Index of the current track within <see cref="Items"/>, or -1 when none.</summary>
|
||||
[Parameter] public int CurrentIndex { get; set; } = -1;
|
||||
|
||||
/// <summary>Raised when the scrim is clicked to dismiss the overlay.</summary>
|
||||
[Parameter] public EventCallback OnClose { get; set; }
|
||||
|
||||
/// <summary>Raised when Clear is pressed — empties the up-next, keeping the current track playing.</summary>
|
||||
[Parameter] public EventCallback OnClear { get; set; }
|
||||
|
||||
/// <summary>Reorder callback forwarded from the hosted <see cref="QueueList"/>.</summary>
|
||||
[Parameter] public EventCallback<(int FromIndex, int ToIndex)> OnReorder { get; set; }
|
||||
|
||||
/// <summary>Remove callback forwarded from the hosted <see cref="QueueList"/>.</summary>
|
||||
[Parameter] public EventCallback<int> OnRemove { get; set; }
|
||||
|
||||
/// <summary>Jump-to-track callback forwarded from the hosted <see cref="QueueList"/>.</summary>
|
||||
[Parameter] public EventCallback<int> OnJump { get; set; }
|
||||
|
||||
// Clear is meaningful only when there is something beyond the current track to discard.
|
||||
private bool CanClear => Items is { Count: > 1 };
|
||||
}
|
||||
Reference in New Issue
Block a user