public FinishedViewModel(MainWindowViewModel mainWindow) { this.mainWindow = mainWindow ?? throw new ArgumentNullException(nameof(mainWindow)); RestartCommand = ReactiveCommand.CreateFromTask(() => Restart()); }
public AdvanceReceiptBillPageViewModel(INavigationService navigationService, IProductService productService, IUserService userService, ITerminalService terminalService, IWareHousesService wareHousesService, IAccountingService accountingService, IDialogService dialogService , IAdvanceReceiptService advanceReceiptService) : base(navigationService, productService, terminalService, userService, wareHousesService, accountingService, dialogService) { Title = "预收款单据"; _advanceReceiptService = advanceReceiptService; InitBill(); //选择预收款科目 this.AccountingSelected = ReactiveCommand.Create <object>(async e => { await SelectAccounting((data) => { Bill.AccountingOptionId = data.AccountingOptionId; Bill.AccountingOptionName = data.Name; }, (int)this.BillType, true); }); //选择支付方式 this.MorePaymentCommand = ReactiveCommand.Create <object>(e => { SelectPaymentMethods(("PaymentMethods", PaymentMethods), ("BillType", this.BillType), ("Reference", PageName)); }); //验证 var valid_IsReversed = this.ValidationRule(x => x.Bill.ReversedStatus, _isBool, "已红冲单据不能操作"); var valid_IsAudited = this.ValidationRule(x => x.Bill.AuditedStatus, _isBool, "已审核单据不能操作"); var valid_TerminalId = this.ValidationRule(x => x.Bill.TerminalId, _isZero, "客户未指定"); var valid_BusinessUserId = this.ValidationRule(x => x.Bill.AdvanceAmount, _isDZero, "预收金额未指定"); var valid_SelectesCount = this.ValidationRule(x => x.PaymentMethods.Selectes.Count, _isZero, "请选择支付方式"); //提交单据 this.SubmitDataCommand = ReactiveCommand.CreateFromTask <object, Unit>(async _ => { if (this.Bill.ReversedStatus) { _dialogService.ShortAlert("已红冲单据不能操作"); return(Unit.Default); } return(await this.Access(AccessGranularityEnum.ReceivablesBillsSave, async() => { var postData = new AdvanceReceiptUpdateModel() { BillNumber = this.Bill.BillNumber, CustomerId = Bill.TerminalId, Payeer = Settings.UserId, AdvanceAmount = Bill.AdvanceAmount, DiscountAmount = Bill.DiscountAmount, OweCash = Bill.OweCash, Remark = Bill.Remark, AccountingOptionId = Bill.AccountingOptionId ?? 0, Accounting = PaymentMethods.Selectes.Select(a => { return new AccountMaping() { AccountingOptionId = a.AccountingOptionId, CollectionAmount = a.CollectionAmount, Name = a.Name, BillId = 0, }; }).ToList(), }; return await SubmitAsync(postData, Bill.Id, _advanceReceiptService.CreateOrUpdateAsync, (result) => { Bill = new AdvanceReceiptBillModel(); }, token: new System.Threading.CancellationToken()); })); }, this.IsValid()); //存储记录 this.SaveCommand = ReactiveCommand.Create <object>(async e => { var c1 = this.Bill.TerminalId != 0 && this.Bill.TerminalId != (Settings.AdvanceReceiptBill?.TerminalId ?? 0); var c2 = this.Bill.AdvanceAmount != 0 && this.Bill.AdvanceAmount != (Settings.AdvanceReceiptBill?.AdvanceAmount ?? 0); if ((c1 || c2)) { if (!this.Bill.AuditedStatus && !this.Bill.IsSubmitBill) { var ok = await _dialogService.ShowConfirmAsync("你是否要保存单据?", "提示", "确定", "取消"); if (ok) { Settings.AdvanceReceiptBill = this.Bill; } else { await _navigationService.GoBackAsync(); } } } else { await _navigationService.GoBackAsync(); } }); //更改输入 this.TextChangedCommand = ReactiveCommand.Create <object>(e => { Observable.Timer(TimeSpan.FromSeconds(2)).Subscribe(x => { UpdateUI(); }); }); //审核 this.AuditingDataCommand = ReactiveCommand.CreateFromTask <object>(async _ => { //是否具有审核权限 await this.Access(AccessGranularityEnum.ReceivablesBillsApproved); await SubmitAsync(Bill.Id, _advanceReceiptService.AuditingAsync, async(result) => { //红冲审核水印 this.Bill.AuditedStatus = true; var _conn = App.Resolve <ILiteDbService <MessageInfo> >(); var ms = await _conn.Table.FindByIdAsync(SelecterMessage.Id); if (ms != null) { ms.IsRead = true; await _conn.UpsertAsync(ms); } }); }, this.WhenAny(x => x.Bill.Id, (x) => x.GetValue() > 0)); //绑定页面菜单 _popupMenu = new PopupMenu(this, new Dictionary <MenuEnum, Action <SubMenu, ViewModelBase> > { //清空单据 { MenuEnum.CLEAR, (m, vm) => { ClearForm(() => { Bill = new AdvanceReceiptBillModel() { Payeer = Settings.UserId, CreatedOnUtc = DateTime.Now, BillNumber = CommonHelper.GetBillNumber( CommonHelper.GetEnumDescription( BillTypeEnum.AdvanceReceiptBill).Split(',')[1], Settings.StoreId) }; }); } }, //打印 { MenuEnum.PRINT, async(m, vm) => { Bill.BillType = BillTypeEnum.AdvanceReceiptBill; await SelectPrint(Bill); } }, //审核 { MenuEnum.SHENGHE, async(m, vm) => { ResultData result = null; using (UserDialogs.Instance.Loading("审核中...")) { result = await _advanceReceiptService.AuditingAsync(Bill.Id); } if (result != null && result.Success) { //红冲审核水印 this.EnableOperation = true; this.Bill.AuditedStatus = true; await ShowConfirm(true, "审核成功", true, goReceipt: false); } else { await ShowConfirm(false, $"审核失败!{result?.Message}", false, goReceipt: false); } } }, //红冲 { MenuEnum.HONGCHOU, async(m, vm) => { var remark = await CrossDiaglogKit.Current.GetInputTextAsync("红冲备注", "", Keyboard.Text); if (!string.IsNullOrEmpty(remark)) { bool result = false; using (UserDialogs.Instance.Loading("红冲中...")) { //红冲审核水印 this.EnableOperation = true; this.Bill.ReversedStatus = true; result = await _advanceReceiptService.ReverseAsync(Bill.Id, remark); } if (result) { await ShowConfirm(true, "红冲成功", true); } else { await ShowConfirm(false, "红冲失败!", false, goReceipt: false); } } } }, //冲改 { MenuEnum.CHOUGAI, async(m, vm) => { await _advanceReceiptService.ReverseAsync(Bill.Id); } } }); }
public ConfigurationVM(MainVM mvm) { MainVM = mvm; ProfilesDisplay = Profiles.Connect().ToObservableCollection(this); PatchersDisplay = this.WhenAnyValue(x => x.SelectedProfile) .Select(p => p?.Patchers.Connect() ?? Observable.Empty <IChangeSet <PatcherVM> >()) .Switch() .ToObservableCollection(this); CompleteConfiguration = ReactiveCommand.CreateFromTask( async() => { var initializer = this.NewPatcher; if (initializer == null) { return; } AddNewPatchers(await initializer.Construct().ToListAsync()); }, canExecute: this.WhenAnyValue(x => x.NewPatcher) .Select(patcher => { if (patcher == null) { return(Observable.Return(false)); } return(patcher.WhenAnyValue(x => x.CanCompleteConfiguration) .Select(e => e.Succeeded)); }) .Switch()); CancelConfiguration = ReactiveCommand.Create( () => { NewPatcher?.Cancel(); NewPatcher = null; }); // Dispose any old patcher initializations this.WhenAnyValue(x => x.NewPatcher) .DisposePrevious() .Subscribe() .DisposeWith(this); _DisplayedObject = this.WhenAnyValue( x => x.SelectedPatcher, x => x.NewPatcher, (selected, newConfig) => (newConfig as object) ?? selected) .ToGuiProperty(this, nameof(DisplayedObject)); RunPatchers = NoggogCommand.CreateFromJob( extraInput: this.WhenAnyValue(x => x.SelectedProfile), jobCreator: (profile) => { if (SelectedProfile == null) { return(default(PatchersRunVM?), Observable.Return(Unit.Default)); } var ret = new PatchersRunVM(this, SelectedProfile); var completeSignal = ret.WhenAnyValue(x => x.Running) .TurnedOff() .FirstAsync(); return(ret, completeSignal); }, createdJobs: out var createdRuns, canExecute: this.WhenAnyFallback(x => x.SelectedProfile !.BlockingError, fallback: ErrorResponse.Failure) .Select(err => err.Succeeded)) .DisposeWith(this); _CurrentRun = createdRuns .ToGuiProperty(this, nameof(CurrentRun)); this.WhenAnyValue(x => x.CurrentRun) .NotNull() .Do(run => MainVM.ActivePanel = run) .ObserveOn(RxApp.TaskpoolScheduler) .Subscribe(r => r.Run()) .DisposeWith(this); ShowHelpToggleCommand = ReactiveCommand.Create(() => ShowHelp = !ShowHelp); }
public DebugSettingsViewModel(IMediator mediator) { this.SearchItemFromClipboardCommand = ReactiveCommand.CreateFromTask(() => mediator.Send(new SearchItemCommand())); }
public MainViewModel(ICollection <IDetector> detectors, WoaDeployer deployer, IDialogService dialogService, IFilePicker filePicker, OperationProgressViewModel operationProgress) { OperationProgress = operationProgress; Detect = ReactiveCommand.CreateFromTask(async() => { var detections = await Task.WhenAll(detectors.Select(d => d.Detect())); return(detections.FirstOrDefault(d => d != null)); }); var hasDevice = this.WhenAnyValue(model => model.Device).Select(d => d != null); Detect.Subscribe(detected => { Device = detected; }).DisposeWith(disposables); Detect.SelectMany(async d => { if (d == null) { await dialogService.Notice("Cannot autodetect any device", "Cannot detect any device. Please, select your device manually"); } return(Unit.Default); }) .Subscribe() .DisposeWith(disposables); GetRequirements = ReactiveCommand.CreateFromTask(() => deployer.GetRequirements(Device), hasDevice); requirements = GetRequirements.ToProperty(this, model => model.Requirements); Deploy = ReactiveCommand.CreateFromTask(async() => { try { await deployer.Deploy(Device); messages.OnNext("Deployment finished!"); } catch (DeploymentCancelledException) { messages.OnNext("Deployment cancelled"); Log.Information("Deployment cancelled"); } catch (Exception e) { messages.OnNext("Deployment failed"); Log.Error(e, "Deployment failed"); } }, hasDevice); RunScript = ReactiveCommand.CreateFromObservable(() => { var filter = new FileTypeFilter("Deployer Script", new[] { "*.ds", "*.txt" }); return(filePicker .Open("Select a script", new[] { filter }) .Where(x => x != null) .SelectMany(file => Observable.FromAsync(() => deployer.RunScript(file.Source.LocalPath)))); }); dialogService.HandleExceptionsFromCommand(RunScript); dialogService.HandleExceptionsFromCommand(Deploy); isDeploying = Deploy.IsExecuting.Merge(RunScript.IsExecuting).ToProperty(this, x => x.IsBusy); }
public ViewSubscribePageViewModel(INavigationService navigationService, ILiteDbService <MessageInfo> conn, IDialogService dialogService ) : base(navigationService, dialogService) { _conn = conn; Title = "待办提示"; //载入消息 this.Load = MessageLoader.Load(async() => { this.Title = MType == MTypeEnum.All ? "" : CommonHelper.GetEnumDescription(this.MType); var messageItems = new List <MessageInfo>(); //取待办 if (MType == MTypeEnum.Message || MType == MTypeEnum.Receipt || MType == MTypeEnum.Hold) { var data = await _conn.Table.FindAllAsync(); var messages = data.Where(a => new[] { 0, 1, 2, 3 }.Contains(a.MTypeId)); if (messages != null) { messageItems = messages.Where(s => s.MType == MType).ToList(); } } //取通知 else { var data = await _conn.Table.FindAllAsync(); var messages = data.Where(a => new[] { 4, 5, 6, 7, 8, 9, 10, 11, 12 }.Contains(a.MTypeId)); if (messages != null) { messageItems = messages.Where(s => s.MType == MType).ToList(); } } //分组 var messagesGroups = messageItems.GroupBy(m => m.Date.Day).Select(grp => { var messagesGrp = grp.ToList().OrderBy(m => m.Date); var msg = messagesGrp.First(); var date = msg.Date.Date; var dayDiff = DateTime.Now.Day - date.Day; string groupHeader = string.Empty; //今天 if (dayDiff == 0) { groupHeader = TextResources.Today; } //昨天 else if (dayDiff == 1) { groupHeader = TextResources.Yesterday; } //更早以前 else if (dayDiff >= 7 && dayDiff < 15) { groupHeader = TextResources.BeforeThat; } //年月日 else { groupHeader = date.ToString("yyyy/MM/dd"); } return(new MessageItemsGroup ( dateTime: date, groupHeader: groupHeader, messages: new ObservableCollection <MessageInfo>(messagesGrp) )); }) .OrderBy(m => m.DateTime.Day) .ToList(); this.Notifs = new ObservableCollection <MessageItemsGroup>(messagesGroups); return(Notifs); }); //转向单据 this.WhenAnyValue(x => x.Selecter).Throttle(TimeSpan.FromMilliseconds(500)) .Skip(1) .Where(x => x != null) .SubOnMainThread(async x => { using (UserDialogs.Instance.Loading("加载中...")) { var result = await _conn.Table.FindByIdAsync(x.Id); if (result != null) { result.IsRead = true; await _conn.UpsertAsync(result); } await RedirectAsync(x); } Selecter = null; }) .DisposeWith(DeactivateWith); //删除消息 this.RemoveCommand = ReactiveCommand.Create <MessageInfo>(async x => { var ok = await _dialogService.ShowConfirmAsync("是否要删除该消息?", okText: "确定", cancelText: "取消"); if (ok) { await _conn.Table.DeleteAsync(x.Id); ((ICommand)Load)?.Execute(null); } }); //删除全部消息 this.RemoveAllCommand = ReactiveCommand.CreateFromTask(async() => { if (this.Notifs.Count > 0) { var ok = await _dialogService.ShowConfirmAsync("是否要删除全部消息?", okText: "确定", cancelText: "取消"); if (ok) { await _conn.DeleteAllAsync(); ((ICommand)Load)?.Execute(null); } } }, this.WhenAny(x => x.Notifs, (n) => { return(n.GetValue().Count > 0); })); this.BindBusyCommand(Load); }
public LoadWalletViewModel(WalletManagerViewModel owner, LoadWalletType loadWalletType) : base(loadWalletType == LoadWalletType.Password ? "Test Password" : (loadWalletType == LoadWalletType.Desktop ? "Load Wallet" : "Hardware Wallet")) { Owner = owner; Password = ""; LoadWalletType = loadWalletType; Wallets = new ObservableCollection <LoadWalletEntry>(); WalletLock = new object(); this.WhenAnyValue(x => x.SelectedWallet) .Subscribe(selectedWallet => TrySetWalletStates()); this.WhenAnyValue(x => x.IsWalletOpened) .Subscribe(isWalletOpened => TrySetWalletStates()); this.WhenAnyValue(x => x.IsBusy) .Subscribe(x => TrySetWalletStates()); this.WhenAnyValue(x => x.Password).Subscribe(async x => { try { if (x.NotNullAndNotEmpty()) { char lastChar = x.Last(); if (lastChar == '\r' || lastChar == '\n') // If the last character is cr or lf then act like it'd be a sign to do the job. { Password = x.TrimEnd('\r', '\n'); await LoadKeyManagerAsync(requirePassword: true, isHardwareWallet: false); } } } catch (Exception ex) { Logger.LogTrace(ex); } }); LoadCommand = ReactiveCommand.CreateFromTask(async() => await LoadWalletAsync(), this.WhenAnyValue(x => x.CanLoadWallet)); TestPasswordCommand = ReactiveCommand.CreateFromTask(async() => await LoadKeyManagerAsync(requirePassword: true, isHardwareWallet: false), this.WhenAnyValue(x => x.CanTestPassword)); OpenFolderCommand = ReactiveCommand.Create(OpenWalletsFolder); ImportColdcardCommand = ReactiveCommand.CreateFromTask(async() => { try { var ofd = new OpenFileDialog { AllowMultiple = false, Title = "Import Coldcard" }; var selected = await ofd.ShowAsync(Application.Current.MainWindow, fallBack: true); if (selected != null && selected.Any()) { var path = selected.First(); var jsonString = await File.ReadAllTextAsync(path); var json = JObject.Parse(jsonString); var xpubString = json["ExtPubKey"].ToString(); var mfpString = json["MasterFingerprint"].ToString(); // https://github.com/zkSNACKs/WalletWasabi/pull/1663#issuecomment-508073066 // Coldcard 2.1.0 improperly implemented Wasabi skeleton fingerpring at first, so we must reverse byte order. // The solution was to add a ColdCardFirmwareVersion json field from 2.1.1 and correct the one generated by 2.1.0. var coldCardVersionString = json["ColdCardFirmwareVersion"]?.ToString(); var reverseByteOrder = false; if (coldCardVersionString is null) { reverseByteOrder = true; } else { Version coldCardVersion = new Version(coldCardVersionString); if (coldCardVersion == new Version("2.1.0")) // Should never happen though. { reverseByteOrder = true; } } HDFingerprint mfp = NBitcoinHelpers.BetterParseHDFingerprint(mfpString, reverseByteOrder: reverseByteOrder); ExtPubKey extPubKey = NBitcoinHelpers.BetterParseExtPubKey(xpubString); Logger.LogInfo <LoadWalletViewModel>("Creating new wallet file."); var walletName = Global.GetNextHardwareWalletName(customPrefix: "Coldcard"); var walletFullPath = Global.GetWalletFullPath(walletName); KeyManager.CreateNewHardwareWalletWatchOnly(mfp, extPubKey, walletFullPath); owner.SelectLoadWallet(); } } catch (Exception ex) { SetWarningMessage(ex.ToTypeMessageString()); Logger.LogError <LoadWalletViewModel>(ex); } }, outputScheduler: RxApp.MainThreadScheduler); LoadCommand.ThrownExceptions.Subscribe(Logger.LogWarning <LoadWalletViewModel>); TestPasswordCommand.ThrownExceptions.Subscribe(Logger.LogWarning <LoadWalletViewModel>); OpenFolderCommand.ThrownExceptions.Subscribe(Logger.LogWarning <LoadWalletViewModel>); ImportColdcardCommand.ThrownExceptions.Subscribe(Logger.LogWarning <LoadWalletViewModel>); SetLoadButtonText(); IsHwWalletSearchTextVisible = LoadWalletType == LoadWalletType.Hardware; }
public ReconciliationORreceivablesPageViewModel(INavigationService navigationService, IProductService productService, IUserService userService, ITerminalService terminalService, IWareHousesService wareHousesService, IAccountingService accountingService, IFinanceReceiveAccountService financeReceiveAccountService, IDialogService dialogService) : base(navigationService, productService, terminalService, userService, wareHousesService, accountingService, dialogService) { Title = "收款对账"; _financeReceiveAccountService = financeReceiveAccountService; //默认 //Filter.BusinessUserName = Settings.UserRealName; //Filter.BusinessUserId = Settings.UserId; //载入单据 this.Load = ReactiveCommand.CreateFromTask(async() => { try { //筛选 DateTime?start = !Filter.StartTime.HasValue ? DateTime.Now.AddMonths(-1) : Filter.StartTime; DateTime?end = !Filter.EndTime.HasValue ? DateTime.Now.AddDays(1) : Filter.EndTime; int?businessUserId = Filter.BusinessUserId; //收款方式 var accounts = await _accountingService.GetDefaultAccountingAsync((int)BillTypeEnum.FinanceReceiveAccount, this.ForceRefresh, new System.Threading.CancellationToken()); var payments = accounts?.Item3?.Where(s => s != null).Select(s => { return(new AccountMaping { AccountingOptionId = s.Id, CollectionAmount = 0, Name = s.Name }); })?.ToList(); //获取汇总 var summeries = await _financeReceiveAccountService.GetFinanceReceiveAccounts(start, end, businessUserId, 0, 0, "", force: this.ForceRefresh, calToken: new System.Threading.CancellationToken()); var sales = summeries?.Where(s => s.BillType == (int)BillTypeEnum.SaleBill)?.ToList(); var returns = summeries?.Where(s => s.BillType == (int)BillTypeEnum.ReturnBill)?.ToList(); var cashReceipts = summeries?.Where(s => s.BillType == (int)BillTypeEnum.CashReceiptBill)?.ToList(); var advanceReceipts = summeries?.Where(s => s.BillType == (int)BillTypeEnum.AdvanceReceiptBill)?.ToList(); var costExpenditures = summeries?.Where(s => s.BillType == (int)BillTypeEnum.CostExpenditureBill)?.ToList(); if (sales != null && sales.Any()) { sales.ForEach(s => { s.BillTypeId = (int)BillTypeEnum.SaleBill; s.BType = BillTypeEnum.SaleBill; }); } if (returns != null && returns.Any()) { returns.ForEach(s => { s.BillTypeId = (int)BillTypeEnum.ReturnBill; s.BType = BillTypeEnum.ReturnBill; }); } if (cashReceipts != null && cashReceipts.Any()) { cashReceipts.ForEach(s => { s.BillTypeId = (int)BillTypeEnum.CashReceiptBill; s.BType = BillTypeEnum.CashReceiptBill; }); } if (advanceReceipts != null && advanceReceipts.Any()) { advanceReceipts.ForEach(s => { s.BillTypeId = (int)BillTypeEnum.AdvanceReceiptBill; s.BType = BillTypeEnum.AdvanceReceiptBill; }); } if (costExpenditures != null && costExpenditures.Any()) { costExpenditures.ForEach(s => { s.BillTypeId = (int)BillTypeEnum.CostExpenditureBill; s.BType = BillTypeEnum.CostExpenditureBill; }); } //销售收款 var sale = new FRABViewModel() { BType = BillTypeEnum.SaleBill, BillType = (int)BillTypeEnum.SaleBill, BillTypeName = "销售收款", TotalSaleAmountSum = sales?.Sum(s => s.SaleAmountSum) ?? 0, TotalSaleAmount = sales?.Sum(s => s.SaleAmount) ?? 0, TotalSaleAdvanceReceiptAmount = sales?.Sum(s => s.SaleAdvanceReceiptAmount) ?? 0, TotalSaleOweCashAmount = sales?.Sum(s => s.SaleOweCashAmount) ?? 0, SaleBillCount = sales?.Count() ?? 0, }; if (sales != null && sales.Any()) { sale.SaleBills = new ObservableCollection <FinanceReceiveAccountBillModel>(sales); } //退货款 var @return = new FRABViewModel() { BType = BillTypeEnum.ReturnBill, BillType = (int)BillTypeEnum.ReturnBill, BillTypeName = "退货款", TotalReturnAmountSum = returns?.Sum(s => s.ReturnAmountSum) ?? 0, TotalReturnAmount = returns?.Sum(s => s.ReturnAmount) ?? 0, TotalReturnAdvanceReceiptAmount = returns?.Sum(s => s.ReturnAdvanceReceiptAmount) ?? 0, TotalReturnOweCashAmount = returns?.Sum(s => s.ReturnOweCashAmount) ?? 0, ReturnBillCount = returns?.Count() ?? 0, }; if (returns != null && returns.Any()) { @return.ReturnBills = new ObservableCollection <FinanceReceiveAccountBillModel>(returns); } //收欠款 var cashReceipt = new FRABViewModel() { BType = BillTypeEnum.CashReceiptBill, BillType = (int)BillTypeEnum.CashReceiptBill, BillTypeName = "收欠款", TotalReceiptCashOweCashAmountSum = cashReceipts?.Sum(s => s.ReceiptCashOweCashAmountSum) ?? 0, TotalReceiptCashReceivableAmount = cashReceipts?.Sum(s => s.ReceiptCashReceivableAmount) ?? 0, TotalReceiptCashAdvanceReceiptAmount = cashReceipts?.Sum(s => s.ReceiptCashAdvanceReceiptAmount) ?? 0, ReceiptCashOweCashBillCount = cashReceipts?.Count() ?? 0, }; if (cashReceipts != null && cashReceipts.Any()) { cashReceipt.ReceiptCashOweCashBills = new ObservableCollection <FinanceReceiveAccountBillModel>(cashReceipts); } //收预收款 var advanceReceipt = new FRABViewModel() { BType = BillTypeEnum.AdvanceReceiptBill, BillType = (int)BillTypeEnum.AdvanceReceiptBill, BillTypeName = "收预收款", TotalAdvanceReceiptSum = advanceReceipts?.Sum(s => s.AdvanceReceiptSum) ?? 0, TotalAdvanceReceiptAmount = advanceReceipts?.Sum(s => s.AdvanceReceiptAmount) ?? 0, TotalAdvanceReceiptOweCashAmount = advanceReceipts?.Sum(s => s.AdvanceReceiptOweCashAmount) ?? 0, AdvanceReceiptBillCount = advanceReceipts?.Count() ?? 0, }; if (advanceReceipts != null && advanceReceipts.Any()) { advanceReceipt.AdvanceReceiptBills = new ObservableCollection <FinanceReceiveAccountBillModel>(advanceReceipts); } //费用支出 var costExpenditure = new FRABViewModel() { BType = BillTypeEnum.CostExpenditureBill, BillType = (int)BillTypeEnum.CostExpenditureBill, BillTypeName = "费用支出", TotalCostExpenditureSum = costExpenditures?.Sum(s => s.CostExpenditureSum) ?? 0, TotalCostExpenditureAmount = costExpenditures?.Sum(s => s.CostExpenditureAmount) ?? 0, TotalCostExpenditureOweCashAmount = costExpenditures?.Sum(s => s.CostExpenditureOweCashAmount) ?? 0, CostExpenditureBillCount = costExpenditures?.Count() ?? 0, }; if (costExpenditures != null && costExpenditures.Any()) { costExpenditure.CostExpenditureBills = new ObservableCollection <FinanceReceiveAccountBillModel>(costExpenditures); } //追加 this.Bills.Clear(); this.Bills.Add(sale); this.Bills.Add(@return); this.Bills.Add(cashReceipt); this.Bills.Add(advanceReceipt); this.Bills.Add(costExpenditure); //合计收款金额 if (payments != null && payments.Any()) { var allAccounts = new List <AccountMaping>(); if (summeries != null && summeries.Any()) { foreach (var bill in summeries) { allAccounts.AddRange(bill.Accounts); } } payments.ForEach(pay => { pay.CollectionAmount = allAccounts.Where(s => s.AccountingOptionId == pay.AccountingOptionId).Sum(s => s.CollectionAmount); }); this.HeightRequest = (payments?.Count() ?? 1) * 40.7; this.Payments = new ObservableCollection <AccountMaping>(payments); } //合计商品 var spc = new List <AccountProductModel>(); var gpc = new List <AccountProductModel>(); var rpc = new List <AccountProductModel>(); foreach (var s in summeries) { foreach (var p in s.SaleProducts) { if (!spc.Select(s => s.ProductId).Contains(p.ProductId)) { spc.Add(p); } } foreach (var p in s.GiftProducts) { if (!gpc.Select(s => s.ProductId).Contains(p.ProductId)) { gpc.Add(p); } } foreach (var p in s.ReturnProducts) { if (!rpc.Select(s => s.ProductId).Contains(p.ProductId)) { rpc.Add(p); } } } this.SaleProductCount = spc.Count(); this.GiftProductCount = gpc.Count(); this.ReturnProductCount = rpc.Count(); this.SaleProducts.Clear(); this.GiftProducts.Clear(); this.ReturnProducts.Clear(); if (summeries != null && summeries.Any()) { foreach (var sp in summeries) { this.GiftProducts.AddRange(sp.GiftProducts); this.SaleProducts.AddRange(sp.SaleProducts); this.ReturnProducts.AddRange(sp.ReturnProducts); } } //总计 this.TotalCount = this.Bills.Sum(s => s.SaleBillCount) + this.Bills.Sum(s => s.ReturnBillCount) + this.Bills.Sum(s => s.ReceiptCashOweCashBillCount) + this.Bills.Sum(s => s.AdvanceReceiptBillCount) + this.Bills.Sum(s => s.CostExpenditureBillCount); this.TotalAmount = this.Bills.Sum(s => s.TotalSaleAmountSum) + this.Bills.Sum(s => s.TotalReturnAmountSum) + this.Bills.Sum(s => s.TotalReceiptCashOweCashAmountSum) + this.Bills.Sum(s => s.TotalAdvanceReceiptSum) + this.Bills.Sum(s => s.TotalCostExpenditureSum); } catch (Exception ex) { Crashes.TrackError(ex); } }); //选择类型 this.WhenAnyValue(x => x.Selecter).Throttle(TimeSpan.FromMilliseconds(500)) .Skip(1) .Where(x => x != null) .SubOnMainThread(async x => { switch (x.BType) { case BillTypeEnum.SaleBill: { if ((x?.SaleBills?.Count ?? 0) > 0) { await this.NavigateAsync("ReconciliationDetailPage", ("Bills", x?.SaleBills), ("BillType", x.BillType)); } } break; case BillTypeEnum.ReturnBill: { if ((x?.ReturnBills?.Count ?? 0) > 0) { await this.NavigateAsync("ReconciliationDetailPage", ("Bills", x?.ReturnBills), ("BillType", x.BillType)); } } break; case BillTypeEnum.CashReceiptBill: { if ((x?.ReceiptCashOweCashBills?.Count ?? 0) > 0) { await this.NavigateAsync("ReconciliationDetailPage", ("Bills", x?.ReceiptCashOweCashBills), ("BillType", x.BillType)); } } break; case BillTypeEnum.AdvanceReceiptBill: { if ((x?.AdvanceReceiptBills?.Count ?? 0) > 0) { await this.NavigateAsync("ReconciliationDetailPage", ("Bills", x?.AdvanceReceiptBills), ("BillType", x.BillType)); } } break; case BillTypeEnum.CostExpenditureBill: { if ((x?.CostExpenditureBills?.Count ?? 0) > 0) { await this.NavigateAsync("ReconciliationDetailPage", ("Bills", x?.CostExpenditureBills), ("BillType", x.BillType)); } } break; default: break; } }) .DisposeWith(DeactivateWith); //预览商品 this.ViewProducts = ReactiveCommand.Create <string>(async e => { try { if (e.Equals("SaleProducts")) { if ((this.SaleProducts?.Count ?? 0) > 0) { await this.NavigateAsync("ReconciliationProductsPage", ("ReconciliationProducts", this.SaleProducts), ("Title", "销售商品")); } } else if (e.Equals("GiftProducts")) { if ((this.GiftProducts?.Count ?? 0) > 0) { await this.NavigateAsync("ReconciliationProductsPage", ("ReconciliationProducts", this.GiftProducts), ("Title", "赠送商品")); } } else if (e.Equals("ReturnProducts")) { if ((this.ReturnProducts?.Count ?? 0) > 0) { await this.NavigateAsync("ReconciliationProductsPage", ("ReconciliationProducts", this.ReturnProducts), ("Title", "退货商品")); } } } catch (Exception ex) { Crashes.TrackError(ex); } }); //员工选择时 this.WhenAnyValue(x => x.Filter.BusinessUserId) .Skip(1) .Where(s => s > 0) .Select(s => s) .Throttle(TimeSpan.FromSeconds(1), RxApp.MainThreadScheduler) .Subscribe(s => ((ICommand)Load)?.Execute(null)) .DisposeWith(DeactivateWith); //绑定页面菜单 _popupMenu = new PopupMenu(this, new Dictionary <MenuEnum, Action <SubMenu, ViewModelBase> > { //TODAY { MenuEnum.TODAY, (m, vm) => { Filter.StartTime = DateTime.Parse(DateTime.Now.ToString("yyyy-MM-dd 00:00:00")); Filter.EndTime = DateTime.Now; ((ICommand)Load)?.Execute(null); } }, //YESTDAY { MenuEnum.YESTDAY, (m, vm) => { Filter.StartTime = DateTime.Now.AddDays(-1); Filter.EndTime = DateTime.Now; ((ICommand)Load)?.Execute(null); } }, //OTHER { MenuEnum.OTHER, (m, vm) => { SelectDateRang(); ((ICommand)Load)?.Execute(null); } }, //SUBMIT30 { MenuEnum.SUBMIT30, (m, vm) => { Filter.StartTime = DateTime.Now.AddMonths(-1); Filter.EndTime = DateTime.Now; ((ICommand)Load)?.Execute(null); } } }); this.BindBusyCommand(Load); }
public MarketFeedbackPageViewModel(INavigationService navigationService, IDialogService dialogService, IFeedbackService feedbackService, IMediaPickerService mediaPickerService ) : base(navigationService, dialogService) { _feedbackService = feedbackService; _mediaPickerService = mediaPickerService; Title = "市场反馈"; this.TextCounterTxt1 = "0/500"; this.TextCounterTxt2 = "0/500"; this.WhenAnyValue(x => x.CompetitiveDescribe) .Skip(1) .Where(x => x != null) .Select(x => { if (!string.IsNullOrEmpty(x)) { return($"{x.Length}/500"); } else { return($"0/500"); } }).Subscribe(x => { this.TextCounterTxt1 = x; }).DisposeWith(DeactivateWith); this.WhenAnyValue(x => x.ConditionDescribe) .Skip(1) .Where(x => x != null) .Select(x => { if (!string.IsNullOrEmpty(x)) { return($"{x.Length}/500"); } else { return($"0/500"); } }).Subscribe(x => { this.TextCounterTxt2 = x; }).DisposeWith(DeactivateWith); this.TextChangedCommand = ReactiveCommand.Create <string>((e) => { if (CompetitiveDescribe.Length > 500 || ConditionDescribe.Length > 500) { IsEnabled = false; _dialogService.ShortAlert("字数超过限制!"); } else { IsEnabled = true; } }); //验证 //var valid_Describe1 = this.ValidationRule(x => x.ConditionDescribe, _isDefined, "请先输入内容"); //var valid_Describe2 = this.ValidationRule(x => x.CompetitiveDescribe, _isDefined, "请先输入内容"); //var valid_Photos = this.ValidationRule(x => x.DisplayPhotos.Count, _isZero, "请先上传截图"); //var canExcute = this.WhenAnyValue(x => x.DisplayPhotos.Count).Select(x => x <= 4).Do(x => { if (!x) { this.Alert("最多只能五张哦!"); } }); //提交 this.SubmitCommand = ReactiveCommand.CreateFromTask <object>(async e => { try { //if (!valid_Describe1.IsValid) { this.Alert(valid_Describe1.Message[0]); return; } //if (!valid_Describe2.IsValid) { this.Alert(valid_Describe2.Message[0]); return; } //if (!valid_Photos.IsValid) { this.Alert(valid_Photos.Message[0]); return; } var feedback = new MarketFeedback { UserId = Settings.UserId, MType = 0, CompetitiveDescribe = CompetitiveDescribe, ConditionDescribe = ConditionDescribe, UserName = Settings.UserRealName, CreatedOnUtc = DateTime.Now }; if (DisplayPhotos != null && DisplayPhotos.Count > 0) { switch (DisplayPhotos.Count) { case 1: feedback.Screenshot1 = DisplayPhotos[0] == null ? "" : DisplayPhotos[0].DisplayPath; break; case 2: feedback.Screenshot1 = DisplayPhotos[0] == null ? "" : DisplayPhotos[0].DisplayPath; feedback.Screenshot2 = DisplayPhotos[1] == null ? "" : DisplayPhotos[1].DisplayPath; break; case 3: feedback.Screenshot1 = DisplayPhotos[0] == null ? "" : DisplayPhotos[0].DisplayPath; feedback.Screenshot2 = DisplayPhotos[1] == null ? "" : DisplayPhotos[1].DisplayPath; feedback.Screenshot3 = DisplayPhotos[2] == null ? "" : DisplayPhotos[2].DisplayPath; break; case 4: feedback.Screenshot1 = DisplayPhotos[0] == null ? "" : DisplayPhotos[0].DisplayPath; feedback.Screenshot2 = DisplayPhotos[1] == null ? "" : DisplayPhotos[1].DisplayPath; feedback.Screenshot3 = DisplayPhotos[2] == null ? "" : DisplayPhotos[2].DisplayPath; feedback.Screenshot4 = DisplayPhotos[3] == null ? "" : DisplayPhotos[3].DisplayPath; break; case 5: feedback.Screenshot1 = DisplayPhotos[0] == null ? "" : DisplayPhotos[0].DisplayPath; feedback.Screenshot2 = DisplayPhotos[1] == null ? "" : DisplayPhotos[1].DisplayPath; feedback.Screenshot3 = DisplayPhotos[2] == null ? "" : DisplayPhotos[2].DisplayPath; feedback.Screenshot4 = DisplayPhotos[3] == null ? "" : DisplayPhotos[3].DisplayPath; feedback.Screenshot5 = DisplayPhotos[4] == null ? "" : DisplayPhotos[4].DisplayPath; break; } } await SubmitAsync(feedback, _feedbackService.CreateOrUpdateMarketAsync, (result) => { if (result.Success) { this.CompetitiveDescribe = ""; this.SelectedSegment = 0; this.ConditionDescribe = ""; } }); } catch (Exception) { await ShowAlert(false, $"出错啦,内部异常!"); return; } }); //拍照选择 this.CameraPhotoCmd = ReactiveCommand.CreateFromTask <string>(async(r) => { try { //var resultMedia = await CrossDiaglogKit.Current.GetMediaResultAsync("请选择", ""); //if (resultMedia != null) //{ // //上传图片 // using (UserDialogs.Instance.Loading("上传中...")) // { // byte[] base64Stream = Convert.FromBase64String(resultMedia.ToString()); // Stream resultStream = null; // //裁切图片481X480 // using (var imageEditor = await _mediaPickerService.CreateImageAsync(base64Stream)) // { // imageEditor.Resize(480, 480); // resultStream = CommonHelper.BytesToStream(imageEditor.ToJpeg()); // } // if (resultStream == null) // { // return; // } // var content = new MultipartFormDataContent // { // { new StreamContent(resultStream), "\"file\"", $"\"{Settings.UserId}_feedBack.jpg\"" } // }; // using (var httpClient = new HttpClient()) // { // var uploadServiceBaseAddress = $"{GlobalSettings.FileCenterEndpoint}document/reomte/fileupload/HRXHJS"; // var httpResponseMessage = await httpClient.PostAsync(uploadServiceBaseAddress, content); // var result = await httpResponseMessage.Content.ReadAsStringAsync(); // var uploadResult = new UploadResult(); // try // { // if (!string.IsNullOrEmpty(result)) // { // uploadResult = JsonConvert.DeserializeObject<UploadResult>(result); // } // } // catch (Exception) // { // uploadResult = null; // } // finally // { // if (httpResponseMessage != null) // httpResponseMessage.Dispose(); // } // if (uploadResult != null) // { // var displayPhoto = new DisplayPhoto // { // DisplayPath = $"{GlobalSettings.FileCenterEndpoint}HRXHJS/document/image/" + uploadResult.Id + "" // }; // DisplayPhotos.Add(displayPhoto); // } // } // if (resultStream != null) // resultStream.Dispose(); // }; //} } catch (Exception) { await _dialogService.ShowAlertAsync("上传失败,服务器错误!", "提示", "取消"); } }); //删除 this.RemoveCommand = ReactiveCommand.Create <string>(async x => { var ok = await _dialogService.ShowConfirmAsync("是否要删除该图片?", okText: "确定", cancelText: "取消"); if (ok) { var temp = DisplayPhotos.FirstOrDefault(c => c.DisplayPath == x); if (temp != null) { DisplayPhotos.Remove(temp); } } }); }
public CoinViewModel(Wallet wallet, CoinListViewModel owner, SmartCoin model) { Global = Locator.Current.GetService <Global>(); Model = model; Wallet = wallet; Owner = owner; RefreshSmartCoinStatus(); Disposables = new CompositeDisposable(); _coinJoinInProgress = Model .WhenAnyValue(x => x.CoinJoinInProgress) .ToProperty(this, x => x.CoinJoinInProgress, scheduler: RxApp.MainThreadScheduler) .DisposeWith(Disposables); _unspent = Model .WhenAnyValue(x => x.Unspent) .ToProperty(this, x => x.Unspent, scheduler: RxApp.MainThreadScheduler) .DisposeWith(Disposables); _confirmed = Model .WhenAnyValue(x => x.Confirmed) .ToProperty(this, x => x.Confirmed, scheduler: RxApp.MainThreadScheduler) .DisposeWith(Disposables); _cluster = Model .WhenAnyValue(x => x.Cluster, x => x.Cluster.Labels) .Select(x => x.Item2.ToString()) .ToProperty(this, x => x.Cluster, scheduler: RxApp.MainThreadScheduler) .DisposeWith(Disposables); _unavailable = Model .WhenAnyValue(x => x.Unavailable) .ToProperty(this, x => x.Unavailable, scheduler: RxApp.MainThreadScheduler) .DisposeWith(Disposables); this.WhenAnyValue(x => x.Status) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(_ => this.RaisePropertyChanged(nameof(ToolTip))); Observable .Merge(Model.WhenAnyValue(x => x.IsBanned, x => x.SpentAccordingToBackend, x => x.Confirmed, x => x.CoinJoinInProgress).Select(_ => Unit.Default)) .Merge(Observable.FromEventPattern(Wallet.ChaumianClient, nameof(Wallet.ChaumianClient.StateUpdated)).Select(_ => Unit.Default)) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(_ => RefreshSmartCoinStatus()) .DisposeWith(Disposables); Global.BitcoinStore.SmartHeaderChain .WhenAnyValue(x => x.TipHeight).Select(_ => Unit.Default) .Merge(Model.WhenAnyValue(x => x.Height).Select(_ => Unit.Default)) .Throttle(TimeSpan.FromSeconds(0.1)) // DO NOT TAKE THIS THROTTLE OUT, OTHERWISE SYNCING WITH COINS IN THE WALLET WILL STACKOVERFLOW! .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(_ => this.RaisePropertyChanged(nameof(Confirmations))) .DisposeWith(Disposables); Global.UiConfig .WhenAnyValue(x => x.PrivacyMode) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(_ => { this.RaisePropertyChanged(nameof(AmountBtc)); this.RaisePropertyChanged(nameof(Cluster)); }).DisposeWith(Disposables); DequeueCoin = ReactiveCommand.Create(() => Owner.PressDequeue(Model), this.WhenAnyValue(x => x.CoinJoinInProgress)); OpenCoinInfo = ReactiveCommand.Create(() => { var shell = IoC.Get <IShell>(); var coinInfo = shell.Documents?.OfType <CoinInfoTabViewModel>()?.FirstOrDefault(x => x.Coin?.Model == Model); if (coinInfo is null) { coinInfo = new CoinInfoTabViewModel(this); shell.AddDocument(coinInfo); } shell.Select(coinInfo); }); CopyCluster = ReactiveCommand.CreateFromTask(async() => await Application.Current.Clipboard.SetTextAsync(Cluster)); Observable .Merge(DequeueCoin.ThrownExceptions) // Don't notify about it. Dequeue failure (and success) is notified by other mechanism. .Merge(OpenCoinInfo.ThrownExceptions) .Merge(CopyCluster.ThrownExceptions) .ObserveOn(RxApp.TaskpoolScheduler) .Subscribe(ex => Logger.LogError(ex)); }
public PodcastViewModel(IScreen hostScreen, IPlayerModel player, IEventAggregator eventAggregator, IDialogService dialogService, IFeedParser feedParser, IChannelStore channelStore, IPlaylistStore playlistStore) : base(eventAggregator) { HostScreen = hostScreen; Player = player; DialogService = dialogService; FeedParser = feedParser; this.channelStore = channelStore; this.playlistStore = playlistStore; GetChannelsCommand = ReactiveCommand.CreateFromTask(async _ => await GetChannels()); GetChannelsCommand.IsExecuting.ObserveOn(RxApp.MainThreadScheduler) .Subscribe(_ => OnChannelsBusy(GetChannelsCommand.GetHashCode(), _)); PlayItemCommand = ReactiveCommand.CreateFromTask <IPlayable>(async _ => await OnPlayEpisode(_ as Episode)); // open url OpenUrlDialogCommand = ReactiveCommand.CreateFromTask(async _ => await OpenUrlDialog()); OpenUrlDialogCommand.ThrownExceptions.ObserveOn(RxApp.MainThreadScheduler) .Subscribe(_ => LogAndNotify(NotificationType.Error, Messages.ERR_CHANNEL_LOAD)); // channels busy indicator this.WhenAnyObservable(_ => _.ChannelsBusyList.CountChanged).DistinctUntilChanged() .Subscribe(_ => IsChannelsBusy = _ > 0); // episodes busy indicator this.WhenAnyObservable(_ => _.EpisodesBusyList.CountChanged).DistinctUntilChanged() .Subscribe(_ => IsEpisodesBusy = _ > 0); OpenUrlCommand = ReactiveCommand.CreateFromTask <string>(async _ => await OnOpenUrl(_)); OpenUrlCommand.ThrownExceptions.ObserveOn(RxApp.MainThreadScheduler) .Subscribe(_ => LogAndNotify(NotificationType.Error, Messages.ERR_CHANNEL_LOAD)); // load channel LoadChannelFromUrlCommand = ReactiveCommand.CreateFromTask <string>(LoadChannelFromUrlAsync); OpenUrlCommand.IsExecuting.ObserveOn(RxApp.MainThreadScheduler).Subscribe(_ => { OnChannelsBusy(OpenUrlCommand.GetHashCode(), _); OnEpisodesBusy(OpenUrlCommand.GetHashCode(), _); }); LoadChannelFromUrlCommand.ThrownExceptions.ObserveOn(RxApp.MainThreadScheduler) .Subscribe(_ => LogAndNotify(NotificationType.Error, Messages.ERR_CHANNEL_LOAD)); // delete channel ConfirmDeleteChannelCommand = ReactiveCommand.CreateFromTask <Channel>(async _ => await ConfirmDelete(_)); DeleteChannelCommand = ReactiveCommand.CreateFromTask <Channel>(async _ => await DeleteChannel(_)); DeleteChannelCommand.ThrownExceptions.ObserveOn(RxApp.MainThreadScheduler) .Subscribe(_ => LogAndNotify(NotificationType.Error, Messages.ERR_CHANNEL_DELETE)); DeleteChannelCommand.IsExecuting.Subscribe(_ => { OnChannelsBusy(DeleteChannelCommand.GetHashCode(), _); OnEpisodesBusy(DeleteChannelCommand.GetHashCode(), _); }); var existsSelectedChannel = this.WhenAny(vm => vm.SelectedChannel, _ => SelectedChannel != null); this.WhenAnyValue(vm => vm.SelectedChannel).Select(_ => _ == null ? 0 : SelectedChannel.Id) .ToProperty(this, _ => _.SelectedChannelId, out selectedChannelId); RemoveFilterCommand = ReactiveCommand.Create <Unit>(_ => SelectedChannel = null, existsSelectedChannel); MarkAllPlayedCommand = ReactiveCommand.CreateFromTask <Channel>(async _ => await MarkChannelPlayed(_)); CopyUrlCommand = ReactiveCommand.Create <Channel>(_ => Clipboard.SetText(_.Link)); var episodeSet = this.WhenAnyValue(_ => _.SelectedEpisode); // detail this.WhenAnyValue(vm => vm.SelectedChannel).NotNull().Cast <IDetailEntity>() .Merge(episodeSet.Cast <IDetailEntity>()) .ToProperty(this, _ => _.CurrentDetailEntity, out currentDetailEntity); this.WhenAnyValue(vm => vm.Player.LocateCurrent).NotNull() .Subscribe(c => c.Subscribe(_ => LocatePageForCurrent())); // episode list is loading this.WhenAnyValue(_ => _.EpisodeList.IsLoading).SubscribeOn(RxApp.MainThreadScheduler) .Subscribe(_ => OnEpisodesBusy(EpisodeList.GetHashCode(), _)); ScrollIntoView = ReactiveCommand.Create <int, int>(_ => _); // playlist AddToPlaylist = ReactiveCommand.CreateFromTask <Playlist>(async _ => await AddEpisodeToPlaylist(_)); // sort order this.WhenAnyValue(_ => _.SelectedEpisodeSortOrder) .Subscribe(_ => EpisodeOrderBy.OnNext(GetEpisodeSortOrder(_))); ToggleSortDirectionCommand = ReactiveCommand.Create( () => EpisodeOrderBy.OnNext(GetEpisodeSortOrder(SelectedEpisodeSortOrder, false))); // on channels changed this.WhenAnyValue(_ => _.Channels).NotNull().Subscribe(_ => OnChannelsChanged()); // update channels var canUpdate = new BehaviorSubject <bool>(false); UpdateChannelsCommand = ReactiveCommand.CreateFromTask(async _ => await UpdateChannelsAsync(), canUpdate.DistinctUntilChanged()); UpdateChannelsCommand.IsExecuting.CombineLatest(this.WhenAnyValue(_ => _.Channels.IsEmpty), (exec, empty) => !exec && !empty && IsUpdateEnabled).DistinctUntilChanged() .Subscribe(_ => canUpdate.OnNext(_)); UpdateChannelsCommand.IsExecuting.ObserveOn(RxApp.MainThreadScheduler).Subscribe(_ => IsUpdating = _); UpdateChannelsCommand.ThrownExceptions.ObserveOn(RxApp.MainThreadScheduler) .Subscribe(_ => LogAndNotify(NotificationType.Error, Messages.ERR_CHANNEL_UPDATE)); // init episodes EpisodeList = InitEpisodeList(); EpisodeList.Changed.Subscribe(_ => InitActivePlaylist()); // detail ToggleShowDetailCommand = ReactiveCommand.Create <bool, bool>(_ => _); DeactivateCommand = ReactiveCommand.Create(() => { }); }
public PerformanceViewModel(IBleManager centralManager, BleConfiguration configuration) { this.centralManager = centralManager; if (this.IsAndroid) { this.AndroidUseInternalSyncQueue = configuration.AndroidUseInternalSyncQueue; this.AndroidUseMainThread = configuration.AndroidShouldInvokeOnMainThread; this.WhenAnyValue(x => x.AndroidUseMainThread) .Skip(1) .Subscribe(x => configuration.AndroidShouldInvokeOnMainThread = x); this.WhenAnyValue(x => x.AndroidUseInternalSyncQueue) .Skip(1) .Subscribe(x => configuration.AndroidUseInternalSyncQueue = x); } this.WhenAnyValue(x => x.IsRunning) .Skip(1) .Subscribe(x => { if (!x) { this.speedSub?.Dispose(); } else { this.speedSub = Observable.Interval(TimeSpan.FromSeconds(2)).Subscribe(_ => { this.Speed = (this.bytes / 2).Bytes().Humanize("0.0"); Interlocked.Exchange(ref this.bytes, 0); }); } }); this.Permissions = ReactiveCommand.CreateFromTask(async() => this.Status = await this.centralManager.RequestAccess().ToTask() ); this.WriteTest = this.DoWrite(true); this.WriteWithoutResponseTest = this.DoWrite(false); this.ReadTest = this.DoWork("Read", async(ch, ct) => { var read = await ch.Read().ToTask(ct); return(read.Data?.Length ?? 0); }); this.NotifyTest = ReactiveCommand.CreateFromTask( async() => { this.IsRunning = true; this.Errors = 0; this.Packets = 0; var characteristic = await this.SetupCharacteristic(this.cancelSrc.Token); this.Info = "Running Notify Test"; this.notifySub = characteristic .Notify(true) .Where(x => x.Type == GattCharacteristicResultType.Notification) .Subscribe(x => { Interlocked.Add(ref this.bytes, x.Data?.Length ?? 0); this.Packets++; }); }, this.CanRun() ); this.Stop = ReactiveCommand.Create( () => { this.IsRunning = false; this.peripheral?.CancelConnection(); this.Info = "Test Stopped"; this.cancelSrc?.Cancel(); this.notifySub?.Dispose(); this.notifySub = null; }, this.WhenAny( x => x.IsRunning, x => x.GetValue() ) ); }
ICommand DoWork(string testName, Func <IGattCharacteristic, CancellationToken, Task <int> > func) => ReactiveCommand .CreateFromTask(async() => { this.IsRunning = true; this.Errors = 0; this.Packets = 0; this.cancelSrc = new CancellationTokenSource(); var characteristic = await this.SetupCharacteristic(this.cancelSrc.Token); this.Info = $"Running {testName} Test"; while (!this.cancelSrc.IsCancellationRequested) { try { var length = await func(characteristic, this.cancelSrc.Token); Interlocked.Add(ref this.bytes, length); this.Packets++; } catch (Exception ex) { Console.WriteLine(ex); this.Errors++; } } }, this.CanRun() );
/// <summary> /// Initializes a new instance of the <see cref="SearchSettingsViewModel"/> class. /// </summary> /// <param name="dialogService">Dialog service for opening dialogs from view model.</param> public SearchSettingsViewModel(IMainDialogService dialogService) { this.dialogService = dialogService; SearchModes = new[] { InternalCleavageType.MultipleInternalCleavages, InternalCleavageType.SingleInternalCleavage, InternalCleavageType.NoInternalCleavage }; ToleranceUnits = new[] { ToleranceUnit.Ppm, ToleranceUnit.Mz }; SelectedSequence = string.Empty; FastaEntries = new ReactiveList <FastaEntry>(); SequenceProteins = new FastaEntry[0]; SearchRunning = false; FromFastaEntry = true; FromSequence = false; // Browse Spectrum Files Command BrowseSpectrumFilesCommand = ReactiveCommand.Create(BrowseSpectrumFilesImplementation); // Browse Feature Files Command BrowseFeatureFilesCommand = ReactiveCommand.Create(BrowseFeatureFilesImplementation); // Browse Fasta DB Files Command BrowseFastaDbFilesCommand = ReactiveCommand.Create(BrowseFastaDbFilesImplementation); // Browse Output Directories Command BrowseOutputDirectoriesCommand = ReactiveCommand.Create(BrowseOutputDirectoriesImplementation); // Select All Proteins Command SelectAllProteinsCommand = ReactiveCommand.Create(() => SelectProteinsImplementation(true), FastaEntries.WhenAnyValue(x => x.Count).Select(count => count > 0)); // Select No Proteins Command SelectNoProteinsCommand = ReactiveCommand.Create(() => SelectProteinsImplementation(false), FastaEntries.WhenAnyValue(x => x.Count).Select(count => count > 0)); // Manage Modifications Command ManageModificationsCommand = ReactiveCommand.Create(ManageModificationsImplementation); // Add Modifications Command AddModificationCommand = ReactiveCommand.Create(AddModificationImplementation); // Run Command - Disabled when there is no SpectrumFilePath, FastaDbFilePath, or OutputFilePath selected RunCommand = ReactiveCommand.CreateFromTask(async _ => await RunImplementation(), this.WhenAnyValue( x => x.SpectrumFilePath, x => x.FastaDbFilePath, x => x.OutputFilePath) .Select(x => !string.IsNullOrWhiteSpace(x.Item1) && !string.IsNullOrWhiteSpace(x.Item2) && !string.IsNullOrWhiteSpace(x.Item3)) ); // Prev tab command PrevTabCommand = ReactiveCommand.Create(() => TabIndex--, Observable.Merge( new[] { this.WhenAnyValue(x => x.TabIndex).Select(tabIndex => tabIndex > 0), RunCommand.IsExecuting.Select(exec => !exec) })); // Next tab command NextTabCommand = ReactiveCommand.Create(() => TabIndex++, Observable.Merge( new[] { this.WhenAnyValue(x => x.TabIndex).Select(tabIndex => tabIndex < MaxTabIndex), RunCommand.IsExecuting.Select(exec => !exec) })); // Cancel Command CancelCommand = ReactiveCommand.Create(CancelImplementation); // Default values SelectedSearchMode = InternalCleavageType.SingleInternalCleavage; MinSequenceLength = 21; MaxSequenceLength = 300; MinPrecursorIonCharge = 2; MaxPrecursorIonCharge = 30; MinProductIonCharge = 1; MaxProductIonCharge = 15; MinSequenceMass = 3000.0; MaxSequenceMass = 50000.0; PrecursorIonToleranceValue = 10; PrecursorIonToleranceUnit = ToleranceUnit.Ppm; ProductIonToleranceValue = 10; PrecursorIonToleranceUnit = ToleranceUnit.Ppm; minScanNumber = 0; maxScanNumber = 0; maxDynamicModificationsPerSequence = 0; FixedNTerm = true; FixedCTerm = true; NumMatchesPerSpectrum = 1; // When search mode is selected, display correct search mode description this.WhenAnyValue(x => x.SelectedSearchMode) .Subscribe(searchMode => SearchModeDescription = searchModeDescriptions[(int)searchMode]); // When Spectrum file path is selected, use its directory for the output path by default if a output path // has not already been selected. this.WhenAnyValue(x => x.SpectrumFilePath) .Where(_ => string.IsNullOrWhiteSpace(OutputFilePath)) .Select(Path.GetDirectoryName) .Subscribe(specDir => OutputFilePath = specDir); SearchModifications = new ReactiveList <SearchModificationViewModel> { ChangeTrackingEnabled = true }; this.WhenAnyValue(x => x.FastaDbFilePath).Subscribe(_ => LoadFastaFile()); this.WhenAnyValue(x => x.FastaEntries.Count, x => x.SelectedSequence) .Select(x => FastaEntries.Where(entry => entry.ProteinSequenceText.Contains(x.Item2)).ToArray()) .Subscribe(entries => SequenceProteins = entries); // Remove search modification when its Remove property is set to true. SearchModifications.ItemChanged.Where(x => x.PropertyName == "Remove") .Select(x => x.Sender).Where(sender => sender.Remove) .Subscribe(searchMod => SearchModifications.Remove(searchMod)); ModificationsUpdated = false; }
protected override void Initialize() { SaveSettings = ReactiveCommand.CreateFromTask(Save).AddDisposableTo(Disposables); }
private GlobalStatusStore() { Test = ReactiveCommand.CreateFromTask(TestImpl); var canOperate = this.WhenAnyValue(x => x.ConnectStatus) .Select(p => { if (p == ConnectStatus.Checking && p == ConnectStatus.Connecting && p == ConnectStatus.Disconnecting) { return(false); } else { return(true); } }); _canConnect = canOperate.ToProperty(this, x => x.CanOperate, false); Connect = ReactiveCommand.CreateFromTask(async() => { ConnectStatus = ConnectStatus.Connecting; if (await Locator.Current.GetService <IUserStorageService>().CheckUserPinExist(CurrentUser.Username)) { throw new ConnectionException(ConnectionError.LostPin); } else { await DoConnect.Execute(""); } }, canOperate); Connect.ThrownExceptions.Subscribe(ex => { }); DoConnect = ReactiveCommand.CreateFromTask <string, bool>(async(pin) => { string password; try { password = await Locator.Current.GetService <IUserStorageService>().DecryptedUserPassword(CurrentUser.Username, pin); } catch { throw new ConnectionException(ConnectionError.InvalidPin); } return(await Locator.Current.GetService <IInternetGatewayService>().Connect(CurrentUser.Username, password)); }, canOperate); DoConnect.ThrownExceptions.Subscribe(ex => { }); DoConnect.Where(u => u).Subscribe(p => { ConnectStatus = ConnectStatus.Connected; }); Disconnect = ReactiveCommand.CreateFromTask(async() => { ConnectStatus = ConnectStatus.Disconnecting; return(await Locator.Current.GetService <IInternetGatewayService>().Disconnect()); }, canOperate); Disconnect.Where(u => u).Subscribe(_ => { ConnectStatus = ConnectStatus.Disconnected; }); Disconnect.ThrownExceptions.Subscribe(ex => { }); Toggle = ReactiveCommand.CreateFromTask(async() => { if (ConnectStatus == ConnectStatus.Disconnected) { await Connect.Execute(); } else if (ConnectStatus == ConnectStatus.Connected) { await Disconnect.Execute(); } }, canOperate); Toggle.ThrownExceptions.Subscribe(_ => { }); }
public MoneyTypeViewModel(IScreen screen = null, IConfiguration configuration = null) { this.HostScreen = screen ?? Locator.Current.GetService <IScreen>(); this._configuration = configuration ?? Locator.Current.GetService <IConfiguration>(); this._moneyTypesSource .AsObservableCache() .Connect() .Transform(c => c) .ObserveOn(RxApp.MainThreadScheduler) .Bind(out this._moneyTypes) .Subscribe(); isValid = this.WhenAnyValue(vm => vm.Name, vm => vm.Description, vm => vm.SelectedMoneyType) .Select(o => { if (string.IsNullOrWhiteSpace(o.Item1)) { Message = "Name is invalid"; return(false); } else if (o.Item1.Length > 50) { Message = "Name is too long"; return(false); } if (!string.IsNullOrWhiteSpace(o.Item2) && o.Item2.Length > 256) { Message = "Description is too long"; return(false); } if (string.IsNullOrEmpty(o.Item1) && string.IsNullOrEmpty(o.Item2)) { Message = string.Empty; return(false); } Message = string.Empty; return(true); }).ToProperty(this, vm => vm.IsValid, out isValid); var canEdit = this.WhenAnyValue(vm => vm.IsValid, vm => vm.SelectedMoneyType) .Select(o => { return(o.Item1 && (o.Item2 != null)); }); this.EditMoneyTypeCommand = ReactiveCommand.CreateFromTask(editMoneyType, canEdit, RxApp.MainThreadScheduler); var canAdd = this.WhenAnyValue(vm => vm.IsValid); this.AddMoneyTypeCommand = ReactiveCommand.CreateFromTask(addMoneyType, canAdd, RxApp.MainThreadScheduler); var canDelete = this.WhenAnyValue(vm => vm.SelectedMoneyType) .Select(o => o != null); this.DeleteMoneyTypeCommand = ReactiveCommand.CreateFromTask(deleteMoneyType, canDelete, RxApp.MainThreadScheduler); this.ToggleList = ReactiveCommand.Create(() => this.IsListCollapsed = !this.IsListCollapsed); getMoneyTypes(); }
public SearchViewModel() { this.WhenActivated((CompositeDisposable disposables) => { // ReactiveCommand has built-in support for background operations and // guarantees that this block will only run exactly once at a time, and // that the CanExecute will auto-disable and that property IsExecuting will // be set according whilst it is running. Search = ReactiveCommand .CreateFromTask <string, List <SearchResult> >( // Here we're describing here, in a *declarative way*, the conditions in // which the Search command is enabled. Now our Command IsEnabled is // perfectly efficient, because we're only updating the UI in the scenario // when it should change. async searchQuery => { var random = new Random(Guid.NewGuid().GetHashCode()); await Task.Delay(random.Next(250, 2500)); //This is just here so simulate a network type exception if (DateTime.Now.Second % 9 == 0) { throw new TimeoutException("Unable to connect to web service"); } var searchService = Locator.CurrentMutable.GetService <IDuckDuckGoApi>(); var searchResult = await searchService.Search(searchQuery); return(searchResult .RelatedTopics .Select(rt => new SearchResult { DisplayText = rt.Text, ImageUrl = rt?.Icon?.Url ?? string.Empty }) .ToList()); }, Observable .CombineLatest( this.WhenAnyValue(vm => vm.SearchQuery).Select(searchQuery => !string.IsNullOrEmpty(searchQuery)).DistinctUntilChanged(), this.WhenAnyObservable(x => x.Search.IsExecuting).DistinctUntilChanged(), (hasSearchQuery, isExecuting) => hasSearchQuery && !isExecuting) .Do(cps => System.Diagnostics.Debug.WriteLine($"Can Perform Search: {cps}")) .DistinctUntilChanged()) .DisposeWith(disposables); //// ReactiveCommands are themselves IObservables, whose value are the results //// from the async method, guaranteed to arrive on the given scheduler. //// We're going to take the list of search results that the background //// operation loaded, and them into our SearchResults. Search .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(searchResults => { using (SearchResults.SuppressChangeNotifications()){ SearchResults.Clear(); SearchResults.AddRange(searchResults); } }) .DisposeWith(disposables); // ThrownExceptions is any exception thrown from the CreateFromObservable piped // to this Observable. Subscribing to this allows you to handle errors on // the UI thread. Search .ThrownExceptions .Subscribe(async ex => { await SearchError.Handle("Potential Network Connectivity Error"); }) .DisposeWith(disposables); //Behaviors this .WhenAnyValue(x => x.SearchQuery) .Throttle(TimeSpan.FromSeconds(.75), TaskPoolScheduler.Default) .Do(x => System.Diagnostics.Debug.WriteLine($"Throttle fired for {x}")) .ObserveOn(RxApp.MainThreadScheduler) .InvokeCommand(Search) .DisposeWith(disposables); }); }
public AuthenticationViewModel() { Login = ReactiveCommand.CreateFromTask(LoginImpl); }
public ExportViewModel(IShell sh, IAppModel am, IDialogCoordinator dc, IAppConfig cfg, IMapper mapper, IExportService ex) { shell = sh; appModel = am; dialCoord = dc; this.mapper = mapper; export = ex; AvailableBoxes = appModel.Boxes; boards = new SourceList <BoardToExport>(); AvailableBoards = boards.SpawnCollection(); ExportJson = true; DatePostfix = true; SplitBoardsToFiles = false; PdfOptionsAvailable = new PdfOptionsAvailable { PageSizes = Enum.GetValues(typeof(PageSize)).Cast <PageSize>().ToArray(), PageOrientations = Enum.GetValues(typeof(PageOrientation)).Cast <PageOrientation>().ToArray(), ScaleFittings = Enum.GetValues(typeof(ScaleFitting)).Cast <ScaleFitting>().ToArray() }; PdfOptions = new PdfOptions { PageSize = PageSize.A4, PageOrientation = PageOrientation.Portrait, ScaleOptions = new ScaleOptions { Padding = new Thickness(), ScaleToFit = true, ScaleFitting = ScaleFitting.BothDirections, MaxScale = 1.0, MinScale = 0.0 } }; var canExport = boards .Connect() .AutoRefresh() .Filter(x => x.IsChecked) .Select(x => AvailableBoards.Count(y => y.IsChecked) > 0 && !string.IsNullOrEmpty(SelectedBox.Uri) && File.Exists(SelectedBox.Uri)); ExportCommand = ReactiveCommand.CreateFromTask(ExportCommandExecute, canExport); SelectTargetFolderCommand = ReactiveCommand.Create(SelectTargetFolderCommandExecute); CancelCommand = ReactiveCommand.Create(Close); this.ObservableForProperty(x => x.SelectedBox) .Where(x => x.Value != null) .Select(x => x.Value) .Subscribe(box => { boards.ClearAndAddRange(box.Boards.Items .Select(x => new BoardToExport { Board = x, IsChecked = true })); TargetFile = Path.GetFileNameWithoutExtension(box.Uri) + "_export"; }); this.ObservableForProperty(x => x.TargetFolder) .Subscribe(x => cfg.ArchiveFolder = x.Value); SelectedBox = AvailableBoxes.First(); var fi = new FileInfo(SelectedBox.Uri); TargetFolder = cfg.ArchiveFolder ?? fi.DirectoryName; }
public CreateViewModel(INavigationService navigator, IDialogs dialogs, IBeaconRangingManager rangingManager, IBeaconMonitoringManager?monitorManager = null) { this.IsMonitoringSupported = monitorManager != null; this.EstimoteDefaults = ReactiveCommand.Create(() => { this.Identifier = "Estimote"; this.Uuid = EstimoteUuid; }); this.WhenAnyValue(x => x.Major) .Select(x => !x.IsEmpty() && UInt16.TryParse(x, out _)) .ToPropertyEx(this, x => x.IsMajorSet); this.StartMonitoring = ReactiveCommand.CreateFromTask( async() => { var result = await monitorManager.RequestAccess(); if (result != AccessState.Available) { await dialogs.AlertAccess(result); } else { await monitorManager.StartMonitoring(this.GetBeaconRegion()); await navigator.GoBack(); } }, this.WhenAny( x => x.Identifier, x => x.Uuid, x => x.Major, x => x.Minor, x => x.NotifyOnEntry, x => x.NotifyOnExit, (idValue, uuidValue, majorValue, minorValue, entry, exit) => { if (monitorManager == null) { return(false); } var atLeast1Notification = entry.GetValue() || exit.GetValue(); if (!atLeast1Notification) { return(false); } return(this.IsValid()); } ) ); this.StartRanging = ReactiveCommand.CreateFromTask( async() => { var result = await rangingManager.RequestAccess(); if (result != AccessState.Available) { await dialogs.AlertAccess(result); } else { var region = this.GetBeaconRegion(); await navigator.GoBack(false, (nameof(BeaconRegion), region)); } }, this.WhenAny( x => x.Identifier, x => x.Uuid, x => x.Major, x => x.Minor, (idValue, uuidValue, majorValue, minorValue) => this.IsValid() ) ); }
public EditInstrumentViewModel(Instrument model, IDataClient client, IClosableView view, IDialogCoordinator dialogCoordinator) : base(model, new InstrumentValidator()) { _view = view; DialogCoordinator = dialogCoordinator; if (model.Sessions == null) { model.Sessions = new List <InstrumentSession>(); } if (model.Tags == null) { model.Tags = new List <Tag>(); } foreach (var session in model.Sessions) { Sessions.Add(new SessionViewModel(session)); } ContractMonths = new ObservableCollection <KeyValuePair <int, string> >(); //fill the continuous futures contrat month combobox for (int i = 1; i < 10; i++) { ContractMonths.Add(new KeyValuePair <int, string>(i, MyUtils.Ordinal(i) + " Contract")); } Load = ReactiveCommand.CreateFromTask(async _ => { var tags = client.GetTags(); var sessionTemplates = client.GetSessionTemplates(); var exchanges = client.GetExchanges(); var underlyingSymbols = client.GetUnderlyingSymbols(); var datasources = client.GetDatasources(); await Task.WhenAll(tags, sessionTemplates, exchanges, underlyingSymbols, datasources).ConfigureAwait(true); var responses = new ApiResponse[] { tags.Result, sessionTemplates.Result, exchanges.Result, underlyingSymbols.Result, datasources.Result }; if (await responses.DisplayErrors(this, DialogCoordinator).ConfigureAwait(true)) { return; } foreach (var tag in tags.Result.Result.Select(x => new CheckBoxTag(x, model.Tags.Contains(x)))) { AllTags.Add(tag); tag.PropertyChanged += Tag_PropertyChanged; } Exchanges.AddRange(exchanges.Result.Result); foreach (var template in sessionTemplates.Result.Result) { SessionTemplates.Add(template); } foreach (var us in underlyingSymbols.Result.Result) { UnderlyingSymbols.Add(us); } foreach (var ds in datasources.Result.Result) { Datasources.Add(ds); } }); //Sessions AddNewSession = ReactiveCommand.Create(() => AddSession()); RemoveSession = ReactiveCommand.Create <SessionViewModel>(ExecRemoveSession); //Save var saveCanExecute = this .WhenAnyValue(x => x.HasErrors) .Select(x => !x); Save = ReactiveCommand.CreateFromTask(async _ => { if (model.ID == null || model.ID <= 0) { //adding a new instrument return(await client.AddInstrument(model).ConfigureAwait(true)); } else { //updating an existing one return(await client.UpdateInstrument(model).ConfigureAwait(true)); } } , saveCanExecute); Save.Subscribe(async result => { var errors = await result.DisplayErrors(this, DialogCoordinator).ConfigureAwait(true); if (!errors) { AddedInstrument = result.Result; _view.Close(); } }); this.Validate(); }
public SettingsViewModel() : base("Settings") { Global = Locator.Current.GetService <Global>(); this.ValidateProperty(x => x.SomePrivacyLevel, ValidateSomePrivacyLevel); this.ValidateProperty(x => x.FinePrivacyLevel, ValidateFinePrivacyLevel); this.ValidateProperty(x => x.StrongPrivacyLevel, ValidateStrongPrivacyLevel); this.ValidateProperty(x => x.DustThreshold, ValidateDustThreshold); this.ValidateProperty(x => x.BitcoinP2pEndPoint, ValidateBitcoinP2pEndPoint); Autocopy = Global.UiConfig.Autocopy; CustomFee = Global.UiConfig.IsCustomFee; CustomChangeAddress = Global.UiConfig.IsCustomChangeAddress; var config = new Config(Global.Config.FilePath); config.LoadOrCreateDefaultFile(); _network = config.Network; UseTor = config.UseTor; TerminateTorOnExit = config.TerminateTorOnExit; StartLocalBitcoinCoreOnStartup = config.StartLocalBitcoinCoreOnStartup; StopLocalBitcoinCoreOnShutdown = config.StopLocalBitcoinCoreOnShutdown; _somePrivacyLevel = config.PrivacyLevelSome.ToString(); _finePrivacyLevel = config.PrivacyLevelFine.ToString(); _strongPrivacyLevel = config.PrivacyLevelStrong.ToString(); _dustThreshold = config.DustThreshold.ToString(); _bitcoinP2pEndPoint = config.GetBitcoinP2pEndPoint().ToString(defaultPort: -1); _localBitcoinCoreDataDir = config.LocalBitcoinCoreDataDir; IsModified = !Global.Config.AreDeepEqual(config); this.WhenAnyValue( x => x.Network, x => x.UseTor, x => x.TerminateTorOnExit, x => x.StartLocalBitcoinCoreOnStartup, x => x.StopLocalBitcoinCoreOnShutdown) .ObserveOn(RxApp.TaskpoolScheduler) .Subscribe(_ => Save()); this.WhenAnyValue(x => x.Autocopy) .ObserveOn(RxApp.TaskpoolScheduler) .Subscribe(x => Global.UiConfig.Autocopy = x); this.WhenAnyValue(x => x.CustomFee) .ObserveOn(RxApp.TaskpoolScheduler) .Subscribe(x => Global.UiConfig.IsCustomFee = x); this.WhenAnyValue(x => x.CustomChangeAddress) .ObserveOn(RxApp.TaskpoolScheduler) .Subscribe(x => Global.UiConfig.IsCustomChangeAddress = x); OpenConfigFileCommand = ReactiveCommand.CreateFromTask(OpenConfigFileAsync); SetClearPinCommand = ReactiveCommand.Create(() => { var pinBoxText = PinBoxText; if (string.IsNullOrEmpty(pinBoxText)) { NotificationHelpers.Error("Please provide a PIN."); return; } var trimmedPinBoxText = pinBoxText?.Trim(); if (string.IsNullOrEmpty(trimmedPinBoxText) || trimmedPinBoxText.Any(x => !char.IsDigit(x))) { NotificationHelpers.Error("Invalid PIN."); return; } if (trimmedPinBoxText.Length > 10) { NotificationHelpers.Error("PIN is too long."); return; } var uiConfigPinHash = Global.UiConfig.LockScreenPinHash; var enteredPinHash = HashHelpers.GenerateSha256Hash(trimmedPinBoxText); if (IsPinSet) { if (uiConfigPinHash != enteredPinHash) { NotificationHelpers.Error("PIN is incorrect."); PinBoxText = ""; return; } Global.UiConfig.LockScreenPinHash = ""; NotificationHelpers.Success("PIN was cleared."); } else { Global.UiConfig.LockScreenPinHash = enteredPinHash; NotificationHelpers.Success("PIN was changed."); } PinBoxText = ""; }); TextBoxLostFocusCommand = ReactiveCommand.Create(Save); Observable .Merge(OpenConfigFileCommand.ThrownExceptions) .Merge(SetClearPinCommand.ThrownExceptions) .Merge(TextBoxLostFocusCommand.ThrownExceptions) .ObserveOn(RxApp.TaskpoolScheduler) .Subscribe(ex => Logger.LogError(ex)); SelectedFeeDisplayFormat = Enum.IsDefined(typeof(FeeDisplayFormat), Global.UiConfig.FeeDisplayFormat) ? (FeeDisplayFormat)Global.UiConfig.FeeDisplayFormat : FeeDisplayFormat.SatoshiPerByte; this.WhenAnyValue(x => x.SelectedFeeDisplayFormat) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(x => Global.UiConfig.FeeDisplayFormat = (int)x); }
public StartupViewModel(IShell shell, IAppModel appModel, IDialogCoordinator dc, IMapper mp, IAppConfig cfg, ILogger l) { this.shell = shell as IShell; this.appModel = appModel; dialCoord = dc; mapper = mp; appConfig = cfg; log = l; ColorTheme = appConfig.ColorTheme; initialized = false; OpenRecentBoxCommand = ReactiveCommand.Create <RecentViewModel>(async(rvm) => { if (await OpenBoardView(rvm.Uri)) { appConfig.UpdateRecent(rvm.Uri, rvm.Pinned); } }); NewFileCommand = ReactiveCommand.Create(() => this.shell.ShowView <WizardView>( new WizardViewRequest { ViewId = "Creating new file", Uri = null })); OpenFileCommand = ReactiveCommand.CreateFromTask(async _ => { var dialog = new OpenFileDialog { Filter = @"SQLite DataBase | *.kam", Title = @"Select exists database" }; if (dialog.ShowDialog() == DialogResult.OK) { var uri = dialog.FileName; if (await OpenBoardView(uri)) { appConfig.UpdateRecent(uri, false); } } }); OpenPublicBoardCommand = ReactiveCommand .CreateFromTask <PublicBoardJson>(OpenPublicBoardCommandExecute); ImportCommand = ReactiveCommand.Create(() => this.shell.ShowView <ImportView>(null, new UiShowOptions { Title = "Import" })); var whenBoardSelected = shell .WhenAny(x => x.SelectedView, x => x.Value?.ViewModel is BoardEditViewModel) .Publish(); ExportCommand = ReactiveCommand.Create(() => this.shell.ShowView <ExportView>(null, new UiShowOptions { Title = "Export" }), whenBoardSelected); PrintCommand = ReactiveCommand.Create(PrintCommandExecute, whenBoardSelected); whenBoardSelected.Connect(); ShowStartupCommand = ReactiveCommand.Create(() => { shell.ShowView <StartupView>( viewRequest: new ViewRequest { ViewId = StartupViewModel.StartupViewId }, options: new UiShowOptions { Title = "Start Page", CanClose = false }); }); SettingsCommand = ReactiveCommand.Create(() => { shell.ShowView <SettingsView>( viewRequest: new ViewRequest { ViewId = SettingsViewModel.StartupViewId }, options: new UiShowOptions { Title = "Settings", CanClose = true }); }); ExitCommand = ReactiveCommand.Create(() => App.Current.Shutdown()); Pinned = appConfig.RecentObservable .Filter(x => x.Pinned); var notPinned = appConfig.RecentObservable .Filter(x => !x.Pinned); Today = notPinned .Filter(x => x.LastAccess.IsToday()); Yesterday = notPinned .Filter(x => x.LastAccess.IsYesterday()); ThisMonth = notPinned .Filter(x => !x.LastAccess.IsToday() && !x.LastAccess.IsYesterday() && x.LastAccess.IsThisMonth()); Older = notPinned .Filter(x => !x.LastAccess.IsToday() && !x.LastAccess.IsYesterday() && !x.LastAccess.IsThisMonth()); // TODO: move autosaver to AppConfig appConfig.RecentObservable .WhenAnyPropertyChanged("Pinned") .Subscribe(x => appConfig.UpdateRecent(x.Uri, x.Pinned)); appConfig.GetStarted.Subscribe(x => GetStarted = x); var ver = Assembly.GetExecutingAssembly().GetName(); appConfig.Basement .Subscribe(x => Basement = x + $"v{ver.Version.Major}.{ver.Version.Minor}.{ver.Version.Build}"); if (appConfig.OpenLatestAtStartup) { foreach (var uri in appConfig.LastOpenedAtStartup) { Dispatcher.CurrentDispatcher.InvokeAsync(() => OpenBoardView(uri)); } } appConfig.ColorThemeObservable .Subscribe(x => UpdateColorTheme()); } //ctor
public CoinJoinTabViewModel(WalletViewModel walletViewModel) : base("CoinJoin", walletViewModel) { Global = Locator.Current.GetService <Global>(); Password = ""; TimeLeftTillRoundTimeout = TimeSpan.Zero; CoinsList = new CoinListViewModel(CoinListContainerType.CoinJoinTabViewModel); Observable .FromEventPattern <SmartCoin>(CoinsList, nameof(CoinsList.DequeueCoinsPressed)) .Subscribe(async x => await DoDequeueAsync(x.EventArgs)); AmountQueued = Money.Zero; // Global.ChaumianClient.State.SumAllQueuedCoinAmounts(); EnqueueCommand = ReactiveCommand.CreateFromTask(async() => await DoEnqueueAsync(CoinsList.Coins.Where(c => c.IsSelected).Select(c => c.Model))); DequeueCommand = ReactiveCommand.CreateFromTask(async() => await DoDequeueAsync(CoinsList.Coins.Where(c => c.IsSelected).Select(x => x.Model))); PrivacySomeCommand = ReactiveCommand.Create(() => TargetPrivacy = TargetPrivacy.Some); PrivacyFineCommand = ReactiveCommand.Create(() => TargetPrivacy = TargetPrivacy.Fine); PrivacyStrongCommand = ReactiveCommand.Create(() => TargetPrivacy = TargetPrivacy.Strong); TargetButtonCommand = ReactiveCommand.CreateFromTask(async() => { switch (TargetPrivacy) { case TargetPrivacy.None: TargetPrivacy = TargetPrivacy.Some; break; case TargetPrivacy.Some: TargetPrivacy = TargetPrivacy.Fine; break; case TargetPrivacy.Fine: TargetPrivacy = TargetPrivacy.Strong; break; case TargetPrivacy.Strong: TargetPrivacy = TargetPrivacy.Some; break; } Global.Config.MixUntilAnonymitySet = CoinJoinUntilAnonymitySet; await Global.Config.ToFileAsync(); }); this.WhenAnyValue(x => x.IsEnqueueBusy) .Select(x => x ? EnqueuingButtonTextString : EnqueueButtonTextString) .Subscribe(text => EnqueueButtonText = text); this.WhenAnyValue(x => x.IsDequeueBusy) .Select(x => x ? DequeuingButtonTextString : DequeueButtonTextString) .Subscribe(text => DequeueButtonText = text); this.WhenAnyValue(x => x.TargetPrivacy) .Subscribe(target => CoinJoinUntilAnonymitySet = Global.Config.GetTargetLevel(target)); this.WhenAnyValue(x => x.RoundTimesout) .ObserveOn(RxApp.MainThreadScheduler) .Subscribe(x => { TimeSpan left = x - DateTimeOffset.UtcNow; TimeLeftTillRoundTimeout = left > TimeSpan.Zero ? left : TimeSpan.Zero; // Make sure cannot be less than zero. }); Observable .Merge(EnqueueCommand.ThrownExceptions) .Merge(DequeueCommand.ThrownExceptions) .Merge(PrivacySomeCommand.ThrownExceptions) .Merge(PrivacyFineCommand.ThrownExceptions) .Merge(PrivacyStrongCommand.ThrownExceptions) .Merge(TargetButtonCommand.ThrownExceptions) .ObserveOn(RxApp.TaskpoolScheduler) .Subscribe(ex => Logger.LogError(ex)); }
public HelpCommands(CommandIconService commandIconService) { AboutCommand = new CommandDefinition( "About", commandIconService.GetCompletionKindImage("About"), ReactiveCommand.Create(() => IoC.Get <IShell>().AddOrSelectDocument(() => new AboutViewModel()))); UserSupportCommand = new CommandDefinition( "User Support", commandIconService.GetCompletionKindImage("UserSupport"), ReactiveCommand.CreateFromTask(async() => { try { await IoHelpers.OpenBrowserAsync("https://www.reddit.com/r/WasabiWallet/"); } catch (Exception ex) { Logger.LogWarning(ex); IoC.Get <IShell>().AddOrSelectDocument(() => new AboutViewModel()); } })); ReportBugCommand = new CommandDefinition( "Report Bug", commandIconService.GetCompletionKindImage("ReportBug"), ReactiveCommand.CreateFromTask(async() => { try { await IoHelpers.OpenBrowserAsync("https://github.com/zkSNACKs/WalletWasabi/issues"); } catch (Exception ex) { Logger.LogWarning(ex); IoC.Get <IShell>().AddOrSelectDocument(() => new AboutViewModel()); } })); DocsCommand = new CommandDefinition( "Documentation", commandIconService.GetCompletionKindImage("Documentation"), ReactiveCommand.CreateFromTask(async() => { try { await IoHelpers.OpenBrowserAsync("https://docs.wasabiwallet.io/"); } catch (Exception ex) { Logger.LogWarning(ex); IoC.Get <IShell>().AddOrSelectDocument(() => new AboutViewModel()); } })); LegalDocumentsCommand = new CommandDefinition( "Legal Documents", commandIconService.GetCompletionKindImage("LegalDocuments"), ReactiveCommand.Create(() => IoC.Get <IShell>().AddOrSelectDocument(() => new LegalDocumentsViewModel(legalDoc: Locator.Current.GetService <Global>()?.LegalDocuments)))); Observable .Merge(AboutCommand.GetReactiveCommand().ThrownExceptions) .Merge(UserSupportCommand.GetReactiveCommand().ThrownExceptions) .Merge(ReportBugCommand.GetReactiveCommand().ThrownExceptions) .Merge(DocsCommand.GetReactiveCommand().ThrownExceptions) .Merge(LegalDocumentsCommand.GetReactiveCommand().ThrownExceptions) .ObserveOn(RxApp.TaskpoolScheduler) .Subscribe(ex => { Logger.LogError(ex); NotificationHelpers.Error(ex.ToUserFriendlyString()); }); }
public MenuPageViewModel() { OpenCommand = ReactiveCommand.CreateFromTask(Open); SaveCommand = ReactiveCommand.Create(Save); OpenRecentCommand = ReactiveCommand.Create <string>(OpenRecent); }
public DeviceViewModel(IUserDialogs dialogs) { this.SelectCharacteristic = ReactiveCommand.Create <GattCharacteristicViewModel>(x => x.Select()); this.ConnectionToggle = ReactiveCommand.Create(() => { // don't cleanup connection - force user to d/c if (this.device.Status == ConnectionStatus.Disconnected) { this.device.Connect(); } else { this.device.CancelConnection(); } }); this.PairToDevice = ReactiveCommand.Create(() => { if (!this.device.Features.HasFlag(DeviceFeatures.PairingRequests)) { dialogs.Toast("Pairing is not supported on this platform"); } else if (this.device.PairingStatus == PairingStatus.Paired) { dialogs.Toast("Device is already paired"); } else { this.device .PairingRequest() .Subscribe(x => { var txt = x ? "Device Paired Successfully" : "Device Pairing Failed"; dialogs.Toast(txt); this.RaisePropertyChanged(nameof(this.PairingText)); }); } }); this.RequestMtu = ReactiveCommand.CreateFromTask( async x => { if (!this.device.Features.HasFlag(DeviceFeatures.MtuRequests)) { dialogs.Alert("MTU Request not supported on this platform"); } else { var result = await dialogs.PromptAsync(new PromptConfig() .SetTitle("MTU Request") .SetMessage("Range 20-512") .SetInputMode(InputType.Number) .SetOnTextChanged(args => { var len = args.Value?.Length ?? 0; if (len > 0) { if (len > 3) { args.Value = args.Value.Substring(0, 3); } else { var value = Int32.Parse(args.Value); args.IsValid = value >= 20 && value <= 512; } } }) ); if (result.Ok) { var actual = await this.device.RequestMtu(Int32.Parse(result.Text)); dialogs.Toast("MTU Changed to " + actual); } } }, this.WhenAny( x => x.ConnectText, x => x.GetValue().Equals("Disconnect") ) ); }
protected NavigationBaseViewModel(TNavigate navigateService) { NavigateService = navigateService; NavigateBackCommand = ReactiveCommand.CreateFromTask(_ => NavigateService.NavigateBack()); }
public AssetBrowserViewModel( IProjectManager projectManager, INotificationService notificationService, IGameControllerFactory gameController, IArchiveManager archiveManager, ISettingsManager settings, IProgressService <double> progressService ) : base(ToolTitle) { _projectManager = projectManager; _notificationService = notificationService; _gameController = gameController; _archiveManager = archiveManager; _settings = settings; _progressService = progressService; ContentId = ToolContentId; State = DockState.Dock; SideInDockedMode = DockSide.Tabbed; TogglePreviewCommand = new RelayCommand(ExecuteTogglePreview, CanTogglePreview); OpenFileSystemItemCommand = new RelayCommand(ExecuteOpenFile, CanOpenFile); ToggleModBrowserCommand = new RelayCommand(ExecuteToggleModBrowser, CanToggleModBrowser); OpenFileLocationCommand = new RelayCommand(ExecuteOpenFileLocationCommand, CanOpenFileLocationCommand); CopyRelPathCommand = new RelayCommand(ExecuteCopyRelPath, CanCopyRelPath); OpenFileOnlyCommand = new RelayCommand(ExecuteOpenFileOnly, CanOpenFileOnly); AddSelectedCommand = new RelayCommand(ExecuteAddSelected, CanAddSelected); ExpandAll = ReactiveCommand.Create(() => { }); CollapseAll = ReactiveCommand.Create(() => { }); Collapse = ReactiveCommand.Create(() => { }); Expand = ReactiveCommand.Create(() => { }); AddSearchKeyCommand = ReactiveCommand.Create <string>(x => SearchBarText += $" {x}:"); FindUsingCommand = ReactiveCommand.CreateFromTask(FindUsing); LoadAssetBrowserCommand = ReactiveCommand.CreateFromTask(LoadAssetBrowser); archiveManager.ConnectGameRoot() .ObserveOn(RxApp.MainThreadScheduler) .Bind(out _boundRootNodes) .Subscribe( _ => { // binds only the root node LeftItems = new ObservableCollection <RedFileSystemModel>(_boundRootNodes); }); _archiveManager .WhenAnyValue(x => x.IsManagerLoaded) .Subscribe(loaded => { LoadVisibility = loaded ? Visibility.Collapsed : Visibility.Visible; if (loaded) { _notificationService.Success($"Asset Browser is initialized"); NoProjectBorderVisibility = Visibility.Collapsed; } }); _projectManager .WhenAnyValue(_ => _.IsProjectLoaded) .Subscribe(loaded => { _projectLoaded = loaded; ShouldShowLoadButton = !_manuallyLoading && !_projectLoaded; }); //Classes = _gameController // .GetController() // .GetAvaliableClasses(); }