Some checks failed
CI / build-and-test (push) Has been cancelled
Two big findings from a custom MddBootstrapInitialize2 P/Invoke probe
this session:
1. The original WinUI 3 activation failure ("this application could not
be started") was MDD_E_BOOTSTRAP_INITIALIZE_DDLM_NOT_FOUND (HR
0x80670016). The framework package Microsoft.WindowsAppRuntime.1.6
was installed, but the Dynamic Dependency Lifetime Manager sibling
(MicrosoftCorporationII.WinAppRuntime.Main.1.6) wasn't. This machine
has Main.1.5 and Main.1.8 packages but no Main.1.6, so bootstrap for
1.6 fails.
2. Switching the WindowsAppSDK NuGet to 1.8.250916003 + the bootstrap
major.minor to 0x00010008 in Program.cs gets past activation. The
.exe now launches and Bootstrap.TryInitialize returns S_OK. The 1.8
DDLM is present and the runtime spins up.
Also lands `src/TeamsISO.App.WinUI.Probe/`, a tiny console diagnostic
that calls MddBootstrapInitialize2 directly via P/Invoke (bypassing the
full WindowsAppSDK NuGet to avoid the MRT/PRI MSBuild tasks that need
VS's AppxPackage tooling installed). The probe prints the HResult and a
human-readable description; use it to triage WindowsAppSDK activation
on any deployment target:
dotnet run --project src/TeamsISO.App.WinUI.Probe
A SECOND ISSUE surfaces after activation: the .exe crashes 1 second
after launch with 0xC000027B inside Microsoft.UI.Xaml.dll, sub-code
0x802b000a (XAML_E_PARSER_GENERAL_ERROR). The participants ItemsRepeater
with {Binding ...} markup is suspect (WinUI 3 prefers x:Bind with
x:DataType, and Visibility="{Binding bool}" needs a converter). The
ItemsRepeater is stubbed out to a plain "Participants list renders here"
TextBlock placeholder for now; same crash recurs, so the XAML issue is
elsewhere — likely in Controls.xaml (one of CharacterSpacing /
TextCaption / etc. unsupported), in App.xaml's MergedDictionary chain,
or in MainWindow.xaml's Storyboard target.
Triaging the XAML parse error is the next session's first action. The
sub-code 0x802b000a will help (search WindowsAppSDK source for the
matching XAML parser error). The migration plan in
docs/superpowers/plans/2026-05-12-winui3-migration.md is updated.
Build remains clean.
447 lines
22 KiB
XML
447 lines
22 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<Window
|
|
x:Class="TeamsISO.App.WinUI.Views.MainWindow"
|
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
xmlns:models="using:TeamsISO.App.WinUI.Models"
|
|
xmlns:views="using:TeamsISO.App.WinUI.Views">
|
|
|
|
<!--
|
|
TeamsISO MainWindow — redesigned IA per the approved shape brief.
|
|
|
|
Structure:
|
|
[64 rail] [content]
|
|
[44 title bar — drag region]
|
|
[section header]
|
|
[participants list — hero]
|
|
[in-call control — conditional]
|
|
[32 status bar]
|
|
|
|
The rail's bottom puck opens the engine-status popover that absorbs
|
|
what used to live in the WPF footer (logs path, version, control
|
|
surface URL details). The title bar absorbs the live state pills
|
|
(session timer · REC · disk free) so the operator's at-a-glance
|
|
read stays in peripheral vision regardless of scroll position.
|
|
|
|
Settings is a right-side drawer (opened from the rail settings icon)
|
|
rather than a permanent 380px panel — the participants list claims
|
|
the full content width when settings aren't being actively edited.
|
|
-->
|
|
|
|
<Grid Background="{ThemeResource BgCanvas}">
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="64"/>
|
|
<ColumnDefinition Width="*"/>
|
|
</Grid.ColumnDefinitions>
|
|
<Grid.Resources>
|
|
<!-- Drawer slide-in: 220ms ease-out-quart, translates 400px → 0 -->
|
|
<Storyboard x:Key="DrawerSlideIn">
|
|
<DoubleAnimation Storyboard.TargetName="DrawerTransform"
|
|
Storyboard.TargetProperty="X"
|
|
To="0"
|
|
Duration="0:0:0.22">
|
|
<DoubleAnimation.EasingFunction>
|
|
<QuarticEase EasingMode="EaseOut"/>
|
|
</DoubleAnimation.EasingFunction>
|
|
</DoubleAnimation>
|
|
</Storyboard>
|
|
<Storyboard x:Key="DrawerSlideOut">
|
|
<DoubleAnimation Storyboard.TargetName="DrawerTransform"
|
|
Storyboard.TargetProperty="X"
|
|
To="400"
|
|
Duration="0:0:0.18">
|
|
<DoubleAnimation.EasingFunction>
|
|
<QuarticEase EasingMode="EaseIn"/>
|
|
</DoubleAnimation.EasingFunction>
|
|
</DoubleAnimation>
|
|
</Storyboard>
|
|
</Grid.Resources>
|
|
|
|
<!-- ═══════════════════════ LEFT RAIL ═══════════════════════ -->
|
|
<Border Grid.Column="0"
|
|
Background="{ThemeResource BgRail}"
|
|
BorderBrush="{ThemeResource BorderSubtle}"
|
|
BorderThickness="0,0,1,0">
|
|
<Grid>
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="*"/>
|
|
<RowDefinition Height="Auto"/>
|
|
</Grid.RowDefinitions>
|
|
|
|
<StackPanel Grid.Row="0" Spacing="2" Padding="0,12,0,0">
|
|
<!-- Wild Dragon brand mark -->
|
|
<Button x:Name="BrandButton"
|
|
Style="{StaticResource ButtonRailIcon}"
|
|
Width="48" Height="56"
|
|
Margin="8,0,8,8"
|
|
ToolTipService.ToolTip="About TeamsISO">
|
|
<Border Width="40" Height="40"
|
|
CornerRadius="{ThemeResource RadiusM}"
|
|
Background="{ThemeResource AccentCyanMuted}">
|
|
<TextBlock Text="W"
|
|
FontFamily="{ThemeResource FontSans}"
|
|
FontSize="22"
|
|
FontWeight="Bold"
|
|
Foreground="{ThemeResource AccentCyanText}"
|
|
HorizontalAlignment="Center"
|
|
VerticalAlignment="Center"/>
|
|
</Border>
|
|
</Button>
|
|
|
|
<Border Height="1"
|
|
Background="{ThemeResource BorderSubtle}"
|
|
Margin="14,4,14,12"/>
|
|
|
|
<!-- Participants / Home (active) -->
|
|
<Button Style="{StaticResource ButtonRailIcon}"
|
|
Margin="8,0"
|
|
ToolTipService.ToolTip="Participants">
|
|
<Grid>
|
|
<Border Width="48" Height="48"
|
|
CornerRadius="{ThemeResource RadiusM}"
|
|
Background="{ThemeResource AccentCyanMuted}"/>
|
|
<FontIcon Glyph=""
|
|
FontSize="20"
|
|
Foreground="{ThemeResource AccentCyanText}"
|
|
HorizontalAlignment="Center"
|
|
VerticalAlignment="Center"/>
|
|
</Grid>
|
|
</Button>
|
|
|
|
<!-- Launch / surface Teams -->
|
|
<Button Style="{StaticResource ButtonRailIcon}"
|
|
Margin="8,0"
|
|
ToolTipService.ToolTip="Launch Microsoft Teams (or surface its window)">
|
|
<FontIcon Glyph=""
|
|
FontSize="20"
|
|
Foreground="{ThemeResource FgSecondary}"/>
|
|
</Button>
|
|
|
|
<!-- Hide / show Teams windows -->
|
|
<Button Style="{StaticResource ButtonRailIcon}"
|
|
Margin="8,0"
|
|
ToolTipService.ToolTip="Hide / show Microsoft Teams windows">
|
|
<FontIcon Glyph=""
|
|
FontSize="20"
|
|
Foreground="{ThemeResource FgSecondary}"/>
|
|
</Button>
|
|
|
|
<!-- Settings drawer trigger -->
|
|
<Button x:Name="SettingsButton"
|
|
Style="{StaticResource ButtonRailIcon}"
|
|
Margin="8,0"
|
|
Click="OnSettingsClick"
|
|
ToolTipService.ToolTip="Settings">
|
|
<FontIcon Glyph=""
|
|
FontSize="20"
|
|
Foreground="{ThemeResource FgSecondary}"/>
|
|
</Button>
|
|
</StackPanel>
|
|
|
|
<!-- Engine status puck — opens the status popover -->
|
|
<Button x:Name="StatusPuckButton"
|
|
Grid.Row="1"
|
|
Style="{StaticResource ButtonRailIcon}"
|
|
Width="48" Height="48"
|
|
Margin="8,12"
|
|
CornerRadius="24"
|
|
Background="{ThemeResource StatusLiveBg}"
|
|
ToolTipService.ToolTip="Engine status">
|
|
<Ellipse Width="10" Height="10"
|
|
Fill="{ThemeResource StatusLive}"/>
|
|
</Button>
|
|
</Grid>
|
|
</Border>
|
|
|
|
<!-- ═══════════════════════ CONTENT ═══════════════════════ -->
|
|
<Grid Grid.Column="1">
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="44"/>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="*"/>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="32"/>
|
|
</Grid.RowDefinitions>
|
|
|
|
<!-- ─── Title bar ─── -->
|
|
<!--
|
|
AppTitleBar is the drag region. Window.SetTitleBar(AppTitleBar)
|
|
in code-behind makes this element the operating-system-defined
|
|
drag area. The system Min/Max/Close buttons render to the right
|
|
of this element automatically (their colors come from
|
|
AppWindow.TitleBar.ButtonForegroundColor etc.); we draw
|
|
everything else.
|
|
-->
|
|
<Grid x:Name="AppTitleBar"
|
|
Grid.Row="0"
|
|
Background="{ThemeResource BgCanvas}">
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="Auto"/>
|
|
<ColumnDefinition Width="*"/>
|
|
<ColumnDefinition Width="Auto"/>
|
|
<ColumnDefinition Width="Auto"/>
|
|
<ColumnDefinition Width="Auto"/>
|
|
<ColumnDefinition Width="Auto"/>
|
|
</Grid.ColumnDefinitions>
|
|
|
|
<StackPanel Grid.Column="0"
|
|
Orientation="Horizontal"
|
|
Spacing="12"
|
|
Padding="24,0,0,0"
|
|
VerticalAlignment="Center">
|
|
<TextBlock Text="TeamsISO"
|
|
Style="{StaticResource TextHeading}"
|
|
VerticalAlignment="Center"/>
|
|
<TextBlock x:Name="VersionLabel"
|
|
Text="v1.0.0-alpha"
|
|
Style="{StaticResource TextMono}"
|
|
FontSize="11"
|
|
Foreground="{ThemeResource FgTertiary}"
|
|
VerticalAlignment="Center"/>
|
|
</StackPanel>
|
|
|
|
<!-- Live pills (session timer / REC count / disk) live in the
|
|
title bar so peripheral-vision status reads from the same
|
|
place whether the operator is scrolled, settings-drawer
|
|
open, or in-call. Conditionally shown via code-behind. -->
|
|
<StackPanel x:Name="LivePillsPanel"
|
|
Grid.Column="2"
|
|
Orientation="Horizontal"
|
|
Spacing="8"
|
|
VerticalAlignment="Center"
|
|
Padding="0,0,12,0">
|
|
<Border CornerRadius="{ThemeResource RadiusPill}"
|
|
Background="{ThemeResource StatusLiveBg}"
|
|
Padding="10,4">
|
|
<StackPanel Orientation="Horizontal" Spacing="6">
|
|
<Ellipse Width="7" Height="7"
|
|
Fill="{ThemeResource StatusLive}"
|
|
VerticalAlignment="Center"/>
|
|
<TextBlock x:Name="SessionTimerText"
|
|
Text="live · 00:14:32"
|
|
Style="{StaticResource TextMono}"
|
|
FontSize="11"
|
|
Foreground="{ThemeResource StatusLive}"
|
|
VerticalAlignment="Center"/>
|
|
</StackPanel>
|
|
</Border>
|
|
|
|
<Border CornerRadius="{ThemeResource RadiusPill}"
|
|
Background="{ThemeResource AccentCoralBg}"
|
|
Padding="10,4">
|
|
<StackPanel Orientation="Horizontal" Spacing="6">
|
|
<Ellipse Width="7" Height="7"
|
|
Fill="{ThemeResource AccentCoral}"
|
|
VerticalAlignment="Center"/>
|
|
<TextBlock x:Name="RecPillText"
|
|
Text="rec 3 · 00:11:08"
|
|
Style="{StaticResource TextMono}"
|
|
FontSize="11"
|
|
Foreground="{ThemeResource AccentCoral}"
|
|
VerticalAlignment="Center"/>
|
|
</StackPanel>
|
|
</Border>
|
|
|
|
<Border CornerRadius="{ThemeResource RadiusPill}"
|
|
Background="{ThemeResource BgSurface}"
|
|
BorderBrush="{ThemeResource BorderSubtle}"
|
|
BorderThickness="1"
|
|
Padding="10,4">
|
|
<TextBlock x:Name="DiskFreeText"
|
|
Text="482 GB free"
|
|
Style="{StaticResource TextMono}"
|
|
FontSize="11"
|
|
Foreground="{ThemeResource FgSecondary}"
|
|
VerticalAlignment="Center"/>
|
|
</Border>
|
|
</StackPanel>
|
|
|
|
<!-- Theme toggle — single-click cycle between Dark and Light.
|
|
Persisted to UIPreferences.Theme on click. -->
|
|
<Button x:Name="ThemeToggleButton"
|
|
Grid.Column="3"
|
|
Style="{StaticResource ButtonCaption}"
|
|
Click="OnThemeToggleClick"
|
|
ToolTipService.ToolTip="Toggle theme (dark / light)">
|
|
<FontIcon x:Name="ThemeToggleIcon"
|
|
Glyph=""
|
|
FontSize="14"/>
|
|
</Button>
|
|
|
|
<!-- The Min / Max / Close buttons that follow in Grid.Column 4,5
|
|
are NOT drawn here — the WindowsAppSDK title-bar API draws
|
|
them itself, overlaid on the drag region we've defined.
|
|
The reserved columns 4 and 5 are just visual placeholders
|
|
in this layout to remind future readers where they land. -->
|
|
<Border Grid.Column="4" Width="138" Background="Transparent"/>
|
|
</Grid>
|
|
|
|
<!-- ─── Section header ─── -->
|
|
<Grid Grid.Row="1" Padding="32,18,32,12">
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="Auto"/>
|
|
<ColumnDefinition Width="*"/>
|
|
<ColumnDefinition Width="Auto"/>
|
|
</Grid.ColumnDefinitions>
|
|
|
|
<StackPanel Grid.Column="0"
|
|
Orientation="Horizontal"
|
|
Spacing="12"
|
|
VerticalAlignment="Center">
|
|
<TextBlock Text="Participants"
|
|
Style="{StaticResource TextDisplay}"/>
|
|
<Border CornerRadius="{ThemeResource RadiusPill}"
|
|
Background="{ThemeResource BgSurface}"
|
|
BorderBrush="{ThemeResource BorderSubtle}"
|
|
BorderThickness="1"
|
|
Padding="10,3"
|
|
VerticalAlignment="Center">
|
|
<TextBlock x:Name="ParticipantCountText"
|
|
Text="4"
|
|
Style="{StaticResource TextMono}"
|
|
FontSize="11"
|
|
Foreground="{ThemeResource FgSecondary}"/>
|
|
</Border>
|
|
</StackPanel>
|
|
|
|
<StackPanel Grid.Column="2"
|
|
Orientation="Horizontal"
|
|
Spacing="8"
|
|
VerticalAlignment="Center">
|
|
<TextBox x:Name="FilterInput"
|
|
PlaceholderText="Filter"
|
|
Width="200"
|
|
VerticalAlignment="Center"/>
|
|
<Button Style="{StaticResource ButtonSecondary}"
|
|
Content="Refresh"
|
|
ToolTipService.ToolTip="Refresh NDI discovery"/>
|
|
<Button Style="{StaticResource ButtonSecondary}"
|
|
Content="Presets"
|
|
ToolTipService.ToolTip="Save or load operator presets"/>
|
|
<Button Style="{StaticResource ButtonPrimary}"
|
|
Content="Enable all online"
|
|
HorizontalAlignment="Right"
|
|
ToolTipService.ToolTip="Enable ISOs for every online participant"/>
|
|
</StackPanel>
|
|
</Grid>
|
|
|
|
<!-- ─── Participants list (hero) ─── -->
|
|
<!--
|
|
ItemsRepeater + DataTemplate with bindings deferred to the
|
|
view-model-wiring commit (Phase 4 of the migration plan).
|
|
For now, a single stub row renders so the layout's vertical
|
|
rhythm is verifiable even without real data. The full row
|
|
template (with active-speaker accent, avatar circle, signal
|
|
lock, audio meter, ISO toggle) is captured in the HTML
|
|
preview at docs/preview/redesigned-mainwindow.html and the
|
|
git history of this file shows the binding-heavy version
|
|
we'll re-introduce once the engine is wired in.
|
|
-->
|
|
<Grid Grid.Row="2" Padding="32,0,32,0">
|
|
<StackPanel x:Name="ParticipantsStub"
|
|
VerticalAlignment="Center"
|
|
HorizontalAlignment="Center"
|
|
Spacing="8">
|
|
<TextBlock Text="Participants list renders here"
|
|
Style="{StaticResource TextHeading}"
|
|
HorizontalAlignment="Center"/>
|
|
<TextBlock Text="View-model wiring queued for the next session."
|
|
Style="{StaticResource TextSubtle}"
|
|
HorizontalAlignment="Center"/>
|
|
</StackPanel>
|
|
</Grid>
|
|
|
|
<!-- ─── In-call control (conditional) ─── -->
|
|
<Border Grid.Row="3"
|
|
Padding="32,12,32,12"
|
|
BorderBrush="{ThemeResource BorderSubtle}"
|
|
BorderThickness="0,1,0,0"
|
|
Background="{ThemeResource BgCanvas}">
|
|
<StackPanel Orientation="Horizontal" Spacing="8">
|
|
<TextBlock Text="IN-CALL"
|
|
Style="{StaticResource TextCaption}"
|
|
VerticalAlignment="Center"
|
|
Margin="0,0,8,0"/>
|
|
<Button Style="{StaticResource ButtonDestructive}"
|
|
ToolTipService.ToolTip="Toggle microphone mute">
|
|
<StackPanel Orientation="Horizontal" Spacing="6">
|
|
<FontIcon Glyph="" FontSize="14"/>
|
|
<TextBlock Text="Muted"/>
|
|
</StackPanel>
|
|
</Button>
|
|
<Button Style="{StaticResource ButtonSecondary}"
|
|
ToolTipService.ToolTip="Toggle camera">
|
|
<StackPanel Orientation="Horizontal" Spacing="6">
|
|
<FontIcon Glyph="" FontSize="14"/>
|
|
<TextBlock Text="Camera"/>
|
|
</StackPanel>
|
|
</Button>
|
|
<Button Style="{StaticResource ButtonSecondary}"
|
|
ToolTipService.ToolTip="Open Teams share tray">
|
|
<StackPanel Orientation="Horizontal" Spacing="6">
|
|
<FontIcon Glyph="" FontSize="14"/>
|
|
<TextBlock Text="Share"/>
|
|
</StackPanel>
|
|
</Button>
|
|
<Button Style="{StaticResource ButtonSecondary}"
|
|
ToolTipService.ToolTip="Drop a timestamped marker into every active recording">
|
|
<StackPanel Orientation="Horizontal" Spacing="6">
|
|
<FontIcon Glyph="" FontSize="14"/>
|
|
<TextBlock Text="Marker"/>
|
|
</StackPanel>
|
|
</Button>
|
|
<Button Style="{StaticResource ButtonDestructive}"
|
|
ToolTipService.ToolTip="Leave the Teams call">
|
|
<TextBlock Text="Leave"/>
|
|
</Button>
|
|
</StackPanel>
|
|
</Border>
|
|
|
|
<!-- ─── Settings drawer (slides over rows 1-3) ─── -->
|
|
<views:SettingsDrawer x:Name="SettingsDrawerHost"
|
|
Grid.Row="0"
|
|
Grid.RowSpan="4"
|
|
HorizontalAlignment="Right"
|
|
Width="400"
|
|
IsHitTestVisible="False">
|
|
<views:SettingsDrawer.RenderTransform>
|
|
<TranslateTransform x:Name="DrawerTransform" X="400"/>
|
|
</views:SettingsDrawer.RenderTransform>
|
|
</views:SettingsDrawer>
|
|
|
|
<!-- ─── Status bar ─── -->
|
|
<Grid Grid.Row="4"
|
|
Padding="32,8,32,8"
|
|
Background="{ThemeResource BgCanvas}"
|
|
BorderBrush="{ThemeResource BorderSubtle}"
|
|
BorderThickness="0,1,0,0">
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="Auto"/>
|
|
<ColumnDefinition Width="*"/>
|
|
<ColumnDefinition Width="Auto"/>
|
|
</Grid.ColumnDefinitions>
|
|
|
|
<StackPanel Grid.Column="0"
|
|
Orientation="Horizontal"
|
|
Spacing="8"
|
|
VerticalAlignment="Center">
|
|
<Ellipse Width="6" Height="6"
|
|
Fill="{ThemeResource AccentCyanText}"
|
|
VerticalAlignment="Center"/>
|
|
<TextBlock Text="control surface · 127.0.0.1:9755"
|
|
Style="{StaticResource TextMono}"
|
|
FontSize="11"
|
|
Foreground="{ThemeResource FgSecondary}"
|
|
VerticalAlignment="Center"/>
|
|
</StackPanel>
|
|
|
|
<TextBlock Grid.Column="2"
|
|
Text="F1 help · Ctrl+M marker · Ctrl+Shift+S panic stop · Ctrl+K command palette"
|
|
Style="{StaticResource TextMono}"
|
|
FontSize="11"
|
|
Foreground="{ThemeResource FgTertiary}"
|
|
VerticalAlignment="Center"/>
|
|
</Grid>
|
|
</Grid>
|
|
</Grid>
|
|
</Window>
|