teamsiso/src/TeamsISO.App.WinUI/Views/MainWindow.xaml.cs

90 lines
4.4 KiB
C#
Raw Normal View History

feat(winui3): redesigned MainWindow + custom title bar + theme toggle Lands the approved shape brief as the WinUI 3 MainWindow: * 64px left rail with brand mark, primary nav (participants), Teams launch / hide / settings buttons, and the engine-status puck at the bottom. All five rail buttons use Segoe Fluent Icons glyphs at a uniform 20px optical size; no more bespoke <Path Data> shapes with inconsistent stroke weights. * 44px custom title bar via ExtendsContentIntoTitleBar + SetTitleBar(AppTitleBar). The drag region absorbs the three live-state pills inline (session timer 'live * 00:14:32', REC count + elapsed, disk free) and a slim sun/moon theme-toggle button to the left of the system Min/Max/Close controls. System buttons inherit ButtonForeground Color etc. from AppWindow.TitleBar so they match palette in both themes. * Section header with 'Participants * count' display, filter input, Refresh + Presets (Secondary buttons), and 'Enable all online' as the single cyan Primary button - finally a real button hierarchy instead of seven indistinguishable ghost buttons. * Participants list rendered as ItemsRepeater + DataTemplate for now; the CommunityToolkit DataGrid migration follows in a separate commit. Row template at 64px height with: 3px cyan left border for active speaker, avatar with initials in cyan-muted circle, name + codec line, signal lock state with dot, audio meter via ProgressBar, output name in JetBrains Mono, ISO state pill (LIVE/OFF/ERROR) at right. * Conditional in-call control bar below the table: Mute / Camera / Share / Marker / Leave + overflow kebab. Muted state binds the destructive coral treatment to the Mute button; Leave is also destructive (coral border + text); everything else is Secondary. Tight 8px spacing keeps the bar dense without crowding. * Slim 32px status bar at the bottom: control-surface URL on the left (cyan dot indicator), keyboard-shortcut hints on the right in tertiary mono. Replaces the WPF host's six-column footer. Implementation notes: * MockParticipant model populates the table with representative data (Maya / Daniel / Aicha / Sam, one as active speaker) until the ParticipantViewModel binding migrates over from the WPF host. * Custom Program.cs takes ownership of Main from the XAML compiler (DISABLE_XAML_GENERATED_MAIN). Calls Bootstrap.TryInitialize(0x00010006) before Application.Start so the unpackaged .exe can locate the WindowsAppSDK 1.6 framework MSIX at launch. Shutdown is paired in a finally block. * Theme toggle in code-behind flips Window.Content.RequestedTheme between Dark and Light. {ThemeResource} bindings auto-swap across the visual tree; system title-bar buttons (outside the XAML tree) get color updates inline so they stay readable in both modes. * app.manifest deferred from build - the framework-emitted manifest covers DPI awareness and supportedOS GUIDs; reintroducing our own goes in the next commit alongside the bootstrapper hardening. Known issue: the unpackaged .exe currently fails to activate on this build host with 'this application could not be started' before Main runs. Build is clean; published output runs the same way. Diagnosing the activation failure is the next session's first task (likely the runtimeconfig.json including Microsoft.WindowsDesktop.App which WinUI 3 doesn't want, or a missing CRT redistributable). The WPF host remains the running build until that's resolved. dotnet build TeamsISO.Windows.slnf -c Debug: 0 warnings, 0 errors.
2026-05-13 00:03:12 -04:00
using Microsoft.UI;
using Microsoft.UI.Windowing;
feat(winui3): scaffold TeamsISO.App.WinUI alongside the WPF host First step of the WinUI 3 replatform per the approved redesign brief. The new project coexists with the existing src/TeamsISO.App (WPF) so the WPF host keeps building and shipping while the WinUI 3 redesign lands incrementally. Once the WinUI 3 build is feature-complete and tested against a real Teams meeting, the WPF project is retired. Scaffold contents: * src/TeamsISO.App.WinUI/TeamsISO.App.WinUI.csproj Windows App SDK 1.6 LTS (250602001), unpackaged mode (WindowsPackageType=None) so the existing MSI installer keeps working. Target framework net8.0-windows10.0.19041.0, min platform 10.0.17763.0 to preserve Win10 1809+ compatibility for working broadcast hardware. Pins WindowsSdkPackageVersion=10.0.19041.38 so .NET SDK 8.0.301 builds cleanly without an SDK upgrade on the build host. * src/TeamsISO.App.WinUI/app.manifest PerMonitorV2 DPI awareness + gdiScaling for crisp text on high-DPI broadcast monitors. asInvoker trust level (control surface :9755 and OSC :9000 bind to 127.0.0.1, no admin needed). * App.xaml + App.xaml.cs Minimal startup: brings up MainWindow. The full pipeline (NDI runtime preflight, IsoController wiring, single-instance mutex, REST + OSC bridge, tray icon, crash diagnostics, auto-update banner, onboarding) migrates in subsequent commits. * Themes/Tokens.xaml Wild Dragon design tokens as ThemeDictionary entries (Default = Dark, Light). Colors as Color resources, Brushes paired per theme so {ThemeResource} auto-swaps when RequestedTheme flips — no app restart, no flicker. Spacing/radii/typography tokens are theme-agnostic at the outer level. Light palette maintains brand recognition via cyan-tinted off-whites (#FAFAFB canvas, #F0F1F3 rail) rather than pure white, and splits cyan into accent.cyan.surface (#97EDF0, works in both modes because text on top is near-black) and accent.cyan.text (#97EDF0 dark / #0E7C82 light) so captions and inline labels keep AA contrast. * Themes/Controls.xaml Button hierarchy with real commitments: Primary (cyan fill, one per surface), Secondary (transparent bordered), Tertiary (text only), Destructive (coral border + text), Caption (titlebar), RailIcon. Typographic ramp (Display / Title / Heading / Body / Subtle / Caption / Mono) at the DESIGN.md 1.25 ratio. * CommunityToolkit.WinUI.UI.Controls.DataGrid 7.1.2 referenced for the participants table migration. (Toolkit 8.x dropped DataGrid; 7.x is the only currently-maintained free option for WinUI 3.) * Inter.ttf + JetBrainsMono.ttf + dragon-mark.png + teamsiso.ico copied from the WPF project's Assets/ so the WinUI 3 host is self-contained. * TeamsISO.sln + TeamsISO.Windows.slnf updated to include the new project. The .slnf paths switch to backslash form so MSBuild can match them against the .sln's canonical path representation. Verified: dotnet build TeamsISO.Windows.slnf -c Debug succeeds with 0 warnings and 0 errors for all 8 projects (WPF host, WinUI 3 host, engine, NDI interop, console, three test projects).
2026-05-12 23:52:35 -04:00
using Microsoft.UI.Xaml;
feat(winui3): redesigned MainWindow + custom title bar + theme toggle Lands the approved shape brief as the WinUI 3 MainWindow: * 64px left rail with brand mark, primary nav (participants), Teams launch / hide / settings buttons, and the engine-status puck at the bottom. All five rail buttons use Segoe Fluent Icons glyphs at a uniform 20px optical size; no more bespoke <Path Data> shapes with inconsistent stroke weights. * 44px custom title bar via ExtendsContentIntoTitleBar + SetTitleBar(AppTitleBar). The drag region absorbs the three live-state pills inline (session timer 'live * 00:14:32', REC count + elapsed, disk free) and a slim sun/moon theme-toggle button to the left of the system Min/Max/Close controls. System buttons inherit ButtonForeground Color etc. from AppWindow.TitleBar so they match palette in both themes. * Section header with 'Participants * count' display, filter input, Refresh + Presets (Secondary buttons), and 'Enable all online' as the single cyan Primary button - finally a real button hierarchy instead of seven indistinguishable ghost buttons. * Participants list rendered as ItemsRepeater + DataTemplate for now; the CommunityToolkit DataGrid migration follows in a separate commit. Row template at 64px height with: 3px cyan left border for active speaker, avatar with initials in cyan-muted circle, name + codec line, signal lock state with dot, audio meter via ProgressBar, output name in JetBrains Mono, ISO state pill (LIVE/OFF/ERROR) at right. * Conditional in-call control bar below the table: Mute / Camera / Share / Marker / Leave + overflow kebab. Muted state binds the destructive coral treatment to the Mute button; Leave is also destructive (coral border + text); everything else is Secondary. Tight 8px spacing keeps the bar dense without crowding. * Slim 32px status bar at the bottom: control-surface URL on the left (cyan dot indicator), keyboard-shortcut hints on the right in tertiary mono. Replaces the WPF host's six-column footer. Implementation notes: * MockParticipant model populates the table with representative data (Maya / Daniel / Aicha / Sam, one as active speaker) until the ParticipantViewModel binding migrates over from the WPF host. * Custom Program.cs takes ownership of Main from the XAML compiler (DISABLE_XAML_GENERATED_MAIN). Calls Bootstrap.TryInitialize(0x00010006) before Application.Start so the unpackaged .exe can locate the WindowsAppSDK 1.6 framework MSIX at launch. Shutdown is paired in a finally block. * Theme toggle in code-behind flips Window.Content.RequestedTheme between Dark and Light. {ThemeResource} bindings auto-swap across the visual tree; system title-bar buttons (outside the XAML tree) get color updates inline so they stay readable in both modes. * app.manifest deferred from build - the framework-emitted manifest covers DPI awareness and supportedOS GUIDs; reintroducing our own goes in the next commit alongside the bootstrapper hardening. Known issue: the unpackaged .exe currently fails to activate on this build host with 'this application could not be started' before Main runs. Build is clean; published output runs the same way. Diagnosing the activation failure is the next session's first task (likely the runtimeconfig.json including Microsoft.WindowsDesktop.App which WinUI 3 doesn't want, or a missing CRT redistributable). The WPF host remains the running build until that's resolved. dotnet build TeamsISO.Windows.slnf -c Debug: 0 warnings, 0 errors.
2026-05-13 00:03:12 -04:00
using TeamsISO.App.WinUI.Models;
using Windows.Graphics;
using Windows.UI;
feat(winui3): scaffold TeamsISO.App.WinUI alongside the WPF host First step of the WinUI 3 replatform per the approved redesign brief. The new project coexists with the existing src/TeamsISO.App (WPF) so the WPF host keeps building and shipping while the WinUI 3 redesign lands incrementally. Once the WinUI 3 build is feature-complete and tested against a real Teams meeting, the WPF project is retired. Scaffold contents: * src/TeamsISO.App.WinUI/TeamsISO.App.WinUI.csproj Windows App SDK 1.6 LTS (250602001), unpackaged mode (WindowsPackageType=None) so the existing MSI installer keeps working. Target framework net8.0-windows10.0.19041.0, min platform 10.0.17763.0 to preserve Win10 1809+ compatibility for working broadcast hardware. Pins WindowsSdkPackageVersion=10.0.19041.38 so .NET SDK 8.0.301 builds cleanly without an SDK upgrade on the build host. * src/TeamsISO.App.WinUI/app.manifest PerMonitorV2 DPI awareness + gdiScaling for crisp text on high-DPI broadcast monitors. asInvoker trust level (control surface :9755 and OSC :9000 bind to 127.0.0.1, no admin needed). * App.xaml + App.xaml.cs Minimal startup: brings up MainWindow. The full pipeline (NDI runtime preflight, IsoController wiring, single-instance mutex, REST + OSC bridge, tray icon, crash diagnostics, auto-update banner, onboarding) migrates in subsequent commits. * Themes/Tokens.xaml Wild Dragon design tokens as ThemeDictionary entries (Default = Dark, Light). Colors as Color resources, Brushes paired per theme so {ThemeResource} auto-swaps when RequestedTheme flips — no app restart, no flicker. Spacing/radii/typography tokens are theme-agnostic at the outer level. Light palette maintains brand recognition via cyan-tinted off-whites (#FAFAFB canvas, #F0F1F3 rail) rather than pure white, and splits cyan into accent.cyan.surface (#97EDF0, works in both modes because text on top is near-black) and accent.cyan.text (#97EDF0 dark / #0E7C82 light) so captions and inline labels keep AA contrast. * Themes/Controls.xaml Button hierarchy with real commitments: Primary (cyan fill, one per surface), Secondary (transparent bordered), Tertiary (text only), Destructive (coral border + text), Caption (titlebar), RailIcon. Typographic ramp (Display / Title / Heading / Body / Subtle / Caption / Mono) at the DESIGN.md 1.25 ratio. * CommunityToolkit.WinUI.UI.Controls.DataGrid 7.1.2 referenced for the participants table migration. (Toolkit 8.x dropped DataGrid; 7.x is the only currently-maintained free option for WinUI 3.) * Inter.ttf + JetBrainsMono.ttf + dragon-mark.png + teamsiso.ico copied from the WPF project's Assets/ so the WinUI 3 host is self-contained. * TeamsISO.sln + TeamsISO.Windows.slnf updated to include the new project. The .slnf paths switch to backslash form so MSBuild can match them against the .sln's canonical path representation. Verified: dotnet build TeamsISO.Windows.slnf -c Debug succeeds with 0 warnings and 0 errors for all 8 projects (WPF host, WinUI 3 host, engine, NDI interop, console, three test projects).
2026-05-12 23:52:35 -04:00
namespace TeamsISO.App.WinUI.Views;
public sealed partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
feat(winui3): redesigned MainWindow + custom title bar + theme toggle Lands the approved shape brief as the WinUI 3 MainWindow: * 64px left rail with brand mark, primary nav (participants), Teams launch / hide / settings buttons, and the engine-status puck at the bottom. All five rail buttons use Segoe Fluent Icons glyphs at a uniform 20px optical size; no more bespoke <Path Data> shapes with inconsistent stroke weights. * 44px custom title bar via ExtendsContentIntoTitleBar + SetTitleBar(AppTitleBar). The drag region absorbs the three live-state pills inline (session timer 'live * 00:14:32', REC count + elapsed, disk free) and a slim sun/moon theme-toggle button to the left of the system Min/Max/Close controls. System buttons inherit ButtonForeground Color etc. from AppWindow.TitleBar so they match palette in both themes. * Section header with 'Participants * count' display, filter input, Refresh + Presets (Secondary buttons), and 'Enable all online' as the single cyan Primary button - finally a real button hierarchy instead of seven indistinguishable ghost buttons. * Participants list rendered as ItemsRepeater + DataTemplate for now; the CommunityToolkit DataGrid migration follows in a separate commit. Row template at 64px height with: 3px cyan left border for active speaker, avatar with initials in cyan-muted circle, name + codec line, signal lock state with dot, audio meter via ProgressBar, output name in JetBrains Mono, ISO state pill (LIVE/OFF/ERROR) at right. * Conditional in-call control bar below the table: Mute / Camera / Share / Marker / Leave + overflow kebab. Muted state binds the destructive coral treatment to the Mute button; Leave is also destructive (coral border + text); everything else is Secondary. Tight 8px spacing keeps the bar dense without crowding. * Slim 32px status bar at the bottom: control-surface URL on the left (cyan dot indicator), keyboard-shortcut hints on the right in tertiary mono. Replaces the WPF host's six-column footer. Implementation notes: * MockParticipant model populates the table with representative data (Maya / Daniel / Aicha / Sam, one as active speaker) until the ParticipantViewModel binding migrates over from the WPF host. * Custom Program.cs takes ownership of Main from the XAML compiler (DISABLE_XAML_GENERATED_MAIN). Calls Bootstrap.TryInitialize(0x00010006) before Application.Start so the unpackaged .exe can locate the WindowsAppSDK 1.6 framework MSIX at launch. Shutdown is paired in a finally block. * Theme toggle in code-behind flips Window.Content.RequestedTheme between Dark and Light. {ThemeResource} bindings auto-swap across the visual tree; system title-bar buttons (outside the XAML tree) get color updates inline so they stay readable in both modes. * app.manifest deferred from build - the framework-emitted manifest covers DPI awareness and supportedOS GUIDs; reintroducing our own goes in the next commit alongside the bootstrapper hardening. Known issue: the unpackaged .exe currently fails to activate on this build host with 'this application could not be started' before Main runs. Build is clean; published output runs the same way. Diagnosing the activation failure is the next session's first task (likely the runtimeconfig.json including Microsoft.WindowsDesktop.App which WinUI 3 doesn't want, or a missing CRT redistributable). The WPF host remains the running build until that's resolved. dotnet build TeamsISO.Windows.slnf -c Debug: 0 warnings, 0 errors.
2026-05-13 00:03:12 -04:00
feat(winui3): scaffold TeamsISO.App.WinUI alongside the WPF host First step of the WinUI 3 replatform per the approved redesign brief. The new project coexists with the existing src/TeamsISO.App (WPF) so the WPF host keeps building and shipping while the WinUI 3 redesign lands incrementally. Once the WinUI 3 build is feature-complete and tested against a real Teams meeting, the WPF project is retired. Scaffold contents: * src/TeamsISO.App.WinUI/TeamsISO.App.WinUI.csproj Windows App SDK 1.6 LTS (250602001), unpackaged mode (WindowsPackageType=None) so the existing MSI installer keeps working. Target framework net8.0-windows10.0.19041.0, min platform 10.0.17763.0 to preserve Win10 1809+ compatibility for working broadcast hardware. Pins WindowsSdkPackageVersion=10.0.19041.38 so .NET SDK 8.0.301 builds cleanly without an SDK upgrade on the build host. * src/TeamsISO.App.WinUI/app.manifest PerMonitorV2 DPI awareness + gdiScaling for crisp text on high-DPI broadcast monitors. asInvoker trust level (control surface :9755 and OSC :9000 bind to 127.0.0.1, no admin needed). * App.xaml + App.xaml.cs Minimal startup: brings up MainWindow. The full pipeline (NDI runtime preflight, IsoController wiring, single-instance mutex, REST + OSC bridge, tray icon, crash diagnostics, auto-update banner, onboarding) migrates in subsequent commits. * Themes/Tokens.xaml Wild Dragon design tokens as ThemeDictionary entries (Default = Dark, Light). Colors as Color resources, Brushes paired per theme so {ThemeResource} auto-swaps when RequestedTheme flips — no app restart, no flicker. Spacing/radii/typography tokens are theme-agnostic at the outer level. Light palette maintains brand recognition via cyan-tinted off-whites (#FAFAFB canvas, #F0F1F3 rail) rather than pure white, and splits cyan into accent.cyan.surface (#97EDF0, works in both modes because text on top is near-black) and accent.cyan.text (#97EDF0 dark / #0E7C82 light) so captions and inline labels keep AA contrast. * Themes/Controls.xaml Button hierarchy with real commitments: Primary (cyan fill, one per surface), Secondary (transparent bordered), Tertiary (text only), Destructive (coral border + text), Caption (titlebar), RailIcon. Typographic ramp (Display / Title / Heading / Body / Subtle / Caption / Mono) at the DESIGN.md 1.25 ratio. * CommunityToolkit.WinUI.UI.Controls.DataGrid 7.1.2 referenced for the participants table migration. (Toolkit 8.x dropped DataGrid; 7.x is the only currently-maintained free option for WinUI 3.) * Inter.ttf + JetBrainsMono.ttf + dragon-mark.png + teamsiso.ico copied from the WPF project's Assets/ so the WinUI 3 host is self-contained. * TeamsISO.sln + TeamsISO.Windows.slnf updated to include the new project. The .slnf paths switch to backslash form so MSBuild can match them against the .sln's canonical path representation. Verified: dotnet build TeamsISO.Windows.slnf -c Debug succeeds with 0 warnings and 0 errors for all 8 projects (WPF host, WinUI 3 host, engine, NDI interop, console, three test projects).
2026-05-12 23:52:35 -04:00
Title = "TeamsISO";
feat(winui3): redesigned MainWindow + custom title bar + theme toggle Lands the approved shape brief as the WinUI 3 MainWindow: * 64px left rail with brand mark, primary nav (participants), Teams launch / hide / settings buttons, and the engine-status puck at the bottom. All five rail buttons use Segoe Fluent Icons glyphs at a uniform 20px optical size; no more bespoke <Path Data> shapes with inconsistent stroke weights. * 44px custom title bar via ExtendsContentIntoTitleBar + SetTitleBar(AppTitleBar). The drag region absorbs the three live-state pills inline (session timer 'live * 00:14:32', REC count + elapsed, disk free) and a slim sun/moon theme-toggle button to the left of the system Min/Max/Close controls. System buttons inherit ButtonForeground Color etc. from AppWindow.TitleBar so they match palette in both themes. * Section header with 'Participants * count' display, filter input, Refresh + Presets (Secondary buttons), and 'Enable all online' as the single cyan Primary button - finally a real button hierarchy instead of seven indistinguishable ghost buttons. * Participants list rendered as ItemsRepeater + DataTemplate for now; the CommunityToolkit DataGrid migration follows in a separate commit. Row template at 64px height with: 3px cyan left border for active speaker, avatar with initials in cyan-muted circle, name + codec line, signal lock state with dot, audio meter via ProgressBar, output name in JetBrains Mono, ISO state pill (LIVE/OFF/ERROR) at right. * Conditional in-call control bar below the table: Mute / Camera / Share / Marker / Leave + overflow kebab. Muted state binds the destructive coral treatment to the Mute button; Leave is also destructive (coral border + text); everything else is Secondary. Tight 8px spacing keeps the bar dense without crowding. * Slim 32px status bar at the bottom: control-surface URL on the left (cyan dot indicator), keyboard-shortcut hints on the right in tertiary mono. Replaces the WPF host's six-column footer. Implementation notes: * MockParticipant model populates the table with representative data (Maya / Daniel / Aicha / Sam, one as active speaker) until the ParticipantViewModel binding migrates over from the WPF host. * Custom Program.cs takes ownership of Main from the XAML compiler (DISABLE_XAML_GENERATED_MAIN). Calls Bootstrap.TryInitialize(0x00010006) before Application.Start so the unpackaged .exe can locate the WindowsAppSDK 1.6 framework MSIX at launch. Shutdown is paired in a finally block. * Theme toggle in code-behind flips Window.Content.RequestedTheme between Dark and Light. {ThemeResource} bindings auto-swap across the visual tree; system title-bar buttons (outside the XAML tree) get color updates inline so they stay readable in both modes. * app.manifest deferred from build - the framework-emitted manifest covers DPI awareness and supportedOS GUIDs; reintroducing our own goes in the next commit alongside the bootstrapper hardening. Known issue: the unpackaged .exe currently fails to activate on this build host with 'this application could not be started' before Main runs. Build is clean; published output runs the same way. Diagnosing the activation failure is the next session's first task (likely the runtimeconfig.json including Microsoft.WindowsDesktop.App which WinUI 3 doesn't want, or a missing CRT redistributable). The WPF host remains the running build until that's resolved. dotnet build TeamsISO.Windows.slnf -c Debug: 0 warnings, 0 errors.
2026-05-13 00:03:12 -04:00
// ── Custom title bar wiring ───────────────────────────────────────
// ExtendsContentIntoTitleBar=true tells WindowsAppSDK to draw the
// window chrome over our content instead of reserving a Windows-default
// caption strip. SetTitleBar marks AppTitleBar as the drag region —
// clicks on it route to the system drag handler, everything else stays
// hit-testable as a normal XAML element. The system min/max/close
// buttons render on top of the right edge regardless; we just provide
// their colors so they match our palette.
ExtendsContentIntoTitleBar = true;
SetTitleBar(AppTitleBar);
AppWindow.TitleBar.ButtonBackgroundColor = Colors.Transparent;
AppWindow.TitleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
AppWindow.TitleBar.ButtonHoverBackgroundColor = Color.FromArgb(0xFF, 0x33, 0x34, 0x3A);
AppWindow.TitleBar.ButtonPressedBackgroundColor = Color.FromArgb(0xFF, 0x3F, 0x3F, 0x47);
AppWindow.TitleBar.ButtonForegroundColor = Color.FromArgb(0xFF, 0xF4, 0xF4, 0xF6);
AppWindow.TitleBar.ButtonHoverForegroundColor = Colors.White;
// ── Initial size & position ───────────────────────────────────────
// 1280x780 matches the WPF host's default — fits comfortably on a
// 14-inch laptop while giving the participants table 600+ pixels
// of vertical breathing room.
AppWindow.Resize(new SizeInt32(1280, 780));
// ── Mock data wiring (interim) ────────────────────────────────────
// Until ParticipantViewModel binds in the engine wiring commit, the
// table is populated from a static sample list so the visual design
// can be validated end-to-end against representative data.
ParticipantsRepeater.ItemsSource = MockParticipant.Sample();
}
/// <summary>
/// Cycle the active theme between Dark and Light. The actual swap target
/// is the window's root visual element — RequestedTheme on that element
/// propagates the {ThemeResource} swap across the whole tree, with no
/// flicker. The system title-bar buttons aren't part of the visual tree,
/// so their colors are recomputed inline.
///
/// Persistence to UIPreferences.Theme happens in the view-model wiring
/// commit (the WinUI host doesn't yet share UIPreferences with the WPF
/// host; both will once the WinUI host owns the .NET startup).
/// </summary>
private void OnThemeToggleClick(object sender, RoutedEventArgs e)
{
if (Content is FrameworkElement root)
{
var next = root.ActualTheme == ElementTheme.Dark
? ElementTheme.Light
: ElementTheme.Dark;
root.RequestedTheme = next;
// Title-bar system buttons read from AppWindow.TitleBar directly,
// not from the XAML resource dictionary, so we set them inline
// for both themes. Dark-mode chrome lands on near-white glyphs;
// light-mode chrome lands on near-black glyphs.
if (next == ElementTheme.Dark)
{
AppWindow.TitleBar.ButtonForegroundColor = Color.FromArgb(0xFF, 0xF4, 0xF4, 0xF6);
AppWindow.TitleBar.ButtonHoverBackgroundColor = Color.FromArgb(0xFF, 0x33, 0x34, 0x3A);
AppWindow.TitleBar.ButtonPressedBackgroundColor = Color.FromArgb(0xFF, 0x3F, 0x3F, 0x47);
ThemeToggleIcon.Glyph = ""; // sun
}
else
{
AppWindow.TitleBar.ButtonForegroundColor = Color.FromArgb(0xFF, 0x0A, 0x0A, 0x0A);
AppWindow.TitleBar.ButtonHoverBackgroundColor = Color.FromArgb(0xFF, 0xEC, 0xEE, 0xF1);
AppWindow.TitleBar.ButtonPressedBackgroundColor = Color.FromArgb(0xFF, 0xE0, 0xE3, 0xE7);
ThemeToggleIcon.Glyph = ""; // moon
}
}
feat(winui3): scaffold TeamsISO.App.WinUI alongside the WPF host First step of the WinUI 3 replatform per the approved redesign brief. The new project coexists with the existing src/TeamsISO.App (WPF) so the WPF host keeps building and shipping while the WinUI 3 redesign lands incrementally. Once the WinUI 3 build is feature-complete and tested against a real Teams meeting, the WPF project is retired. Scaffold contents: * src/TeamsISO.App.WinUI/TeamsISO.App.WinUI.csproj Windows App SDK 1.6 LTS (250602001), unpackaged mode (WindowsPackageType=None) so the existing MSI installer keeps working. Target framework net8.0-windows10.0.19041.0, min platform 10.0.17763.0 to preserve Win10 1809+ compatibility for working broadcast hardware. Pins WindowsSdkPackageVersion=10.0.19041.38 so .NET SDK 8.0.301 builds cleanly without an SDK upgrade on the build host. * src/TeamsISO.App.WinUI/app.manifest PerMonitorV2 DPI awareness + gdiScaling for crisp text on high-DPI broadcast monitors. asInvoker trust level (control surface :9755 and OSC :9000 bind to 127.0.0.1, no admin needed). * App.xaml + App.xaml.cs Minimal startup: brings up MainWindow. The full pipeline (NDI runtime preflight, IsoController wiring, single-instance mutex, REST + OSC bridge, tray icon, crash diagnostics, auto-update banner, onboarding) migrates in subsequent commits. * Themes/Tokens.xaml Wild Dragon design tokens as ThemeDictionary entries (Default = Dark, Light). Colors as Color resources, Brushes paired per theme so {ThemeResource} auto-swaps when RequestedTheme flips — no app restart, no flicker. Spacing/radii/typography tokens are theme-agnostic at the outer level. Light palette maintains brand recognition via cyan-tinted off-whites (#FAFAFB canvas, #F0F1F3 rail) rather than pure white, and splits cyan into accent.cyan.surface (#97EDF0, works in both modes because text on top is near-black) and accent.cyan.text (#97EDF0 dark / #0E7C82 light) so captions and inline labels keep AA contrast. * Themes/Controls.xaml Button hierarchy with real commitments: Primary (cyan fill, one per surface), Secondary (transparent bordered), Tertiary (text only), Destructive (coral border + text), Caption (titlebar), RailIcon. Typographic ramp (Display / Title / Heading / Body / Subtle / Caption / Mono) at the DESIGN.md 1.25 ratio. * CommunityToolkit.WinUI.UI.Controls.DataGrid 7.1.2 referenced for the participants table migration. (Toolkit 8.x dropped DataGrid; 7.x is the only currently-maintained free option for WinUI 3.) * Inter.ttf + JetBrainsMono.ttf + dragon-mark.png + teamsiso.ico copied from the WPF project's Assets/ so the WinUI 3 host is self-contained. * TeamsISO.sln + TeamsISO.Windows.slnf updated to include the new project. The .slnf paths switch to backslash form so MSBuild can match them against the .sln's canonical path representation. Verified: dotnet build TeamsISO.Windows.slnf -c Debug succeeds with 0 warnings and 0 errors for all 8 projects (WPF host, WinUI 3 host, engine, NDI interop, console, three test projects).
2026-05-12 23:52:35 -04:00
}
}