restart with shutdown prevention
MODIFY
WalletWasabi.Fluent/ApplicationStateManager.cs
WalletWasabi.Fluent/ApplicationStateManager.cs
@@ -3,6 +3,7 @@ using System.Reactive.Disposables;
using System.Reactive.Linq;
using Avalonia.Controls.ApplicationLifetimes;
using ReactiveUI;
+using WalletWasabi.Fluent.Helpers;
using WalletWasabi.Fluent.Providers;
using WalletWasabi.Fluent.State;
using WalletWasabi.Fluent.ViewModels;
@@ -38,6 +39,7 @@ public class ApplicationStateManager : IMainWindowService
private CompositeDisposable? _compositeDisposable;
private bool _hideRequest;
private bool _isShuttingDown;
+ private bool _restartRequest;
internal ApplicationStateManager(IClassicDesktopStyleApplicationLifetime lifetime, bool startInBg)
{
@@ -52,8 +54,20 @@ public class ApplicationStateManager : IMainWindowService
_stateMachine.Configure(State.InitialState)
.InitialTransition(State.Open)
- .OnTrigger(Trigger.ShutdownRequested, () => lifetime.Shutdown())
- .OnTrigger(Trigger.ShutdownPrevented, () => ApplicationViewModel.OnShutdownPrevented());
+ .OnTrigger(Trigger.ShutdownRequested, () =>
+ {
+ if (_restartRequest)
+ {
+ AppLifetimeHelper.StartAppWithArgs();
+ }
+
+ lifetime.Shutdown();
+ })
+ .OnTrigger(Trigger.ShutdownPrevented, () =>
+ {
+ ApplicationViewModel.OnShutdownPrevented(_restartRequest);
+ _restartRequest = false; // reset the value.
+ });
_stateMachine.Configure(State.Closed)
.SubstateOf(State.InitialState)
@@ -160,8 +174,9 @@ public class ApplicationStateManager : IMainWindowService
_stateMachine.Fire(Trigger.Hide);
}
- void IMainWindowService.Shutdown()
+ void IMainWindowService.Shutdown(bool restart)
{
+ _restartRequest = restart;
_stateMachine.Fire(ApplicationViewModel.CanShutdown() ? Trigger.ShutdownRequested : Trigger.ShutdownPrevented);
}
}

MODIFY
WalletWasabi.Fluent/CrashReport/ViewModels/CrashReportWindowViewModel.cs
WalletWasabi.Fluent/CrashReport/ViewModels/CrashReportWindowViewModel.cs
@@ -15,7 +15,7 @@ public class CrashReportWindowViewModel : ViewModelBase
{
SerializedException = serializedException;
CancelCommand = ReactiveCommand.Create(AppLifetimeHelper.Restart);
- NextCommand = ReactiveCommand.Create(AppLifetimeHelper.Shutdown);
+ NextCommand = ReactiveCommand.Create(AppLifetimeHelper.ForceShutdown);
OpenGitHubRepoCommand = ReactiveCommand.CreateFromTask(async () => await IoHelpers.OpenBrowserAsync(AboutViewModel.UserSupportLink));

MODIFY
WalletWasabi.Fluent/Helpers/AppLifetimeHelper.cs
WalletWasabi.Fluent/Helpers/AppLifetimeHelper.cs
using System.Diagnostics;
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
+using WalletWasabi.Fluent.ViewModels;
using WalletWasabi.Microservices;
namespace WalletWasabi.Fluent.Helpers;
@@ -20,7 +21,19 @@ public static class AppLifetimeHelper
public static void Restart()
{
StartAppWithArgs();
- Shutdown();
+ ForceShutdown();
+ }
+
+ /// <summary>
+ /// Restarts the application with shutdown prevention.
+ /// </summary>
+ /// <remarks>
+ /// This method is only functional on the published builds
+ /// and not on debugging runs.
+ /// </remarks>
+ public static void RestartWithShutdownPrevention()
+ {
+ SafeShutdown(restart: true);
}
/// <summary>
@@ -45,9 +58,20 @@ public static class AppLifetimeHelper
}
/// <summary>
- /// Attempts to shutdown the current instance of the app safely.
+ /// Attempts to shutdown the current instance of the app safely with shutdown prevention.
+ /// </summary>
+ public static void SafeShutdown(bool restart = false)
+ {
+ if (Application.Current?.DataContext is ApplicationViewModel app)
+ {
+ app.Shutdown(restart);
+ }
+ }
+
+ /// <summary>
+ /// Attempts to shutdown the current instance of the app safely without shutdown prevention.
/// </summary>
- public static void Shutdown()
+ public static void ForceShutdown()
{
(Application.Current?.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime)?.Shutdown();
}

MODIFY
WalletWasabi.Fluent/Providers/IMainWindowService.cs
WalletWasabi.Fluent/Providers/IMainWindowService.cs
@@ -6,5 +6,5 @@ public interface IMainWindowService
void Hide();
- void Shutdown();
+ void Shutdown(bool restart);
}

MODIFY
WalletWasabi.Fluent/ViewModels/ApplicationViewModel.cs
WalletWasabi.Fluent/ViewModels/ApplicationViewModel.cs
@@ -19,7 +19,7 @@ public partial class ApplicationViewModel : ViewModelBase, ICanShutdownProvider
{
_mainWindowService = mainWindowService;
- QuitCommand = ReactiveCommand.Create(ShutDown);
+ QuitCommand = ReactiveCommand.Create(() => Shutdown(false));
ShowHideCommand = ReactiveCommand.Create(() =>
{
@@ -51,12 +51,12 @@ public partial class ApplicationViewModel : ViewModelBase, ICanShutdownProvider
public ICommand QuitCommand { get; }
- public void ShutDown() => _mainWindowService.Shutdown();
+ public void Shutdown(bool restart) => _mainWindowService.Shutdown(restart);
- public void OnShutdownPrevented()
+ public void OnShutdownPrevented(bool restartRequest)
{
MainViewModel.Instance.ApplyUiConfigWindowSate(); // Will pop the window if it was minimized.
- MainViewModel.Instance.CompactDialogScreen.To(new ShuttingDownViewModel(this));
+ MainViewModel.Instance.CompactDialogScreen.To(new ShuttingDownViewModel(this, restartRequest));
}
public bool CanShutdown()

MODIFY
WalletWasabi.Fluent/ViewModels/Dialogs/ShuttingDownViewModel.cs
WalletWasabi.Fluent/ViewModels/Dialogs/ShuttingDownViewModel.cs
@@ -9,10 +9,12 @@ namespace WalletWasabi.Fluent.ViewModels.Dialogs;
public partial class ShuttingDownViewModel : RoutableViewModel
{
private readonly ApplicationViewModel _applicationViewModel;
+ private readonly bool _restart;
- public ShuttingDownViewModel(ApplicationViewModel applicationViewModel)
+ public ShuttingDownViewModel(ApplicationViewModel applicationViewModel, bool restart)
{
_applicationViewModel = applicationViewModel;
+ _restart = restart;
NextCommand = CancelCommand;
}
@@ -25,7 +27,7 @@ public partial class ShuttingDownViewModel : RoutableViewModel
if (_applicationViewModel.CanShutdown())
{
Navigate().Clear();
- _applicationViewModel.ShutDown();
+ _applicationViewModel.Shutdown(_restart);
}
})
.DisposeWith(disposables);

MODIFY
WalletWasabi.Fluent/ViewModels/SearchBar/Settings/RestartViewModel.cs
WalletWasabi.Fluent/ViewModels/SearchBar/Settings/RestartViewModel.cs
@@ -9,7 +9,7 @@ public class RestartViewModel : ViewModelBase
public RestartViewModel(string message)
{
Message = message;
- RestartCommand = ReactiveCommand.Create(AppLifetimeHelper.Restart);
+ RestartCommand = ReactiveCommand.Create(AppLifetimeHelper.RestartWithShutdownPrevention);
}
public string Message { get; }

MODIFY
WalletWasabi.Fluent/ViewModels/Settings/SettingsPageViewModel.cs
WalletWasabi.Fluent/ViewModels/Settings/SettingsPageViewModel.cs
@@ -36,7 +36,7 @@ public partial class SettingsPageViewModel : DialogViewModelBase<Unit>
BitcoinTabSettings = new BitcoinTabSettingsViewModel();
AdvancedSettingsTab = new AdvancedSettingsTabViewModel();
- RestartCommand = ReactiveCommand.Create(AppLifetimeHelper.Restart);
+ RestartCommand = ReactiveCommand.Create(AppLifetimeHelper.RestartWithShutdownPrevention);
NextCommand = CancelCommand;
}

MODIFY
WalletWasabi.Fluent/ViewModels/StatusIcon/StatusIconViewModel.cs
WalletWasabi.Fluent/ViewModels/StatusIcon/StatusIconViewModel.cs
@@ -43,7 +43,7 @@ public partial class StatusIconViewModel : IStatusIconViewModel, IDisposable
UpdateCommand = ReactiveCommand.Create(() =>
{
Services.UpdateManager.DoUpdateOnClose = true;
- AppLifetimeHelper.Shutdown();
+ AppLifetimeHelper.SafeShutdown();
});
AskMeLaterCommand = ReactiveCommand.Create(() => UpdateAvailable = false);

restart with shutdown prevention