use statemachine to track state of main window.
MODIFY
WalletWasabi.Fluent.Desktop/Program.cs
WalletWasabi.Fluent.Desktop/Program.cs
@@ -34,7 +34,7 @@ public class Program
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
bool runGui = true;
- bool runGuiMinimized = args.Any(arg => arg.Contains(StartupHelper.SilentArgument));
+ bool runGuiInBackground = args.Any(arg => arg.Contains(StartupHelper.SilentArgument));
// Initialize the logger.
string dataDir = EnvironmentHelpers.GetDataDir(Path.Combine("WalletWasabi", "Client"));
@@ -74,7 +74,7 @@ public class Program
Services.Initialize(Global, singleInstanceChecker);
Logger.LogSoftwareStarted("Wasabi GUI");
- BuildAvaloniaApp()
+ BuildAvaloniaApp(runGuiInBackground)
.AfterSetup(_ => ThemeHelper.ApplyTheme(Global.UiConfig.DarkModeEnabled ? Theme.Dark : Theme.Light))
.StartWithClassicDesktopLifetime(args);
}
@@ -180,7 +180,7 @@ public class Program
}
// Avalonia configuration, don't remove; also used by visual designer.
- private static AppBuilder BuildAvaloniaApp()
+ private static AppBuilder BuildAvaloniaApp(bool startInBg)
{
bool useGpuLinux = true;
@@ -190,7 +190,7 @@ public class Program
{
await global.InitializeNoWalletAsync(TerminateService);
}
- }))
+ }, startInBg))
.UseReactiveUI();
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))

MODIFY
WalletWasabi.Fluent/App.axaml
WalletWasabi.Fluent/App.axaml
xmlns:converters="clr-namespace:WalletWasabi.Fluent.Converters"
x:DataType="vm:ApplicationViewModel"
x:CompileBindings="True"
- x:Class="WalletWasabi.Fluent.App" CanShutdownProvider="{Binding .}">
+ x:Class="WalletWasabi.Fluent.App">
<Application.DataTemplates>
<local:ViewLocator />
<DataTemplate DataType="models:ErrorDescriptor" x:DataType="models:ErrorDescriptor">

MODIFY
WalletWasabi.Fluent/App.axaml.cs
WalletWasabi.Fluent/App.axaml.cs
using System.Reactive.Concurrency;
-using System.Reactive.Linq;
using System.Threading.Tasks;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
-using Avalonia.Data;
using Avalonia.Markup.Xaml;
using ReactiveUI;
using WalletWasabi.Fluent.Providers;
using WalletWasabi.Fluent.ViewModels;
-using WalletWasabi.Fluent.Views;
-using WalletWasabi.Logging;
namespace WalletWasabi.Fluent;
-
-
-public class App : Application, IMainWindowService
+public class App : Application
{
private readonly Func<Task>? _backendInitialiseAsync;
-
- /// <summary>
- /// Defines the <see cref="CanShutdownProvider"/> property.
- /// </summary>/
- public static readonly StyledProperty<ICanShutdownProvider?> CanShutdownProviderProperty =
- AvaloniaProperty.Register<App, ICanShutdownProvider?>(nameof(CanShutdownProvider), null, defaultBindingMode: BindingMode.TwoWay);
+ private ApplicationStateManager? _applicationStateManager;
+ private readonly bool _startInBg;
public App()
{
Name = "Wasabi Wallet";
-
- if (!Design.IsDesignMode)
- {
- DataContext = new ApplicationViewModel(this);
- }
}
- public App(Func<Task> backendInitialiseAsync) : this()
+ public App(Func<Task> backendInitialiseAsync, bool startInBg) : this()
{
+ _startInBg = startInBg;
_backendInitialiseAsync = backendInitialiseAsync;
}
- public ICanShutdownProvider? CanShutdownProvider
- {
- get => GetValue(CanShutdownProviderProperty);
- set => SetValue(CanShutdownProviderProperty, value);
- }
-
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
@@ -58,11 +38,14 @@ public class App : Application, IMainWindowService
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
- desktop.ShutdownMode = ShutdownMode.OnExplicitShutdown;
+ _applicationStateManager =
+ new ApplicationStateManager(desktop, _startInBg);
- desktop.ShutdownRequested += DesktopOnShutdownRequested;
+ _applicationStateManager.ApplicationViewModel = new ApplicationViewModel(_applicationStateManager);
- desktop.MainWindow = CreateMainWindow();
+ DataContext = _applicationStateManager.ApplicationViewModel;
+
+ desktop.ShutdownMode = ShutdownMode.OnExplicitShutdown;
RxApp.MainThreadScheduler.Schedule(
async () =>
@@ -76,63 +59,4 @@ public class App : Application, IMainWindowService
base.OnFrameworkInitializationCompleted();
}
-
- private Window CreateMainWindow()
- {
- var result = new MainWindow
- {
- DataContext = MainViewModel.Instance
- };
-
- Observable.FromEventPattern(result, nameof(result.Closed))
- .Take(1)
- .Subscribe(x =>
- {
- if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop && desktop.MainWindow is { })
- {
- desktop.MainWindow = null;
-
- if (DataContext is ApplicationViewModel avm)
- {
- avm.IsMainWindowShown = false;
- }
- }
- });
-
- return result;
- }
-
- private void DesktopOnShutdownRequested(object? sender, ShutdownRequestedEventArgs e)
- {
- if (CanShutdownProvider is { } provider)
- {
- // Shutdown prevention will only work if you directly run the executable.
- e.Cancel = !provider.CanShutdown();
-
- if (e.Cancel && DataContext is ApplicationViewModel avm)
- {
- avm.OnClosePrevented();
- }
-
- Logger.LogDebug($"Cancellation of the shutdown set to: {e.Cancel}.");
- }
- }
-
- void IMainWindowService.Show()
- {
- if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop && desktop.MainWindow is null)
- {
- desktop.MainWindow = CreateMainWindow();
- desktop.MainWindow.Show();
- }
- }
-
- void IMainWindowService.Close()
- {
- if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop && desktop.MainWindow is { })
- {
- desktop.MainWindow.Close();
- desktop.MainWindow = null;
- }
- }
}

MODIFY
WalletWasabi.Fluent/State/StateMachine.cs
WalletWasabi.Fluent/State/StateMachine.cs
@@ -44,6 +44,8 @@ public class StateMachine<TState, TTrigger> where TTrigger : Enum where TState :
public void Fire(TTrigger trigger)
{
+ _currentState.Process(trigger);
+
if (_currentState.CanTransit(trigger))
{
Goto(trigger, _currentState.GetDestination(trigger));
@@ -53,10 +55,6 @@ public class StateMachine<TState, TTrigger> where TTrigger : Enum where TState :
Goto(trigger, _currentState.Parent.StateId, true, false);
Goto(trigger, _currentState.GetDestination(trigger));
}
- else
- {
- _currentState.Process(trigger);
- }
}
public void Start()

MODIFY
WalletWasabi.Fluent/ViewModels/ApplicationViewModel.cs
WalletWasabi.Fluent/ViewModels/ApplicationViewModel.cs
@@ -42,24 +42,12 @@ public partial class ApplicationViewModel : ViewModelBase, ICanShutdownProvider
ShowCommand = ReactiveCommand.Create(() =>
{
if (IsMainWindowShown)
- {
- if (Services.UiConfig.HideOnClose)
{
_mainWindowService.Close();
}
else
- {
- MainViewModel.Instance.WindowState = WindowState.Minimized;
- }
-
- IsMainWindowShown = false;
- }
- else
{
_mainWindowService.Show();
- IsMainWindowShown = true;
-
- MainViewModel.Instance.WindowState = WindowState.Normal;
}
});

use statemachine to track state of main window.