using System; using System.Linq; using System.Threading.Tasks; using Avalonia.Controls; using Avalonia.Interactivity; using Avalonia.VisualTree; using AvaloniaEdit; using MarkdownEditor.Constants; using MarkdownEditor.ViewModels; namespace MarkdownEditor.Views; /// /// Main application window. /// Handles initialization and coordination between the view and view model. /// public partial class MainWindow : Window { private bool _isClosingConfirmed = false; /// /// Initializes a new instance of the class. /// public MainWindow() { InitializeComponent(); // Subscribe to pointer pressed to capture selection before command executes this.AddHandler(Button.PointerPressedEvent, OnButtonPointerPressed, Avalonia.Interactivity.RoutingStrategies.Tunnel); } /// protected override void OnOpened(EventArgs e) { base.OnOpened(e); if (DataContext is MainWindowViewModel viewModel) { viewModel.StorageProvider = StorageProvider; // Restore session after StorageProvider is set _ = viewModel.RestoreSessionAsync(); } } /// protected override async void OnClosing(WindowClosingEventArgs e) { if (DataContext is not MainWindowViewModel viewModel) { base.OnClosing(e); return; } // If we've already confirmed the close (from a previous call), just save session and close if (_isClosingConfirmed) { await viewModel.SaveSessionAsync(); base.OnClosing(e); return; } // Check for unsaved changes if (viewModel.HasUnsavedChanges()) { // Cancel the close event to prevent immediate closing e.Cancel = true; // Show save confirmation dialog var unsavedCount = viewModel.GetUnsavedChangesCount(); var message = unsavedCount == 1 ? AppConstants.Messages.SaveChangesBeforeClose : string.Format(AppConstants.Messages.SaveChangesBeforeCloseMultiple, unsavedCount); var dialog = new SaveConfirmationDialog(message); await dialog.ShowDialog(this); var result = dialog.Result; switch (result) { case SaveConfirmationResult.Save: // User wants to save - save all unsaved changes var saved = await viewModel.SaveAllUnsavedChangesAsync(); if (saved) { // All files saved successfully - mark as confirmed and close _isClosingConfirmed = true; await viewModel.SaveSessionAsync(); Close(); } // If save was cancelled, keep the window open (e.Cancel is already true) // Don't call base.OnClosing since we're cancelling return; case SaveConfirmationResult.DontSave: // User doesn't want to save - mark as confirmed and close _isClosingConfirmed = true; await viewModel.SaveSessionAsync(); Close(); // Don't call base.OnClosing here - Close() will trigger OnClosing again return; case SaveConfirmationResult.Cancel: default: // User cancelled - keep the window open (e.Cancel is already true) // Don't call base.OnClosing since we're cancelling return; } } else { // No unsaved changes - just save session and close normally await viewModel.SaveSessionAsync(); } base.OnClosing(e); } /// /// Handles pointer pressed events to capture text selection before formatting commands execute. /// This is necessary because toolbar buttons take focus, losing the text selection. /// private void OnButtonPointerPressed(object? sender, Avalonia.Input.PointerPressedEventArgs e) { // Walk up the visual tree to find the Button Button? button = null; if (e.Source is Control sourceControl) { button = sourceControl.GetVisualAncestors().OfType