docs(plan): mark Phase 20 Theater Mode scoped after sign-off

This commit is contained in:
daniel-c-harvey
2026-06-20 21:40:56 -04:00
parent 021801999c
commit 835fb71337
2 changed files with 43 additions and 54 deletions
+10 -13
View File
@@ -462,10 +462,10 @@ across all three; the Session-doesn't-use-the-scaffold asymmetry is the key cons
works around. works around.
**Architectural spine.** **One boolean, multiple observers** (memory: *one source, multiple views*). **Architectural spine.** **One boolean, multiple observers** (memory: *one source, multiple views*).
Recommended home: **widen `WaveformVisualizerControlState` with a `TheaterMode` flag** (Option A — the State home (OQ3, resolved): **widen `WaveformVisualizerControlState` with a `TheaterMode` flag**
object is already scoped, session-persistent, observed via its `Changed` event, gated on the same the object is already scoped, session-persistent, observed via its `Changed` event, gated on the same
`LavaEnabled || WaveformEnabled` the Theater button reads, and *explicitly designed to widen by adding a `LavaEnabled || WaveformEnabled` the Theater button reads, and *explicitly designed to widen by adding a
field + default*); the SRP-purist alternative is a dedicated `TheaterModeState` holder (Option B). The field + default*. The
**detail pages own only the content `@if`** (each page gates the fragments it renders, so the scaffold **detail pages own only the content `@if`** (each page gates the fragments it renders, so the scaffold
stays Theater-unaware and Session is covered the same way); the **player bar owns only the enlargement** stays Theater-unaware and Session is covered the same way); the **player bar owns only the enlargement**
(reads `CurrentTrack.Release` — `Title`/`ImagePath`/`EntryKey`/`Medium`, all already on the DTO — and (reads `CurrentTrack.Release` — `Title`/`ImagePath`/`EntryKey`/`Medium`, all already on the DTO — and
@@ -482,17 +482,14 @@ existing theme-aware aliases (`--deepdrft-page-surface`/`-text`/`-text-muted`),
visible only when `LavaEnabled || WaveformEnabled`, disabled until interactive, with an on/off active visible only when `LavaEnabled || WaveformEnabled`, disabled until interactive, with an on/off active
state. Material `Theaters` glyph for v1 (bespoke `DDIcons` deferred — Phase 17 OQ7 precedent). state. Material `Theaters` glyph for v1 (bespoke `DDIcons` deferred — Phase 17 OQ7 precedent).
**Open questions for Daniel (spec §9) — none block a first cut, but several are genuine product calls:** **Open questions — all six resolved (Daniel, 2026-06-20; spec §9).** OQ1: Material `Theaters` glyph for
(OQ1) Theater icon — Material `Theaters` vs. bespoke (recommend Material now); (OQ2) bar enlargement when v1. OQ2: playing-release only — bar stays a pure function of player state. OQ3: Option A — widen
nothing is playing — page's release vs. playing-release-only (recommend playing-only, keeps the seam `WaveformVisualizerControlState` with a `TheaterMode` flag. OQ4: top action row (back, lava, theater)
clean); (OQ3) state home — Option A widen vs. Option B dedicated holder; (OQ4) back link stays in Theater stays visible — it's controls, not content. OQ5: session-scoped, resets to OFF on fresh page load.
(recommend keep — it's navigation chrome); (OQ5) persistence — session-scoped/reset-on-reload vs. cookie OQ6: detail-pages-only for v1; no Theater affordance on the home hero.
(recommend session-scoped, matches visualizer-state precedent); (OQ6) Theater on the home hero/NowPlaying
panel too, or detail-pages-only (recommend detail-pages-only for v1, as scoped).
**Status: proposed — awaiting Daniel sign-off on §9 before scoping waves.** Cold-start once signed off; **Status: scoped and approved — Phase 20, Wave 1.** Cold-start; no dependency on any in-flight phase
no dependency on any in-flight phase (Phases 11/16/17 — the player bar, queue, and visualizer it builds (Phases 11/16/17 — the player bar, queue, and visualizer it builds on — are all complete).
on — are all complete).
--- ---
+33 -41
View File
@@ -1,6 +1,6 @@
# Phase 20 — Theater Mode (public Release Detail views) # Phase 20 — Theater Mode (public Release Detail views)
Product spec. Status: **proposed, awaiting Daniel sign-off on the open questions in §9.** Product spec. Status: **scoped and approved for implementation — Phase 20, Wave 1** (Daniel sign-off 2026-06-20; all §9 open questions resolved).
Surface: **public listener site only** (`DeepDrftPublic` / `DeepDrftPublic.Client`). No CMS Surface: **public listener site only** (`DeepDrftPublic` / `DeepDrftPublic.Client`). No CMS
(`DeepDrftManager`) change. No API, data, or schema change — Theater Mode is a pure (`DeepDrftManager`) change. No API, data, or schema change — Theater Mode is a pure
presentation-layer feature riding data the player already carries. presentation-layer feature riding data the player already carries.
@@ -72,10 +72,10 @@ this.
4. **Disabled until interactive** (`!RendererInfo.IsInteractive`) — same guard the lava-lamp button and 4. **Disabled until interactive** (`!RendererInfo.IsInteractive`) — same guard the lava-lamp button and
Play buttons already carry, so it does nothing during prerender. Play buttons already carry, so it does nothing during prerender.
**Iconography:** Material `Theaters` (a film-strip glyph) is the obvious stock choice and reads as **Iconography:** Material `Theaters` (a film-strip glyph). A bespoke `DDIcons` glyph in the
"theater" immediately. A bespoke `DDIcons` glyph in the hand-rolled house style is the higher-craft hand-rolled house style is the higher-craft option but is **not** required for v1 (this matches the
option but is **not** required for v1 (this matches the Phase 17 OQ7 precedent — Material icons now, Phase 17 OQ7 precedent — Material icons now, bespoke later). **Resolved: Material `Theaters` for v1
bespoke later). **Open question OQ1 (§9).** (OQ1, Daniel 2026-06-20).**
--- ---
@@ -134,13 +134,10 @@ state without the detail page reaching across to it.
**Edge — Theater ON but nothing playing:** the bar's enlargement keys off `CurrentTrack?.Release`. If no **Edge — Theater ON but nothing playing:** the bar's enlargement keys off `CurrentTrack?.Release`. If no
track is playing (the listener opened the page and toggled Theater without pressing play), there is no track is playing (the listener opened the page and toggled Theater without pressing play), there is no
current release to surface in the bar. **Open question OQ2 (§9):** does Theater Mode surface *the page's* current release to surface in the bar. **Resolved (OQ2, Daniel 2026-06-20): playing-release only**
release in the bar even when not playing (the page knows its release), or only the *playing* release the bar stays a pure function of player state; no detail-page→bar data push. The listener who toggles
(simpler, but the bar shows nothing extra until play starts)? Recommendation: **playing-release only** Theater is almost always already listening; the visualizer itself is blank until a track resolves, so a
keeps the bar a pure function of player state and avoids a detail-page→bar data push that would blank-ish enlarged bar in that rare pre-play window is coherent.
re-entangle the two. The listener who toggles Theater is almost always already listening; the visualizer
itself is blank until a track resolves, so a blank-ish enlarged bar in that rare pre-play window is
coherent.
--- ---
@@ -174,11 +171,11 @@ Two viable homes for the boolean:
(`LavaEnabled || WaveformEnabled`) to know whether to show the button, so the two are coupled at the (`LavaEnabled || WaveformEnabled`) to know whether to show the button, so the two are coupled at the
read site anyway. read site anyway.
**Steer: Option A.** The visualizer-control state is already the "how the visualizer presents" object, **Resolved (OQ3, Daniel 2026-06-20): Option A** — widen `WaveformVisualizerControlState` with a
`TheaterMode` flag. The visualizer-control state is already the "how the visualizer presents" object,
Theater Mode is a visualizer-presentation concern, and the object was explicitly designed to widen this Theater Mode is a visualizer-presentation concern, and the object was explicitly designed to widen this
way. Option B is the defensible SRP-purist alternative if Daniel wants the visualizer dials kept way. Final structural call is staff-engineer's at implementation (matching the standing convention on
pristine. **Open question OQ3 (§9).** Final structural call is staff-engineer's at implementation `IQueueService`-shape decisions).
(matching the standing convention on `IQueueService`-shape decisions).
**Why this satisfies SOLID / the "cleanly separated concerns" constraint:** **Why this satisfies SOLID / the "cleanly separated concerns" constraint:**
- **Single source of truth, multiple observers.** One boolean; the three pages observe it for the - **Single source of truth, multiple observers.** One boolean; the three pages observe it for the
@@ -247,31 +244,26 @@ convention. **No new per-component dark overrides.** Concretely:
--- ---
## 9. Open questions (Daniel decisions, not implementation calls) ## 9. Open questions — all resolved (Daniel, 2026-06-20)
- **OQ1 — Theater toggle icon.** Material `Theaters` (film-strip) for v1, or commission a bespoke All six open questions are resolved. Every resolution matches the spec's recommendation.
`DDIcons` glyph in the hand-rolled house style? *Recommend: Material `Theaters` now, bespoke deferred
(Phase 17 OQ7 precedent).* — **product call.** - **OQ1 — Theater toggle icon. RESOLVED: Material `Theaters` (film-strip) for v1.** Bespoke `DDIcons`
- **OQ2 — bar enlargement when nothing is playing.** Surface the *page's* release in the bar even with no glyph deferred (Phase 17 OQ7 precedent).
current track (needs a page→bar data path), or only the *playing* release (bar stays a pure function of - **OQ2 — bar enlargement when nothing is playing. RESOLVED: playing-release only.** The bar stays a
player state)? *Recommend: playing-release only.* — **product + architecture call; the recommendation pure function of player state; no page→bar data path. The listener who opens Theater without pressing
keeps the SOLID seam clean, so it leans toward an implementation default unless Daniel wants the play sees a blank-ish enlarged bar — coherent, because the visualizer itself is also blank.
page's release shown pre-play.** - **OQ3 — state home. RESOLVED: Option A — widen `WaveformVisualizerControlState` with a `TheaterMode`
- **OQ3 — state home.** Extend `WaveformVisualizerControlState` with `TheaterMode` (Option A, flag.** Theater Mode is a visualizer-presentation concern; the object was explicitly designed to widen
recommended) or a dedicated `TheaterModeState` holder (Option B, SRP-purist)? — *Structural; this way. Staff-engineer makes the final structural call at implementation.
staff-engineer's final call, but Daniel may have a taste here.* - **OQ4 — back link in Theater Mode. RESOLVED: stays visible.** The top action row (back, lava-lamp,
- **OQ4 — does the back link stay in Theater Mode?** Recommendation keeps it (it is navigation chrome, theater) is controls, not release content — it remains in Theater Mode.
not release content). Confirm Daniel agrees the top action row (back + lava + theater) is "controls," - **OQ5 — persistence scope. RESOLVED: session-scoped, resets to OFF on fresh page load.** Persists
not "content." *Recommend: keep.* — **product call, low-stakes.** across SPA navigation within a session; a full reload (F5) resets it to OFF. Matches the
- **OQ5 — persistence scope.** Theater Mode follows the visualizer-state convention: persists across SPA visualizer-control-state precedent; no cookie round-trip.
navigation within a session, resets to OFF on a fresh page load (F5). Confirm that is the wanted - **OQ6 — Theater on the home hero / NowPlaying panel. RESOLVED: detail-pages-only for v1.** The three
behavior (vs. a cookie that remembers Theater across reloads). *Recommend: session-scoped, reset on Release Detail views are the scope; the home hero's `WaveformVisualizerControlPopover` does not get a
reload — matches the visualizer-control-state precedent; no cookie round-trip.* — **product call.** Theater affordance in this phase.
- **OQ6 — Theater on the home hero / NowPlaying panel?** The `WaveformVisualizerControlPopover` also
appears on the home hero's NowPlaying panel (mode C). This spec scopes Theater Mode to the **three
Release Detail views only** (Daniel's framing). Flag: should the home hero get a Theater affordance
too, or is it deliberately detail-pages-only? *Recommend: detail-pages-only for v1, as scoped.*
**product call, adjacent.**
--- ---
@@ -295,7 +287,7 @@ convention. **No new per-component dark overrides.** Concretely:
8. No API / data / schema change. No CMS change. The enlarged bar reads only `CurrentTrack.Release` 8. No API / data / schema change. No CMS change. The enlarged bar reads only `CurrentTrack.Release`
fields the DTO already carries. fields the DTO already carries.
9. Theater Mode persists across SPA navigation within a session and resets to OFF on a fresh page load 9. Theater Mode persists across SPA navigation within a session and resets to OFF on a fresh page load
(per OQ5, if confirmed). (OQ5, confirmed).
--- ---