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 StatusBarViewModel(NodesCollection nodes, WasabiSynchronizer synchronizer, UpdateChecker updateChecker) { UpdateStatus = UpdateStatus.Latest; Nodes = nodes; Synchronizer = synchronizer; BlocksLeft = 0; FiltersLeft = synchronizer.GetFiltersLeft(); 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 => { SetPeers(Nodes.Count); }).DisposeWith(Disposables); Observable.FromEventPattern <NodeEventArgs>(nodes, nameof(nodes.Removed)) .Subscribe(x => { SetPeers(Nodes.Count); }).DisposeWith(Disposables); SetPeers(Nodes.Count); Observable.FromEventPattern <int>(typeof(WalletService), nameof(WalletService.ConcurrentBlockDownloadNumberChanged)) .Subscribe(x => { BlocksLeft = x.EventArgs; }).DisposeWith(Disposables); Observable.FromEventPattern(synchronizer, nameof(synchronizer.NewFilter)).Subscribe(x => { FiltersLeft = Synchronizer.GetFiltersLeft(); }).DisposeWith(Disposables); synchronizer.WhenAnyValue(x => x.TorStatus).Subscribe(status => { SetTor(status); SetPeers(Nodes.Count); }).DisposeWith(Disposables); synchronizer.WhenAnyValue(x => x.BackendStatus).Subscribe(_ => { Backend = Synchronizer.BackendStatus; }).DisposeWith(Disposables); synchronizer.WhenAnyValue(x => x.BestBlockchainHeight).Subscribe(_ => { FiltersLeft = Synchronizer.GetFiltersLeft(); }).DisposeWith(Disposables); synchronizer.WhenAnyValue(x => x.UsdExchangeRate).Subscribe(usd => { BtcPrice = $"${(long)usd}"; }).DisposeWith(Disposables); Observable.FromEventPattern <bool>(synchronizer, nameof(synchronizer.ResponseArrivedIsGenSocksServFail)) .Subscribe(e => { OnResponseArrivedIsGenSocksServFail(e.EventArgs); }).DisposeWith(Disposables); this.WhenAnyValue(x => x.BlocksLeft).Subscribe(blocks => { RefreshStatus(); }); this.WhenAnyValue(x => x.FiltersLeft).Subscribe(filters => { RefreshStatus(); }); this.WhenAnyValue(x => x.Tor).Subscribe(tor => { RefreshStatus(); }); this.WhenAnyValue(x => x.Backend).Subscribe(backend => { RefreshStatus(); }); this.WhenAnyValue(x => x.Peers).Subscribe(peers => { RefreshStatus(); }); this.WhenAnyValue(x => x.UpdateStatus).Subscribe(_ => { 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 { IoHelpers.OpenBrowser("https://wasabiwallet.io/#download"); } catch (Exception ex) { Logging.Logger.LogWarning <StatusBarViewModel>(ex); IoC.Get <IShell>().AddOrSelectDocument(() => new AboutViewModel()); } }, this.WhenAnyValue(x => x.UpdateStatus).Select(x => x != UpdateStatus.Latest)); updateChecker.Start(TimeSpan.FromMinutes(7), () => { UpdateStatus = UpdateStatus.Critical; return(Task.CompletedTask); }, () => { if (UpdateStatus != UpdateStatus.Critical) { UpdateStatus = UpdateStatus.Optional; } return(Task.CompletedTask); }); }