move quit mechanism to MainWindow OnClosing
MODIFY
WalletWasabi.Gui/Behaviors/PredicateCloseBehavior.cs
WalletWasabi.Gui/Behaviors/PredicateCloseBehavior.cs
@@ -23,8 +23,6 @@ namespace WalletWasabi.Gui.Behaviors
public static readonly AvaloniaProperty<bool> CanCloseProperty =
AvaloniaProperty.Register<PredicateCloseBehavior, bool>(nameof(CanClose));
- public Task DialogWindowTask = null;
-
public bool CanClose
{
get => GetValue(CanCloseProperty);
@@ -37,13 +35,6 @@ namespace WalletWasabi.Gui.Behaviors
_disposables = new CompositeDisposable
{
- Observable.FromEventPattern<CancelEventArgs>(AssociatedObject, nameof(AssociatedObject.Closing)).Subscribe(ev =>
- {
- if(!CanClose)
- {
- ev.EventArgs.Cancel = true;
- }
- })
};
}

MODIFY
WalletWasabi.Gui/Dialogs/CannotCloseDialogViewModel.cs
WalletWasabi.Gui/Dialogs/CannotCloseDialogViewModel.cs
@@ -4,6 +4,7 @@ using AvalonStudio.Extensibility.Dialogs;
using ReactiveUI;
using System;
using System.Collections.Generic;
+using System.Reactive.Disposables;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
@@ -11,12 +12,13 @@ using WalletWasabi;
namespace WalletWasabi.Gui.Dialogs
{
- internal class CannotCloseDialogViewModel : ModalDialogViewModelBase
+ internal class CannotCloseDialogViewModel : ModalDialogViewModelBase, IDisposable
{
private bool _isBusy;
private string _warningMessage;
private string _operationMessage;
private CancellationTokenSource _cancelTokenSource;
+ private CompositeDisposable Disposables { get; } = new CompositeDisposable();
public bool IsBusy
{
@@ -58,7 +60,7 @@ namespace WalletWasabi.Gui.Dialogs
// OK pressed.
Close(false);
},
- canOk);
+ canOk).DisposeWith(Disposables);
CancelCommand = ReactiveCommand.CreateFromTask(async () =>
{
@@ -71,9 +73,10 @@ namespace WalletWasabi.Gui.Dialogs
// OK pressed.
Close(false);
},
- canCancel);
+ canCancel).DisposeWith(Disposables);
_cancelTokenSource = new CancellationTokenSource();
+ Disposables.Add(_cancelTokenSource);
OKCommand.ThrownExceptions.Subscribe(ex => Logging.Logger.LogWarning<CannotCloseDialogViewModel>(ex));
CancelCommand.ThrownExceptions.Subscribe(ex => Logging.Logger.LogWarning<CannotCloseDialogViewModel>(ex));
@@ -147,5 +150,29 @@ namespace WalletWasabi.Gui.Dialogs
}
});
}
+
+ #region IDisposable Support
+
+ private volatile bool _disposedValue = false; // To detect redundant calls
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!_disposedValue)
+ {
+ if (disposing)
+ {
+ Disposables.Dispose();
+ }
+
+ _disposedValue = true;
+ }
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ #endregion IDisposable Support
}
}

MODIFY
WalletWasabi.Gui/Global.cs
WalletWasabi.Gui/Global.cs
@@ -75,7 +75,6 @@ namespace WalletWasabi.Gui
public static Config Config { get; private set; }
public static UiConfig UiConfig { get; private set; }
- public static bool IsQuitPending { get; private set; }
public static void InitializeConfig(Config config)
{
@@ -359,32 +358,6 @@ namespace WalletWasabi.Gui
Logger.LogInfo($"{nameof(ChaumianClient)} is stopped.", nameof(Global));
}
- public static async Task QuitApplicationAsync()
- {
- if (IsQuitPending) return;
- IsQuitPending = true;
- try
- {
- if (ChaumianClient != null)
- ChaumianClient.IsQuitPending = true;
- bool closeApplication = false;
-
- if (!MainWindowViewModel.Instance.CanClose)
- closeApplication = await MainWindowViewModel.Instance.ShowDialogAsync(new CannotCloseDialogViewModel());
- else
- closeApplication = true;
-
- if (closeApplication)
- Application.Current.MainWindow.Close();
- }
- finally
- {
- if (ChaumianClient != null)
- ChaumianClient.IsQuitPending = false;
- IsQuitPending = false;
- }
- }
-
public static async Task DisposeAsync()
{
try

MODIFY
WalletWasabi.Gui/MainWindow.xaml.cs
WalletWasabi.Gui/MainWindow.xaml.cs
@@ -3,6 +3,7 @@ using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
+using System.Threading.Tasks;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
@@ -11,6 +12,7 @@ using AvalonStudio.Extensibility;
using AvalonStudio.Extensibility.Theme;
using AvalonStudio.Shell;
using AvalonStudio.Shell.Controls;
+using WalletWasabi.Gui.Dialogs;
using WalletWasabi.Gui.Tabs.WalletManager;
using WalletWasabi.Gui.ViewModels;
@@ -18,6 +20,8 @@ namespace WalletWasabi.Gui
{
public class MainWindow : MetroWindow
{
+ public bool IsQuitPending { get; private set; }
+
public MainWindow()
{
InitializeComponent();
@@ -46,6 +50,33 @@ namespace WalletWasabi.Gui
{
try
{
+ if (IsQuitPending) return;
+ IsQuitPending = true;
+ try
+ {
+ if (Global.ChaumianClient != null)
+ Global.ChaumianClient.IsQuitPending = true;
+ bool closeApplication = false;
+
+ if (!MainWindowViewModel.Instance.CanClose)
+ {
+ using (var dialog = new CannotCloseDialogViewModel())
+ {
+ closeApplication = await MainWindowViewModel.Instance.ShowDialogAsync(dialog);
+ }
+ }
+ else
+ closeApplication = true;
+
+ e.Cancel = !closeApplication;
+ }
+ finally
+ {
+ if (Global.ChaumianClient != null)
+ Global.ChaumianClient.IsQuitPending = false;
+ IsQuitPending = false;
+ }
+
Global.UiConfig.WindowState = WindowState;
Global.UiConfig.Width = Width;
Global.UiConfig.Height = Height;

MODIFY
WalletWasabi.Gui/Shell/Commands/ExitCommands.cs
WalletWasabi.Gui/Shell/Commands/ExitCommands.cs
@@ -3,6 +3,7 @@ using System.Threading.Tasks;
using AvalonStudio.Commands;
using ReactiveUI;
using System;
+using Avalonia;
namespace WalletWasabi.Gui.Shell.Commands
{
@@ -14,7 +15,7 @@ namespace WalletWasabi.Gui.Shell.Commands
[ImportingConstructor]
public ExitCommands(CommandIconService commandIconService)
{
- var exit = ReactiveCommand.CreateFromTask(OnExitAsync);
+ var exit = ReactiveCommand.Create(OnExit);
exit.ThrownExceptions.Subscribe(ex => Logging.Logger.LogWarning<ExitCommands>(ex));
@@ -24,9 +25,9 @@ namespace WalletWasabi.Gui.Shell.Commands
exit);
}
- private async Task OnExitAsync()
+ private void OnExit()
{
- await Global.QuitApplicationAsync();
+ Application.Current.MainWindow.Close();
}
}
}

move quit mechanism to MainWindow OnClosing