feat: window-scoped keyboard shortcuts + help cheat sheet (F1)

This commit is contained in:
Zac Gaetano 2026-05-10 09:41:31 -04:00
parent 670813f18e
commit 6882e654d5
2 changed files with 242 additions and 0 deletions

View file

@ -0,0 +1,210 @@
<Window x:Class="TeamsISO.App.HelpWindow"
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="Help"
Icon="/Assets/teamsiso.ico"
Width="540" Height="560"
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="28,18,28,22">
<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="HELP"
Style="{StaticResource Wd.Text.Caption}"
VerticalAlignment="Center"/>
<Button Grid.Column="1"
Style="{StaticResource Wd.Button.CaptionClose}"
Click="OnClose"
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>
<!-- Header -->
<StackPanel Grid.Row="1" Margin="0,16,0,16">
<TextBlock Text="TeamsISO cheat sheet"
Style="{StaticResource Wd.Text.Title}"/>
<TextBlock Text="Keyboard shortcuts, file locations, and quick links."
Style="{StaticResource Wd.Text.Subtle}"
Foreground="{DynamicResource Wd.Text.Tertiary}"
Margin="0,4,0,0"/>
</StackPanel>
<!-- Body -->
<ScrollViewer Grid.Row="2" VerticalScrollBarVisibility="Auto">
<StackPanel>
<Border Style="{StaticResource Wd.Card}" Padding="16" Margin="0,0,0,12">
<StackPanel>
<TextBlock Text="KEYBOARD SHORTCUTS"
Style="{StaticResource Wd.Text.Caption}"
Margin="0,0,0,12"/>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0"
Text="F1"
Style="{StaticResource Wd.Text.Mono}"
Foreground="{DynamicResource Wd.Accent.Cyan}"
Margin="0,0,16,6"/>
<TextBlock Grid.Row="0" Grid.Column="1"
Text="Open this help"
Style="{StaticResource Wd.Text.Body}"
FontSize="12"
Margin="0,0,0,6"/>
<TextBlock Grid.Row="1" Grid.Column="0"
Text="Ctrl + M"
Style="{StaticResource Wd.Text.Mono}"
Foreground="{DynamicResource Wd.Accent.Cyan}"
Margin="0,0,16,6"/>
<TextBlock Grid.Row="1" Grid.Column="1"
Text="Drop a timestamped marker into every active recording"
Style="{StaticResource Wd.Text.Body}"
FontSize="12"
Margin="0,0,0,6"/>
<TextBlock Grid.Row="2" Grid.Column="0"
Text="Ctrl + Shift + S"
Style="{StaticResource Wd.Text.Mono}"
Foreground="{DynamicResource Wd.Accent.Cyan}"
Margin="0,0,16,6"/>
<TextBlock Grid.Row="2" Grid.Column="1"
Text="Stop every running ISO (emergency)"
Style="{StaticResource Wd.Text.Body}"
FontSize="12"
Margin="0,0,0,6"/>
<TextBlock Grid.Row="3" Grid.Column="0"
Text="Ctrl + R"
Style="{StaticResource Wd.Text.Mono}"
Foreground="{DynamicResource Wd.Accent.Cyan}"
Margin="0,0,16,0"/>
<TextBlock Grid.Row="3" Grid.Column="1"
Text="Refresh NDI discovery (rebuild finder)"
Style="{StaticResource Wd.Text.Body}"
FontSize="12"/>
</Grid>
</StackPanel>
</Border>
<Border Style="{StaticResource Wd.Card}" Padding="16" Margin="0,0,0,12">
<StackPanel>
<TextBlock Text="FILE LOCATIONS"
Style="{StaticResource Wd.Text.Caption}"
Margin="0,0,0,12"/>
<TextBlock Style="{StaticResource Wd.Text.Mono}"
FontSize="11"
Foreground="{DynamicResource Wd.Text.Secondary}"
TextWrapping="Wrap"
LineHeight="20">
<Run Text="Engine config" Foreground="{DynamicResource Wd.Text.Tertiary}"/>
<LineBreak/>
<Run Text="%APPDATA%\TeamsISO\config.json"/>
<LineBreak/>
<LineBreak/>
<Run Text="Operator presets" Foreground="{DynamicResource Wd.Text.Tertiary}"/>
<LineBreak/>
<Run Text="%LOCALAPPDATA%\TeamsISO\presets.json"/>
<LineBreak/>
<LineBreak/>
<Run Text="Diagnostic logs (rolling daily)" Foreground="{DynamicResource Wd.Text.Tertiary}"/>
<LineBreak/>
<Run Text="%LOCALAPPDATA%\TeamsISO\Logs\"/>
<LineBreak/>
<LineBreak/>
<Run Text="Recordings (default)" Foreground="{DynamicResource Wd.Text.Tertiary}"/>
<LineBreak/>
<Run Text="%USERPROFILE%\Videos\TeamsISO\&lt;date&gt;\"/>
<LineBreak/>
<LineBreak/>
<Run Text="NDI Access Manager config" Foreground="{DynamicResource Wd.Text.Tertiary}"/>
<LineBreak/>
<Run Text="%APPDATA%\NDI\ndi-config.v1.json"/>
</TextBlock>
</StackPanel>
</Border>
<Border Style="{StaticResource Wd.Card}" Padding="16">
<StackPanel>
<TextBlock Text="EXTERNAL CONTROL"
Style="{StaticResource Wd.Text.Caption}"
Margin="0,0,0,12"/>
<TextBlock Style="{StaticResource Wd.Text.Body}"
FontSize="12"
Foreground="{DynamicResource Wd.Text.Secondary}"
TextWrapping="Wrap"
Text="REST API (default :9755) and OSC bridge (default :9000) are off by default. Enable from Settings → DISPLAY. Stream Deck / Companion / TouchOSC can drive ISO toggles, presets, recording, mute/camera/leave, and marker drops. See docs/CONTROL-SURFACE.md for the full vocabulary."
Margin="0,0,0,8"/>
<TextBlock Style="{StaticResource Wd.Text.Mono}"
FontSize="11"
Foreground="{DynamicResource Wd.Text.Tertiary}">
<Hyperlink x:Name="DocsLink"
Foreground="{DynamicResource Wd.Accent.Cyan}"
TextDecorations="None"
Click="OnDocsClick">
forge.wilddragon.net/zgaetano/teamsiso
</Hyperlink>
</TextBlock>
</StackPanel>
</Border>
</StackPanel>
</ScrollViewer>
<!-- Footer -->
<Grid Grid.Row="3" Margin="0,18,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Button Grid.Column="1"
Style="{StaticResource Wd.Button.Primary}"
Content="Got it"
Click="OnClose"
Padding="22,8"/>
</Grid>
</Grid>
</Border>
</Window>

View file

@ -0,0 +1,32 @@
using System.Diagnostics;
using System.Windows;
namespace TeamsISO.App;
/// <summary>
/// F1 cheat-sheet dialog. Lists keyboard shortcuts, file locations, and a
/// link to the public documentation. Same chromeless style as the rest of
/// the host's modal dialogs.
/// </summary>
public partial class HelpWindow : Window
{
public HelpWindow() => InitializeComponent();
private void OnClose(object sender, RoutedEventArgs e) => Close();
private void OnDocsClick(object sender, RoutedEventArgs e)
{
try
{
Process.Start(new ProcessStartInfo
{
FileName = "https://forge.wilddragon.net/zgaetano/teamsiso",
UseShellExecute = true,
});
}
catch
{
// Best-effort browser launch
}
}
}