7.2 KiB
7.2 KiB
Controls — index
The phase-2 carved pieces of what used to be one monolithic MainWindow.xaml
(1,681 lines → a 123-line shell). Each is a UserControl in the ytLive.Controls
namespace, extracted one roll-back commit at a time (refactor-commit-12..18).
See schema.md for the memory-map conventions.
| File | Purpose |
|---|---|
BottomBar.xaml(.cs) |
Footer (Row 3): stream stats (bitrate/fps/dropped/duration/health), resolution dropdown (gear menu moved up to TopBar 2026-09-22) |
HealthBanner.xaml(.cs) |
Row 1 status banner + the 7 value→visibility converters live in the app theme, not here |
TopBar.xaml(.cs) |
Row 0 session surface (2026-09-22 redesign): brand + gear menu (left), one segmented REC |
PreviewPane.xaml(.cs) |
Row 1 Col 1 center: the 1920×1080 OverlayCanvas/SelectionOverlay/BrandFlashLayer/SocialBarElement, text pull-out drawer, and the live-controls row (TRAX / game / mic meters + sliders + speakers + socials). TASK 57: dragging a webcam under the vertical tier routes through MainViewModel.MoveWebcamInVerticalTier (the six-spot snap inside the cropped band) instead of free-floating over the master, and a resize re-snaps the tile onto its spot (TASK 57 Unit 2: the resize routes through MainViewModel.ResizeWebcamInVerticalTier — the Chat camera's two sizes, then the snap) |
SceneThumbnailStrip.xaml(.cs) |
Row 0 scene-picker strip (ItemsControl over Scenes), staged-red / live-green border highlight |
LeftPanel.xaml(.cs) |
Row 1 Col 0 left panel: edit mode → layers+properties; live → YouTube chat. Source add/edit/remove, list drag-to-reorder, snapshot revert-accept. TASK 51: the webcam properties carry the Background section — RemoveBackgroundPill / BlurBackgroundPill (PillToggle, radio-exclusive via WebcamSceneConfig.RemoveBackground/BlurBackground) + BackgroundStrengthSlider (0..1, 5% snaps, shown only while an effect is on). TASK 57: the webcam properties carry a Geometry section (X/Y/W/H) — manual placement of the camera, bound to the live placement (the one the current tier shows), gated on IsWebcamSelected (not SelectedElement.IsWebcam — the TASK 51 test finds that panel by binding text and would match twice); the Shape button's Visibility is bound to CanToggleClipShape, so the circle option is NOT OFFERED in the vertical Chat layout. TASK 58: every drop-down, check box and field in the properties panel carries the theme's style (YtComboBox/YtCheckBox/YtTextBoxCompact) and paints no colour of its own — the guard is ytLive.Tests/PropertiesStyleTests.cs. TASK 59: the webcam's properties are a HIERARCHY — a Shape title owns the mirror switch and the shape choice (Rect |
OverlayHost.xaml(.cs) |
Root-grid overlay dialogs: Settings / Report Bug / Feature Request / About (+ licenses + license-key entry). BackToAbout_Click lives here |
SceneThumbnailStrip.xaml.cs |
Code-behind for the strip above |
LeftPanel.xaml.cs |
Code-behind for the panel above |
Window ↔ control contract
The shell (MainWindow.xaml(.cs)) wires up each control and routes the few
cross-cutting calls through it:
- Ctor finds each control by
x:Name(TopBar,PreviewPane,LeftPanel) AFTERInitializeComponent, before any method touches it (null-ref guard). _previewPane.IsClickInsidePreview/Drawer+_leftPanel.IsClickInside→ deselection guard inWindow_PreviewMouseLeftButtonDown._previewPane.UpdateSelectionOverlay(bool)+_leftPanel.OnSelectionChanged(vm)→ selection/edit-mode routing from the VM'sSelectedElementchange._topBar.RefreshAvatar()onIsConnected/AccountAvatarUrlchange.- Handlers in moved controls cast
(DataContext as MainViewModel)— controls inherit the window's DataContext; never pass the VM through a property.
Gotchas learned the hard way
- A UserControl cannot see
Window.Resources(StaticResource resolves by element lookup, so it stops at the control boundary). The 7 converters (BoolToVis,InverseBoolToVis,NotNullToVis,NullToVis,HiddenBoolToVis,EnumToBool,AllTrueToVis) were promoted fromMainWindow.ResourcesintoThemes/Controls.xaml(seeThemes/index.md). - Moved XAML can lose its namespace: a block cut from MainWindow carries no
root xmlns, so any
models:/Helpers:ref in it breaks the build withMC2000: Value cannot be null (key). Declarexmlns:models/xmlns:Helperson each control's root (LeftPanel hit this). - Name-looked-up host stubs must stay in the window, not a control:
WebViewHostPanel(ctorInitWebView2(WebViewHostPanel)) andToastArea(NotificationService.InArea("ToastArea")) are resolved by name from the window root — soOverlayHostdeliberately leaves them as thin window-root children (Commit 18). Since the 2026-09-14 composition-capture redesign onlyToastArearemains —WebViewHostPanelis deleted (web sources no longer host a multiline XAML control;InitWebView2()runs fromMainWindow_Loadedwith no panel argument). - When cutting visual wrappers, don't drop the outer
Border's background/glow/margin — Commit 15 initially lost the preview's outer border and had to restore it same-commit.
Related: ViewModels/index.md (MainViewModel the
controls bind to), Themes/index.md (styles/converters),
Helpers/index.md (ViewModelBase, converters), the
MainWindow.xaml shell at repo root that hosts these.