Files
LlamaCasty/RenameRecordingDialog.xaml.cs
T
gramps e3e69d941d 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).
2026-09-27 09:25:21 -07:00

68 lines
2.4 KiB
C#

using System.IO;
using System.Windows;
using System.Windows.Input;
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> 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> when the box was
/// cleared on an explicit Save. Never set on Cancel.</summary>
public string? ResultFileName { get; private set; }
public RenameRecordingDialog(string autoStem)
{
InitializeComponent();
_autoStem = autoStem;
NameBox.Text = autoStem;
Loaded += (_, _) => { NameBox.Focus(); NameBox.SelectAll(); };
NameBox.KeyDown += OnKeyDown;
}
private void OnKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter) { Save(); e.Handled = true; }
else if (e.Key == Key.Escape) { DialogResult = false; e.Handled = true; }
}
private void Cancel_Click(object sender, RoutedEventArgs e) => DialogResult = false;
private void Save_Click(object sender, RoutedEventArgs e) => Save();
private void Save()
{
var name = NameBox.Text?.Trim();
if (string.IsNullOrEmpty(name))
{
// Empty = keep the auto name.
ResultFileName = null;
DialogResult = true;
return;
}
// Strip any accidental ".mp4" so we return a clean stem.
if (name.EndsWith(".mp4", StringComparison.OrdinalIgnoreCase))
name = Path.GetFileNameWithoutExtension(name);
// Reject characters that are illegal in Windows file names.
if (name.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0)
{
MessageBox.Show(this, "That name contains characters not allowed in file names.",
"Invalid name", MessageBoxButton.OK, MessageBoxImage.Warning);
NameBox.Focus();
return;
}
ResultFileName = name;
DialogResult = true;
}
}