Beispiel #1
0
        public void Initialize(NodesCollection nodes, WasabiSynchronizer synchronizer, UpdateChecker updateChecker)
        {
            Nodes        = nodes;
            Synchronizer = synchronizer;
            HashChain    = synchronizer.BitcoinStore.HashChain;
            UseTor       = Global.Config.UseTor.Value;       // Don't make it dynamic, because if you change this config settings only next time will it activate.

            _status = ActiveStatuses.WhenAnyValue(x => x.CurrentStatus)
                      .ObserveOn(RxApp.MainThreadScheduler)
                      .ToProperty(this, x => x.Status)
                      .DisposeWith(Disposables);

            Observable.FromEventPattern <NodeEventArgs>(nodes, nameof(nodes.Added))
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(x =>
            {
                SetPeers(Nodes.Count);
            }).DisposeWith(Disposables);

            Observable.FromEventPattern <NodeEventArgs>(nodes, nameof(nodes.Removed))
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(x =>
            {
                SetPeers(Nodes.Count);
            }).DisposeWith(Disposables);

            SetPeers(Nodes.Count);

            Observable.FromEventPattern <int>(typeof(WalletService), nameof(WalletService.ConcurrentBlockDownloadNumberChanged))
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(x =>
            {
                BlocksLeft = x.EventArgs;
            }).DisposeWith(Disposables);

            Synchronizer.WhenAnyValue(x => x.TorStatus)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(status =>
            {
                SetTor(status);
                SetPeers(Nodes.Count);
            }).DisposeWith(Disposables);

            Synchronizer.WhenAnyValue(x => x.BackendStatus)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ =>
            {
                Backend = Synchronizer.BackendStatus;
            }).DisposeWith(Disposables);

            _filtersLeft = HashChain.WhenAnyValue(x => x.HashesLeft)
                           .ObserveOn(RxApp.MainThreadScheduler)
                           .ToProperty(this, x => x.FiltersLeft)
                           .DisposeWith(Disposables);

            Synchronizer.WhenAnyValue(x => x.UsdExchangeRate)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(usd =>
            {
                BtcPrice = $"${(long)usd}";
            }).DisposeWith(Disposables);

            Observable.FromEventPattern <bool>(Synchronizer, nameof(Synchronizer.ResponseArrivedIsGenSocksServFail))
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(e =>
            {
                OnResponseArrivedIsGenSocksServFail(e.EventArgs);
            }).DisposeWith(Disposables);

            this.WhenAnyValue(x => x.FiltersLeft, x => x.BlocksLeft)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(tup =>
            {
                (int filtersLeft, int blocksLeft) = tup.ToValueTuple();
                if (filtersLeft == 0 && blocksLeft == 0)
                {
                    TryRemoveStatus(StatusBarStatus.Synchronizing);
                }
                else
                {
                    TryAddStatus(StatusBarStatus.Synchronizing);
                }
            });

            this.WhenAnyValue(x => x.Tor, x => x.Backend, x => x.Peers)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(tup =>
            {
                (TorStatus tor, BackendStatus backend, int peers) = tup.ToValueTuple();
                if (tor == TorStatus.NotRunning || backend != BackendStatus.Connected || peers < 1)
                {
                    TryAddStatus(StatusBarStatus.Connecting);
                }
                else
                {
                    TryRemoveStatus(StatusBarStatus.Connecting);
                }
            });

            this.WhenAnyValue(x => x.UpdateStatus)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(x =>
            {
                if (x == UpdateStatus.Critical)
                {
                    TryAddStatus(StatusBarStatus.CriticalUpdate);
                }
                else
                {
                    TryRemoveStatus(StatusBarStatus.CriticalUpdate);
                }

                if (x == UpdateStatus.Optional)
                {
                    TryAddStatus(StatusBarStatus.OptionalUpdate);
                }
                else
                {
                    TryRemoveStatus(StatusBarStatus.OptionalUpdate);
                }
            });

            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)
                                                   .ObserveOn(RxApp.MainThreadScheduler)
                                                   .Select(x => x != UpdateStatus.Latest));
            this.RaisePropertyChanged(nameof(UpdateCommand));             // The binding happens after the constructor. So, if the command is not in constructor, then we need this line.

            updateChecker.Start(TimeSpan.FromMinutes(7),
                                () =>
            {
                UpdateStatus = UpdateStatus.Critical;
                return(Task.CompletedTask);
            },
                                () =>
            {
                if (UpdateStatus != UpdateStatus.Critical)
                {
                    UpdateStatus = UpdateStatus.Optional;
                }
                return(Task.CompletedTask);
            });
        }
Beispiel #2
0
        public void Initialize(NodesCollection nodes, WasabiSynchronizer synchronizer, UpdateChecker updateChecker)
        {
            Nodes        = nodes;
            Synchronizer = synchronizer;
            HashChain    = synchronizer.BitcoinStore.HashChain;
            UseTor       = Global.Config.UseTor;       // Do not make it dynamic, because if you change this config settings only next time will it activate.

            _status = ActiveStatuses.WhenAnyValue(x => x.CurrentStatus)
                      .ObserveOn(RxApp.MainThreadScheduler)
                      .ToProperty(this, x => x.Status)
                      .DisposeWith(Disposables);

            Observable
            .Merge(Observable.FromEventPattern <NodeEventArgs>(nodes, nameof(nodes.Added)).Select(x => true)
                   .Merge(Observable.FromEventPattern <NodeEventArgs>(nodes, nameof(nodes.Removed)).Select(x => true)
                          .Merge(Synchronizer.WhenAnyValue(x => x.TorStatus).Select(x => true))))
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ => Peers = Synchronizer.TorStatus == TorStatus.NotRunning ? 0 : Nodes.Count)                     // Set peers to 0 if Tor is not running, because we get Tor status from backend answer so it seems to the user that peers are connected over clearnet, while they are not.
            .DisposeWith(Disposables);

            Peers = Tor == TorStatus.NotRunning ? 0 : Nodes.Count;

            Observable.FromEventPattern <bool>(typeof(WalletService), nameof(WalletService.DownloadingBlockChanged))
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(x => DownloadingBlock = x.EventArgs)
            .DisposeWith(Disposables);

            Synchronizer.WhenAnyValue(x => x.TorStatus)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(status => Tor = UseTor ? status : TorStatus.TurnedOff)
            .DisposeWith(Disposables);

            Synchronizer.WhenAnyValue(x => x.BackendStatus)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ => Backend = Synchronizer.BackendStatus)
            .DisposeWith(Disposables);

            _filtersLeft = HashChain.WhenAnyValue(x => x.HashesLeft)
                           .Throttle(TimeSpan.FromMilliseconds(100))
                           .ObserveOn(RxApp.MainThreadScheduler)
                           .ToProperty(this, x => x.FiltersLeft)
                           .DisposeWith(Disposables);

            Synchronizer.WhenAnyValue(x => x.UsdExchangeRate)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(usd => BtcPrice = $"${(long)usd}")
            .DisposeWith(Disposables);

            Observable.FromEventPattern <bool>(Synchronizer, nameof(Synchronizer.ResponseArrivedIsGenSocksServFail))
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(e => OnResponseArrivedIsGenSocksServFail(e.EventArgs))
            .DisposeWith(Disposables);

            this.WhenAnyValue(x => x.FiltersLeft, x => x.DownloadingBlock)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(tup =>
            {
                (int filtersLeft, bool downloadingBlock) = tup.ToValueTuple();
                if (filtersLeft == 0 && !downloadingBlock)
                {
                    TryRemoveStatus(StatusBarStatus.Synchronizing);
                }
                else
                {
                    TryAddStatus(StatusBarStatus.Synchronizing);
                }
            });

            this.WhenAnyValue(x => x.Tor, x => x.Backend, x => x.Peers)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(tup =>
            {
                (TorStatus tor, BackendStatus backend, int peers) = tup.ToValueTuple();
                if (tor == TorStatus.NotRunning || backend != BackendStatus.Connected || peers < 1)
                {
                    TryAddStatus(StatusBarStatus.Connecting);
                }
                else
                {
                    TryRemoveStatus(StatusBarStatus.Connecting);
                }
            });

            this.WhenAnyValue(x => x.UpdateStatus)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(x =>
            {
                if (x == UpdateStatus.Critical)
                {
                    TryAddStatus(StatusBarStatus.CriticalUpdate);
                }
                else
                {
                    TryRemoveStatus(StatusBarStatus.CriticalUpdate);
                }

                if (x == UpdateStatus.Optional)
                {
                    TryAddStatus(StatusBarStatus.OptionalUpdate);
                }
                else
                {
                    TryRemoveStatus(StatusBarStatus.OptionalUpdate);
                }
            });

            UpdateCommand = ReactiveCommand.Create(() =>
            {
                try
                {
                    IoHelpers.OpenBrowser("https://wasabiwallet.io/#download");
                }
                catch (Exception ex)
                {
                    Logger.LogWarning(ex);
                    IoC.Get <IShell>().AddOrSelectDocument(() => new AboutViewModel(Global));
                }
            },
                                                   this.WhenAnyValue(x => x.UpdateStatus)
                                                   .ObserveOn(RxApp.MainThreadScheduler)
                                                   .Select(x => x != UpdateStatus.Latest));

            this.RaisePropertyChanged(nameof(UpdateCommand));             // The binding happens after the constructor. So, if the command is not in constructor, then we need this line.

            Observable.FromEventPattern <UpdateStatusResult>(updateChecker, nameof(updateChecker.UpdateChecked))
            .Select(x => x.EventArgs)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(x =>
            {
                if (x.BackendCompatible)
                {
                    if (x.ClientUpToDate)
                    {
                        UpdateStatus = UpdateStatus.Latest;
                    }
                    else
                    {
                        UpdateStatus = UpdateStatus.Optional;
                    }
                }
                else
                {
                    UpdateStatus = UpdateStatus.Critical;
                }

                UpdateAvailable         = !x.ClientUpToDate;
                CriticalUpdateAvailable = !x.BackendCompatible;
            }).DisposeWith(Disposables);

            updateChecker.Start(TimeSpan.FromMinutes(7));
        }