public AddressViewModel(HdPubKey model)
            : base(Locator.Current.GetService <IViewStackService>())
        {
            Global = Locator.Current.GetService <Global>();
            Global.NotificationManager.RequestAuthorization();

            Model = model;

            _bitcoinUri = this
                          .WhenAnyValue(x => x.RequestAmountViewModel.RequestAmount)
                          .Select(amount => {
                return($"bitcoin:{Address}?amount={amount}");
            })
                          .ToProperty(this, nameof(BitcoinUri));

            this.WhenAnyValue(x => x.BitcoinUri)
            .Subscribe((uri) => EncodeQRCode());

            RequestAmountCommand = ReactiveCommand.CreateFromObservable <Unit, Unit>(_ =>
            {
                if (RequestAmountViewModel is null)
                {
                    RequestAmountViewModel = new RequestAmountViewModel();
                }

                ViewStackService.PushModal(RequestAmountViewModel).Subscribe();
                return(Observable.Return(Unit.Default));
            });
            ShareCommand     = ReactiveCommand.CreateFromTask <string>(ShareBoundString);
            NavWalletCommand = ReactiveCommand.CreateFromObservable <Unit, Unit>(_ =>
            {
                ViewStackService.PopPage(false);
                return(ViewStackService.PopPage(true));
            });
        }
Beispiel #2
0
 public GreenViewModel(IViewStackService viewStackService)
     : base(viewStackService)
 {
     OpenModal = ReactiveCommand
                 .CreateFromObservable(() =>
                                       ViewStackService.PushModal(new FirstModalViewModel(viewStackService), string.Empty, false),
                                       outputScheduler: RxApp.MainThreadScheduler);
 }
Beispiel #3
0
        public static IObservable <Unit> PushModal(this ViewStackService viewStackService, IViewModel viewModel, string contract = null, int pages = 1)
        {
            for (var i = 0; i < pages; i++)
            {
                viewStackService.PushModal(viewModel, contract).Subscribe();
            }

            return(Observable.Return(Unit.Default));
        }
Beispiel #4
0
        public CoinListViewModel(bool isPrivate = false)
            : base(Locator.Current.GetService <IViewStackService>())
        {
            Global   = Locator.Current.GetService <Global>();
            RootList = new SourceList <CoinViewModel>();
            RootList
            .Connect()
            .ObserveOn(RxApp.MainThreadScheduler)
            .Bind(out _coinViewModels)
            .Subscribe();

            SelectPrivateSwitchState = true;

            Disposables = Disposables is null ?
                          new CompositeDisposable() :
                          throw new NotSupportedException($"Cannot open {GetType().Name} before closing it.");

            UpdateRootList();
            Observable
            .Merge(Observable.FromEventPattern <ProcessedResult>(Global.Wallet.TransactionProcessor, nameof(Global.Wallet.TransactionProcessor.WalletRelevantTransactionProcessed)).Select(_ => Unit.Default))
            .Throttle(TimeSpan.FromSeconds(1))     // Throttle TransactionProcessor events adds/removes.
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ =>
            {
                UpdateRootList();
            })
            .DisposeWith(Disposables);

            SelectPrivateSwitchCommand = ReactiveCommand.Create(() =>
            {
                switch (SelectPrivateSwitchState)
                {
                case true:
                    // FIXME MixUntilAnonymitySet
                    SelectCoins(x => x.AnonymitySet >= Global.Config.PrivacyLevelSome);
                    break;

                case false:
                    SelectCoins(x => false);
                    SelectPrivateSwitchState = false;
                    break;
                }
            });

            OpenCoinDetail = ReactiveCommand.CreateFromObservable((CoinViewModel cvm) =>
            {
                ViewStackService.PushModal(cvm).Subscribe();
                return(Observable.Return(Unit.Default));
            });

            NavBackCommand = ReactiveCommand.CreateFromObservable <Unit, Unit>(_ =>
            {
                return(ViewStackService.PopModal());
            });
        }
Beispiel #5
0
        public void Should_InvokeViewShellPushModal_When_PushModalIsInvoked()
        {
            // Arrange
            var sut = new ViewStackService(_viewShell);

            // Act
            sut.PushModal(_page).Subscribe();

            // Assert
            _viewShell.Received(1).PushModal(_page, null, false);
        }
Beispiel #6
0
        public void Should_AddViewModelToModalStack_When_Pushed()
        {
            // Arrange
            var sut = new ViewStackService(_viewShell);

            // Act
            sut.PushModal(_page).Subscribe();

            // Assert
            sut.ModalStack.FirstAsync().Wait().Count.Should().Be(1);
        }
Beispiel #7
0
        public HomeViewModel(IViewStackService viewStackService)
            : base(viewStackService)
        {
            OpenModal = ReactiveCommand
                        .CreateFromObservable(() =>
                                              ViewStackService.PushModal(new FirstModalViewModel(ViewStackService)),
                                              outputScheduler: RxApp.MainThreadScheduler);

            PushPage = ReactiveCommand
                       .CreateFromObservable(() =>
                                             ViewStackService.PushPage(new RedViewModel(ViewStackService)),
                                             outputScheduler: RxApp.MainThreadScheduler);

            OpenModal.Subscribe(x => Debug.WriteLine("PagePushed"));
        }
Beispiel #8
0
        public FirstModalViewModel(IViewStackService viewStackService) : base(viewStackService)
        {
            OpenModal = ReactiveCommand
                        .CreateFromObservable(() =>
                                              ViewStackService.PushModal(new SecondModalViewModel(viewStackService)),
                                              outputScheduler: RxApp.MainThreadScheduler);

            PopModal = ReactiveCommand
                       .CreateFromObservable(() =>
                                             ViewStackService.PopModal(),
                                             outputScheduler: RxApp.MainThreadScheduler);

            OpenModal.Subscribe(x => Debug.WriteLine("PagePushed"));
            PopModal.Subscribe(x => Debug.WriteLine("PagePopped"));
            PopModal.ThrownExceptions.Subscribe(error => Interactions.ErrorMessage.Handle(error).Subscribe());
        }
Beispiel #9
0
        public SendWhoViewModel(SendAmountViewModel savm)
            : base(Locator.Current.GetService <IViewStackService>())
        {
            Global  = Locator.Current.GetService <Global>();
            Memo    = "";
            Address = "";

            SendAmountViewModel = savm;

            var canPromptPassword = this.WhenAnyValue(x => x.Memo, x => x.Address, x => x.IsBusy,
                                                      (memo, addr, isBusy) =>
            {
                BitcoinAddress address;
                try
                {
                    address = BitcoinAddress.Create(addr.Trim(), Global.Network);
                }
                catch (FormatException)
                {
                    // SetWarningMessage("Invalid address.");
                    return(false);
                }
                return(!isBusy && memo.Length > 0 && address is BitcoinAddress);
            });

            _promptViewModel = new PasswordPromptViewModel("SEND");
            _promptViewModel.ValidatePasswordCommand.Subscribe(async validPassword =>
            {
                if (validPassword != null)
                {
                    await ViewStackService.PopModal();
                    await BuildTransaction(validPassword);
                    await ViewStackService.PushPage(new SentViewModel());
                }
            });
            PromptCommand = ReactiveCommand.CreateFromObservable(() =>
            {
                ViewStackService.PushModal(_promptViewModel).Subscribe();
                return(Observable.Return(Unit.Default));
            }, canPromptPassword);
        }
Beispiel #10
0
        public HomeViewModel()
            : base(Locator.Current.GetService <IViewStackService>())
        {
            OpenModal = ReactiveCommand
                        .CreateFromObservable(() =>
                                              ViewStackService.PushModal(new FirstModalViewModel(ViewStackService)),
                                              outputScheduler: RxApp.MainThreadScheduler);

            PushPage = ReactiveCommand
                       .CreateFromObservable(() =>
                                             ViewStackService.PushPage(new RedViewModel(ViewStackService)),
                                             outputScheduler: RxApp.MainThreadScheduler);

            PushGenericPage = ReactiveCommand
                              .CreateFromObservable(() =>
                                                    ViewStackService.PushPage <GreenViewModel>(),
                                                    outputScheduler: RxApp.MainThreadScheduler);

            PushPage.ThrownExceptions.Subscribe(error => Interactions.ErrorMessage.Handle(error).Subscribe());
            PushGenericPage.ThrownExceptions.Subscribe(error => Interactions.ErrorMessage.Handle(error).Subscribe());
            OpenModal.ThrownExceptions.Subscribe(error => Interactions.ErrorMessage.Handle(error).Subscribe());
        }
Beispiel #11
0
 private IObservable <Unit> ExecuteSignUp() =>
 ViewStackService.PushModal <SignUpViewModel>(withNavigationPage: true);
Beispiel #12
0
        public HomeViewModel(IViewStackService viewStackService)
            : base(viewStackService)
        {
            PushPage = ReactiveCommand.CreateFromObservable(
                () =>
            {
                return(ViewStackService.PushPage(new HomeViewModel(ViewStackService)));
            });

            PushModalWithNav = ReactiveCommand.CreateFromObservable(
                () =>
            {
                return(ViewStackService.PushModal(new NavigationPageViewModel(new HomeViewModel(ViewStackService))));
            });

            PushModalWithoutNav = ReactiveCommand.CreateFromObservable(
                () =>
            {
                return(ViewStackService.PushModal(new HomeViewModel(ViewStackService)));
            });

            PopModal = ReactiveCommand.CreateFromObservable(
                () =>
            {
                return(ViewStackService.PopModal());
            });

            var canPop = this.WhenAnyValue(
                vm => vm.PopCount,
                vm => vm.PageCount,
                (popCount, pageCount) => popCount > 0 && popCount < pageCount);

            PopPages = ReactiveCommand.CreateFromObservable(
                () =>
            {
                return(ViewStackService
                       .PopPages(_popCount ?? 0, true));
            },
                canPop);

            var canPopToNewPage = this.WhenAnyValue(
                vm => vm.PageIndex,
                pageIndex => pageIndex >= 0 && pageIndex < PageCount);

            PopToNewPage = ReactiveCommand.CreateFromObservable(
                () =>
            {
                return(Observable
                       .Start(() => ViewStackService.InsertPage(PageIndex ?? 0, new LoginViewModel(ViewStackService)), RxApp.MainThreadScheduler)
                       .SelectMany(_ => ViewStackService.PopToPage(PageIndex ?? 0)));
            },
                canPopToNewPage);

            this.WhenActivated(
                disposables =>
            {
                _pageCount = ViewStackService
                             .PageStack
                             .Select(
                    x =>
                {
                    return(x != null ? x.Count : 0);
                })
                             .ToProperty(this, vm => vm.PageCount, default(int), false, RxApp.MainThreadScheduler)
                             .DisposeWith(disposables);
            });
        }
Beispiel #13
0
        public SendAmountViewModel(CoinListViewModel coinList)
            : base(Locator.Current.GetService <IViewStackService>())
        {
            Global            = Locator.Current.GetService <Global>();
            CoinList          = coinList;
            AmountText        = "0.0";
            AllSelectedAmount = Money.Zero;
            EstimatedBtcFee   = Money.Zero;

            this.WhenAnyValue(x => x.AmountText)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(amount =>
            {
                // Correct amount
                if (IsMax)
                {
                    SetAmountIfMax();
                }
                else
                {
                    Regex digitsOnly    = new Regex(@"[^\d,.]");
                    string betterAmount = digitsOnly.Replace(amount, "");     // Make it digits , and . only.

                    betterAmount          = betterAmount.Replace(',', '.');
                    int countBetterAmount = betterAmount.Count(x => x == '.');
                    if (countBetterAmount > 1)     // Do not enable typing two dots.
                    {
                        var index = betterAmount.IndexOf('.', betterAmount.IndexOf('.') + 1);
                        if (index > 0)
                        {
                            betterAmount = betterAmount.Substring(0, index);
                        }
                    }
                    var dotIndex = betterAmount.IndexOf('.');
                    if (dotIndex != -1 && betterAmount.Length - dotIndex > 8)     // Enable max 8 decimals.
                    {
                        betterAmount = betterAmount.Substring(0, dotIndex + 1 + 8);
                    }

                    if (betterAmount != amount)
                    {
                        AmountText = betterAmount;
                    }
                }
            });

            _sendFromText = this
                            .WhenAnyValue(x => x.CoinList.SelectPrivateSwitchState, x => x.CoinList.SelectedCount)
                            .Select(tup =>
            {
                var coinGrammaticalNumber = tup.Item2 == 1 ? " Coin ▾" : " Coins ▾";
                return(tup.Item1 ? "Auto-Select Private ▾" : (tup.Item2.ToString() + coinGrammaticalNumber));
            })
                            .ToProperty(this, nameof(SendFromText));

            this.WhenAnyValue(x => x.IsMax)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(isMax =>
            {
                if (isMax)
                {
                    SetAmountIfMax();
                }
            });

            Observable.FromEventPattern(CoinList, nameof(CoinList.SelectionChanged))
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ => SetFees());

            _minMaxFeeTargetsEqual = this.WhenAnyValue(x => x.MinimumFeeTarget, x => x.MaximumFeeTarget, (x, y) => x == y)
                                     .ToProperty(this, x => x.MinMaxFeeTargetsEqual, scheduler: RxApp.MainThreadScheduler);

            SetFeeTargetLimits();
            FeeTarget = Global.UiConfig.FeeTarget;
            FeeRate   = new FeeRate((decimal)50); //50 sat/vByte placeholder til loads
            SetFees();

            Observable
            .FromEventPattern <AllFeeEstimate>(Global.FeeProviders, nameof(Global.FeeProviders.AllFeeEstimateChanged))
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ =>
            {
                SetFeeTargetLimits();

                if (FeeTarget < MinimumFeeTarget)     // Should never happen.
                {
                    FeeTarget = MinimumFeeTarget;
                }
                else if (FeeTarget > MaximumFeeTarget)
                {
                    FeeTarget = MaximumFeeTarget;
                }

                SetFees();
            })
            .DisposeWith(Disposables);

            GoNext = ReactiveCommand.CreateFromObservable(() =>
            {
                ViewStackService.PushPage(new SendWhoViewModel(this)).Subscribe();
                return(Observable.Return(Unit.Default));
            }, this.WhenAnyValue(
                                                              x => x.AmountText,
                                                              x => x.CoinList.SelectedAmount,
                                                              (amountToSpend, selectedAmount) =>
            {
                return(AmountTextPositive(amountToSpend) &&
                       Money.Parse(amountToSpend.TrimStart('~', ' ')) + EstimatedBtcFee <= selectedAmount);
            }));

            SelectCoins = ReactiveCommand.CreateFromObservable(() =>
            {
                ViewStackService.PushModal(CoinList).Subscribe();
                return(Observable.Return(Unit.Default));
            });

            SelectFee = ReactiveCommand.CreateFromObservable(() =>
            {
                ViewStackService.PushModal(new FeeViewModel(this)).Subscribe();
                return(Observable.Return(Unit.Default));
            });

            this.WhenAnyValue(x => x.FeeTarget)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(_ =>
            {
                SetFees();
            });
        }