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;
|
feat(winui3): ThemeManager service + Settings drawer + Help/About/Onboarding
Builds out the secondary surfaces of the redesigned WinUI 3 host.
ThemeManager (Services/ThemeManager.cs)
Single-source-of-truth for the active theme. Holds the user preference
(System / Dark / Light), resolves it to ElementTheme at request, and
raises a Themed event when it changes so the MainWindow can push the
AppWindow title-bar button colors. Uses Windows.UI.ViewManagement
UISettings to follow the OS app-mode when preference is System.
Persistence to UIPreferences lands in the engine-wiring commit.
MainWindow theme wiring
Replaces the per-handler theme toggle with a ThemeManager subscription:
click the title-bar sun/moon -> Toggle() -> Themed event ->
ApplyResolvedTheme on the visual tree + the title-bar buttons. Glyph
cue: sun = "current is Light, click to Dark"; moon = "current is Dark,
click to Light." Initial state applied at construction so the first
frame matches the preference.
SettingsDrawer (Views/SettingsDrawer.xaml + .cs)
UserControl that slides in from the right over the participants table.
56px header, NavigationView with five tabs (Appearance, Routing,
Display, Control, Advanced), footer with Reset-to-defaults +
Apply/Close. Appearance tab has the theme tri-state picker (System /
Dark / Light radio group) and an "Accent peek" row showing the four
brand accents (cyan / coral / live / warn) as swatches so the
operator can verify Wild Dragon brand is respected on a light desk.
CloseRequested event signals the host to collapse the drawer.
HelpDialog (Views/HelpDialog.xaml + .cs)
ContentDialog with the keyboard shortcut cheat sheet, grouped by
category (Global / Participants / Look / Control surface). 540px max
height with scroll, mono-spaced shortcut labels at left, body text at
right. Replaces the WPF host's HelpWindow at parity.
AboutDialog (Views/AboutDialog.xaml + .cs)
ContentDialog with the Wild Dragon mark, version + host + engine +
brand info as label/value rows, and three quick action buttons
(open logs folder, open recordings, check for updates). Mirrors the
WPF host's AboutWindow.
OnboardingDialog (Views/OnboardingDialog.xaml + .cs)
Three numbered steps (Install NDI Runtime / Enable Teams NDI / Pick
transcoder topology), no carousel, operator-tone copy ("Don't show
this again" defaults checked). PrimaryButtonText "Get started",
SecondaryButtonText "Skip" so the dialog is skippable from the first
frame as the PRODUCT.md anti-references demand.
Build clean: dotnet build TeamsISO.App.WinUI -c Debug -> 0 / 0.
Next: wire the drawer's CloseRequested into MainWindow (so the settings
icon actually opens / collapses the drawer), then attack the runtime
activation blocker (Phase 3 of the migration plan).
2026-05-13 00:13:58 -04:00
|
|
|
using TeamsISO.App.WinUI.Services;
|
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 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.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));
|
|
|
|
|
|
2026-05-13 00:39:43 -04:00
|
|
|
// Participants stub is now declarative in MainWindow.xaml; no
|
|
|
|
|
// runtime population needed until the view-model wires up.
|
feat(winui3): ThemeManager service + Settings drawer + Help/About/Onboarding
Builds out the secondary surfaces of the redesigned WinUI 3 host.
ThemeManager (Services/ThemeManager.cs)
Single-source-of-truth for the active theme. Holds the user preference
(System / Dark / Light), resolves it to ElementTheme at request, and
raises a Themed event when it changes so the MainWindow can push the
AppWindow title-bar button colors. Uses Windows.UI.ViewManagement
UISettings to follow the OS app-mode when preference is System.
Persistence to UIPreferences lands in the engine-wiring commit.
MainWindow theme wiring
Replaces the per-handler theme toggle with a ThemeManager subscription:
click the title-bar sun/moon -> Toggle() -> Themed event ->
ApplyResolvedTheme on the visual tree + the title-bar buttons. Glyph
cue: sun = "current is Light, click to Dark"; moon = "current is Dark,
click to Light." Initial state applied at construction so the first
frame matches the preference.
SettingsDrawer (Views/SettingsDrawer.xaml + .cs)
UserControl that slides in from the right over the participants table.
56px header, NavigationView with five tabs (Appearance, Routing,
Display, Control, Advanced), footer with Reset-to-defaults +
Apply/Close. Appearance tab has the theme tri-state picker (System /
Dark / Light radio group) and an "Accent peek" row showing the four
brand accents (cyan / coral / live / warn) as swatches so the
operator can verify Wild Dragon brand is respected on a light desk.
CloseRequested event signals the host to collapse the drawer.
HelpDialog (Views/HelpDialog.xaml + .cs)
ContentDialog with the keyboard shortcut cheat sheet, grouped by
category (Global / Participants / Look / Control surface). 540px max
height with scroll, mono-spaced shortcut labels at left, body text at
right. Replaces the WPF host's HelpWindow at parity.
AboutDialog (Views/AboutDialog.xaml + .cs)
ContentDialog with the Wild Dragon mark, version + host + engine +
brand info as label/value rows, and three quick action buttons
(open logs folder, open recordings, check for updates). Mirrors the
WPF host's AboutWindow.
OnboardingDialog (Views/OnboardingDialog.xaml + .cs)
Three numbered steps (Install NDI Runtime / Enable Teams NDI / Pick
transcoder topology), no carousel, operator-tone copy ("Don't show
this again" defaults checked). PrimaryButtonText "Get started",
SecondaryButtonText "Skip" so the dialog is skippable from the first
frame as the PRODUCT.md anti-references demand.
Build clean: dotnet build TeamsISO.App.WinUI -c Debug -> 0 / 0.
Next: wire the drawer's CloseRequested into MainWindow (so the settings
icon actually opens / collapses the drawer), then attack the runtime
activation blocker (Phase 3 of the migration plan).
2026-05-13 00:13:58 -04:00
|
|
|
|
|
|
|
|
// ── Theme system ──────────────────────────────────────────────────
|
|
|
|
|
// Subscribe to ThemeManager so picker changes from anywhere
|
|
|
|
|
// (settings drawer, title-bar toggle, system color change) reach
|
|
|
|
|
// the title-bar buttons and the visual tree consistently. Apply
|
|
|
|
|
// once at construction so the initial state matches the preference
|
|
|
|
|
// before the first frame.
|
|
|
|
|
ThemeManager.Current.Themed += (_, theme) => ApplyResolvedTheme(theme);
|
|
|
|
|
ApplyResolvedTheme(ThemeManager.Current.ResolveTheme());
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
feat(winui3): ThemeManager service + Settings drawer + Help/About/Onboarding
Builds out the secondary surfaces of the redesigned WinUI 3 host.
ThemeManager (Services/ThemeManager.cs)
Single-source-of-truth for the active theme. Holds the user preference
(System / Dark / Light), resolves it to ElementTheme at request, and
raises a Themed event when it changes so the MainWindow can push the
AppWindow title-bar button colors. Uses Windows.UI.ViewManagement
UISettings to follow the OS app-mode when preference is System.
Persistence to UIPreferences lands in the engine-wiring commit.
MainWindow theme wiring
Replaces the per-handler theme toggle with a ThemeManager subscription:
click the title-bar sun/moon -> Toggle() -> Themed event ->
ApplyResolvedTheme on the visual tree + the title-bar buttons. Glyph
cue: sun = "current is Light, click to Dark"; moon = "current is Dark,
click to Light." Initial state applied at construction so the first
frame matches the preference.
SettingsDrawer (Views/SettingsDrawer.xaml + .cs)
UserControl that slides in from the right over the participants table.
56px header, NavigationView with five tabs (Appearance, Routing,
Display, Control, Advanced), footer with Reset-to-defaults +
Apply/Close. Appearance tab has the theme tri-state picker (System /
Dark / Light radio group) and an "Accent peek" row showing the four
brand accents (cyan / coral / live / warn) as swatches so the
operator can verify Wild Dragon brand is respected on a light desk.
CloseRequested event signals the host to collapse the drawer.
HelpDialog (Views/HelpDialog.xaml + .cs)
ContentDialog with the keyboard shortcut cheat sheet, grouped by
category (Global / Participants / Look / Control surface). 540px max
height with scroll, mono-spaced shortcut labels at left, body text at
right. Replaces the WPF host's HelpWindow at parity.
AboutDialog (Views/AboutDialog.xaml + .cs)
ContentDialog with the Wild Dragon mark, version + host + engine +
brand info as label/value rows, and three quick action buttons
(open logs folder, open recordings, check for updates). Mirrors the
WPF host's AboutWindow.
OnboardingDialog (Views/OnboardingDialog.xaml + .cs)
Three numbered steps (Install NDI Runtime / Enable Teams NDI / Pick
transcoder topology), no carousel, operator-tone copy ("Don't show
this again" defaults checked). PrimaryButtonText "Get started",
SecondaryButtonText "Skip" so the dialog is skippable from the first
frame as the PRODUCT.md anti-references demand.
Build clean: dotnet build TeamsISO.App.WinUI -c Debug -> 0 / 0.
Next: wire the drawer's CloseRequested into MainWindow (so the settings
icon actually opens / collapses the drawer), then attack the runtime
activation blocker (Phase 3 of the migration plan).
2026-05-13 00:13:58 -04:00
|
|
|
/// Cycle the active theme between Dark and Light from the title-bar
|
|
|
|
|
/// toggle. The actual swap lives in <see cref="ThemeManager"/>; this
|
|
|
|
|
/// handler just calls Toggle() and lets the subscription propagate.
|
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
|
|
|
/// </summary>
|
|
|
|
|
private void OnThemeToggleClick(object sender, RoutedEventArgs e)
|
feat(winui3): ThemeManager service + Settings drawer + Help/About/Onboarding
Builds out the secondary surfaces of the redesigned WinUI 3 host.
ThemeManager (Services/ThemeManager.cs)
Single-source-of-truth for the active theme. Holds the user preference
(System / Dark / Light), resolves it to ElementTheme at request, and
raises a Themed event when it changes so the MainWindow can push the
AppWindow title-bar button colors. Uses Windows.UI.ViewManagement
UISettings to follow the OS app-mode when preference is System.
Persistence to UIPreferences lands in the engine-wiring commit.
MainWindow theme wiring
Replaces the per-handler theme toggle with a ThemeManager subscription:
click the title-bar sun/moon -> Toggle() -> Themed event ->
ApplyResolvedTheme on the visual tree + the title-bar buttons. Glyph
cue: sun = "current is Light, click to Dark"; moon = "current is Dark,
click to Light." Initial state applied at construction so the first
frame matches the preference.
SettingsDrawer (Views/SettingsDrawer.xaml + .cs)
UserControl that slides in from the right over the participants table.
56px header, NavigationView with five tabs (Appearance, Routing,
Display, Control, Advanced), footer with Reset-to-defaults +
Apply/Close. Appearance tab has the theme tri-state picker (System /
Dark / Light radio group) and an "Accent peek" row showing the four
brand accents (cyan / coral / live / warn) as swatches so the
operator can verify Wild Dragon brand is respected on a light desk.
CloseRequested event signals the host to collapse the drawer.
HelpDialog (Views/HelpDialog.xaml + .cs)
ContentDialog with the keyboard shortcut cheat sheet, grouped by
category (Global / Participants / Look / Control surface). 540px max
height with scroll, mono-spaced shortcut labels at left, body text at
right. Replaces the WPF host's HelpWindow at parity.
AboutDialog (Views/AboutDialog.xaml + .cs)
ContentDialog with the Wild Dragon mark, version + host + engine +
brand info as label/value rows, and three quick action buttons
(open logs folder, open recordings, check for updates). Mirrors the
WPF host's AboutWindow.
OnboardingDialog (Views/OnboardingDialog.xaml + .cs)
Three numbered steps (Install NDI Runtime / Enable Teams NDI / Pick
transcoder topology), no carousel, operator-tone copy ("Don't show
this again" defaults checked). PrimaryButtonText "Get started",
SecondaryButtonText "Skip" so the dialog is skippable from the first
frame as the PRODUCT.md anti-references demand.
Build clean: dotnet build TeamsISO.App.WinUI -c Debug -> 0 / 0.
Next: wire the drawer's CloseRequested into MainWindow (so the settings
icon actually opens / collapses the drawer), then attack the runtime
activation blocker (Phase 3 of the migration plan).
2026-05-13 00:13:58 -04:00
|
|
|
{
|
|
|
|
|
ThemeManager.Current.Toggle();
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-13 00:20:23 -04:00
|
|
|
/// <summary>
|
2026-05-13 00:48:03 -04:00
|
|
|
/// Settings drawer toggle. Currently a no-op because the drawer host
|
|
|
|
|
/// can't be inlined in MainWindow.xaml without crashing the XAML parser;
|
|
|
|
|
/// see the comment in MainWindow.xaml at the drawer placeholder.
|
2026-05-13 00:20:23 -04:00
|
|
|
/// </summary>
|
|
|
|
|
private void OnSettingsClick(object sender, RoutedEventArgs e)
|
|
|
|
|
{
|
2026-05-13 00:48:03 -04:00
|
|
|
// No-op until SettingsDrawer.xaml is simplified for WinUI 3 1.8.
|
2026-05-13 00:20:23 -04:00
|
|
|
}
|
|
|
|
|
|
feat(winui3): ThemeManager service + Settings drawer + Help/About/Onboarding
Builds out the secondary surfaces of the redesigned WinUI 3 host.
ThemeManager (Services/ThemeManager.cs)
Single-source-of-truth for the active theme. Holds the user preference
(System / Dark / Light), resolves it to ElementTheme at request, and
raises a Themed event when it changes so the MainWindow can push the
AppWindow title-bar button colors. Uses Windows.UI.ViewManagement
UISettings to follow the OS app-mode when preference is System.
Persistence to UIPreferences lands in the engine-wiring commit.
MainWindow theme wiring
Replaces the per-handler theme toggle with a ThemeManager subscription:
click the title-bar sun/moon -> Toggle() -> Themed event ->
ApplyResolvedTheme on the visual tree + the title-bar buttons. Glyph
cue: sun = "current is Light, click to Dark"; moon = "current is Dark,
click to Light." Initial state applied at construction so the first
frame matches the preference.
SettingsDrawer (Views/SettingsDrawer.xaml + .cs)
UserControl that slides in from the right over the participants table.
56px header, NavigationView with five tabs (Appearance, Routing,
Display, Control, Advanced), footer with Reset-to-defaults +
Apply/Close. Appearance tab has the theme tri-state picker (System /
Dark / Light radio group) and an "Accent peek" row showing the four
brand accents (cyan / coral / live / warn) as swatches so the
operator can verify Wild Dragon brand is respected on a light desk.
CloseRequested event signals the host to collapse the drawer.
HelpDialog (Views/HelpDialog.xaml + .cs)
ContentDialog with the keyboard shortcut cheat sheet, grouped by
category (Global / Participants / Look / Control surface). 540px max
height with scroll, mono-spaced shortcut labels at left, body text at
right. Replaces the WPF host's HelpWindow at parity.
AboutDialog (Views/AboutDialog.xaml + .cs)
ContentDialog with the Wild Dragon mark, version + host + engine +
brand info as label/value rows, and three quick action buttons
(open logs folder, open recordings, check for updates). Mirrors the
WPF host's AboutWindow.
OnboardingDialog (Views/OnboardingDialog.xaml + .cs)
Three numbered steps (Install NDI Runtime / Enable Teams NDI / Pick
transcoder topology), no carousel, operator-tone copy ("Don't show
this again" defaults checked). PrimaryButtonText "Get started",
SecondaryButtonText "Skip" so the dialog is skippable from the first
frame as the PRODUCT.md anti-references demand.
Build clean: dotnet build TeamsISO.App.WinUI -c Debug -> 0 / 0.
Next: wire the drawer's CloseRequested into MainWindow (so the settings
icon actually opens / collapses the drawer), then attack the runtime
activation blocker (Phase 3 of the migration plan).
2026-05-13 00:13:58 -04:00
|
|
|
/// <summary>
|
|
|
|
|
/// Push a resolved theme to the visual tree and to the AppWindow
|
|
|
|
|
/// title-bar buttons. Called on every <see cref="ThemeManager.Themed"/>
|
|
|
|
|
/// event and once at construction.
|
|
|
|
|
/// </summary>
|
|
|
|
|
private void ApplyResolvedTheme(ElementTheme theme)
|
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
|
|
|
{
|
|
|
|
|
if (Content is FrameworkElement root)
|
|
|
|
|
{
|
feat(winui3): ThemeManager service + Settings drawer + Help/About/Onboarding
Builds out the secondary surfaces of the redesigned WinUI 3 host.
ThemeManager (Services/ThemeManager.cs)
Single-source-of-truth for the active theme. Holds the user preference
(System / Dark / Light), resolves it to ElementTheme at request, and
raises a Themed event when it changes so the MainWindow can push the
AppWindow title-bar button colors. Uses Windows.UI.ViewManagement
UISettings to follow the OS app-mode when preference is System.
Persistence to UIPreferences lands in the engine-wiring commit.
MainWindow theme wiring
Replaces the per-handler theme toggle with a ThemeManager subscription:
click the title-bar sun/moon -> Toggle() -> Themed event ->
ApplyResolvedTheme on the visual tree + the title-bar buttons. Glyph
cue: sun = "current is Light, click to Dark"; moon = "current is Dark,
click to Light." Initial state applied at construction so the first
frame matches the preference.
SettingsDrawer (Views/SettingsDrawer.xaml + .cs)
UserControl that slides in from the right over the participants table.
56px header, NavigationView with five tabs (Appearance, Routing,
Display, Control, Advanced), footer with Reset-to-defaults +
Apply/Close. Appearance tab has the theme tri-state picker (System /
Dark / Light radio group) and an "Accent peek" row showing the four
brand accents (cyan / coral / live / warn) as swatches so the
operator can verify Wild Dragon brand is respected on a light desk.
CloseRequested event signals the host to collapse the drawer.
HelpDialog (Views/HelpDialog.xaml + .cs)
ContentDialog with the keyboard shortcut cheat sheet, grouped by
category (Global / Participants / Look / Control surface). 540px max
height with scroll, mono-spaced shortcut labels at left, body text at
right. Replaces the WPF host's HelpWindow at parity.
AboutDialog (Views/AboutDialog.xaml + .cs)
ContentDialog with the Wild Dragon mark, version + host + engine +
brand info as label/value rows, and three quick action buttons
(open logs folder, open recordings, check for updates). Mirrors the
WPF host's AboutWindow.
OnboardingDialog (Views/OnboardingDialog.xaml + .cs)
Three numbered steps (Install NDI Runtime / Enable Teams NDI / Pick
transcoder topology), no carousel, operator-tone copy ("Don't show
this again" defaults checked). PrimaryButtonText "Get started",
SecondaryButtonText "Skip" so the dialog is skippable from the first
frame as the PRODUCT.md anti-references demand.
Build clean: dotnet build TeamsISO.App.WinUI -c Debug -> 0 / 0.
Next: wire the drawer's CloseRequested into MainWindow (so the settings
icon actually opens / collapses the drawer), then attack the runtime
activation blocker (Phase 3 of the migration plan).
2026-05-13 00:13:58 -04:00
|
|
|
root.RequestedTheme = theme;
|
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): ThemeManager service + Settings drawer + Help/About/Onboarding
Builds out the secondary surfaces of the redesigned WinUI 3 host.
ThemeManager (Services/ThemeManager.cs)
Single-source-of-truth for the active theme. Holds the user preference
(System / Dark / Light), resolves it to ElementTheme at request, and
raises a Themed event when it changes so the MainWindow can push the
AppWindow title-bar button colors. Uses Windows.UI.ViewManagement
UISettings to follow the OS app-mode when preference is System.
Persistence to UIPreferences lands in the engine-wiring commit.
MainWindow theme wiring
Replaces the per-handler theme toggle with a ThemeManager subscription:
click the title-bar sun/moon -> Toggle() -> Themed event ->
ApplyResolvedTheme on the visual tree + the title-bar buttons. Glyph
cue: sun = "current is Light, click to Dark"; moon = "current is Dark,
click to Light." Initial state applied at construction so the first
frame matches the preference.
SettingsDrawer (Views/SettingsDrawer.xaml + .cs)
UserControl that slides in from the right over the participants table.
56px header, NavigationView with five tabs (Appearance, Routing,
Display, Control, Advanced), footer with Reset-to-defaults +
Apply/Close. Appearance tab has the theme tri-state picker (System /
Dark / Light radio group) and an "Accent peek" row showing the four
brand accents (cyan / coral / live / warn) as swatches so the
operator can verify Wild Dragon brand is respected on a light desk.
CloseRequested event signals the host to collapse the drawer.
HelpDialog (Views/HelpDialog.xaml + .cs)
ContentDialog with the keyboard shortcut cheat sheet, grouped by
category (Global / Participants / Look / Control surface). 540px max
height with scroll, mono-spaced shortcut labels at left, body text at
right. Replaces the WPF host's HelpWindow at parity.
AboutDialog (Views/AboutDialog.xaml + .cs)
ContentDialog with the Wild Dragon mark, version + host + engine +
brand info as label/value rows, and three quick action buttons
(open logs folder, open recordings, check for updates). Mirrors the
WPF host's AboutWindow.
OnboardingDialog (Views/OnboardingDialog.xaml + .cs)
Three numbered steps (Install NDI Runtime / Enable Teams NDI / Pick
transcoder topology), no carousel, operator-tone copy ("Don't show
this again" defaults checked). PrimaryButtonText "Get started",
SecondaryButtonText "Skip" so the dialog is skippable from the first
frame as the PRODUCT.md anti-references demand.
Build clean: dotnet build TeamsISO.App.WinUI -c Debug -> 0 / 0.
Next: wire the drawer's CloseRequested into MainWindow (so the settings
icon actually opens / collapses the drawer), then attack the runtime
activation blocker (Phase 3 of the migration plan).
2026-05-13 00:13:58 -04:00
|
|
|
|
|
|
|
|
AppWindow.TitleBar.ButtonForegroundColor = ThemeManager.TitleBarForegroundFor(theme);
|
|
|
|
|
AppWindow.TitleBar.ButtonHoverBackgroundColor = ThemeManager.TitleBarHoverBgFor(theme);
|
|
|
|
|
AppWindow.TitleBar.ButtonPressedBackgroundColor = ThemeManager.TitleBarHoverBgFor(theme);
|
|
|
|
|
|
|
|
|
|
// Glyph cue: sun () means current is Light, click moves to Dark;
|
|
|
|
|
// moon () means current is Dark, click moves to Light.
|
|
|
|
|
ThemeToggleIcon.Glyph = theme == ElementTheme.Light ? "" : "";
|
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
|
|
|
}
|
|
|
|
|
}
|