From b988e6d72e722108bfcc73419d0d2c3e90d4ff3d Mon Sep 17 00:00:00 2001 From: gramps Date: Mon, 24 Aug 2026 11:04:41 -0700 Subject: [PATCH] Broadcast Text pull-out (Live screen) + launch geometry 1920x1040/1366x768 with restore --- HANDOFF.md | 37 +++--- MainWindow.xaml | 138 +++++++++++++++++--- MainWindow.xaml.cs | 48 +++++++ Models/BroadcastMetadata.cs | 20 +++ Services/LayoutStore.cs | 49 ++++++++ Services/LiveBroadcastFormViewModel.cs | 168 +++++++++++++++++++++++++ Services/YouTubeStreamService.cs | 47 ++++++- TASKS.md | 2 + ViewModels/MainViewModel.cs | 43 ++++--- ai.md | 17 +++ ytLive.Tests/BroadcastPullOutTests.cs | 149 ++++++++++++++++++++++ 11 files changed, 670 insertions(+), 48 deletions(-) create mode 100644 Models/BroadcastMetadata.cs create mode 100644 Services/LiveBroadcastFormViewModel.cs create mode 100644 ytLive.Tests/BroadcastPullOutTests.cs diff --git a/HANDOFF.md b/HANDOFF.md index bc8a3cb..7b41014 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -2,33 +2,36 @@ ## Branch **`main`** @ HEAD — committed and pushed, working tree clean. **No feature branches pre-1.0 -(decided 2026-08-24): all work lands on `main` per work unit; every `taskNN-*` branch deleted** -(TASK 24/25/26+27 fast-forwarded into main; stale `social-bar`/`webcam-validation` removed too). +(decided 2026-08-24): all work lands on `main` per work unit; every `taskNN-*` branch deleted.** -## Shipped (this session, now all on main) -- TASK 26 — webcam (+) menu gates on the app-wide identity (`CanAddWebcam` = staged != null && `_webcam == null`; XAML binding + tooltip; test `WebcamMenuGateTests`). -- TASK 27 — YouTube Chat layer one-per-layout gate (`CanAddYouTubeChat`, AddSource refuses a second) + legacy label heal ("Chat" → "YouTube Chat" on LoadLayout; creator renames untouched; test `ChatLayerGateTests`). Creator's ask: "do the same thing with the YouTube chat layer" + make the Layers row match the (+) picklist. -- TASK 19/23 status flip — code survey confirmed Control Surface UX fully shipped (thumbnail strip, two-state left panel, right panel gone, transitions, edit gating); map corrected. -- **TASK 20 step 1 — global hotkeys** (`Services/GlobalHotkeys.cs`, `MainViewModel.HandleHotkey`, `MainWindow.OnSourceInitialized` wiring): F1-F5 canonical scenes, F6 start/end stream, F7 mic mute, F8 desktop mute, F9 TRAX. `IHotkeyRegistrar` seam + `RegistrarOverride`. Test `GlobalHotkeyTests.WmHotkey_StagesScene_And_TogglesMic_And_RevokesOnClose`. Hotkeys validated by creator. -- **ON-AIR sign** (creator ask): new status light + "ON-AIR" right of REC in the top bar (`OnAirBrush`: gray offline / red public / green private); old left-of-REC hardcoded indicator removed. Labels share one `StatusSignText` style in Controls.xaml (creator dinged inconsistency when ON-AIR text took the status color — labels are neutral, dots carry state). Test `OnAirSignTests.OnAirBrush_Follows_Offline_Public_And_Private`. -- Suite: 227 total, 226 pass — only failure is the known pre-existing `AudioPipelineTests.Mix_HonorsProviderGains_AndGameMute_KillsTheLoopback`. Build 0 warnings. Docs shipped same-commit. -- Visual pass on TASK 26/27 validated by creator (2026-08-24). +## Shipped (this session, all on main) +- TASK 26 — webcam (+) menu gates on the app-wide identity (test `WebcamMenuGateTests`). +- TASK 27 — YouTube Chat one-per-layout gate + legacy label heal (test `ChatLayerGateTests`). +- TASK 19/23 status flip — Control Surface UX verified shipped; map corrected. +- TASK 20 step 1 — global hotkeys F1-F9 (`Services/GlobalHotkeys.cs`, test `GlobalHotkeyTests`). Validated by creator. +- ON-AIR sign right of REC — gray offline / red public / green private (`OnAirBrush`), shared `StatusSignText` style so REC/ON-AIR can't drift (creator dinged inconsistency when labels took different colors). Test `OnAirSignTests`. +- **Broadcast metadata pull-out + launch geometry** — white "Text" tab on preview's right edge (Live screen only) slides out the broadcast form: Title, Description, Tags csv, Visibility, Made-for-Kids, read-only Scheduled Start. Edits persist to Settings `Broadcast.*` immediately; Update Broadcast PUTs `liveBroadcasts?part=snippet,status` via new `YouTubeStreamService.UpdateBroadcast`. Go Live prefills from the form + captures back what was inserted. Old Default Stream Title/Description removed from App Settings (properties deleted). Window: default 1920×1040, MinWidth 1366, MinHeight 768, Manual startup, size+position persisted on close (`RestoreBounds`) and restored clamped to minimums + primary work area. Test `BroadcastPullOutTests.Metadata_Persists_WindowRestores_Clamped_And_UpdatePatchesRemote`. +- Suite: 228 total, 227 pass — only failure is the known pre-existing `AudioPipelineTests.Mix_HonorsProviderGains_AndGameMute_KillsTheLoopback`. Build 0 warnings. Docs same-commit throughout. ## ⚠️ Landmines -- **User verdict (2026-08-23):** "The AI wrote fucked up code after repeatedly and intentionally misunderstanding instructions." Extends the ai.md 2026-08-22 audit flag — trust nothing from those sessions without manual verification. -- **Pre-existing test failure is ONE** (`AudioPipelineTests.Mix_HonorsProviderGains_AndGameMute_KillsTheLoopback`) — not caused by these branches. +- **User verdict (2026-08-23):** "The AI wrote fucked up code after repeatedly and intentionally misunderstanding instructions." Trust nothing from those sessions without manual verification. +- **Pre-existing test failure is ONE** (`AudioPipelineTests.Mix_HonorsProviderGains_AndGameMute_KillsTheLoopback`) — unrelated to this session. - **Real-MainWindow tests MUST set `LayoutPathOverride`** (ai.md) — DB pollution wiped real data once. -- **WPF handle forcing:** `WindowInteropHelper.Handle` pre-show returns Zero and does NOT raise `SourceInitialized`; use `EnsureHandle()` (does both). Cost a debug cycle in GlobalHotkeyTests. +- **WPF handle forcing:** `WindowInteropHelper.Handle` pre-show returns Zero and does NOT raise `SourceInitialized`; use `EnsureHandle()` (does both). +- **Two MainWindows alive at once double-register hotkeys** — second window's RegisterHotKey fails silently-by-log. Tests close windows before opening the next. +- **Closing a MainWindow OVERWRITES saved window geometry** (Closing → SaveWindowGeometry). In tests that assert restore-from-DB, save state AFTER closing prior windows. +- **liveBroadcasts.update replaces the whole snippet part** — `UpdateBroadcast` echoes scheduledStartTime or YouTube clears the schedule. +- **contentDetails lock in created/ready** — latency/DVR/embed etc. cannot be edited while live; deliberately absent from the pull-out form. - **`Source.Type` setter derives `IsBackground`** (Models/Source.cs:40) — any Type change must re-set IsBackground after. - **vstest quirk:** only one `--tests:` param allowed; plain substrings work, alternation regexes silently match nothing. - Notification.Wpf gotchas (ai.md/TASKS.md): area routing by XAML `Name`; unknown AreaName silently drops; `NeverExpires()` = `TimeSpan.MaxValue`; `ToHex()` = `#AARRGGBB`. -- **Dead code flagged, not touched:** `ShowWebcamCommand` / `CanShowWebcamInStagedScene` are wired in the VM but bound nowhere — audit item, separate branch if wanted. +- **Dead code flagged, not touched:** `ShowWebcamCommand` / `CanShowWebcamInStagedScene` wired but unbound — audit item. ## Next steps -1. Creator visual pass: ON-AIR sign states (gray offline → red on public live → green on private live). -2. Continue TASK 20: config UI + schema persistence for bindings (then conflict detection). -3. Queue after TASK 20: TASK 21 media source, TASK 22 audio sync offset, TASK 17 web source, TASK 18 local recording. +1. Creator visual pass: Text tab appears only while streaming; drawer slides over preview; fields pre-load across restarts; Update button greys until Go Live succeeds (needs real OAuth round-trip to verify remotely). +2. First-launch check: window opens 1920×1040 centered; resize/move/close/reopen restores geometry; can't shrink below 1366×768. +3. Continue queue: TASK 20 step 2 (hotkey config UI + persistence), TASK 17 web source, TASK 18 local recording, TASK 21 media source. 4. Loose ends: dead `ShowWebcamCommand`, AudioPipelineTests failure, Velopack update URL. ## Build diff --git a/MainWindow.xaml b/MainWindow.xaml index 1d55e69..9c70d65 100644 --- a/MainWindow.xaml +++ b/MainWindow.xaml @@ -8,11 +8,11 @@ xmlns:Helpers="clr-namespace:ytLive.Helpers" xmlns:notifications="clr-namespace:Notification.Wpf.Controls;assembly=Notification.Wpf" mc:Ignorable="d" - Title="{Binding WindowTitle}" Height="720" Width="1280" - MinWidth="1180" MinHeight="600" + Title="{Binding WindowTitle}" Height="1040" Width="1920" + MinWidth="1366" MinHeight="768" Icon="/ytLive;component/Assets/llamacasty-icon.png" Background="#1a1a2e" - WindowStartupLocation="CenterScreen" + WindowStartupLocation="Manual" Closing="MainWindow_Closing" Loaded="MainWindow_Loaded" Activated="MainWindow_Activated" @@ -1114,6 +1114,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +