fix(lifecycle): no dialogs while the app is closing

1ce6b9c made closing stop the session first, which was right and incomplete: the stop path opens TWO
modals, and WPF forbids that during a close. The creator's #2 test produced it immediately —

  System.InvalidOperationException: Cannot set Visibility to Visible or call Show, ShowDialog, Close,
  or WindowInteropHelper.EnsureHandle while a Window is closing.

Two prompts are suppressed by a `_shuttingDown` flag, each taking its safe default rather than a prompt
nobody can answer:
- The rename dialog: the recording is saved under its automatic name. Never discard footage the creator
  did not choose to discard.
- The private-broadcast keep/delete prompt: the broadcast is KEPT (stays private on YouTube) instead of
  being deleted by an answer that was never given.

The general rule this establishes: a teardown path may not ask questions. Any future prompt reached from
stop must check IsShuttingDown.

Not covered by a unit test — the trigger is a real WPF close, not reachable from the view model. Verified
against the exception in %APPDATA%\ytLlive\startup.log (09:40:27) and it needs the creator's retest.
This commit is contained in:
2026-11-13 09:42:44 -08:00
parent 5bd750eaf5
commit bd61e8df2a
3 changed files with 25 additions and 5 deletions
+6
View File
@@ -624,10 +624,16 @@ public partial class MainViewModel : ViewModelBase
/// while it was still working. The window now holds itself open until the ordinary stop completes
/// (bounded — a stuck encoder must not trap the creator in an unclosable app).</para>
/// </summary>
/// <summary>True while the app is closing. Dialogs cannot open then, so the stop path skips its
/// prompts and takes the safe default (save under the automatic name, keep the broadcast).</summary>
internal bool IsShuttingDown => _shuttingDown;
private bool _shuttingDown;
internal async Task<bool> StopBeforeShutdownAsync()
{
if (!IsLive && !IsRecording) return true;
_shuttingDown = true;
StopStream();
for (var i = 0; i < 120 && (IsLive || IsRecording); i++) // up to ~6 s
await Task.Delay(50).ConfigureAwait(true);