Improve status bar
MODIFY
WalletWasabi.Gui/Global.cs
WalletWasabi.Gui/Global.cs
@@ -125,12 +125,35 @@ namespace WalletWasabi.Gui
AddressManager = null;
TorManager = null;
+ #region ConfigInitialization
+
Config = new Config(Path.Combine(DataDir, "Config.json"));
await Config.LoadOrCreateDefaultFileAsync();
Logger.LogInfo<Config>("Config is successfully initialized.");
+ #endregion ConfigInitialization
+
BitcoinStore = new BitcoinStore();
- await BitcoinStore.InitializeAsync(Path.Combine(DataDir, "BitcoinStore"), Network);
+ var bstoreInitTask = BitcoinStore.InitializeAsync(Path.Combine(DataDir, "BitcoinStore"), Network);
+ var hwiInitTask = HwiProcessManager.InitializeAsync(DataDir, Network);
+
+ var addressManagerFolderPath = Path.Combine(DataDir, "AddressManager");
+ AddressManagerFilePath = Path.Combine(addressManagerFolderPath, $"AddressManager{Network}.dat");
+ var blocksFolderPath = Path.Combine(DataDir, $"Blocks{Network}");
+ var connectionParameters = new NodeConnectionParameters();
+
+ if (Config.UseTor.Value)
+ {
+ Synchronizer = new WasabiSynchronizer(Network, BitcoinStore, () => Config.GetCurrentBackendUri(), Config.GetTorSocks5EndPoint());
+ }
+ else
+ {
+ Synchronizer = new WasabiSynchronizer(Network, BitcoinStore, Config.GetFallbackBackendUri(), null);
+ }
+
+ UpdateChecker = new UpdateChecker(Synchronizer.WasabiClient);
+
+ #region ProcessKillSubscription
AppDomain.CurrentDomain.ProcessExit += async (s, e) => await TryDesperateDequeueAllCoinsAsync();
Console.CancelKeyPress += async (s, e) =>
@@ -146,10 +169,9 @@ namespace WalletWasabi.Gui
});
};
- var addressManagerFolderPath = Path.Combine(DataDir, "AddressManager");
- AddressManagerFilePath = Path.Combine(addressManagerFolderPath, $"AddressManager{Network}.dat");
- var blocksFolderPath = Path.Combine(DataDir, $"Blocks{Network}");
- var connectionParameters = new NodeConnectionParameters();
+ #endregion ProcessKillSubscription
+
+ #region TorProcessInitialization
if (Config.UseTor.Value)
{
@@ -161,20 +183,15 @@ namespace WalletWasabi.Gui
}
TorManager.Start(false, DataDir);
- try
- {
- await HwiProcessManager.InitializeAsync(DataDir, Network);
- }
- catch (Exception ex)
- {
- Logger.LogError(ex, nameof(Global));
- }
-
var fallbackRequestTestUri = new Uri(Config.GetFallbackBackendUri(), "/api/software/versions");
TorManager.StartMonitor(TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(7), DataDir, fallbackRequestTestUri);
Logger.LogInfo<TorProcessManager>($"{nameof(TorProcessManager)} is initialized.");
+ #endregion TorProcessInitialization
+
+ #region AddressManagerInitialization
+
var needsToDiscoverPeers = true;
if (Network == Network.RegTest)
{
@@ -234,9 +251,37 @@ namespace WalletWasabi.Gui
Mode = needsToDiscoverPeers ? AddressManagerBehaviorMode.Discover : AddressManagerBehaviorMode.None
};
connectionParameters.TemplateBehaviors.Add(addressManagerBehavior);
+
+ #endregion AddressManagerInitialization
+
+ #region MempoolInitialization
+
MemPoolService = new MemPoolService();
connectionParameters.TemplateBehaviors.Add(new MemPoolBehavior(MemPoolService));
+ #endregion MempoolInitialization
+
+ #region HwiProcessInitialization
+
+ try
+ {
+ await hwiInitTask;
+ }
+ catch (Exception ex)
+ {
+ Logger.LogError(ex, nameof(Global));
+ }
+
+ #endregion HwiProcessInitialization
+
+ #region BitcoinStoreInitialization
+
+ await bstoreInitTask;
+
+ #endregion BitcoinStoreInitialization
+
+ #region P2PInitialization
+
if (Network == Network.RegTest)
{
Nodes = new NodesGroup(Network, requirements: Constants.NodeRequirements);
@@ -271,17 +316,6 @@ namespace WalletWasabi.Gui
RegTestMemPoolServingNode = null;
}
- if (Config.UseTor.Value)
- {
- Synchronizer = new WasabiSynchronizer(Network, BitcoinStore, () => Config.GetCurrentBackendUri(), Config.GetTorSocks5EndPoint());
- }
- else
- {
- Synchronizer = new WasabiSynchronizer(Network, BitcoinStore, Config.GetFallbackBackendUri(), null);
- }
-
- UpdateChecker = new UpdateChecker(Synchronizer.WasabiClient);
-
Nodes.Connect();
Logger.LogInfo("Start connecting to nodes...");
@@ -291,6 +325,10 @@ namespace WalletWasabi.Gui
Logger.LogInfo("Start connecting to mempool serving regtest node...");
}
+ #endregion P2PInitialization
+
+ #region SynchronizerInitialization
+
var requestInterval = TimeSpan.FromSeconds(30);
if (Network == Network.RegTest)
{
@@ -301,6 +339,8 @@ namespace WalletWasabi.Gui
Synchronizer.Start(requestInterval, TimeSpan.FromMinutes(5), maxFiltSyncCount);
Logger.LogInfo("Start synchronizing filters...");
+
+ #endregion SynchronizerInitialization
}
private static async Task AddKnownBitcoinFullNodeAsHiddenServiceAsync(AddressManager addressManager)

MODIFY
WalletWasabi.Gui/Program.cs
WalletWasabi.Gui/Program.cs
@@ -39,12 +39,12 @@ namespace WalletWasabi.Gui
.BeforeStarting(async builder =>
{
MainWindowViewModel.Instance = new MainWindowViewModel();
+ statusBar = new StatusBarViewModel();
+ MainWindowViewModel.Instance.StatusBar = statusBar;
await Global.InitializeNoWalletAsync();
- statusBar = new StatusBarViewModel(Global.Nodes.ConnectedNodes, Global.Synchronizer, Global.UpdateChecker);
-
- MainWindowViewModel.Instance.StatusBar = statusBar;
+ statusBar.Initialize(Global.Nodes.ConnectedNodes, Global.Synchronizer, Global.UpdateChecker);
if (Global.Network != Network.Main)
{

MODIFY
WalletWasabi.Gui/ViewModels/StatusBarViewModel.cs
WalletWasabi.Gui/ViewModels/StatusBarViewModel.cs
@@ -35,12 +35,12 @@ namespace WalletWasabi.Gui.ViewModels
public class StatusBarViewModel : ViewModelBase
{
private CompositeDisposable Disposables { get; } = new CompositeDisposable();
- private AsyncLock StatusTextAnimationLock { get; }
- private NodesCollection Nodes { get; }
- private WasabiSynchronizer Synchronizer { get; }
- private HashChain HashChain { get; }
+ private AsyncLock StatusTextAnimationLock { get; set; }
+ private NodesCollection Nodes { get; set; }
+ private WasabiSynchronizer Synchronizer { get; set; }
+ private HashChain HashChain { get; set; }
- private bool UseTor { get; }
+ private bool UseTor { get; set; }
private UpdateStatus _updateStatus;
private bool _updateAvailable;
@@ -54,16 +54,65 @@ namespace WalletWasabi.Gui.ViewModels
private StatusBarStatus _status;
private string _statusText;
- public StatusBarViewModel(NodesCollection nodes, WasabiSynchronizer synchronizer, UpdateChecker updateChecker)
+ public StatusBarViewModel()
{
UpdateStatus = UpdateStatus.Latest;
+ UpdateAvailable = false;
+ CriticalUpdateAvailable = false;
+ Backend = BackendStatus.NotConnected;
+ UseTor = false;
+ Tor = TorStatus.NotRunning;
+ Peers = 0;
+ FiltersLeft = 0;
+ BlocksLeft = 0;
+ BtcPrice = "$0";
+ StatusText = "";
+
+ StatusTextAnimationLock = new AsyncLock();
+
+ this.WhenAnyValue(x => x.Status).Subscribe(status =>
+
+ {
+ StatusText = StatusBarStatusStringConverter.Convert(status);
+ });
+
+ this.WhenAnyValue(x => x.StatusText).Subscribe(async status =>
+ {
+ using (await StatusTextAnimationLock.LockAsync()) // Without this lock the status get stuck once in a while.
+ {
+ if (status.EndsWith(".")) // Then do animation.
+ {
+ string nextAnimation = null;
+ if (status.EndsWith("..."))
+ {
+ nextAnimation = status.TrimEnd("..", StringComparison.Ordinal);
+ }
+ else if (status.EndsWith("."))
+ {
+ nextAnimation = $"{status}.";
+ }
+
+ if (nextAnimation != null)
+ {
+ await Task.Delay(1000);
+ if (StatusText == status) // If still the same.
+ {
+ StatusText = nextAnimation;
+ }
+ }
+ }
+ }
+ });
+
+ Status = StatusBarStatus.Loading;
+ }
+
+ public void Initialize(NodesCollection nodes, WasabiSynchronizer synchronizer, UpdateChecker updateChecker)
+ {
Nodes = nodes;
Synchronizer = synchronizer;
HashChain = synchronizer.BitcoinStore.HashChain;
- BlocksLeft = 0;
- FiltersLeft = 0;
UseTor = Global.Config.UseTor.Value; // Don't make it dynamic, because if you change this config settings only next time will it activate.
- StatusTextAnimationLock = new AsyncLock();
Observable.FromEventPattern<NodeEventArgs>(nodes, nameof(nodes.Added))
.Subscribe(x =>
@@ -85,13 +134,13 @@ namespace WalletWasabi.Gui.ViewModels
BlocksLeft = x.EventArgs;
}).DisposeWith(Disposables);
- synchronizer.WhenAnyValue(x => x.TorStatus).Subscribe(status =>
+ Synchronizer.WhenAnyValue(x => x.TorStatus).Subscribe(status =>
{
SetTor(status);
SetPeers(Nodes.Count);
}).DisposeWith(Disposables);
- synchronizer.WhenAnyValue(x => x.BackendStatus).Subscribe(_ =>
+ Synchronizer.WhenAnyValue(x => x.BackendStatus).Subscribe(_ =>
{
Backend = Synchronizer.BackendStatus;
}).DisposeWith(Disposables);
@@ -101,12 +150,12 @@ namespace WalletWasabi.Gui.ViewModels
FiltersLeft = x;
}).DisposeWith(Disposables);
- synchronizer.WhenAnyValue(x => x.UsdExchangeRate).Subscribe(usd =>
+ Synchronizer.WhenAnyValue(x => x.UsdExchangeRate).Subscribe(usd =>
{
BtcPrice = $"${(long)usd}";
}).DisposeWith(Disposables);
- Observable.FromEventPattern<bool>(synchronizer, nameof(synchronizer.ResponseArrivedIsGenSocksServFail))
+ Observable.FromEventPattern<bool>(Synchronizer, nameof(Synchronizer.ResponseArrivedIsGenSocksServFail))
.Subscribe(e =>
{
OnResponseArrivedIsGenSocksServFail(e.EventArgs);
@@ -142,39 +191,6 @@ namespace WalletWasabi.Gui.ViewModels
RefreshStatus();
});
- this.WhenAnyValue(x => x.Status).Subscribe(status =>
- {
- StatusText = StatusBarStatusStringConverter.Convert(status);
- });
-
- this.WhenAnyValue(x => x.StatusText).Subscribe(async status =>
- {
- using (await StatusTextAnimationLock.LockAsync()) // Without this lock the status get stuck once in a while.
- {
- if (status.EndsWith(".")) // Then do animation.
- {
- string nextAnimation = null;
- if (status.EndsWith("..."))
- {
- nextAnimation = status.TrimEnd("..", StringComparison.Ordinal);
- }
- else if (status.EndsWith("."))
- {
- nextAnimation = $"{status}.";
- }
-
- if (nextAnimation != null)
- {
- await Task.Delay(1000);
- if (StatusText == status) // If still the same.
- {
- StatusText = nextAnimation;
- }
- }
- }
- }
- });
-
UpdateCommand = ReactiveCommand.Create(() =>
{
try
@@ -204,7 +220,7 @@ namespace WalletWasabi.Gui.ViewModels
});
}
- public ReactiveCommand<Unit, Unit> UpdateCommand { get; }
+ public ReactiveCommand<Unit, Unit> UpdateCommand { get; set; }
public UpdateStatus UpdateStatus
{
@@ -228,10 +244,12 @@ namespace WalletWasabi.Gui.ViewModels
public bool UpdateAvailable
{
get => _updateAvailable;
+
set => this.RaiseAndSetIfChanged(ref _updateAvailable, value);
}
public bool CriticalUpdateAvailable
+
{
get => _criticalUpdateAvailable;
set => this.RaiseAndSetIfChanged(ref _criticalUpdateAvailable, value);
@@ -282,6 +300,7 @@ namespace WalletWasabi.Gui.ViewModels
public string StatusText
{
get => _statusText;
+
set => this.RaiseAndSetIfChanged(ref _statusText, value);
}
@@ -328,6 +347,7 @@ namespace WalletWasabi.Gui.ViewModels
}
private List<StatusBarStatus> StatusQueue { get; } = new List<StatusBarStatus>();
+
private object StatusQueueLock { get; } = new object();
public void TryAddStatus(StatusBarStatus status)
@@ -343,6 +363,7 @@ namespace WalletWasabi.Gui.ViewModels
}
}
catch (Exception ex)
+
{
Logging.Logger.LogWarning<StatusBarViewModel>(ex);
}
@@ -383,12 +404,14 @@ namespace WalletWasabi.Gui.ViewModels
private void RefreshStatusNoLock()
{
if (!TrySetPriorityStatus())
+
{
SetCustomStatusOrReady();
}
}
private void SetCustomStatusOrReady()
+
{
if (StatusQueue.Any())
{
@@ -411,14 +434,17 @@ namespace WalletWasabi.Gui.ViewModels
Status = StatusBarStatus.OptionalUpdate;
}
else if (Tor == TorStatus.NotRunning || Backend != BackendStatus.Connected || Peers < 1)
+
{
Status = StatusBarStatus.Connecting;
}
else if (FiltersLeft != 0 || BlocksLeft != 0)
+
{
Status = StatusBarStatus.Synchronizing;
}
else
+
{
return false;
}
@@ -427,12 +453,14 @@ namespace WalletWasabi.Gui.ViewModels
}
private void SetPeers(int peers)
+
{
// Set peers to 0 if Tor is not running, because we get Tor status from backend answer so it's seem to the user that peers are connected over clearnet, while they don't.
Peers = Tor == TorStatus.NotRunning ? 0 : peers;
}
private void SetTor(TorStatus tor)
+
{
// Set peers to 0 if Tor is not running, because we get Tor status from backend answer so it's seem to the user that peers are connected over clearnet, while they don't.
Tor = UseTor ? tor : TorStatus.TurnedOff;
@@ -456,7 +484,9 @@ namespace WalletWasabi.Gui.ViewModels
}
// This code added to correctly implement the disposable pattern.
+
public void Dispose()
+
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(true);

Improve status bar