docs: spec Phase 17 player-bar queue view (queue button, overlay/embed modes, add-to-queue)

This commit is contained in:
daniel-c-harvey
2026-06-19 13:29:57 -04:00
parent 4114aa0be4
commit 90555dc4e0
2 changed files with 436 additions and 0 deletions
+51
View File
@@ -261,6 +261,57 @@ The phase deferred behind the home-hero **Plays** stat card (`NowPlayingStats.ra
---
## Phase 17 — Player-Bar Queue View
Phase 11 (wave 11.F) built the queue **engine** (`IQueueService`/`QueueService` — ordered playback,
auto-advance, skip-prev/next, armed-idle release embeds) but gave it **no UI**. A listener can start
an album and skip through it, but cannot see what is next, reorder it, drop a track, or hand-build a
queue. Phase 17 surfaces the queue as a first-class, visible, editable object in the player bar —
**without** moving any player/queue state out of the layout-level `AudioPlayerProvider` (project
memory; the cascade stays at layout level) and **without** changing the streaming/playback seam.
Four Daniel-stated capabilities, gated by a single new **Queue** toggle button (shown only when a
queue is loaded, mirroring the skip-affordance gating so single-track play is byte-for-byte its
pre-queue self):
1. **Queue button** in the bar — below the transport controls, left of the timestamp.
2. **Non-Fixed (overlay) mode** — a centered, mostly-square panel (borrowing the Phase 15
visualizer-popover idiom) listing the queue with **drag-reorder + per-track removal**.
3. **Fixed (embed) mode** — the queue list is **always shown below** the bar controls (not a toggle),
**read-only** for shared release queues (no reorder, no remove); the embed iframe is resized to fit
the panel.
4. **Add to Queue** affordance — an icon button + tooltip beside every detail-page play button for a
release (→ `EnqueueRange`) or track (→ `Enqueue`), lighting up the dormant `Enqueue` path.
**Architectural spine.** Engine grows **two additive members only**`Move(from, to)` and
`RemoveAt(index)` — interop-free state mutations that re-emit `QueueChanged` and **never re-stream or
interrupt the playing track** (the engine's stated open/closed posture; existing members untouched).
Both view modes render **one shared `QueueList` presentational component** off the same cascaded
`IQueueService.Items`, differing only in presentation + an `Editable` flag (project memory: *one
source, multiple views*). Reorder/remove run safely during prerender (no JS) — only playback
transitions touch interop.
**Sequenced as three waves.** `17.1 → {17.2, 17.3}`. **17.1 (engine `Move`/`RemoveAt` + the shared
`QueueList` view) is the cold-start prerequisite**, settled and independent of the UI decisions —
it can begin immediately. 17.2 (docked overlay, editable) and 17.3 (Fixed embed panel + snippet
resize + Add-to-Queue) hang off it and are largely parallel. Add-to-Queue may split to a standalone
17.4 (it needs only the existing `Enqueue`/`EnqueueRange`, not 17.1's new members).
Full design — goal, constraints, use cases, acceptance criteria, test cases, wave decomposition, and
the open-question set: `product-notes/phase-17-player-queue-view.md`.
**Open questions (Daniel's call — spec §10).** OQ1 (Queue button behavior in embed mode given the
panel is always shown — recommend repurpose as collapse/expand toggle); OQ2 (click-a-row to jump —
recommend yes, both modes); OQ3 (terminal/empty states after removal); OQ4 (drag mechanism + touch
viability — `MudDropContainer` vs. pointer-interop vs. up/down-arrow fallback; mobile is a primary
surface); OQ5 (Clear-queue in the UI and whether it stops playback); OQ6 (embed panel height —
fixed+scroll vs. grow-to-cap); OQ7 (Material vs. bespoke `DDIcons` glyph); OQ8 (Add-to-Queue into a
dormant/empty queue — recommend pure append, keep "add" ≠ "play"); OQ9 (exclude `StreamNowButton`
no fixed track); OQ10 (`ReleaseGallery` cards — recommend defer; cards have no play button today);
OQ11 (removing the current track — recommend keep playing to natural end). **None block 17.1.**
---
## Working with this file
- **Add items by extending an existing phase first**; only create a new phase when the addition genuinely doesn't fit any of 15. Phase numbers are organisational, not sequencing.