TASK 4 ship step 7: one-click go live + private-only enforcement (req 8) — the Go Live dialog is locked to Private (GoLiveViewModel.Visibility is a get-only string, no dropdown; settings' dead Default Visibility dropdown + Visibilities/DefaultStreamVisibility removed); YouTubeStreamService.CreateBroadcast always sends privacyStatus='private' and gained an injectable HttpClient? http = null seam; BeginGoLive fires CreateBroadcastAsync which stashes _currentBroadcastId for TASK 5's bind/transition (failure → StreamStatus.Error via AppLog, never a crash) alongside the frame pump, and StopStream clears it; the REC sign shows a dark-red PRIVATE badge next to REC whenever the live stream is private (IsLivePrivate) — the broadcast-insert integration test asserts the request body carries privacyStatus private (RecordingHandler seam) + a no-session guard test — 173 tests passing, 0 warnings
This commit is contained in:
+33
-47
@@ -5,49 +5,42 @@
|
||||
> a problem. Conventions: [`schema.md`](schema.md). Rewrite this file at session
|
||||
> end, compaction, or any interruption.
|
||||
|
||||
## Session state (last updated: 2026-08-13)
|
||||
## Session state (last updated: 2026-08-14)
|
||||
|
||||
- **Branch:** `main`, in sync with `origin/main`.
|
||||
- **TASK 8 (new, after TASK 7 shipped):** `AudioLevelMeter.ToDisplay` gained **+10 dB input
|
||||
amplification** so the meters use the full bar — speech peaks (~0.2 RMS) now read ~0.93 (red)
|
||||
and normal speech (~0.05) ~0.73 (yellow) at maxed volume; ≤0.001 linear still reads 0 (idle
|
||||
never shows noise). One knob shared by the mic bar and game bar; `× MicVolume` untouched.
|
||||
Tests updated + new `ToDisplay_Pushes_Speech_Peaks_Into_Red_At_Maxed_Volume`. **Uncommitted**
|
||||
(pending user review): `Services/Audio/AudioLevelMeter.cs`, `ytLive.Tests/AudioMixerTests.cs`,
|
||||
`ai.md`, `Services/index.md`, `ViewModels/index.md`, `TASKS.md`, `HANDOFF.md`. Meter tests:
|
||||
7/7 passing, build 0 warnings.
|
||||
- **This session (TASK 7 — UI polish batch, gramps's 6-point review):**
|
||||
1. **Scenes list cleaned:** the per-row edit/trash/visibility icons and the inline
|
||||
rename TextBox are gone. Scenes are pure selection rows; `IsHidden` stays
|
||||
persisted and still dims a hidden row to 45%. Removed dead surface:
|
||||
`EditSceneCommand`/`RemoveSceneCommand`/`ToggleSceneVisibilityCommand` +
|
||||
`BeginEditScene`/`ToggleSceneVisibility`/`RemoveScene` handlers + `Scene.IsEditing`.
|
||||
2. **Sources list upgraded:** each row now has edit + visibility eye + trash. New
|
||||
`EditElementCommand` (`SceneElement.IsEditing` → inline rename TextBox, Enter/Esc/
|
||||
lost-focus commits) and `ToggleElementVisibilityCommand` (flips `SceneElement.IsVisible`);
|
||||
the eye style now binds `IsVisible` and hidden rows dim to 45%.
|
||||
3. **Duplicate naming:** shared `NextSourceName(scene, baseName)` → `Image`, `Image2`,
|
||||
`Image3`… (no space), next free number derived from actual names so deletions never
|
||||
collide. Used by both `AddSource` and `AddReusedImage`.
|
||||
4. **Social bar:** `MaxWidth=200` + `CharacterEllipsis` removed from BOTH
|
||||
`SocialBarRenderer.cs` and the preview DataTemplate — full validated handle renders.
|
||||
5. **Panels:** left 220 / right 300 fixed widths are deliberate — panels never re-layout
|
||||
on resize; the preview absorbs it. No change.
|
||||
6. **Focus-loss capture lag:** recorded in `ai.md` as a known OS limit (DWM/WGC
|
||||
throttling when unfocused + GPU readback contention + the `_framePending` /
|
||||
`DispatcherPriority.Render` gates). NOT an in-app throttle; deferred by user decision.
|
||||
- **Test infra change:** the two real-WPF-App tests (round-clip + new source-naming) now
|
||||
share `RealAppHost` — a dedicated STA thread owning the single `App` — via the `RealApp`
|
||||
serial collection. WPF allows exactly one `Application` per AppDomain; never add a test
|
||||
that calls `new App()` directly again — marshal onto `RealAppHost` instead.
|
||||
- **Uncommitted:** `MainWindow.xaml` + `MainWindow.xaml.cs` (rows), `ViewModels/MainViewModel.cs`
|
||||
(commands + naming), `Models/SceneElement.cs` (+`IsEditing`), `Models/Scene.cs` (−`IsEditing`),
|
||||
`Services/Compositor/SocialBarRenderer.cs` (no truncation), `ytLive.Tests/SourceNamingTests.cs`
|
||||
(new), `ytLive.Tests/RealAppCollection.cs` (new), `ytLive.Tests/RoundClipInteractionTests.cs`
|
||||
(now uses the shared host), `TASKS.md` (TASK 7 ✅), `ai.md`, `ViewModels/index.md`, `HANDOFF`.
|
||||
- **Verified:** build 0 warnings / 0 errors; **170/170 tests pass** (169 + the naming test).
|
||||
- **TASK 8 — meter scaling amplification:** SHIPPED + pushed (`0b71b03`). `AudioLevelMeter.ToDisplay`
|
||||
adds **+10 dB input amplification** before the −60..0 dBFS log map: speech peaks (~0.2 RMS) read
|
||||
~0.93 (red) and normal speech (~0.05) ~0.73 (yellow) at maxed volume; ≤0.001 linear still reads 0
|
||||
(never idles on background noise). One knob shared by the mic + game bars; `× MicVolume` untouched.
|
||||
- **TASK 4 ship step 7 — one-click go live + private-only enforcement: SHIPPED** (this session; the
|
||||
final open TASK 4 requirement). Double-enforced privacy:
|
||||
1. **Dialog locked to Private** — `GoLiveViewModel.Visibility` is a get-only `"Private"`, the
|
||||
visibility ComboBox is gone (replaced by a "Streams always start Private" note); settings' dead
|
||||
"Default Visibility" dropdown + `MainViewModel.Visibilities`/`DefaultStreamVisibility` removed.
|
||||
2. **Service forces private** — `YouTubeStreamService.CreateBroadcast` always sends
|
||||
`privacyStatus="private"`; ctor gained `HttpClient? http = null` seam for tests.
|
||||
3. **Wired into go-live** — `BeginGoLive` fires `CreateBroadcastAsync` (stores `_currentBroadcastId`
|
||||
for TASK 5's bind/transition; failure → `StreamStatus.Error` via AppLog, never a crash) +
|
||||
`_framePump.StartAsync()`; `StopStream` clears `_currentBroadcastId`.
|
||||
4. **PRIVATE badge** — dark-red bordered, next to REC in the top bar, `Visibility="{Binding
|
||||
IsLivePrivate}"` (MainWindow.xaml ~110).
|
||||
5. **Integration test** — `ytLive.Tests/YouTubeStreamServiceTests.cs`: the broadcast-insert request
|
||||
must carry `"privacyStatus":"private"` (RecordingHandler seam) + a no-session → null guard test.
|
||||
- **Verified:** build 0 warnings / 0 errors; **173/173 tests pass** (171 + the 2 stream-service tests).
|
||||
- **Uncommitted (this session's ship step 7 batch):** `GoLiveWindow.xaml`, `ViewModels/GoLiveViewModel.cs`,
|
||||
`ViewModels/MainViewModel.cs`, `Services/YouTubeStreamService.cs`, `MainWindow.xaml`,
|
||||
`ytLive.Tests/YouTubeStreamServiceTests.cs` (new), `TASKS.md`, `ai.md`, `ViewModels/index.md`,
|
||||
`Services/index.md`, `HANDOFF.md`. **Commit + push before continuing.**
|
||||
- **Next step:** commit + push ship step 7, then **TASK 5 — reusable `variable` stream** (create once
|
||||
per channel, cache ingestion URL, bind to broadcast, feed `_rtmpUrlProvider` so the pump actually
|
||||
pushes — `_currentBroadcastId` is already stashed for it). Also queued: task 21 (logo + About hub),
|
||||
task 22 (voice filters). Nothing else queued — do not expand the task queue on your own. Optional,
|
||||
not queued: rewriting the healed entry's `ProfileUrl` to `https://mastodon.llamachile.tube/@gramps`
|
||||
(user must say the word).
|
||||
|
||||
- **Landmines:**
|
||||
- Never add another test that constructs `new App()` — use `RealAppHost.Run(...)`.
|
||||
- Never add another test that constructs `new App()` — use `RealAppHost.Run(...)` (shared STA host
|
||||
for the one WPF App per AppDomain; round-clip + source-naming tests).
|
||||
- Never set a local `Canvas.SetTop` on the social bar — a local value permanently
|
||||
overrides `{Binding SocialBarTop}` (the `ClearValue` lesson from 5.5).
|
||||
- `AudioMixer` meter `Push` is unconditional **by design now**: `OnMicSample`/
|
||||
@@ -78,13 +71,6 @@
|
||||
(red); it goes green ONLY when the mixer's `MicConnected` fires, which comes strictly
|
||||
from the mic source's `Started` event raised after `StartRecording()` succeeds. Zero
|
||||
devices at startup → stays red and the mixer is never started; capture failure → yellow.
|
||||
- **Next step:** commit + push this TASK 7 batch (one commit). Then the remaining TASK 4
|
||||
requirement is **ship step 7 — one-click go live + private-only enforcement** (honor the
|
||||
dialog's chosen visibility / enforce `privacyStatus = "private"`; also fixes the REC sign's
|
||||
private state — see round-3 note). Also queued: task 21 (logo + About hub), task 22 (voice
|
||||
filters). Nothing else queued — do not expand the task queue on your own. Optional, not
|
||||
queued: rewriting the healed entry's `ProfileUrl` to `https://mastodon.llamachile.tube/@gramps`
|
||||
(user must say the word).
|
||||
|
||||
- **Secret/DB/port facts live:** OAuth client id/secret in `Helpers/OAuthCredentials.cs`;
|
||||
OAuth session token in `Helpers/TokenStore.cs` (DPAPI → `%APPDATA%\ytLlive\ytLlive.auth`);
|
||||
|
||||
Reference in New Issue
Block a user