recording save dialog: Cancel discards the footage instead of saving the default

The creator reported that clicking Cancel in the post-recording save prompt still
saved the file under the default name: "cancel should cancel the save option,
discarding the recording" — Enter is what accepts the default.

The modal was always correct (Enter -> DialogResult=true, Cancel/Escape/X -> false).
The bug was in the caller: FinalizeRecordingAsync only overwrote `stem` when the
dialog returned true and then ran File.Move UNCONDITIONALLY, so a falsy result fell
straight through into the save. The nullable stem made "I don't want this" look
like "I accept the default".

Extracted the decision into internal MainViewModel.CompleteRecordingSave so it is
testable against real files without a frame pump:
  creatorSaved == false (Cancel/Escape/X) -> delete the temp file, leave the
      videos folder empty; a failed delete returns DiscardFailed and the toast
      names the file + folder (a "discarded" recording still on disk is worse
      than no report).
  creatorSaved == true (Save, or Enter on the pre-filled default) -> File.Move.
      A blank box still means "keep the auto name", but only on an explicit Save.

Test: ytLive.Tests/RecordingSaveDialogTests.cs — 5 facts over real temp files. The
headline asserts Cancel leaves the directory EMPTY, not merely "the stem is
unchanged"; a modal's own test cannot cover the decision it feeds.

Full suite 362/362 (the RealMouseDrag flake passed this run).
This commit is contained in:
2026-09-27 09:25:21 -07:00
parent de81fa3c5d
commit e3e69d941d
7 changed files with 324 additions and 19 deletions
+6 -2
View File
@@ -6,12 +6,16 @@ namespace ytLive;
/// <summary>Modal that lets the creator rename an auto-named recording before it is
/// finalized. Returns the chosen file stem (no extension) via <see cref="ResultFileName"/>,
/// or <c>null</c> on Cancel / keep-auto-name.</summary>
/// or <c>null</c> when the creator cleared the box and hit Save (keep the auto name).
/// <para><c>DialogResult == false</c> means DISCARD — the caller deletes the footage
/// rather than saving it (CREATOR RULING 2026-09-26). Enter on the pre-filled default
/// is a Save.</para></summary>
public partial class RenameRecordingDialog : Window
{
private readonly string _autoStem;
/// <summary>Stem (no extension) the creator chose, or <c>null</c> to keep auto-name.</summary>
/// <summary>Stem (no extension) the creator chose, or <c>null</c> when the box was
/// cleared on an explicit Save. Never set on Cancel.</summary>
public string? ResultFileName { get; private set; }
public RenameRecordingDialog(string autoStem)