feat(ui): Show Desktop toggle, avatar login, chat preview, backdrop seeding, border animations
- Source.ShowDesktop bool persisted in DB (schema migration + LayoutStore) - ClearBackdropCaptureAsync clears CaptureKey + VideoImageSource for static fallback - Top bar: red/green/pulsing status light, avatar via BitmapImage, Log In button - ShowStartStream now requires IsConnected - RunMockChatPreviewAsync: simple async loop, ChatPreviewEnabled property on Source - EnsureDefaultBackdrop called on every scene switch, seeds all 5 scenes - SeedEndingBackdrop replaces existing, SeedChatBackdrop added - SceneCatalog: Chat scene display name corrected (layer = 'YouTube Chat') - Left panel spacing consistency, context menu reordered - Border animation rendering via code-behind Storyboard approach - 3 new backdrop assets (ending-backdrop.jpg, chat-backdrop.jpg, live-backdrop.jpg) - Build 0 warnings, 178 tests passing
This commit is contained in:
@@ -120,6 +120,12 @@ Lifecycle: `created → ready → [testing] → live → complete` (transitional
|
||||
18. ✅ **Chat box** — YouTube live chat rendered *on* the stream so viewers read along in-video — `ChatBoxRenderer` (WPF FormattedText → VideoFrame), configurable font size/color/badges/timestamps/max-messages via Elements panel, schema v10, persisted across save/load
|
||||
19. ❌ **Background removal (milestone 2)** — ONNX Runtime + DirectML, MediaPipe Selfie Segmentation — deliberately NOT in this build
|
||||
20. ☐ **Alerts** — Super Chat / membership / subscribe pop-ins; build after the six; **the one paid feature** (see Monetization in `ai.md`)
|
||||
21. ✅ **Show Desktop toggle** — `Source.ShowDesktop` bool persisted in DB (schema migration + LayoutStore read/write). When checked, primary monitor captures regardless of fullscreen game state. Toggling off falls back to running game or releases to static placeholder. `ClearBackdropCaptureAsync` clears `CaptureKey` + `VideoImageSource` so static fallback renders. Toggle on Live backdrop context menu (IsCheckable MenuItem).
|
||||
22. ✅ **Top bar — status light + avatar + Log In button** — red/green/pulsing ellipse (disconnected/connected/live). Avatar border visible only when connected, loads via `BitmapImage` code-behind. "Log In" button visible when disconnected, calls `StartStreamCommand` → GoLiveWindow. `ShowStartStream` now requires `IsConnected`.
|
||||
23. ✅ **Chat preview — one-at-a-time mock messages** — `RunMockChatPreviewAsync`: simple async loop, displays `MockChatMessages[n]` via `Take(n+1)`, 1000ms between messages, wraps at end. `ChatPreviewEnabled` property on Source (default true). Stops on real messages, restarts on fade timer clear.
|
||||
24. ✅ **All backdrops seeded + EnsureDefaultBackdrop** — Live, Chat, Ending backdrops added (ending-backdrop.jpg replaced). `EnsureDefaultBackdrop()` called on every scene switch. `SeedEndingBackdrop` replaces existing (not skip-if-exists). Chat scene no longer skipped.
|
||||
25. ✅ **SceneCatalog fix** — Chat scene display name corrected to "Chat" (was "YouTube Chat" — that name belongs to the layer/SourceType.ChatBox, not the scene).
|
||||
26. ✅ **Left panel spacing + context menu reorder** — HR margins matched, Row 4 changed from `*` to `Auto`. Context menu reordered: Border Thickness first, then Opacity, Color, Effect.
|
||||
21. ✅ **Logo + richer in-app About (2026-08-13, queued → 2026-08-14 SHIPPED)** — the ytLlive wordmark in the top bar opens the About overlay (already wired); the About overlay is now the **creator hub**: the real logo (the "llama fortnite superman logo" from the creator's vault, copied to `Assets/llama-logo.png` — the creator's own art, no third-party license), plus **creator-hub links** — llama chile shop on YouTube (`MainViewModel.ChannelUrl`), Mastodon (`https://mastodon.llamachile.tube/@gramps`), **Buy me a coffee** (`https://buymeacoffee.com/llamachiley` — live), and **Unlock Premium** (greyed "coming soon" — the **billing** product URL is a tabled seam, `PremiumUrl`, until TASK 10 picks the subscription provider). A **Licenses & legal** button flips the About overlay to an in-app scrolling panel that loads the full `THIRD-PARTY-NOTICES.txt` text (`MainViewModel.ShowLicenses` reads the shipped file from the executable directory on first open; graceful "not found" fallback — **never the OS viewer, everything stays in-app**); "← Back to About" returns. The About overlay is also the in-app home of the notices — the top-bar About button that opened the file in the OS viewer was removed on 2026-08-13 for exactly this reason. Integration test (Good Dog Rule — ONE): `AboutHubTests.About_Opens_InApp_Licensing_Loads_Shipped_Notices` drives the real window + VM, asserting the hub opens, the link URLs are real, the licensing panel loads the shipped notices text (contains "Third-Party Notices" + "LGPL"), and back returns to the hub. 174 tests passing, 0 warnings
|
||||
22. ✅ **Voice filters on the mic channel (2026-08-13 queued → SHIPPED 2026-08-14 inside TASK 9, the audio milestone)** — the standard four applied to the sound input path (before the meter/encoder mix): **bass boost, treble, noise suppression, compressor** (set decided with the creator 2026-08-13). Noise suppression = a **pure-C# noise gate** (creator chose over RNNoise / a second ffmpeg `afftdn` pipe, 2026-08-14 — KISS). Always-on — no UI knobs; the mic stays the creator's single audio control
|
||||
|
||||
@@ -848,14 +854,14 @@ No changes to `MusicPlayer`, the 0.20 cap, the ducker, or the meter zones. Build
|
||||
**Goal:** branded background images for each canonical scene (Starting, Live, BRB, Chat, Ending)
|
||||
that both provide working hints to creators and self-promote LlamaCasty.
|
||||
|
||||
### Status: 🔶 2/5 seeded — Starting and BRB done; Live, Chat, Ending waiting on user images
|
||||
### Status: ✅ Shipped — all 5 scenes seeded
|
||||
|
||||
1. ✅ **Starting backdrop** — `Assets/starting-backdrop.jpg` (embedded resource), `SeedStartingBackdrop()` in MainViewModel, idempotent
|
||||
2. ✅ **BRB backdrop** — `Assets/brb-backdrop.jpg` (user-provided Gemini image), `SeedBrbBackdrop()` in MainViewModel, idempotent
|
||||
3. ☐ User provides 3 more background images (Live, Chat, Ending), PNG/JPG format, 1920×1080
|
||||
4. ☐ Wire images as default `Background` sources, auto-populated on DB seed
|
||||
5. ☐ Assets stored in DB via `Asset` table (BLOB, SHA-256 keyed) — survives file deletion
|
||||
6. ☐ Used by TASK 16 (infinity display fix) as the static fallback when no game is detected
|
||||
3. ✅ **Live backdrop** — `Assets/live-backdrop.jpg` (user-provided image), seeded via `SeedLiveBackdropAsset()`, used as the static fallback (TASK 16)
|
||||
4. ✅ **Ending backdrop** — `Assets/ending-backdrop.jpg` (user-provided image), `SeedEndingBackdrop()` replaces existing (not skip-if-exists)
|
||||
5. ✅ **Chat backdrop** — `Assets/chat-backdrop.jpg` (user-provided image), `SeedChatBackdrop()` at startup
|
||||
6. ✅ `EnsureDefaultBackdrop()` called on every scene switch — seeds the default backdrop if scene has none
|
||||
|
||||
### Design decisions
|
||||
|
||||
@@ -870,22 +876,24 @@ that both provide working hints to creators and self-promote LlamaCasty.
|
||||
**Goal:** when no full-screen game is detected, show a static branded placeholder instead of
|
||||
capturing the primary display (which causes the infinity mirror effect).
|
||||
|
||||
### Status: ☐ Not started — depends on TASK 15
|
||||
### Status: ✅ Shipped
|
||||
|
||||
1. ☐ Modify `ResolveAutoCaptureKey()` (`MainViewModel.cs:1482`) — return null when no game detected
|
||||
instead of falling back to primary monitor
|
||||
2. ☐ Modify `EnsureBackdrop()` — when `CaptureKey` is null, show the scene's `Background` image
|
||||
(the stock image from TASK 15) instead of creating a capture session
|
||||
3. ☐ "Change Capture…" still available — user can manually pick a display/window via the picker
|
||||
4. ☐ `ReacquireScreenCaptures()` handles null capture key gracefully (no `ScreenCaptureManager.AcquireAsync` call)
|
||||
5. ☐ Update `ai.md` screen backdrop section to document the null-capture-key behavior
|
||||
**Changes:**
|
||||
1. `ResolveAutoCaptureKey()` returns `null` when no full-screen game is detected (was: primary monitor)
|
||||
2. `ReacquireScreenCaptures()` — clears stale `CaptureKey` when `auto == null` (handles DB upgrades);
|
||||
skips `AcquireAsync` when no keys are set
|
||||
3. `SeedLiveBackdropAsset()` — sets `AssetId` on the backdrop element itself (NOT a Background source);
|
||||
called from `ReacquireScreenCaptures()` after `EnsureBackdrop()` guarantees the element exists
|
||||
4. `Source.DisplaySource` falls back to `_imageSource` when `VideoImageSource` is null for live captures
|
||||
5. `Assets/live-backdrop.jpg` — user-provided image, added as `<Resource>` in csproj
|
||||
6. `ResolveOutputFrame()` in compositor — `Source { IsLiveCapture: true, CaptureKey: not null }` already skips null keys; fallback pattern `Source { AssetId: not null }` picks up the static image
|
||||
|
||||
### Design decisions
|
||||
|
||||
- **Option A from user review:** static placeholder when no game, not multi-monitor fallback
|
||||
- The user-provided stock bg image from TASK 15 IS the placeholder — no separate asset needed
|
||||
- Manual capture pick still works — the user can always force a display capture via right-click → "Change Capture…"
|
||||
- Single-monitor setups no longer show the infinity mirror
|
||||
**Rendering flow:**
|
||||
| Scenario | Preview | Compositor |
|
||||
|---|---|---|
|
||||
| Game detected | Live capture (opaque, covers static asset on backdrop) | `ScreenCaptureManager.GetLatestFrame` |
|
||||
| No game | Static image via `DisplaySource` → `_imageSource` on backdrop | `StaticPixelCache.Get(assetId)` |
|
||||
| Manual capture pick | Live capture | Live frame |
|
||||
|
||||
---
|
||||
|
||||
@@ -954,9 +962,8 @@ The tasks below are ordered by dependency and risk. Each task builds on the prev
|
||||
8. **TASK 21** — Media source — video file playback for non-Live scenes.
|
||||
9. **TASK 22** — Audio sync offset — small, quality-of-life.
|
||||
10. **TASK 23** — Studio mode — lightweight preview before live.
|
||||
11. **TASK 15** — Stock bg images — Starting and BRB seeded; Live, Chat, Ending still waiting on user.
|
||||
12. **TASK 16** — Infinity display fix — depends on TASK 15.
|
||||
13. **TASK 13** — Social media launch kit — after all v1 features ship.
|
||||
11. ✅ **TASK 15** — Stock bg images — all 5 scenes seeded (Starting, BRB, Live, Chat, Ending). `EnsureDefaultBackdrop()` runs on every scene switch.
|
||||
12. **TASK 13** — Social media launch kit — after all v1 features ship.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user