Backgrounds: one locked Background per screen + mini rule (TASK 25)

This commit is contained in:
2026-08-23 13:33:33 -07:00
parent b400ab59c5
commit 7dd140a4c0
13 changed files with 554 additions and 309 deletions
+49
View File
@@ -1096,6 +1096,55 @@ Deliberately left alone: offline license re-validation skip (log-only — would
---
## TASK 25 — Background consolidation: one locked Background per screen + mini-view rule
### Status: ✅ Done (shipped 2026-08-23, branch `task25-backgrounds`)
The creator rejected the multi-concept background model ("why are there multiple background
things?"). Locked model, verbatim intent:
1. **Exactly ONE background per screen**, named "Background", at position 0.
2. It cannot be re-ordered or deleted; **no Background/Screen item in the (+) menu**.
3. Context-sensitivity exists **only on the Live screen** (Show Desktop toggle + monitor
switching — behavior kept intact).
4. **Exactly five default background images** live in the DB; stale rows are cleaned up.
### What shipped:
- **Seeder consolidation:** the five near-clone seeders (`Seed{Starting,Brb,Ending,Chat}Background`,
`SeedLiveBackgroundAsset`, `EnsureDefaultBackground`) are gone. One path now:
`EnsureBackground(scene)` → `CreateBackground(name)` — Live = `DisplayCapture` row (capture
machinery untouched), everything else = static `Background` art row; both named "Background".
- **Heal on every load:** `NormalizeBackgrounds(scenes)` keeps the correctly-flavored row,
converts a wrong-flavor survivor in place (`Source.Type`'s setter derives `IsBackground` —
conversions must re-assert the flag), drops duplicates, seeds missing ones, renames, pins to
index 0; non-canonical scenes lose backgrounds + flag. `HealBackgrounds()` stamps default art
(`Assets/{scene}-background.jpg` via `AddAsset`; custom Browse art wins). This fixed the real DB's
rot: four scenes carried a stray "Game Capture" duplicate beside their static row, and Settings
held 16 orphaned `BackgroundUseDefault_{guid}` keys.
- **Settings purge:** `LayoutStore.Save` deletes `BackgroundUseDefault_{id}` / `BackgroundPath_{id}`
keys whose id is no longer a Source row.
- **(+) menu:** Screen + Background items removed → Webcam/Image/Text/Countdown/Web/YouTube Chat;
`AddSource` also hard-refuses DisplayCapture/WindowCapture/Background parameters.
- **Capture controls Live-only:** `CanChangeBackground` = staged scene is Live. The preview
CanvasGrid menu (Show Desktop/Capture Desktop/Refresh Desktop) binds it directly; the layer-row
context menu MultiBindings it with the row's `IsBackground` through a new
`Helpers/AllTrueToVisibilityConverter`. Non-Live screens keep the Use-default pill + Browse.
- **Mini rule:** minis never render live captures. While Live is staged its mini shows the green
placeholder; unstaged it shows `live-background.jpg`. Fixed by making `LoadBackgroundImage`
flavor-blind (`IsBackground`) and gating staged-Live to the placeholder in `RefreshSnapshotsAsync`.
(Real-time rendering stays center-monitor-only — preview lag during live gameplay is a known
unsolved OS-level problem and must not be compounded.)
### Tests (suite went 221/218 → 223/220; the two stale background-policy landmine tests healed here):
- Integration (the ONE): `BackgroundHealIntegrationTests` — seeds a dirty temp DB (duplicate rows,
misnamed Live row, orphaned keys), drives the real window, asserts one Background per scene at
index 0 with correct flavor/name, save purges the orphaned keys.
- Unit: SceneCatalogTests rewritten for NormalizeBackgrounds/EnsureBackground flavors;
BackgroundTests empty-scene flavor updated; SourceNamingTests excludes the always-present
Background from numbered-name expectations.
---
## Backlog (future versions)
1. v1.1 — Stream Deck / Loupedeck integration (requires hotkey foundation from TASK 20)