Files
deepdrft/DeepDrftPublic.Client/Controls/QueueOverlay.razor
T
daniel-c-harvey 214f708e65 feat(queue): two-level deque model — PLAY prepends, add appends, last-track-end empties
Fixes five queue bugs: Playlist relabel, last-track-empties, dormant-seed-from-player on first add, immediate panel reactivity, and front/back deque semantics. Adds JumpTo for row jumps.
2026-06-20 15:26:37 -04:00

70 lines
3.5 KiB
Plaintext

@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">Playlist</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 };
}