Right rail, top bar, bottom bar and chat border: Socials slide-out drawer, tab icons and colors, EDIT toggle, stream readouts moved to the top-left cell, webcam border restored, chat border controls, 30fps vertical tier

- Socials: the dialog is a right-rail drawer (same pattern as Stream Info/YPP/TEST); the live-screen button is removed
- Right rail: Stream Info (was Stream Settings) and YPP show the YouTube logo; Socials and TEST get icons; tab colors and label colors per spec
- Top bar: EDIT toggle beside REC (orange when on, blue when off); going live on YouTube turns it off
- Stream readouts (bitrate, FPS, dropped n (x.y%), Live hh:mm:ss, health) and the resolution dropdown moved to the top-left cell; bottom bar emptied at the same height
- Webcam border drawing restored (it was removed with the CRT bezel change)
- YouTube chat layer: border color, thickness, and opacity controls
- Vertical 1080p30 tier added

Not related to the fps gate yet; no gating is enforced.
This commit is contained in:
2026-10-26 18:24:09 -07:00
parent a8814b42d0
commit 7ae30d4cfc
13 changed files with 341 additions and 102 deletions
+29 -3
View File
@@ -119,20 +119,46 @@ public partial class MainViewModel
/// Opens the Social Media Site Promotion dialog (6 slots, sign-in gate,
/// validation). On save the working copy replaces <see cref="_socials"/>.
/// </summary>
/// <summary>The Socials pull-out (same drawer pattern as Stream Settings / YPP / TEST).</summary>
public bool SocialsDrawerOpen { get; private set; }
public SocialsDialogViewModel? SocialsDrawer { get; private set; }
private void OpenSocialDialog()
{
if (SocialsDrawerOpen)
{
CloseSocialsDrawer();
return;
}
var dialog = new SocialsDialogViewModel(
_socialValidator,
SignInAsync,
SignOutYouTubeAsync,
_youtubeAuth.CurrentChannel,
_socials);
var window = new ytLive.SocialsDialog(dialog) { Owner = Application.Current.MainWindow };
if (window.ShowDialog() == true)
dialog.SaveRequested += () =>
{
_socials = dialog.BuildSocialsConfig();
NotifySocialsChanged();
}
CloseSocialsDrawer();
};
dialog.CancelRequested += CloseSocialsDrawer;
SocialsDrawer = dialog;
BroadcastForm.IsDrawerOpen = false;
Ypp.IsDrawerOpen = false;
TestSession.IsDrawerOpen = false;
SocialsDrawerOpen = true;
OnPropertyChanged(nameof(SocialsDrawer));
OnPropertyChanged(nameof(SocialsDrawerOpen));
}
internal void CloseSocialsDrawer()
{
if (!SocialsDrawerOpen) return;
SocialsDrawerOpen = false;
SocialsDrawer?.AbortPending();
OnPropertyChanged(nameof(SocialsDrawerOpen));
}
private void NotifySocialsChanged()
+1
View File
@@ -364,6 +364,7 @@ public partial class MainViewModel : ViewModelBase
new("1080p30", 30, 8.0, 1920, 1080),
new("720p60", 60, 6.0, 1280, 720),
new("720p30", 30, 6.0, 1280, 720),
new("Vertical 1080p30", 30, 8.0, 1080, 1920),
new("Vertical 1080p60", 60, 8.0, 1080, 1920),
};
+3
View File
@@ -38,6 +38,7 @@ public partial class MainViewModel
{
Ypp.IsDrawerOpen = false;
TestSession.IsDrawerOpen = false;
CloseSocialsDrawer();
}
};
Ypp.PropertyChanged += (_, e) =>
@@ -46,6 +47,7 @@ public partial class MainViewModel
{
BroadcastForm.IsDrawerOpen = false;
TestSession.IsDrawerOpen = false;
CloseSocialsDrawer();
}
};
TestSession.PropertyChanged += (_, e) =>
@@ -54,6 +56,7 @@ public partial class MainViewModel
{
BroadcastForm.IsDrawerOpen = false;
Ypp.IsDrawerOpen = false;
CloseSocialsDrawer();
}
};
}