Some checks failed
CI / build-and-test (push) Failing after 30s
Three small UX wins:
1. Onboarding gained step 5 ('Run Teams headless') and step 6 ('Drive from another machine') so new operators discover the auto-launch/auto-hide + LAN-reachable workflows. Existing 'where things live' step renumbered to 7.
2. Settings → DISPLAY → Control surface URL row gains an Open button next to Copy that fires the URL into the default browser via Process.Start with UseShellExecute. Operators previewing how the embedded /ui control panel looks on a phone/tablet no longer need to copy-paste manually.
3. Recording badge in footer now shows 'REC 3 · 12:45' instead of just 'REC 3'. RecordingElapsed VM property maintains a separate timer from the session timer because recording can start AFTER the meeting begins; operators tracking 'how long has the archive copy been rolling' need that distinct duration.
294 lines
18 KiB
XML
294 lines
18 KiB
XML
<Window x:Class="TeamsISO.App.OnboardingWindow"
|
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
xmlns:shell="clr-namespace:System.Windows.Shell;assembly=PresentationFramework"
|
|
Title="Welcome to TeamsISO"
|
|
Icon="/Assets/teamsiso.ico"
|
|
Width="560" Height="600"
|
|
WindowStartupLocation="CenterOwner"
|
|
WindowStyle="None"
|
|
ResizeMode="NoResize"
|
|
Background="{DynamicResource Wd.Canvas}"
|
|
UseLayoutRounding="True"
|
|
TextOptions.TextFormattingMode="Ideal"
|
|
TextOptions.TextRenderingMode="ClearType">
|
|
|
|
<shell:WindowChrome.WindowChrome>
|
|
<shell:WindowChrome
|
|
CaptionHeight="32"
|
|
ResizeBorderThickness="0"
|
|
CornerRadius="0"
|
|
GlassFrameThickness="0"
|
|
UseAeroCaptionButtons="False"/>
|
|
</shell:WindowChrome.WindowChrome>
|
|
|
|
<Border BorderBrush="{DynamicResource Wd.Border}" BorderThickness="1">
|
|
<Grid Margin="32,20,32,24">
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="*"/>
|
|
<RowDefinition Height="Auto"/>
|
|
</Grid.RowDefinitions>
|
|
|
|
<!-- Caption -->
|
|
<Grid Grid.Row="0">
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="*"/>
|
|
<ColumnDefinition Width="Auto"/>
|
|
</Grid.ColumnDefinitions>
|
|
<TextBlock Text="WELCOME"
|
|
Style="{StaticResource Wd.Text.Caption}"
|
|
VerticalAlignment="Center"/>
|
|
<Button Grid.Column="1"
|
|
Style="{StaticResource Wd.Button.CaptionClose}"
|
|
Click="OnDismiss"
|
|
shell:WindowChrome.IsHitTestVisibleInChrome="True">
|
|
<Path Data="M 0,0 L 10,10 M 10,0 L 0,10"
|
|
Stroke="{DynamicResource Wd.Text.Primary}"
|
|
StrokeThickness="1.2"
|
|
Width="10" Height="10"
|
|
Stretch="None"/>
|
|
</Button>
|
|
</Grid>
|
|
|
|
<!-- Hero -->
|
|
<StackPanel Grid.Row="1" Margin="0,16,0,20">
|
|
<Image Source="/Assets/dragon-mark.png"
|
|
Width="56" Height="56"
|
|
HorizontalAlignment="Left"
|
|
Margin="0,0,0,12"
|
|
RenderOptions.BitmapScalingMode="HighQuality"/>
|
|
<TextBlock Text="TeamsISO routes Microsoft Teams participants as isolated NDI feeds."
|
|
Style="{StaticResource Wd.Text.Title}"
|
|
TextWrapping="Wrap"/>
|
|
<TextBlock Text="A few one-time setup notes before you start."
|
|
Style="{StaticResource Wd.Text.Subtle}"
|
|
Foreground="{DynamicResource Wd.Text.Tertiary}"
|
|
Margin="0,6,0,0"/>
|
|
</StackPanel>
|
|
|
|
<!-- Body: numbered checklist -->
|
|
<ScrollViewer Grid.Row="2" VerticalScrollBarVisibility="Auto">
|
|
<StackPanel>
|
|
|
|
<!-- Step 1 — NDI runtime -->
|
|
<Border Style="{StaticResource Wd.Card}" Padding="16" Margin="0,0,0,12">
|
|
<StackPanel>
|
|
<StackPanel Orientation="Horizontal" Margin="0,0,0,8">
|
|
<Border Width="22" Height="22"
|
|
CornerRadius="11"
|
|
Background="{DynamicResource Wd.Accent.CyanMuted}"
|
|
VerticalAlignment="Center"
|
|
Margin="0,0,12,0">
|
|
<TextBlock Text="1"
|
|
Foreground="{DynamicResource Wd.Accent.Cyan}"
|
|
FontFamily="{StaticResource Wd.Font.Mono}"
|
|
FontSize="12"
|
|
HorizontalAlignment="Center"
|
|
VerticalAlignment="Center"/>
|
|
</Border>
|
|
<TextBlock Text="Install the NDI 6 runtime"
|
|
Style="{StaticResource Wd.Text.Heading}"
|
|
VerticalAlignment="Center"/>
|
|
</StackPanel>
|
|
<TextBlock TextWrapping="Wrap"
|
|
Style="{StaticResource Wd.Text.Body}"
|
|
FontSize="12"
|
|
Foreground="{DynamicResource Wd.Text.Secondary}"
|
|
Text="TeamsISO depends on NDI 6 from NewTek/Vizrt. Get it at ndi.video/tools — pick the Tools bundle for free, or use the Runtime-only installer if you have an NDI subscription."/>
|
|
</StackPanel>
|
|
</Border>
|
|
|
|
<!-- Step 2 — Teams NDI permission -->
|
|
<Border Style="{StaticResource Wd.Card}" Padding="16" Margin="0,0,0,12">
|
|
<StackPanel>
|
|
<StackPanel Orientation="Horizontal" Margin="0,0,0,8">
|
|
<Border Width="22" Height="22"
|
|
CornerRadius="11"
|
|
Background="{DynamicResource Wd.Accent.CyanMuted}"
|
|
VerticalAlignment="Center"
|
|
Margin="0,0,12,0">
|
|
<TextBlock Text="2"
|
|
Foreground="{DynamicResource Wd.Accent.Cyan}"
|
|
FontFamily="{StaticResource Wd.Font.Mono}"
|
|
FontSize="12"
|
|
HorizontalAlignment="Center"
|
|
VerticalAlignment="Center"/>
|
|
</Border>
|
|
<TextBlock Text="Enable broadcast in Teams"
|
|
Style="{StaticResource Wd.Text.Heading}"
|
|
VerticalAlignment="Center"/>
|
|
</StackPanel>
|
|
<TextBlock TextWrapping="Wrap"
|
|
Style="{StaticResource Wd.Text.Body}"
|
|
FontSize="12"
|
|
Foreground="{DynamicResource Wd.Text.Secondary}"
|
|
Text="In Microsoft Teams: Settings → Devices → 'Broadcast over NDI / SDI'. Your Teams admin may need to enable this at the tenant level (Teams admin center → Meetings → Meeting policies → 'Allow NDI broadcasting')."/>
|
|
</StackPanel>
|
|
</Border>
|
|
|
|
<!-- Step 3 — Transcoder topology -->
|
|
<Border Style="{StaticResource Wd.Card}" Padding="16" Margin="0,0,0,12">
|
|
<StackPanel>
|
|
<StackPanel Orientation="Horizontal" Margin="0,0,0,8">
|
|
<Border Width="22" Height="22"
|
|
CornerRadius="11"
|
|
Background="{DynamicResource Wd.Accent.CyanMuted}"
|
|
VerticalAlignment="Center"
|
|
Margin="0,0,12,0">
|
|
<TextBlock Text="3"
|
|
Foreground="{DynamicResource Wd.Accent.Cyan}"
|
|
FontFamily="{StaticResource Wd.Font.Mono}"
|
|
FontSize="12"
|
|
HorizontalAlignment="Center"
|
|
VerticalAlignment="Center"/>
|
|
</Border>
|
|
<TextBlock Text="Click 'Apply transcoder topology'"
|
|
Style="{StaticResource Wd.Text.Heading}"
|
|
VerticalAlignment="Center"/>
|
|
</StackPanel>
|
|
<TextBlock TextWrapping="Wrap"
|
|
Style="{StaticResource Wd.Text.Body}"
|
|
FontSize="12"
|
|
Foreground="{DynamicResource Wd.Text.Secondary}"
|
|
Text="Settings → NETWORK → Apply transcoder topology. This pins Teams' raw NDI broadcasts to a private 'teamsiso-input' group so they don't pollute the Public network. Restart Teams once after applying."/>
|
|
</StackPanel>
|
|
</Border>
|
|
|
|
<!-- Step 4 — Save a preset -->
|
|
<Border Style="{StaticResource Wd.Card}" Padding="16" Margin="0,0,0,12">
|
|
<StackPanel>
|
|
<StackPanel Orientation="Horizontal" Margin="0,0,0,8">
|
|
<Border Width="22" Height="22"
|
|
CornerRadius="11"
|
|
Background="{DynamicResource Wd.Accent.CyanMuted}"
|
|
VerticalAlignment="Center"
|
|
Margin="0,0,12,0">
|
|
<TextBlock Text="4"
|
|
Foreground="{DynamicResource Wd.Accent.Cyan}"
|
|
FontFamily="{StaticResource Wd.Font.Mono}"
|
|
FontSize="12"
|
|
HorizontalAlignment="Center"
|
|
VerticalAlignment="Center"/>
|
|
</Border>
|
|
<TextBlock Text="Save a preset for recurring shows"
|
|
Style="{StaticResource Wd.Text.Heading}"
|
|
VerticalAlignment="Center"/>
|
|
</StackPanel>
|
|
<TextBlock TextWrapping="Wrap"
|
|
Style="{StaticResource Wd.Text.Body}"
|
|
FontSize="12"
|
|
Foreground="{DynamicResource Wd.Text.Secondary}"
|
|
Text="Once you've toggled the right ISOs, click Presets in the participants header to save them by display name. Turn on 'Auto-apply last preset on launch' under DISPLAY settings and TeamsISO will restore that routing on every subsequent launch."/>
|
|
</StackPanel>
|
|
</Border>
|
|
|
|
<!-- Step 5 — Headless Teams ("I only see TeamsISO") -->
|
|
<Border Style="{StaticResource Wd.Card}" Padding="16" Margin="0,0,0,12">
|
|
<StackPanel>
|
|
<StackPanel Orientation="Horizontal" Margin="0,0,0,8">
|
|
<Border Width="22" Height="22"
|
|
CornerRadius="11"
|
|
Background="{DynamicResource Wd.Accent.CyanMuted}"
|
|
VerticalAlignment="Center"
|
|
Margin="0,0,12,0">
|
|
<TextBlock Text="5"
|
|
Foreground="{DynamicResource Wd.Accent.Cyan}"
|
|
FontFamily="{StaticResource Wd.Font.Mono}"
|
|
FontSize="12"
|
|
HorizontalAlignment="Center"
|
|
VerticalAlignment="Center"/>
|
|
</Border>
|
|
<TextBlock Text="Run Teams headless (optional)"
|
|
Style="{StaticResource Wd.Text.Heading}"
|
|
VerticalAlignment="Center"/>
|
|
</StackPanel>
|
|
<TextBlock TextWrapping="Wrap"
|
|
Style="{StaticResource Wd.Text.Body}"
|
|
FontSize="12"
|
|
Foreground="{DynamicResource Wd.Text.Secondary}"
|
|
Text="To use TeamsISO as your only window: tick both 'Launch Microsoft Teams on TeamsISO startup' and 'Auto-hide Teams windows when launched' under Settings → DISPLAY. Teams runs in the background; the IN-CALL bar shows the meeting state (READY / IN CALL · meeting title), the Mute/Camera/Share/Leave buttons drive Teams via UIAutomation, and the URL paste-box joins meetings directly. Use the eye-icon button in the left rail to manually restore Teams' windows when you need them."/>
|
|
</StackPanel>
|
|
</Border>
|
|
|
|
<!-- Step 6 — Where things live -->
|
|
<Border Style="{StaticResource Wd.Card}" Padding="16" Margin="0,0,0,12">
|
|
<StackPanel>
|
|
<StackPanel Orientation="Horizontal" Margin="0,0,0,8">
|
|
<Border Width="22" Height="22"
|
|
CornerRadius="11"
|
|
Background="{DynamicResource Wd.Accent.CyanMuted}"
|
|
VerticalAlignment="Center"
|
|
Margin="0,0,12,0">
|
|
<TextBlock Text="6"
|
|
Foreground="{DynamicResource Wd.Accent.Cyan}"
|
|
FontFamily="{StaticResource Wd.Font.Mono}"
|
|
FontSize="12"
|
|
HorizontalAlignment="Center"
|
|
VerticalAlignment="Center"/>
|
|
</Border>
|
|
<TextBlock Text="Drive from another machine (optional)"
|
|
Style="{StaticResource Wd.Text.Heading}"
|
|
VerticalAlignment="Center"/>
|
|
</StackPanel>
|
|
<TextBlock TextWrapping="Wrap"
|
|
Style="{StaticResource Wd.Text.Body}"
|
|
FontSize="12"
|
|
Foreground="{DynamicResource Wd.Text.Secondary}"
|
|
Text="For headless host PC + thin-client setups: tick 'Control surface' then 'LAN-reachable' under DISPLAY. TeamsISO listens on http://<your-lan-ip>:9755/ui — open that URL from any browser on the LAN. First-time use needs a one-shot 'netsh http add urlacl url=http://+:9755/ user=Everyone' in an Administrator PowerShell."/>
|
|
</StackPanel>
|
|
</Border>
|
|
|
|
<!-- Step 7 — Where things live -->
|
|
<Border Style="{StaticResource Wd.Card}" Padding="16">
|
|
<StackPanel>
|
|
<StackPanel Orientation="Horizontal" Margin="0,0,0,8">
|
|
<Border Width="22" Height="22"
|
|
CornerRadius="11"
|
|
Background="{DynamicResource Wd.Accent.CyanMuted}"
|
|
VerticalAlignment="Center"
|
|
Margin="0,0,12,0">
|
|
<TextBlock Text="7"
|
|
Foreground="{DynamicResource Wd.Accent.Cyan}"
|
|
FontFamily="{StaticResource Wd.Font.Mono}"
|
|
FontSize="12"
|
|
HorizontalAlignment="Center"
|
|
VerticalAlignment="Center"/>
|
|
</Border>
|
|
<TextBlock Text="If something breaks…"
|
|
Style="{StaticResource Wd.Text.Heading}"
|
|
VerticalAlignment="Center"/>
|
|
</StackPanel>
|
|
<TextBlock TextWrapping="Wrap"
|
|
Style="{StaticResource Wd.Text.Body}"
|
|
FontSize="12"
|
|
Foreground="{DynamicResource Wd.Text.Secondary}"
|
|
Text="Diagnostic logs roll daily under %LOCALAPPDATA%\TeamsISO\Logs. Settings live at %APPDATA%\TeamsISO\config.json; presets at %LOCALAPPDATA%\TeamsISO\presets.json. Attach the most recent log when filing an issue at forge.wilddragon.net/zgaetano/teamsiso."/>
|
|
</StackPanel>
|
|
</Border>
|
|
|
|
</StackPanel>
|
|
</ScrollViewer>
|
|
|
|
<!-- Footer -->
|
|
<Grid Grid.Row="3" Margin="0,20,0,0">
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="Auto"/>
|
|
<ColumnDefinition Width="*"/>
|
|
<ColumnDefinition Width="Auto"/>
|
|
</Grid.ColumnDefinitions>
|
|
<CheckBox Grid.Column="0"
|
|
x:Name="SuppressBox"
|
|
Content="Don't show this again"
|
|
IsChecked="True"
|
|
VerticalAlignment="Center"/>
|
|
<Button Grid.Column="2"
|
|
Style="{StaticResource Wd.Button.Primary}"
|
|
Content="Get started"
|
|
Click="OnDismiss"
|
|
Padding="22,8"/>
|
|
</Grid>
|
|
</Grid>
|
|
</Border>
|
|
</Window>
|