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)); }); }
public GreenViewModel(IViewStackService viewStackService) : base(viewStackService) { OpenModal = ReactiveCommand .CreateFromObservable(() => ViewStackService.PushModal(new FirstModalViewModel(viewStackService), string.Empty, false), outputScheduler: RxApp.MainThreadScheduler); }
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)); }
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()); }); }
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); }
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); }
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")); }
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()); }
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); }
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()); }
private IObservable <Unit> ExecuteSignUp() => ViewStackService.PushModal <SignUpViewModel>(withNavigationPage: true);
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); }); }
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(); }); }