docs: resolve remaining seven Phase 17 open questions (all 11 now closed)
This commit is contained in:
@@ -305,21 +305,31 @@ existing `Enqueue`/`EnqueueRange`, not 17.1's new members). **Landed:** 2026-06-
|
|||||||
Full design — goal, constraints, use cases, acceptance criteria, test cases, wave decomposition, and
|
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`.
|
the open-question set: `product-notes/phase-17-player-queue-view.md`.
|
||||||
|
|
||||||
**Open questions — 4 resolved (Daniel, 2026-06-19), 7 pending (spec §10).**
|
**Open questions — all 11 resolved (Daniel, 2026-06-19; spec §10).**
|
||||||
|
|
||||||
- **Resolved (Daniel, 2026-06-19):** **OQ1** → **Option A, conditional** — collapse/expand toggle *if*
|
- **OQ1** → **Option A, conditional** — collapse/expand toggle *if* the embed snippet can dynamically
|
||||||
the embed snippet can dynamically resize the iframe (`postMessage` → host resize handshake), **else
|
resize the iframe (`postMessage` → host resize handshake), **else fall back to Option B** (omit the
|
||||||
fall back to Option B** (omit the button); A preferred, B fallback, deciding factor = iframe-resize
|
button); A preferred, B fallback, deciding factor = iframe-resize feasibility, **determined during
|
||||||
feasibility, **determined during 17.3**. **OQ4** → **`MudDropContainer` for now** (C6 softened —
|
17.3**.
|
||||||
touch-viability is a known risk with a planned pivot path, not a pre-ship blocker). **OQ8** →
|
- **OQ2** → **yes, both modes** — clicking a queued row jumps playback to that track in the docked
|
||||||
**pure append** (add ≠ play; first add into a dormant queue leaves a coherent `CurrentIndex` via the
|
overlay *and* the read-only embed; reuses `PlayRelease(Items, index)`.
|
||||||
17.1 engine affordance, no auto-play). **OQ10** → **deferred** (cards get no Add-to-Queue in Phase
|
- **OQ3 + OQ11** (jointly) → **the currently-playing track cannot be removed at all** — no "remove
|
||||||
17; deferred card work captured in `TODO.md`).
|
current" action; the × is suppressed on the current row. The queue empties only **organically** (the
|
||||||
- **Still pending (recommendations stand, not confirmed):** OQ2 (click-a-row to jump — recommend yes,
|
current track ends with nothing queued after). The engine's `RemoveAt`-of-current path (17.1) stays as
|
||||||
both modes); OQ3 (terminal/empty states after removal); OQ5 (Clear-queue in the UI and whether it
|
defensive, UI-unreachable behavior.
|
||||||
stops playback); OQ6 (embed panel height — fixed+scroll vs. grow-to-cap; couples to OQ1's resize
|
- **OQ4** → **`MudDropContainer` for now** (C6 softened — touch-viability is a known risk with a planned
|
||||||
decision); OQ7 (Material vs. bespoke `DDIcons` glyph); OQ9 (exclude `StreamNowButton` — no fixed
|
pivot path, not a pre-ship blocker).
|
||||||
track); OQ11 (removing the current track — recommend keep playing to natural end).
|
- **OQ5** → **yes, Clear in the overlay header** — but Clear must **not** stop or remove the
|
||||||
|
currently-playing track (it keeps playing and stays in the queue; only the other queued tracks clear).
|
||||||
|
- **OQ6** → **fixed sensible height with internal scroll past N rows** (not grow-to-cap; affects
|
||||||
|
`EmbedSnippetBuilder.ForRelease`).
|
||||||
|
- **OQ7** → **Material icons for now** (`QueueMusic` / `PlaylistAdd`; bespoke `DDIcons` glyph not pursued
|
||||||
|
in Phase 17).
|
||||||
|
- **OQ8** → **pure append** (add ≠ play; first add into a dormant queue leaves a coherent `CurrentIndex`
|
||||||
|
via the 17.1 engine affordance, no auto-play).
|
||||||
|
- **OQ9** → **exclude `StreamNowButton`** (no fixed track until one resolves).
|
||||||
|
- **OQ10** → **deferred** (cards get no Add-to-Queue in Phase 17; deferred card work captured in
|
||||||
|
`TODO.md`).
|
||||||
- **None block 17.1.**
|
- **None block 17.1.**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -1,17 +1,24 @@
|
|||||||
# Phase 17 — Player-Bar Queue View
|
# Phase 17 — Player-Bar Queue View
|
||||||
|
|
||||||
Status: **design spec — 4 of 11 open questions resolved (Daniel, 2026-06-19); 7 still pending.** Author: product-designer. Date: 2026-06-19.
|
Status: **design spec — all 11 open questions resolved (Daniel, 2026-06-19).** Author: product-designer. Date: 2026-06-19.
|
||||||
**Plan only — no code has been written by this doc.**
|
**Plan only — no code has been written by this doc.**
|
||||||
|
|
||||||
**Resolved (Daniel, 2026-06-19):** OQ1 → **Option A, conditional** (collapse/expand toggle *if* dynamic
|
**Resolved (Daniel, 2026-06-19):** OQ1 → **Option A, conditional** (collapse/expand toggle *if* dynamic
|
||||||
iframe resize is achievable in the embed snippet; **else fall back to Option B**, omit the button —
|
iframe resize is achievable in the embed snippet; **else fall back to Option B**, omit the button —
|
||||||
feasibility call made during 17.3). OQ4 → **`MudDropContainer` for now** (pivot to a touch-viable
|
feasibility call made during 17.3). OQ2 → **yes, both modes** (clicking a queued row jumps playback to
|
||||||
mechanism later if mobile issues surface; C6 softened — touch-viability is a known risk, not a pre-ship
|
that track in docked overlay *and* read-only embed; reuses `PlayRelease(Items, index)`). OQ3 + OQ11 →
|
||||||
blocker). OQ8 → **pure append, confirmed** (add ≠ play; first add into a dormant queue leaves a coherent
|
**the currently-playing track cannot be removed at all** (no "remove current" action; remove affordance
|
||||||
`CurrentIndex` via a small additive engine affordance, landing with wave 17.1). OQ10 → **deferred,
|
suppressed on the current row; queue empties only organically when the current track ends with nothing
|
||||||
confirmed** (cards get no Add-to-Queue in Phase 17; the deferred card work is captured in `TODO.md`).
|
queued after). OQ4 → **`MudDropContainer` for now** (pivot to a touch-viable mechanism later if mobile
|
||||||
The remaining seven (OQ2, OQ3, OQ5, OQ6, OQ7, OQ9, OQ11) are **still pending** — their §10
|
issues surface; C6 softened — touch-viability is a known risk, not a pre-ship blocker). OQ5 → **yes,
|
||||||
recommendations stand but are not confirmed.
|
Clear in the overlay header** — but Clear must **not** stop or remove the currently-playing track (it
|
||||||
|
keeps playing and stays in the queue; only the other queued tracks are cleared). OQ6 → **fixed sensible
|
||||||
|
height with internal scroll past N rows** (not grow-to-cap; affects `EmbedSnippetBuilder.ForRelease`).
|
||||||
|
OQ7 → **Material icons for now** (`QueueMusic` / `PlaylistAdd`; bespoke `DDIcons` glyph not pursued in
|
||||||
|
Phase 17). OQ8 → **pure append, confirmed** (add ≠ play; first add into a dormant queue leaves a coherent
|
||||||
|
`CurrentIndex` via a small additive engine affordance, landing with wave 17.1). OQ9 → **exclude
|
||||||
|
`StreamNowButton`** (no fixed track until one resolves). OQ10 → **deferred, confirmed** (cards get no
|
||||||
|
Add-to-Queue in Phase 17; the deferred card work is captured in `TODO.md`).
|
||||||
|
|
||||||
This phase makes the play-queue **visible and manipulable**. Phase 11 (wave 11.F) built the queue
|
This phase makes the play-queue **visible and manipulable**. Phase 11 (wave 11.F) built the queue
|
||||||
*engine* (`IQueueService` / `QueueService`) and wired auto-advance, skip-prev/next, and release
|
*engine* (`IQueueService` / `QueueService`) and wired auto-advance, skip-prev/next, and release
|
||||||
@@ -353,42 +360,56 @@ Component (if/when component test coverage is in scope — today none exists for
|
|||||||
|
|
||||||
## 10. Open questions for Daniel
|
## 10. Open questions for Daniel
|
||||||
|
|
||||||
**Four resolved (Daniel, 2026-06-19): OQ1, OQ4, OQ8, OQ10. Seven still pending: OQ2, OQ3, OQ5, OQ6,
|
**All eleven resolved (Daniel, 2026-06-19): OQ1, OQ2, OQ3, OQ4, OQ5, OQ6, OQ7, OQ8, OQ9, OQ10, OQ11.**
|
||||||
OQ7, OQ9, OQ11 — their recommendations below stand but are not confirmed.**
|
|
||||||
|
|
||||||
- **OQ1 — Queue button in embed (Fixed) mode. RESOLVED → Option A, conditional.** Use Option A
|
- **OQ1 — Queue button in embed (Fixed) mode. RESOLVED → Option A, conditional.** Use Option A
|
||||||
(collapse/expand toggle) **if** the iframe can be dynamically resized for collapse/expand (embed-snippet
|
(collapse/expand toggle) **if** the iframe can be dynamically resized for collapse/expand (embed-snippet
|
||||||
`postMessage` → host resize handshake); **else fall back to Option B** (omit the button). A preferred,
|
`postMessage` → host resize handshake); **else fall back to Option B** (omit the button). A preferred,
|
||||||
B fallback; deciding factor = whether dynamic iframe resize is achievable in the embed snippet;
|
B fallback; deciding factor = whether dynamic iframe resize is achievable in the embed snippet;
|
||||||
determination made during **17.3** (see §4.1).
|
determination made during **17.3** (see §4.1).
|
||||||
- **OQ2 — Click-to-jump.** Does clicking a queued row jump playback to that track? Recommend **yes**
|
- **OQ2 — Click-to-jump. RESOLVED → yes, both modes.** Clicking a queued row jumps playback to that
|
||||||
in both modes (reuses `PlayRelease(Items, index)`); jump is not a forbidden edit, only reorder/
|
track in **both** the docked overlay and the read-only embed, reusing `PlayRelease(Items, index)`.
|
||||||
remove are. Confirm for the read-only embed too.
|
Jump is not a forbidden edit — only reorder/remove are — so the read-only embed allows it too.
|
||||||
- **OQ3 — Terminal/empty states.** When removal empties the queue mid-session: close the overlay?
|
- **OQ3 — Terminal/empty states. RESOLVED (jointly with OQ11) → the currently-playing track cannot be
|
||||||
Show an empty state then auto-close? And when the *current* track is removed, what should the panel
|
removed at all.** There is no "remove current" user action: the remove (×) affordance is **suppressed
|
||||||
and the player show?
|
on the current row** in the overlay. The queue therefore empties only **organically** — when the
|
||||||
|
current track ends and nothing is queued after it. There is no mid-session "removed the current track"
|
||||||
|
state to design for, because the user cannot reach it. (The road not taken — "show an empty state then
|
||||||
|
auto-close on user-driven empty" — is moot: user removal can only ever target non-current rows, so the
|
||||||
|
user cannot remove their way to an empty queue while a track is playing.) The engine's `RemoveAt`-of-
|
||||||
|
current behavior built in 17.1 remains as **defensive engine behavior but is UI-unreachable**.
|
||||||
- **OQ4 — Drag-and-drop mechanism & touch. RESOLVED → `MudDropContainer` for now.** Ship with
|
- **OQ4 — Drag-and-drop mechanism & touch. RESOLVED → `MudDropContainer` for now.** Ship with
|
||||||
MudBlazor's `MudDropContainer`. If mobile/touch issues surface in practice, pivot to a touch-viable
|
MudBlazor's `MudDropContainer`. If mobile/touch issues surface in practice, pivot to a touch-viable
|
||||||
mechanism later (pointer-based interop reorder matching `RadialKnob`'s `capturePointer`, or an
|
mechanism later (pointer-based interop reorder matching `RadialKnob`'s `capturePointer`, or an
|
||||||
up/down-arrow fallback). C6 softened: touch-viability is a known risk with a planned pivot path, **not**
|
up/down-arrow fallback). C6 softened: touch-viability is a known risk with a planned pivot path, **not**
|
||||||
a hard pre-ship blocker (see §2 C6).
|
a hard pre-ship blocker (see §2 C6).
|
||||||
- **OQ5 — "Clear queue" in the UI.** Include a Clear action in the overlay header? Does Clear stop
|
- **OQ5 — "Clear queue" in the UI. RESOLVED → yes, in the overlay header.** Include a Clear action in
|
||||||
playback or just empty the up-next (engine's `Clear` does not stop the player today)?
|
the overlay header. Clear empties the up-next but **must NOT stop the currently-playing track and must
|
||||||
- **OQ6 — Embed panel height.** Fixed sensible height with internal scroll past N rows (recommend),
|
NOT remove it** — the current track keeps playing and stays in the queue; only the *other* queued
|
||||||
vs. height that grows with track count up to a cap. Affects `EmbedSnippetBuilder.ForRelease`.
|
tracks are cleared. (Note: this is a tighter contract than the engine's bare `Clear()`, which empties
|
||||||
- **OQ7 — Glyph.** Material `QueueMusic`/`PlaylistAdd`, or a bespoke hand-rolled `DDIcons` queue
|
the whole list — the UI's Clear preserves the current track. This belongs in the 17.2 overlay wiring.)
|
||||||
glyph to match the gas-lamp/lava-lamp family aesthetic?
|
- **OQ6 — Embed panel height. RESOLVED → fixed sensible height with internal scroll past N rows.** Not
|
||||||
|
grow-to-cap. Especially important for the embed. Affects `EmbedSnippetBuilder.ForRelease`. (Road not
|
||||||
|
taken: a height that grows with track count up to a cap — declined in favor of a fixed height with the
|
||||||
|
panel internally scrollable.)
|
||||||
|
- **OQ7 — Glyph. RESOLVED → Material icons for now.** Use `Icons.Material.Filled.QueueMusic` /
|
||||||
|
`PlaylistAdd`. A bespoke hand-rolled `DDIcons` queue glyph (gas-lamp/lava-lamp family aesthetic) is
|
||||||
|
**not pursued in Phase 17** — left open for a later aesthetic pass.
|
||||||
- **OQ8 — Add-to-Queue into a dormant (empty) queue. RESOLVED → pure append.** Add ≠ play; first add
|
- **OQ8 — Add-to-Queue into a dormant (empty) queue. RESOLVED → pure append.** Add ≠ play; first add
|
||||||
into a dormant queue appends and leaves a coherent `CurrentIndex` (small additive engine affordance)
|
into a dormant queue appends and leaves a coherent `CurrentIndex` (small additive engine affordance)
|
||||||
so the next play/skip behaves correctly, but does **not** auto-play. The engine tweak lands with wave
|
so the next play/skip behaves correctly, but does **not** auto-play. The engine tweak lands with wave
|
||||||
**17.1**. (first-add-stages and first-add-plays both declined — see §5.)
|
**17.1**. (first-add-stages and first-add-plays both declined — see §5.)
|
||||||
- **OQ9 — `StreamNowButton`.** Exclude from Add-to-Queue (recommend — no fixed track until resolved)?
|
- **OQ9 — `StreamNowButton`. RESOLVED → exclude.** `StreamNowButton` is excluded from the Add-to-Queue
|
||||||
|
affordance — it is a "surprise me" trigger with no fixed track until one resolves.
|
||||||
- **OQ10 — `ReleaseGallery` cards. RESOLVED → deferred, confirmed.** Browse-grid cards get **no**
|
- **OQ10 — `ReleaseGallery` cards. RESOLVED → deferred, confirmed.** Browse-grid cards get **no**
|
||||||
Add-to-Queue affordance in Phase 17. Item 4 is scoped to the detail-page play sites (Cut header, Cut
|
Add-to-Queue affordance in Phase 17. Item 4 is scoped to the detail-page play sites (Cut header, Cut
|
||||||
track rows, Session/Mix hero). The deferred card work (play + Add-to-Queue, a card-redesign question)
|
track rows, Session/Mix hero). The deferred card work (play + Add-to-Queue, a card-redesign question)
|
||||||
is captured in `TODO.md`.
|
is captured in `TODO.md`.
|
||||||
- **OQ11 — Removing the current track.** Confirm the recommended "keep playing to natural end, don't
|
- **OQ11 — Removing the current track. RESOLVED (jointly with OQ3) → the current track cannot be removed
|
||||||
stop" behavior (C2-consistent) vs. "removing current skips to next immediately."
|
from the UI at all.** Rather than choosing between "keep playing to natural end" and "skip to next," the
|
||||||
|
user-facing answer is that there is **no remove-current action** — the × is suppressed on the current
|
||||||
|
row (see OQ3). Both candidate behaviors are therefore UI-unreachable; the engine's `RemoveAt`-of-current
|
||||||
|
path remains only as defensive engine behavior.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user