diff --git a/src/TeamsISO.App/MainWindow.xaml b/src/TeamsISO.App/MainWindow.xaml
index fbd0ca4..2867ce0 100644
--- a/src/TeamsISO.App/MainWindow.xaml
+++ b/src/TeamsISO.App/MainWindow.xaml
@@ -39,6 +39,7 @@
FalseValue="Visible"/>
+
@@ -138,7 +139,7 @@
Command="{Binding ToggleThemeCommand}"
Padding="6,4"
Margin="0,0,2,0"
- ToolTip="Toggle theme (Ctrl+T)">
+ ToolTip="Theme (System / Dark / Light)">
+
+ RowHeight="52"
+ Visibility="{Binding ParticipantCount, Converter={StaticResource CountToVis}}">
-
+
-
+
+
+
+
+
+
+
+
diff --git a/src/TeamsISO.App/MainWindow.xaml.cs b/src/TeamsISO.App/MainWindow.xaml.cs
index 5d68c6a..4c3caff 100644
--- a/src/TeamsISO.App/MainWindow.xaml.cs
+++ b/src/TeamsISO.App/MainWindow.xaml.cs
@@ -42,7 +42,12 @@ public partial class MainWindow : Window
/// Persist the placement on close so next launch lands in the same spot.
private void OnClosing(object? sender, System.ComponentModel.CancelEventArgs e)
{
- WindowStateStore.Save(this);
+ // A failure persisting window state must NEVER block the window from
+ // closing — operator's shutdown comes first. WindowStateStore.Save
+ // already swallows its own IO errors; this is defense-in-depth for
+ // anything that escapes (NRE, future regression, etc.).
+ try { WindowStateStore.Save(this); }
+ catch { /* best-effort: forgo placement memory for one launch */ }
}
/// Opens the About dialog — version, NDI runtime, build SHA.
@@ -87,8 +92,8 @@ public partial class MainWindow : Window
if (!TeamsLauncher.IsRunning())
{
MessageBox.Show(
- "Microsoft Teams isn't running. Click the camera icon above to launch it first.",
- "TeamsISO — Hide / show Teams",
+ Properties.Strings.HideShowTeams_NotRunning_Message,
+ Properties.Strings.HideShowTeams_Title,
MessageBoxButton.OK,
MessageBoxImage.Information);
return;
@@ -125,8 +130,8 @@ public partial class MainWindow : Window
if (!TeamsLauncher.TryLaunch(out var error))
{
MessageBox.Show(
- $"Could not launch Microsoft Teams.\n\n{error}",
- "TeamsISO — Launch Teams",
+ string.Format(Properties.Strings.LaunchTeams_Failed_MessageFormat, error),
+ Properties.Strings.LaunchTeams_Title,
MessageBoxButton.OK,
MessageBoxImage.Warning);
}
@@ -159,15 +164,19 @@ public partial class MainWindow : Window
///
/// Right-click on the Launch button asks to stop Teams. Split out from the
/// left-click so a normal click is "open / surface" rather than the previous
- /// "open OR ambush you with a stop dialog".
+ /// "open OR ambush you with a stop dialog". The confirmation dialog here is
+ /// intentional — Stop Teams is a destructive mid-show action; explicit
+ /// confirmation is the right pattern, not the "ambush" anti-pattern that
+ /// was fixed for left-click. The palette also offers Stop Teams for
+ /// keyboard-first operators.
///
private void OnLaunchTeamsRightClick(object sender, MouseButtonEventArgs e)
{
if (!TeamsLauncher.IsRunning()) return;
var confirm = MessageBox.Show(
- "Microsoft Teams is currently running.\n\nClose all Teams windows now?",
- "TeamsISO — Stop Teams",
+ Properties.Strings.StopTeams_Confirm_Message,
+ Properties.Strings.StopTeams_Title,
MessageBoxButton.YesNo,
MessageBoxImage.Question);
if (confirm != MessageBoxResult.Yes) return;
@@ -177,9 +186,9 @@ public partial class MainWindow : Window
{
MessageBox.Show(
asked == 0
- ? "No Teams windows responded to close."
- : $"Sent close to {asked} Teams window(s); some may still be exiting.",
- "TeamsISO — Stop Teams",
+ ? Properties.Strings.StopTeams_NoneResponded
+ : string.Format(Properties.Strings.StopTeams_AskedFormat, asked),
+ Properties.Strings.StopTeams_Title,
MessageBoxButton.OK,
MessageBoxImage.Information);
}
diff --git a/src/TeamsISO.App/Properties/Strings.Designer.cs b/src/TeamsISO.App/Properties/Strings.Designer.cs
new file mode 100644
index 0000000..fc74b0d
--- /dev/null
+++ b/src/TeamsISO.App/Properties/Strings.Designer.cs
@@ -0,0 +1,36 @@
+// Hand-written strongly-typed accessor for Properties/Strings.resx. Kept
+// out of Visual Studio's "ResXFileCodeGenerator" auto-regeneration loop
+// so the .csproj stays simple and the file doesn't churn on every save.
+// If you add a key in Strings.resx, add a matching property here.
+
+// The compiler treats `*.Designer.cs` as auto-generated and refuses
+// nullable annotations without an explicit directive — opt in.
+#nullable enable
+
+using System.Globalization;
+using System.Resources;
+
+namespace TeamsISO.App.Properties;
+
+internal static class Strings
+{
+ private static readonly ResourceManager ResourceManager = new(
+ baseName: "TeamsISO.App.Properties.Strings",
+ assembly: typeof(Strings).Assembly);
+
+ public static CultureInfo? Culture { get; set; }
+
+ private static string Get(string key) =>
+ ResourceManager.GetString(key, Culture) ?? string.Empty;
+
+ public static string HideShowTeams_Title => Get(nameof(HideShowTeams_Title));
+ public static string HideShowTeams_NotRunning_Message => Get(nameof(HideShowTeams_NotRunning_Message));
+
+ public static string LaunchTeams_Title => Get(nameof(LaunchTeams_Title));
+ public static string LaunchTeams_Failed_MessageFormat => Get(nameof(LaunchTeams_Failed_MessageFormat));
+
+ public static string StopTeams_Title => Get(nameof(StopTeams_Title));
+ public static string StopTeams_Confirm_Message => Get(nameof(StopTeams_Confirm_Message));
+ public static string StopTeams_NoneResponded => Get(nameof(StopTeams_NoneResponded));
+ public static string StopTeams_AskedFormat => Get(nameof(StopTeams_AskedFormat));
+}
diff --git a/src/TeamsISO.App/Properties/Strings.resx b/src/TeamsISO.App/Properties/Strings.resx
new file mode 100644
index 0000000..3f04b92
--- /dev/null
+++ b/src/TeamsISO.App/Properties/Strings.resx
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+ 2.0
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ TeamsISO — Hide / show Teams
+
+
+ Microsoft Teams isn't running. Click the camera icon above to launch it first.
+
+
+
+ TeamsISO — Launch Teams
+
+
+ Could not launch Microsoft Teams.
+
+{0}
+ {0} = error string from TeamsLauncher.TryLaunch.
+
+
+
+ TeamsISO — Stop Teams
+
+
+ Microsoft Teams is currently running.
+
+Close all Teams windows now?
+
+
+ No Teams windows responded to close.
+
+
+ Sent close to {0} Teams window(s); some may still be exiting.
+ {0} = number of windows the launcher asked to close.
+
+
diff --git a/src/TeamsISO.App/TeamsISO.App.csproj b/src/TeamsISO.App/TeamsISO.App.csproj
index bca05e1..c430347 100644
--- a/src/TeamsISO.App/TeamsISO.App.csproj
+++ b/src/TeamsISO.App/TeamsISO.App.csproj
@@ -39,6 +39,17 @@
+
+
+
+ TeamsISO.App.Properties.Strings.resources
+
+
+