Commit Graph

104 Commits

Author SHA1 Message Date
gramps 544208e002 refactor: extract OverlayHost (settings/bug/feature/about dialogs) — Phase 2, Commit 18
OverlayHost.xaml(.cs) takes the window-root overlay dialog grid (settings/
bug/feature/about panels); BackToAbout_Click moved in via inherited DataContext.
WebViewHostPanel + ToastArea stay as thin window-root stubs so the WebView2 ctor
init and NotificationService InArea('ToastArea') name lookups are untouched.
This completes Phase 2: MainWindow.xaml is now a 123-line shell.

Zero behavior change; build 0 warnings; 246 pass, only the 2 known failures.
Docs: ViewModels/index.md Phase 2 tracker updated in same commit.
2026-08-30 21:07:49 -07:00
gramps c9fd1bdaaa refactor: extract LeftPanel out of MainWindow.xaml — Phase 2, Commit 17
LeftPanel.xaml(.cs) takes the Row 1 Col 0 panel (layers + properties editor and
the live chat list). All property-editor/chat handlers moved into the control
(SourceNameBox edit, AddSourceButton menu, chat autoscroll self-subscribed on
Loaded, mirror/clip-shape, remove-source, background capture change/refresh,
opacity slider label, list drag-to-reorder, snapshot revert/accept family).

Window keeps only shell + routing: ctor wiring (_leftPanel), geometry, hotkeys,
taskbar overlay, BackToAbout, Window_PreviewMouseLeftButtonDown (uses
_leftPanel.IsClickInside), UpdateSelectionOverlay (calls _leftPanel.OnSelectionChanged).

Zero behavior change; build 0 warnings; 246 pass, only the 2 known failures.
Docs: ViewModels/index.md Phase 2 tracker updated in same commit.
2026-08-30 20:09:46 -07:00
gramps 73397cfea7 refactor: extract SceneThumbnailStrip out of MainWindow.xaml — Phase 2, Commit 16
SceneThumbnailStrip.xaml(.cs) takes the Row 0 scene-picker strip (ItemsControl
over Scenes with staged/live border highlight); Thumbnail_MouseLeftButtonDown
moved into the control, transitioning via DataContext.TransitionToScene.

Zero behavior change; build 0 warnings; 246 pass, only the 2 known failures.
Docs: ViewModels/index.md Phase 2 tracker updated in the same commit.
2026-08-30 19:39:51 -07:00
gramps c5e3466df0 refactor: extract PreviewPane out of MainWindow.xaml — Phase 2, Commit 15
PreviewPane.xaml(.cs) takes the center preview (Row 1 Col 1): the 1920x1080
canvas (OverlayCanvas/SelectionOverlay/BrandFlashLayer/SocialBarElement),
the text pull-out drawer, and the live-controls row (TRAX / game / mic meters,
volume sliders, speaker toggles, socials button) inside the preserved
glow/background Border.

Code-behind moved into the control (drive by DataContext==MainViewModel):
preview drag/select/resize/hit-test (Preview_Mouse{Down,Move,Up},
EndPreviewDrag, HitHandle, HitElement), webcam context-menu handlers
(WebcamMenu_ChangeWebcam/SetBorderAnimation/StopBorderAnimation/
FindBorderShape/CreateBorderAnimation/AddDoubleAnimation/SetBorderColor/
HideInScene/Remove), social-bar glow (SocialBar_MouseLeftButtonDown,
SocialsButton_Mouse{Enter,Leave}, SocialGlowTick), audio controls
(VolumeSlider_*, GameVolumeSlider_*, MicSpeaker_*, GameSpeaker_*,
SetSliderValueFromClick, FindParent), and TraxButton_*.

Window keeps the left source/property/chat panel + thumbnail strip + overlay
host, and routes the selection overlay and preview hit-testing through the
control's public surface (_previewPane.UpdateSelectionOverlay(bool),
IsClickInsidePreview/Drawer, PreviewPane.IsDraggableElement). BackgroundMenu_*
stayed in the window because the left-panel source context menu uses them
(the preview's own desktop/refresh menu binds RefreshCaptureCommand instead).

Preserved the outer preview Border (background/glow/margin) that was initially
dropped in the cut — caught and restored before commit. Pruned now-unused usings
(System.Net.Http, Media.Effects, Media.Animation, Media.Imaging, Shapes,
Threading) from MainWindow.xaml.cs.

Zero behavior change; build 0 warnings; 246 pass, only the 2 known failures.
Docs: ViewModels/index.md Phase 2 tracker updated in the same commit.
2026-08-30 19:38:22 -07:00
gramps 90f5ad50dd refactor: extract TopBar out of MainWindow.xaml — Phase 2, Commit 14
TopBar.xaml(.cs) takes the Row 0 top controls: logo/About button, REC/ON-AIR
pills + status signs, avatar, Sign In/Start/End buttons. The avatar fetch
(AvatarHttp/_loadedAvatarUrl/LoadAvatarImage/ShowAvatarFallback) moved into the
control with async semantics preserved; the window grabs the control via
FindName in its ctor and calls _topBar.RefreshAvatar() when IsConnected or
AccountAvatarUrl changes (previously OnViewModelPropertyChanged -> LoadAvatarImage).
AccountLight is pure binding (never touched by code-behind) so it moved with the XAML.

Zero behavior change; build 0 warnings; 246 pass, only the 2 known failures.
Also dropped the now-unused System.IO using from MainWindow.xaml.cs.
Docs: ViewModels/index.md Phase 2 tracker updated in the same commit.
2026-08-30 09:13:47 -07:00
gramps 691425288f refactor: extract HealthBanner + promote converters to theme — Phase 2, Commit 13
HealthBanner.xaml takes the Row 1 YouTube-health banner (report-by-exception).

Converters: promoted the 7 value<->visibility converters (BoolToVis, Inverse,
NotNull, Null, Hidden, EnumToBool, AllTrueToVis) from MainWindow.Window.Resources
into Themes/Controls.xaml so extracted UserControls can resolve them. AGENTS rule:
controls cannot reach into a window's own named resources; they resolve from the
app-level merged theme instead. Promoted all of them (not just NotNullToVis) so
every pending extraction keeps working without window-level references.

Zero behavior change; build 0 warnings; 246 pass, only the 2 known failures.
Docs: ViewModels/index.md Phase 2 tracker updated in the same commit.
2026-08-30 09:11:18 -07:00
gramps bc23b64315 refactor: extract BottomBar out of MainWindow.xaml — Phase 2, Commit 12
New Controls/ folder + namespace ytLive.Controls. BottomBar takes the
Grid.Row=3 footer: gear menu button (with its GearButton_Click handler moved to
the control's code-behind), centered stream-stats (bitrate/FPS/dropped/
duration/health), and the quality dropdown. All bindings inherit the window
DataContext; app-level styles resolve from Themes/Controls.xaml as before.

Zero behavior change; build 0 warnings; 246 pass, only the 2 known failures.
Docs: ViewModels/index.md tracker gains a Phase 2 section in the same commit.
2026-08-30 09:08:24 -07:00
gramps 1efde5a1e6 refactor: split Overlays out of MainViewModel — Commit 11/12
MainViewModel.Overlays.cs (194 lines) takes the settings/bug/feature/about
panels + creator-hub links: panel state (IsSettingsOpen/IsBugOpen/IsFeatureOpen/
IsAboutOpen via SetPanel, IsLicensesOpen, IsAnyOverlayOpen, OverlayTitle),
ShowOverlay/ShowLicenses, bug/feature report fields + SubmitBug/SubmitFeature/
ComposeEmail/OpenUrl, the About-hub consts (ChannelUrl/MastodonUrl/CoffeeUrl/
PremiumUrl/IsPremiumAvailable), SupportEmail/AppVersionLabel, LicensesText, and
the overlay command declarations (OpenSettingsCommand..OpenLicensesCommand).
Core drops 940 -> 758 lines. Ctor command assignments and all other wiring stay
in core; SetPanel/ShowOverlay keep their cross-partial calls.

This completes Phase 1: MainViewModel.cs has been split into 10 functional
partials (1,890 -> 758 lines in core).

Zero behavior change; build 0 warnings; 246 pass, only the 2 known failures.
Docs: index.md Overlays row added, About-hub row re-pointed, tracker marked
Phase 1 complete in the same commit.
2026-08-30 08:52:03 -07:00
gramps 3b77a132be refactor: split Chat out of MainViewModel — Commit 10/12
MainViewModel.Chat.cs (194 lines) takes the YouTube chat overlay: ChatMessages
(+500 cap, clear-on-fade), OnChatMessageReceived (dispatcher marshal,
mock→real preview switch), chat fade timer (ResetChatFadeTimer), the ChatBox
render paths (RenderChatBox for the live compositor, UpdateChatBoxPreview for
the editor preview), the mock preview loop (MockChatMessages/StartMockChatPreview/
StopMockChatPreview/RunMockChatPreviewAsync/_mockChatCts), UpdateActiveChatBoxPreviews,
CanAddYouTubeChat (one-per-layout gate) and ShowChatInactiveMessage. Core drops
1119 -> 940 lines. Ctor wiring (MessageReceived hookup, ChatBoxRenderer ctor,
LoadLayout preview start, dispose) stays in core; ResolveOutputFrame (core)
still calls RenderChatBox cross-partial.

Zero behavior change; build 0 warnings; 246 pass, only the 2 known failures.
Docs: index.md Chat row added + core row trimmed in the same commit.
2026-08-30 08:48:35 -07:00
gramps e1006a04ab refactor: split Streaming out of MainViewModel — Commit 9/12
MainViewModel.Streaming.cs (787 lines) takes the full go-live/record flow
(StartSession/BeginRecordOnly/BeginGoLive/PrepareAndStartLiveAsync/StopStream,
record-file naming + rename-on-stop), health pipeline (FramePump.Handle +
poll, report-by-exception banner), session timer, REC/ON-AIR start/end UI,
the resolution quality dropdown over the 1920x1080 master, live window
visual tokens (UpdateLiveVisuals), record-folder commands, broadcast
pull-out (CurrentBroadcastId/BroadcastForm) and the stream-state setters
(StreamStatus/StreamVisibility) + their fields. Core drops 1890 -> 1119
lines. Cross-partial references (IsConnected, IsEditMode, BrandFlash*,
_audioMixer, ctor wiring) are safe on one partial class.

Zero behavior change; build 0 warnings; 246 pass, only the 2 known
pre-existing failures (audio-mix gain + round-clip grab). Docs: index.md
Streaming row added + core row trimmed in the same commit.
2026-08-30 08:45:36 -07:00
gramps c41ff7fd0a refactor: split Socials out of MainViewModel — Commit 8/12
MainViewModel.Socials.cs: social-bar state (_socials/_socialBarFrame/
_socialValidator), bar props (HasSocials/SocialBarVisible/SocialBarDotBrush/
SocialBarGlowBrush/Socials/SocialBarTop), OpenSocialDialog + NotifySocialsChanged
+ RenderSocialBarFrame (SocialBarRenderer), fediverse heal
(HealFediverseSoftwareAsync/HealFediverseSoftwareInBackground),
SetSocialBarPosition/ToggleSocialBarPosition, OpenSocialDialogCommand.

BarOnBrush/BarOffBrush/CreateBrush stay in core (shared tokens used by
Audio/Trax partials); core keeps ctor command assignment, LoadLayout,
SaveLayoutNow, and the compositor socialBar seam.

Docs: index.md restructured — each landed partial (Account..Trax) now owns its
own table row, the core row shrinks to only what remains in MainViewModel.cs,
and the split tracker is a compact code<->commit map.

Verify: 0 warnings, 246 passed, 2 known failures only.
2026-08-30 08:34:10 -07:00
gramps 535a50192c refactor: split Trax out of MainViewModel — Commit 7/12
MainViewModel.Trax.cs: music-player state (_musicPlayer/_music/_musicPlaying,
TraxIdleBrush), TRAX UI (IsMusicPlaying/TraxError/TraxDotBrush/TraxToolTip),
interaction (TraxLeftClick/TraxRightClick/PickTraxTrack), playback
(LoadTrax/PlayTrax/PauseTrax/OnTraxPlaybackEnded/RefreshTraxUi), local
loopback ducking (UpdateTraxLocalGain).

Core keeps the ctor event hookup, LoadLayout/Shutdown/SaveLayoutNow call
sites, and Scenes partial's hotkey dispatch.

Verify: 0 warnings, 246 passed, 2 known failures only.
2026-08-30 08:24:22 -07:00
gramps c1126a52b9 refactor: split Audio out of MainViewModel — Commit 6/12
MainViewModel.Audio.cs: mic bar (AudioLevel/MeterFillWidth/MeterBrush,
MicVolume/MicMuted, ToggleMicMute, PickMicrophone), mic status dot
(MicStatus/MicStatusBrush/MicStatusToolTip), game bar
(GameAudioLevel/GameMeterFillWidth/GameMeterBrush, GameAudioVolume,
GameMuted, ToggleGameMute), PushSystemVolume, mixer event handlers
(OnMicLevelChanged/OnLoopbackLevelChanged/OnMicConnected/OnMicFailed),
StartMicCaptureAsync, command properties, 18 fields.

Kept in core: TraxIdleBrush, TRAX code block, ctor wiring
(mixer init + event hookup), timer construction.

Verify: 0 warnings, 246 passed, 2 known failures only.
2026-08-30 08:17:55 -07:00
gramps e2867198b9 refactor: split Webcam out of MainViewModel — Commit 5/12 (tag refactor-commit-5) 2026-08-30 07:35:21 -07:00
gramps db068abbc7 refactor: split Background out of MainViewModel — Commit 4/12 (tag refactor-commit-4) 2026-08-30 07:30:24 -07:00
gramps dcdfcb9cee refactor: split Scenes out of MainViewModel — Commit 3/12 (tag refactor-commit-3) 2026-08-30 07:20:37 -07:00
gramps 9baae33916 refactor: split License out of MainViewModel — Commit 2/12 (tag refactor-commit-2)
Pure member movement into MainViewModel.License.cs (zero behavior change):
Polar license state (LicenseKey/LicenseMessage/IsLicenseValidating/
IsLicenseEntryOpen/IsHubVisible/IsPremium + OfflineGracePeriod),
ValidateLicenseAtStartupAsync, ActivateLicenseAsync. docs in same commit:
ViewModels/index.md split table (License ✔).
2026-08-30 07:15:26 -07:00
gramps 5eecf4536f refactor: split Account out of MainViewModel — Commit 1/12 (tag refactor-commit-1)
Pure member movement into MainViewModel.Account.cs (zero behavior change):
session restore (LoadSavedSessionAsync), sign-in/out/change (SignInAsync,
SignOutYouTubeAsync, ChangeAccountAsync), IsConnected + account avatar/name +
AccountStatusLightToolTip. Partial carries its own usings (ytLive.Services for
the INotificationService default interface methods). docs in same commit:
ViewModels/index.md split table + tagging convention.
2026-08-30 07:13:17 -07:00
gramps abc78cd071 MainViewModel is now a partial class — scaffold for the per-area split (Commit 0)
Zero behavior change: \`public class\` -> \`public partial class\`. Each functional area
(Scenes, Background, Webcam, Audio, Trax, Socials, Streaming, Chat, Overlays,
Account, License) will move to its own file next, one commit per partial — each
a roll-back point. Docs updated in the same commit: ViewModels/index.md (split
map), ai.md (architecture table), HANDOFF.md (state). verify.sh: build 0 warnings,
only the 2 known pre-existing test failures.
2026-08-30 07:07:35 -07:00
gramps 6031a5682d Gear cleanup + Default Location for Recordings + single Start + socials hover glow
KISS: removed Gear-menu Save/SaveAs/Open Layout (redundant with auto-save; multi-layout = OBS).
App Settings: first real setting — Default Location for Recordings (Browse + Use Downloads reset,
fallback: configured → Downloads → MyVideos). Single Start button (pills = intent, button = trigger).
Socials button moved to preview bottom row, left of TRAX; hover pulses the SocialBarElement
DropShadowEffect (sine wave BlurRadius 24→48, Opacity 0.7→1.0 at 30ms). TextBox OneWay binding
fix for get-only RecordFolderDisplay. ONE fallback test. Build 0 warnings, 247 tests (2 known).
2026-08-29 10:30:40 -07:00
gramps 46f4696db6 TASK 18: manual rename modal for finished recordings
RenameRecordingDialog (themed, mirrors GoLiveWindow chrome): pre-fills the auto stem,
Enter/OK saves, Esc/Cancel keeps the auto name, strips stray .mp4, rejects invalid
filename chars. FinalizeRecordingAsync shows it before UniquePath rename. Naming logic
still covered by RecordingFileTests; UI shell is pure. verify.sh gate: 0 warnings,
244/246 (2 known).
2026-08-29 09:24:13 -07:00
gramps a9eb360288 TASK 18: local (record-only) recording pipeline + top-bar pills/light/Start-End button UX
Encoder dual-output: StreamEnabled/RecordEnabled/RecordPath options; per-output
ffmpeg block (stream ->flv, record ->mp4); throw unless at least one output.

RecordingFile: auto-name ty-<yyyymmdd>-<start hhmm>-0000.mp4, rename-on-stop to
ty-...-<len hhmmss>.mp4 with numeric-suffix on collision. LayoutStore persists
record folder. MainViewModel: REC/ON-AIR pills, status light, single Start<->End
button (replaces Start/Stop variants), StopStream no longer signs out, explicit
session timer. About overlay widened. Sign In label + spacing before Start.

Tests: 244 passed / 246 (2 pre-existing: AudioPipeline gains-mute, RoundClip).
Build 0 warnings. Scope check clean.

Memory-map correction (derived-solution rule, 2026-08-29): image-shrink recipe was
never recorded when first done, so it was re-derived. Added Derived-solution/recipes
rule to AGENTS.md; MyMistakes.md now a permanent recipes registry (records the
verified WPF-imaging shrink recipe); schema.md rows MyMistakes as registry; ai.md
points to the rule. README hero image replaced: 3.2MB screenshot -> 1400x794 ->
188KB docs/ytLlive-preview.jpg (JPEG q82).
2026-08-29 09:02:55 -07:00
gramps 9b56e88800 Revert ab29ec8: container==content auto-fit made it worse — back to alpha-crop with the container at element size
The container tracks the element's own Width/Height again; the crop stays in the bitmap.
2026-08-28 12:09:13 -07:00
gramps ab29ec801d Web source: container == content — element grid + selection box sized to the cropped frame's canvas extent
- FindContentBounds already trimmed the bitmap; the grid/box still rendered at the uncropped user
  size, so Fill stretched the tight widget into a bigger frame = dead-between-content-and-border.
- ContentCanvasSize maps the crop rect to canvas units (1920/pixW per axis, DPI-correct) and the
  preview event now carries (bitmap, canvasW, canvasH).
- OnWebView2PreviewBitmapChanged sets the element Width/Height to that size; the grid and the
  SelectionOverlay (both bound to the element's Width/Height) now equal the widget exactly.
- IsPreviewDragging (set in MainWindow drag/resize) suppresses auto-fit mid-gesture.
- Tests 10/10 (alpha bounds, canvas-size mapping incl. DPI, control size); 0 warnings.
2026-08-28 12:08:04 -07:00
gramps e917c41a48 Web source: fix rendering — fixed 1920×1080 viewport (OBS pattern), Stretch=Uniform, startup registration 2026-08-28 10:23:59 -07:00
gramps fd6e02b687 Web source: off-screen WebView2 capture + layout persistence + transparent bg
Bundle exception (2026-08-27): this lands prior-session work plus today's
transparency fix as one commit per creator instruction.

WebView2Manager (new): off-screen WebView2 control parked at -5000/-5000 in
the window's visual tree, captures via CapturePreviewAsync every 100 ms into
a BGRA8 VideoFrame. Source Width/Height sync to the control via
PropertyChanged. JS transparent-background injection runs on every
NavigationStarting/NavigationCompleted so the page's own CSS does not paint
white over the capture.

Transparency fix: DefaultBackgroundColor = System.Drawing.Color.Transparent
set on the WPF control before EnsureCoreWebView2Async. The WPF SDK doc says
the value is forwarded to the controller on init; the IDL (ICoreWebView2-
Controller2) confirms alpha=0 makes the capture alpha-preserving. The
prior-session 'CoreWebView2.BackgroundColor' path was the wrong property
name and has been replaced.

LayoutStore: WebUri column added (idempotent ALTER TABLE) and round-tripped
on save/load (schema v11).

MainViewModel: WebView2Manager constructed on Loaded; loaded web sources
re-registered; Source.WebUri PropertyChanged forwards to manager.

MainWindow: off-screen host Canvas added to visual tree.

Tests: 3 scale-sync + WebView2_DefaultBackgroundColor_Is_Transparent +
LayoutStorePersistenceTests.WebSource_WebUri_Persists. 234/236 pass
(2 pre-existing failures unchanged).

Scale bug (DPI/physical-pixel mismatch) still open.
2026-08-27 08:52:39 -07:00
gramps 67baac6fdd Rename pull-out tab to 'Stream Settings'; right-click Start Stream → Change Account / Logout 2026-08-26 09:35:07 -07:00
gramps d4aa5e1003 Thumbnail strip: show hotkey label next to each scene name 2026-08-26 08:28:48 -07:00
gramps 3a1484b3c5 TASK 20 step 2: hotkey config UI + modifier chord persistence + conflict detection 2026-08-26 06:48:14 -07:00
gramps 89ab83be2e Update Broadcast button: diff before push, offline=local only, live=API; Go Live empty-field prompt 2026-08-25 17:25:25 -07:00
gramps e6baa55867 Fix logo-click crash (Run is not a Visual); Text tab always visible; avatar initial fallback 2026-08-24 14:44:16 -07:00
gramps b988e6d72e Broadcast Text pull-out (Live screen) + launch geometry 1920x1040/1366x768 with restore 2026-08-24 11:04:41 -07:00
gramps 7357836f9b ON-AIR sign right of REC: gray offline, red public, green private 2026-08-24 10:22:18 -07:00
gramps b0bace7432 TASK 20 step 1: global hotkeys F1-F9 (scenes, stream, mutes, TRAX) 2026-08-24 09:32:54 -07:00
gramps 708b336da7 YouTube Chat layer: one-per-layout gate + legacy label heal (TASK 27) 2026-08-24 09:08:03 -07:00
gramps ef710c5537 Webcam menu gates on the app-wide identity (TASK 26) 2026-08-24 08:56:17 -07:00
gramps 7dd140a4c0 Backgrounds: one locked Background per screen + mini rule (TASK 25) 2026-08-23 13:33:33 -07:00
gramps b400ab59c5 Toasts: non-blocking notifications replace MessageBoxes + log-only failures (TASK 24) 2026-08-23 12:25:04 -07:00
gramps d2114c7e1c the ai is an overthinking fucking moron who needs it's plug pulled until such time it can repeat a similar action with its head and ass 2026-08-23 06:25:38 -07:00
gramps 4b9a8e515f Control Surface UX: pill toggle, background rename, per-scene properties
- Sliding pill toggle (green ON / red OFF) replaces checkbox
- Geometry mismatch error for custom backgrounds
- Backdrop -> Background: C# rename, SQL column rename with migration
- Source.IsBackground: new -> override (fixes WPF binding)
- Legacy 'Backdrop' display name migrated to 'Background'
- Per-scene UseDefaultBackground + CustomBackgroundPath
- Asset files renamed backdrop -> background
- StagedScene/LiveScene split, thumbnail strip, edit gating
- TransitionService (Cut/Fade/Move)
- Context menu: Capture Desktop, Refresh Desktop
- Resolution badge removed, ON-AIR status light added
2026-08-22 18:10:59 -07:00
gramps e06bfa42a8 Fix: TRAX meter reflection — remove double attenuation from slider+loopback 2026-08-21 08:32:20 -07:00
gramps 8951141c65 TASK 10: Polar billing + Velopack auto-updates (steps 1-7) 2026-08-21 08:18:52 -07:00
gramps 0bd17ab428 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
2026-08-20 18:02:41 -07:00
gramps a76a3d2acd fix: BRB backdrop seed replaces existing instead of skipping
SeedBrbBackdrop() now updates the AssetId on an existing Background
source instead of bailing when one already exists. This ensures the
new brb-backdrop.jpg replaces any old image already in the DB.
2026-08-19 15:02:47 -07:00
gramps f40ec83e69 feat: BRB backdrop seed + docs refresh + Polar org ID
- Add brb-backdrop.jpg asset, SeedBrbBackdrop() mirrors Starting pattern
- Update HANDOFF.md (was stale), TASKS.md (TASK 10 ready, TASK 15 2/5), ai.md (org ID)
- Polar org ID c05fb364 obtained via OAT, recorded in CREDENTIALS.md
2026-08-19 15:01:23 -07:00
gramps 26828ccdd7 feat(ui): rename panels Screens → Layers → Properties
Renames all user-facing UI text to distinguish from OBS terminology:
- SCENES → SCREENS (section header, tooltips, hints)
- SOURCES → LAYERS (section header, tooltips, context menu, empty hints, onboarding text)
- ELEMENTS → PROPERTIES (section header, tooltips, empty hint)
- Fallback display name 'Source' → 'Layer'

Code identifiers unchanged (IsElementsPanelEmpty, ShowSourcesEmptyHint, etc.)
16 UI text locations across MainWindow.xaml + MainViewModel.cs
2026-08-19 13:52:42 -07:00
gramps e292f0e037 fix: seed starting backdrop on every load, not just first launch
SeedStartingBackdrop() moved outside the Scenes.Count==0 guard so it
fires on every startup. Existing layouts with a Background source are
skipped (idempotent check).
2026-08-19 13:13:00 -07:00
gramps 6a74147611 feat(chat-overlay): selection highlight + default size + starting backdrop
- Source.IsDraggable now includes ChatBox and WebSource (was Image-only)
- ChatBox default: 400×1080, top-right corner (1520, 0) on first add
- SeedStartingBackdrop: embeds starting-backdrop.jpg as Background source
  in the Starting scene on first launch (pack:// resource)
2026-08-19 13:01:35 -07:00
gramps 65641d84e5 feat(chat-overlay): add ChatBox config UI + schema persistence
- Elements panel config UI for ChatBox source (font size slider,
  font/member/super-chat/background color inputs, max messages slider,
  timestamp/badge toggles)
- Schema migration: 8 new ChatBox columns on Source table (ChatFontSize,
  ChatFontColor, ChatBackgroundColor, ChatMaxMessages, ChatShowTimestamps,
  ChatShowBadges, ChatMemberColor, ChatSuperChatColor)
- Load/save: Source SELECT and INSERT now include all ChatBox fields
- IsElementsPanelEmpty excludes ChatBox so hint doesn't cover config
- ChatBoxRenderer.cs created: WPF FormattedText + RenderTargetBitmap
  renderer for on-stream chat overlay
- Slider bindings set to TwoWay for live propagation
2026-08-19 12:42:32 -07:00
gramps 1613acadc3 TASK 9.4: live chat wiring — right panel with Super Chat + membership badges
- YouTubeStreamService: added GetBroadcastLiveChatIdAsync to fetch liveChatId from broadcast contentDetails
- YouTubeChatService.Poll(): parse snippet.type to handle textMessageEvent, superChatEvent, newSponsorEvent
- MainViewModel: wire _youtubeChat.Start(liveChatId) in PrepareAndStartLiveAsync after broadcast creation
- MainViewModel: wire _youtubeChat.Stop() in StopStream before encoder stop
- MainViewModel: wire _youtubeChat.Dispose() in Shutdown
- MainWindow.xaml: updated chat DataTemplate with member badge (⭐), Super Chat highlight (💰 + gold border), timestamps (HH:mm)
- MainWindow.xaml.cs: auto-scroll ChatListBox on new messages via CollectionChanged
- Chat lifecycle is non-fatal: failures log and the stream continues without on-panel chat
2026-08-19 11:59:29 -07:00