using System; using System.IO; using System.Threading.Tasks; using System.Windows; using Microsoft.Win32; using ytLive.Helpers; using ytLive.Services; namespace ytLive.ViewModels; public partial class MainViewModel : ViewModelBase { private string? _recordFolder; public string RecordFolderDisplay => _recordFolder ?? DefaultRecordFolder(); private string? _activeRecordPath; private DateTime _recordStartTime; private TimeSpan _recordLength; private string? StartRecordFile() { try { var folder = _recordFolder ?? DefaultRecordFolder(); Directory.CreateDirectory(folder); var name = RecordingFile.BuildStartName(DateTime.Now) + ".mp4"; var path = Path.Combine(folder, name); _activeRecordPath = path; return path; } catch (Exception ex) { AppLog.Write(ex, "Recording: failed to prepare output path"); return null; } } private async Task FinalizeRecordingAsync() { var startPath = _activeRecordPath; _activeRecordPath = null; if (string.IsNullOrEmpty(startPath)) return; try { while (_framePump.IsRunning) await Task.Delay(50); if (!File.Exists(startPath)) { AppLog.Write($"Recording: output not found for rename: {startPath}"); return; } _recordLength = _liveElapsed; var autoStem = RecordingFile.BuildFinalName(_recordStartTime, _recordLength); var dir = Path.GetDirectoryName(startPath)!; // Manual rename modal: give the creator a chance to name the recording; // null = keep the auto name (or the default recorded above). string stem = autoStem; var dialog = new RenameRecordingDialog(autoStem); if (dialog.ShowDialog() == true && !string.IsNullOrEmpty(dialog.ResultFileName)) stem = dialog.ResultFileName; var finalPath = UniquePath(Path.Combine(dir, stem + ".mp4")); File.Move(startPath, finalPath); AppLog.Write($"Recording saved: {finalPath}"); _notifications.Info("Recording saved", Path.GetFileName(finalPath) + " — you can rename it in your videos folder at any time."); } catch (Exception ex) { AppLog.Write(ex, "Recording: rename-on-stop failed"); _notifications.Error("Recording saved", $"The recording was written but couldn't be renamed: {Path.GetFileName(startPath)}"); } } private static string UniquePath(string path) { if (!File.Exists(path)) return path; var dir = Path.GetDirectoryName(path)!; var name = Path.GetFileNameWithoutExtension(path); var ext = Path.GetExtension(path); for (var i = 2; ; i++) { var candidate = Path.Combine(dir, $"{name}-{i}{ext}"); if (!File.Exists(candidate)) return candidate; } } private void ChooseRecordFolder() { var dialog = new Microsoft.Win32.OpenFolderDialog { Title = "Choose a folder for local recordings", InitialDirectory = _recordFolder ?? DefaultRecordFolder(), }; if (dialog.ShowDialog() == true) { _recordFolder = dialog.FolderName; _layoutStore.SaveRecordFolder(_recordFolder); OnPropertyChanged(nameof(RecordFolderDisplay)); _notifications.Info("Record folder set", _recordFolder); } } private void ResetRecordFolder() { _recordFolder = null; _layoutStore.SaveRecordFolder(null); OnPropertyChanged(nameof(RecordFolderDisplay)); _notifications.Info("Record folder reset", RecordFolderDisplay); } internal static string DefaultRecordFolder() { var downloads = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Downloads"); return Directory.Exists(downloads) ? downloads : Environment.GetFolderPath(Environment.SpecialFolder.MyVideos); } }