Closing the main window used to silently kill every open Mission Control ConPTY session (App's ShutdownMode.OnMainWindowClose tears the process down without warning). Intercept Window.Closing, and when at least one pane is open, ask via the existing ConfirmAsync pattern before proceeding; cancelling leaves the window and sessions alive, confirming force-closes as before.
117 lines
3.9 KiB
C#
117 lines
3.9 KiB
C#
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using Avalonia;
|
|
using Avalonia.Controls;
|
|
using Avalonia.Input;
|
|
using Avalonia.Layout;
|
|
using Avalonia.Media;
|
|
using ClaudeDo.Ui.Localization;
|
|
using ClaudeDo.Ui.Services;
|
|
using ClaudeDo.Ui.ViewModels;
|
|
using ClaudeDo.Ui.ViewModels.Islands;
|
|
using ClaudeDo.Ui.ViewModels.Modals;
|
|
using ClaudeDo.Ui.Views.Modals;
|
|
|
|
namespace ClaudeDo.Ui.Views;
|
|
|
|
public partial class MainWindow : Window
|
|
{
|
|
private bool _forceClose;
|
|
|
|
public MainWindow()
|
|
{
|
|
InitializeComponent();
|
|
KeyDown += OnWindowKeyDown;
|
|
DataContextChanged += OnDataContextChanged;
|
|
UpdateMaxIcon();
|
|
}
|
|
|
|
// Closing the main window kills every open Mission Control ConPTY session without
|
|
// warning (App.axaml.cs: ShutdownMode.OnMainWindowClose). Ask first — never silently.
|
|
protected override void OnClosing(WindowClosingEventArgs e)
|
|
{
|
|
if (!_forceClose
|
|
&& DataContext is IslandsShellViewModel { Dialogs: { } dialogs } vm
|
|
&& IslandsShellViewModel.RequiresCloseConfirmation(vm.OpenMissionControlSessionCount))
|
|
{
|
|
e.Cancel = true;
|
|
_ = ConfirmCloseWithOpenSessionsAsync(dialogs, vm.OpenMissionControlSessionCount);
|
|
return;
|
|
}
|
|
base.OnClosing(e);
|
|
}
|
|
|
|
private async Task ConfirmCloseWithOpenSessionsAsync(IDialogService dialogs, int openSessionCount)
|
|
{
|
|
var confirmed = await dialogs.ConfirmAsync(Loc.T("vm.mainWindow.closeConfirm.message", openSessionCount));
|
|
if (!confirmed) return;
|
|
_forceClose = true;
|
|
Close();
|
|
}
|
|
|
|
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
|
{
|
|
base.OnPropertyChanged(change);
|
|
if (change.Property == WindowStateProperty)
|
|
{
|
|
UpdateMaxIcon();
|
|
if (DataContext is IslandsShellViewModel vm && vm.Tasks is not null)
|
|
vm.Tasks.IsWindowVisible = WindowState != WindowState.Minimized;
|
|
}
|
|
if (change.Property == OffScreenMarginProperty)
|
|
RootGrid.Margin = OffScreenMargin;
|
|
}
|
|
|
|
private void UpdateMaxIcon()
|
|
{
|
|
var key = WindowState == WindowState.Maximized ? "Icon.WinRestore" : "Icon.WinMax";
|
|
if (this.TryFindResource(key, out var geometry) && geometry is Geometry g)
|
|
MaxIcon.Data = g;
|
|
}
|
|
|
|
private void OnDataContextChanged(object? sender, EventArgs e)
|
|
{
|
|
if (DataContext is IslandsShellViewModel vm)
|
|
{
|
|
vm.Dialogs = new WindowDialogService(this);
|
|
vm.BringToFront = () =>
|
|
{
|
|
if (WindowState == WindowState.Minimized)
|
|
WindowState = WindowState.Normal;
|
|
Activate();
|
|
};
|
|
if (vm.Tasks is not null)
|
|
vm.Tasks.IsWindowVisible = WindowState != WindowState.Minimized;
|
|
}
|
|
}
|
|
|
|
private void OnWindowKeyDown(object? sender, KeyEventArgs e)
|
|
{
|
|
if (e.Key == Key.Space
|
|
&& FocusManager?.GetFocusedElement() is not TextBox
|
|
&& DataContext is IslandsShellViewModel vm)
|
|
{
|
|
e.Handled = true;
|
|
_ = vm.ToggleSelectedDoneAsync();
|
|
}
|
|
}
|
|
|
|
private void OnTitleBarPressed(object? sender, PointerPressedEventArgs e)
|
|
{
|
|
if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
|
|
BeginMoveDrag(e);
|
|
}
|
|
private void OnMinimize(object? s, Avalonia.Interactivity.RoutedEventArgs e) =>
|
|
WindowState = WindowState.Minimized;
|
|
private void OnToggleMax(object? s, Avalonia.Interactivity.RoutedEventArgs e) =>
|
|
WindowState = WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;
|
|
private void OnClose(object? s, Avalonia.Interactivity.RoutedEventArgs e) => Close();
|
|
|
|
protected override void OnSizeChanged(SizeChangedEventArgs e)
|
|
{
|
|
base.OnSizeChanged(e);
|
|
if (DataContext is IslandsShellViewModel vm) vm.WindowWidth = Bounds.Width;
|
|
}
|
|
|
|
}
|