public StatisticService(INorthwindRepository northwindRepository)
        {
            this.northwindRepository = northwindRepository;

            productsList     = new SourceList <Product>();
            customersList    = new SourceList <Customer>();
            orderDetailsList = new SourceList <Order_Detail>();
            ordersList       = new SourceList <Order>();

            #region Customers statistics
            customersByCountries = customersList.Connect().
                                   GroupOn(customer => customer.Country).
                                   Transform(customersGroup => new CustomersByCountry()
            {
                CountryName = customersGroup.GroupKey, CustomersCount = customersGroup.List.Count
            }).
                                   ObserveOnDispatcher().
                                   Bind(out _customersByCountries);

            purchasesByCustomers = orderDetailsList.Connect().
                                   Transform(orderDetail => new { CompanyName = orderDetail.Order.Customer.CompanyName, PurchaseByOrderDetail = orderDetail.UnitPrice * orderDetail.Quantity }).
                                   GroupOn(orderDetail => orderDetail.CompanyName).
                                   Transform(groupOfOrderDetails => new PurchasesByCustomers()
            {
                CompanyName = groupOfOrderDetails.GroupKey, Purchases = groupOfOrderDetails.List.Items.Sum(a => a.PurchaseByOrderDetail)
            }).
                                   Sort(SortExpressionComparer <PurchasesByCustomers> .Descending(a => a.Purchases)).
                                   Top(10).
                                   ObserveOnDispatcher().
                                   Bind(out _purchasesByCustomers);
            #endregion

            #region Employees statistics
            salesByEmployees = orderDetailsList.Connect().
                               Transform(orderDetail => new { LastName = orderDetail.Order.Employee.LastName, SaleByOrderDetail = orderDetail.UnitPrice * orderDetail.Quantity }).
                               GroupOn(orderDetail => orderDetail.LastName).
                               Transform(groupOfOrderDetail => new EmployeeSales()
            {
                LastName = groupOfOrderDetail.GroupKey, Sales = groupOfOrderDetail.List.Items.Sum(a => a.SaleByOrderDetail)
            }).
                               ObserveOnDispatcher().
                               Sort(SortExpressionComparer <EmployeeSales> .Ascending(a => a.Sales)).
                               Bind(out _salesByEmployees);
            #endregion

            #region Products statistics
            productsByCategories = productsList.Connect().
                                   GroupOn(product => product.Category.CategoryName).
                                   Transform(groupOfProducts => new ProductsByCateogries()
            {
                CategoryName = groupOfProducts.GroupKey, NumberOfProducts = groupOfProducts.List.Count
            }).
                                   ObserveOnDispatcher().
                                   Bind(out _productsByCategories);
            #endregion

            #region Orders statistics
            ordersByCountries = ordersList.Connect().
                                GroupOn(order => order.Customer.Country).
                                Transform(groupOfOrders => new OrdersByCountry()
            {
                Country = groupOfOrders.GroupKey, NumberOfOrders = groupOfOrders.List.Count
            }).
                                ObserveOnDispatcher().
                                Top(10).
                                Bind(out _ordersByCountries);

            salesByCountries = orderDetailsList.Connect().Transform(orderDetail => new { Country = orderDetail.Order.Customer.Country, SaleByOrderDetail = orderDetail.UnitPrice * orderDetail.Quantity }).
                               GroupOn(orderDetail => orderDetail.Country).
                               Transform(groupOfOrderDetails => new SalesByCountry()
            {
                Country = groupOfOrderDetails.GroupKey, Sales = groupOfOrderDetails.List.Items.Sum(a => a.SaleByOrderDetail)
            }).
                               Sort(SortExpressionComparer <SalesByCountry> .Ascending(a => a.Sales)).
                               ObserveOnDispatcher().
                               Bind(out _salesByCountries);

            salesByCategories = orderDetailsList.Connect().
                                Transform(orderDetail => new { Category = orderDetail.Product.Category.CategoryName, SaleByOrderDetail = orderDetail.UnitPrice * orderDetail.Quantity }).
                                GroupOn(orderDetail => orderDetail.Category).
                                Transform(groupOfOrderDeatils => new SalesByCategory()
            {
                Category = groupOfOrderDeatils.GroupKey, Sales = groupOfOrderDeatils.List.Items.Sum(a => a.SaleByOrderDetail)
            }).
                                ObserveOnDispatcher().
                                Bind(out _salesByCategories);
            #endregion

            FillCollections();
        }
Example #2
0
        public MailBoxViewModel(IProfileDataQueryFactory queryFactory, IMailService mailService)
        {
            _queryFactory = queryFactory;
            _mailService  = mailService;
            _mailFolderSelectionViewModel = new MailFolderSelectionViewModel(_sourceFolders.AsObservableCache());

            var folderChanges = _sourceFolders.Connect(f => f.Type != FolderType.Root)
                                .ObserveOn(RxApp.TaskpoolScheduler)
                                .Sort(SortExpressionComparer <MailFolder> .Ascending(f => f.Type).ThenByAscending(f => f.Name))
                                .TransformToTree(f => f.ParentId)
                                .Transform(n => new MailFolderViewModel(n, this, queryFactory, mailService))
                                .DisposeMany()
                                .Publish();

            folderChanges
            .ObserveOn(RxApp.MainThreadScheduler)
            .Bind(out _allFolders)
            .Subscribe()
            .DisposeWith(_disposables);
            folderChanges
            .Filter(f => f.IsFavorite)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Bind(out _favoriteFolders)
            .Subscribe()
            .DisposeWith(_disposables);
            folderChanges.Connect()
            .DisposeWith(_disposables);

            var folderCollection = folderChanges
                                   .ToCollection()
                                   .Publish();

            folderCollection
            .Select(folders => folders.FirstOrDefault(f => f.Type == FolderType.Inbox))
            .ObserveOn(RxApp.MainThreadScheduler)
            .ToPropertyEx(this, x => x.Inbox)
            .DisposeWith(_disposables);
            folderCollection.Connect()
            .DisposeWith(_disposables);

            _mailService.FolderChanges
            .ObserveOn(RxApp.TaskpoolScheduler)
            .Subscribe(changes =>
            {
                _sourceFolders.Edit(updater =>
                {
                    foreach (var c in changes)
                    {
                        switch (c.State)
                        {
                        case DeltaState.Add:
                        case DeltaState.Update:
                            updater.AddOrUpdate(c.Entity);
                            break;

                        case DeltaState.Remove:
                            updater.RemoveKey(c.Entity.Id);
                            break;
                        }
                    }
                });
            })
            .DisposeWith(_disposables);

            Synchronize = ReactiveCommand.CreateFromTask(_mailService.SynchronizeFoldersAsync);
            //Synchronize.WithLatestFrom(folderCollection, (_, folders) => folders.Where(f => f.IsFavorite))
            //    .Subscribe(favoriteFolders =>
            //    {
            //        foreach (var f in favoriteFolders)
            //        {
            //            f.Synchronize.Execute().Subscribe();
            //        }
            //    })
            //    .DisposeWith(_disposables);
            Synchronize.ThrownExceptions
            .Subscribe(ex => this.Log().Error(ex))
            .DisposeWith(_disposables);
            Synchronize.IsExecuting
            .ToPropertyEx(this, x => x.IsSynchronizing)
            .DisposeWith(_disposables);
        }
        public MetricsViewModel(ISourcesCacheProvider cacheProvider)
        {
            _model = new MetricsModel
            {
                Caption = "Metrics",
                Cache   = cacheProvider.CurrentCache
            };
            Disposables.Add(_model);

            _model.WhenAnyValue(x => x.Caption, x => x.Online)
            .Subscribe(v => Title = v.Item1 + (v.Item2 ? " >" : " ||"));

            var dynamicFilter = _model.SelectedSourcesChanged
                                .Select(_ => Filters.CreateFilterMetricBySources(_model));

            var observable = _model.Cache.Metrics
                             .Connect()
                             .Filter(dynamicFilter)
                             .Publish();

            _metricsCache = observable
                            .AsObservableCache()
                            .DisposeWith(Disposables);

            observable
            .Transform(x => new MetricValueItem {
                Metric = x
            })
            .Sort(SortExpressionComparer <MetricValueItem>
                  .Ascending(x => x.Metric.Instance.Source.Name)
                  .ThenByAscending(x => x.Metric.Instance.Name)
                  .ThenByAscending(x => x.Metric.Name))
            .ObserveOnDispatcher()
            .Bind(out var metricValuesStatic)
            .Subscribe()
            .DisposeWith(Disposables);

            observable
            .Connect()
            .DisposeWith(Disposables);

            var metricValuesDynamicSource = new SourceList <MetricValueItem>()
                                            .DisposeWith(Disposables);

            metricValuesDynamicSource
            .Connect()
            .ObserveOnDispatcher()
            .Bind(out var metricValuesDynamic)
            .Subscribe()
            .DisposeWith(Disposables);

            _model.WhenAnyValue(x => x.MetricDiagramVisible)
            .Subscribe(x => MetricValuesList = x ? metricValuesStatic : metricValuesDynamic);

            _model.SelectedSourcesChanged.Subscribe(_ => UpdateSelectedMetrics());
            UpdateSelectedMetrics();

            var canStart = _model.WhenAny(x => x.Online, x => !x.Value);

            StartCommand = ReactiveCommand.Create(OnStart, canStart);

            var canStop = _model.WhenAny(x => x.Online, x => x.Value);

            StopCommand = ReactiveCommand.Create(OnStop, canStop);

            UpdateCommand = ReactiveCommand.Create(OnUpdate, canStop);

            var mapper = Mappers.Xy <MetricValueItem>()
                         .X(item => (double)item.Interval.Ticks / TimeSpan.FromMinutes(5).Ticks)
                         .Y(item => item.Value);

            //lets save the mapper globally.
            Charting.For <MetricValueItem>(mapper);

            SeriesCollection = new ChartValues <MetricValueItem>();

            //lets set how to display the X Labels
            DateTimeFormatter = value => new DateTime((long)value * TimeSpan.FromMinutes(5).Ticks).ToString("t");

            UpdateCommand.Subscribe(results =>
            {
                if (_model.MetricDiagramVisible)
                {
                    SeriesCollection.Clear();
                    if (results != null)
                    {
                        SeriesCollection.AddRange(results);
                    }
                }
                else
                {
                    metricValuesDynamicSource.Edit(innerList =>
                    {
                        innerList.Clear();
                        innerList.AddRange(results);
                    });
                }
            });
        }
Example #4
0
        public TailViewModel([NotNull] ILogger logger,
                             [NotNull] ISchedulerProvider schedulerProvider,
                             [NotNull] IFileWatcher fileWatcher,
                             [NotNull] ISelectionMonitor selectionMonitor,
                             [NotNull] IClipboardHandler clipboardHandler,
                             [NotNull] ISearchInfoCollection searchInfoCollection,
                             [NotNull] IInlineViewerFactory inlineViewerFactory,
                             [NotNull] ISetting <GeneralOptions> generalOptions,
                             [NotNull] ISearchMetadataCollection searchMetadataCollection,
                             [NotNull] IStateBucketService stateBucketService,
                             [NotNull] SearchOptionsViewModel searchOptionsViewModel,
                             [NotNull] ITailViewStateRestorer restorer,
                             [NotNull] SearchHints searchHints,
                             [NotNull]  ITailViewStateControllerFactory tailViewStateControllerFactory)
        {
            if (logger == null)
            {
                throw new ArgumentNullException(nameof(logger));
            }
            if (schedulerProvider == null)
            {
                throw new ArgumentNullException(nameof(schedulerProvider));
            }
            if (fileWatcher == null)
            {
                throw new ArgumentNullException(nameof(fileWatcher));
            }
            if (selectionMonitor == null)
            {
                throw new ArgumentNullException(nameof(selectionMonitor));
            }
            if (clipboardHandler == null)
            {
                throw new ArgumentNullException(nameof(clipboardHandler));
            }
            if (searchInfoCollection == null)
            {
                throw new ArgumentNullException(nameof(searchInfoCollection));
            }
            if (inlineViewerFactory == null)
            {
                throw new ArgumentNullException(nameof(inlineViewerFactory));
            }
            if (generalOptions == null)
            {
                throw new ArgumentNullException(nameof(generalOptions));
            }
            if (searchMetadataCollection == null)
            {
                throw new ArgumentNullException(nameof(searchMetadataCollection));
            }
            if (stateBucketService == null)
            {
                throw new ArgumentNullException(nameof(stateBucketService));
            }
            if (searchOptionsViewModel == null)
            {
                throw new ArgumentNullException(nameof(searchOptionsViewModel));
            }
            if (searchHints == null)
            {
                throw new ArgumentNullException(nameof(searchHints));
            }

            Name                     = fileWatcher.FullName;
            SelectionMonitor         = selectionMonitor;
            SearchOptions            = searchOptionsViewModel;
            SearchHints              = searchHints;
            SearchCollection         = new SearchCollection(searchInfoCollection, schedulerProvider);
            CopyToClipboardCommand   = new Command(() => clipboardHandler.WriteToClipboard(selectionMonitor.GetSelectedText()));
            OpenFileCommand          = new Command(() => Process.Start(fileWatcher.FullName));
            OpenFolderCommand        = new Command(() => Process.Start(fileWatcher.Folder));
            SearchMetadataCollection = searchMetadataCollection;

            UsingDarkTheme = generalOptions.Value
                             .ObserveOn(schedulerProvider.MainThread)
                             .Select(options => options.Theme == Theme.Dark)
                             .ForBinding();

            HighlightTail = generalOptions.Value
                            .ObserveOn(schedulerProvider.MainThread)
                            .Select(options => options.HighlightTail)
                            .ForBinding();

            HighlightDuration = generalOptions.Value
                                .ObserveOn(schedulerProvider.MainThread)
                                .Select(options => new Duration(TimeSpan.FromSeconds(options.HighlightDuration)))
                                .ForBinding();

            //this deails with state when loading the system at start up and at shut-down
            _stateProvider = new TailViewPersister(this, restorer);

            //this controller responsible for loading and persisting user search stuff as the user changes stuff
            var stateController = tailViewStateControllerFactory.Create(this);

            //An observable which acts as a scroll command
            var autoChanged = this.WhenValueChanged(vm => vm.AutoTail);
            var scroller    = _userScrollRequested.CombineLatest(autoChanged, (user, auto) =>
            {
                var mode = AutoTail ? ScrollReason.Tail : ScrollReason.User;
                return(new ScrollRequest(mode, user.PageSize, user.FirstIndex));
            })
                              .Do(x => logger.Info("Scrolling to {0}/{1}", x.FirstIndex, x.PageSize))
                              .DistinctUntilChanged();

            FileStatus = fileWatcher.Status.ForBinding();

            //command to add the current search to the tail collection
            var searchInvoker = SearchHints.SearchRequested.Subscribe(request =>
            {
                searchInfoCollection.Add(request.Text, request.UseRegEx);
            });

            //User feedback to show file size
            FileSizeText = fileWatcher.Latest.Select(fn => fn.Size)
                           .Select(size => size.FormatWithAbbreviation())
                           .DistinctUntilChanged()
                           .ForBinding();

            //tailer is the main object used to tail, scroll and filter in a file
            var lineScroller = new LineScroller(SearchCollection.Latest.ObserveOn(schedulerProvider.Background), scroller);

            //load lines into observable collection
            var lineProxyFactory = new LineProxyFactory(new TextFormatter(searchMetadataCollection), new LineMatches(searchMetadataCollection));
            var loader           = lineScroller.Lines.Connect()

                                   .LogChanges(logger, "Received")
                                   .Transform(lineProxyFactory.Create, new ParallelisationOptions(ParallelType.Ordered, 3))
                                   .LogChanges(logger, "Sorting")
                                   .Sort(SortExpressionComparer <LineProxy> .Ascending(proxy => proxy))
                                   .ObserveOn(schedulerProvider.MainThread)
                                   .Bind(out _data, 100)
                                   .LogChanges(logger, "Bound")
                                   .DisposeMany()
                                   .LogErrors(logger)
                                   .Subscribe();


            //monitor matching lines and start index,
            Count       = searchInfoCollection.All.Select(latest => latest.Count).ForBinding();
            CountText   = searchInfoCollection.All.Select(latest => $"{latest.Count.ToString("##,###")} lines").ForBinding();
            LatestCount = SearchCollection.Latest.Select(latest => latest.Count).ForBinding();

            ////track first visible index
            var firstIndexMonitor = lineScroller.Lines.Connect()
                                    .Buffer(TimeSpan.FromMilliseconds(25)).FlattenBufferResult()
                                    .ToCollection()
                                    .Select(lines => lines.Count == 0 ? 0 : lines.Select(l => l.Index).Max() - lines.Count + 1)
                                    .ObserveOn(schedulerProvider.MainThread)
                                    .Subscribe(first =>
            {
                FirstIndex = first;
            });

            //Create objects required for inline viewing
            var isUserDefinedChanged = SearchCollection.WhenValueChanged(sc => sc.Selected)
                                       .Where(selected => selected != null)
                                       .Select(selected => selected.IsUserDefined)
                                       .DistinctUntilChanged()
                                       .Replay(1)
                                       .RefCount();

            var inlineViewerVisible = isUserDefinedChanged.CombineLatest(this.WhenValueChanged(vm => vm.ShowInline),
                                                                         (userDefined, showInline) => userDefined && showInline);

            CanViewInline       = isUserDefinedChanged.ForBinding();
            InlineViewerVisible = inlineViewerVisible.ForBinding();

            //return an empty line provider unless user is viewing inline - this saves needless trips to the file
            var inline = searchInfoCollection.All.CombineLatest(inlineViewerVisible, (index, ud) => ud ? index : new EmptyLineProvider());

            InlineViewer = inlineViewerFactory.Create(inline, this.WhenValueChanged(vm => vm.SelectedItem), lineProxyFactory);

            _cleanUp = new CompositeDisposable(lineScroller,
                                               loader,
                                               firstIndexMonitor,
                                               FileStatus,
                                               Count,
                                               LatestCount,
                                               FileSizeText,
                                               CanViewInline,
                                               InlineViewer,
                                               InlineViewerVisible,
                                               SearchCollection,
                                               searchInfoCollection,
                                               HighlightTail,
                                               UsingDarkTheme,
                                               searchHints,
                                               searchMetadataCollection,
                                               SelectionMonitor,
                                               SearchOptions,
                                               searchInvoker,
                                               stateController,
                                               _userScrollRequested.SetAsComplete());
        }
Example #5
0
        public MailFolderViewModel(Node <MailFolder, string> node,
                                   MailBoxViewModel mailBox,
                                   IProfileDataQueryFactory queryFactory,
                                   IMailService mailService)
        {
            Id         = node.Item.Id;
            ParentId   = node.Item.ParentId;
            Name       = node.Item.Name;
            Type       = node.Item.Type;
            IsFavorite = node.Item.IsFavorite;
            Messages   = new MessageListViewModel(node.Item.Id, node.Item.Type,
                                                  mailBox, queryFactory, mailService, Activator);

            Synchronize = ReactiveCommand.CreateFromObservable(() => Observable
                                                               .StartAsync((token) => mailService.SynchronizeMessagesAsync(node.Item.Id, token))
                                                               .TakeUntil(CancelSynchronization));
            Synchronize.IsExecuting
            .ToPropertyEx(this, x => x.IsSynchronizing)
            .DisposeWith(_disposables);
            Synchronize.ThrownExceptions
            .Subscribe(ex => this.Log().Error(ex))
            .DisposeWith(_disposables);
            CancelSynchronization = ReactiveCommand.Create(() => { }, Synchronize.IsExecuting);

            Move = ReactiveCommand.CreateFromTask(async() =>
            {
                var result = await mailBox.PromptUserToSelectFolder(
                    "Move a folder",
                    "Select another folder to move to:",
                    includeRoot: true,
                    CanMoveTo);
                this.Log().Debug(result);
            });

            node.Children.Connect()
            .Transform(n => new MailFolderViewModel(n, mailBox, queryFactory, mailService))
            .Sort(SortExpressionComparer <MailFolderViewModel> .Ascending(f => f.Name))
            .ObserveOn(RxApp.MainThreadScheduler)
            .Bind(out _childFolders)
            .DisposeMany()
            .Subscribe()
            .DisposeWith(_disposables);

            mailService.MessageChanges
            .Where(changes => changes.AffectsFolder(node.Item.Id))
            .SelectMany(_ => CountMessages(queryFactory, node.Item.Id))
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(x =>
            {
                UnreadCount = x.UnreadCount;
                TotalCount  = x.TotalCount;
            })
            .DisposeWith(_disposables);

            CountMessages(queryFactory, node.Item.Id)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(x =>
            {
                UnreadCount = x.UnreadCount;
                TotalCount  = x.TotalCount;
            })
            .DisposeWith(_disposables);
        }
        private ProxyService()
        {
            mCurrent = this;

            ProxyDomains = new SourceList <AccelerateProjectGroupDTO>();
            ProxyScripts = new SourceList <ScriptDTO>();

            ProxyDomains
            .Connect()
            .ObserveOn(RxApp.MainThreadScheduler)
            .Sort(SortExpressionComparer <AccelerateProjectGroupDTO> .Ascending(x => x.Order).ThenBy(x => x.Name))
            .Bind(out _ProxyDomainsList)
            .Subscribe(_ => SelectGroup = ProxyDomains.Items.FirstOrDefault());


            this.WhenValueChanged(x => x.ProxyStatus, false)
            .Subscribe(async x =>
            {
                if (x)
                {
                    httpProxyService.ProxyDomains   = EnableProxyDomains;
                    httpProxyService.IsEnableScript = ProxySettings.IsEnableScript.Value;
                    httpProxyService.Scripts        = EnableProxyScripts;
                    if (IApplication.IsDesktopPlatform)
                    {
                        httpProxyService.IsOnlyWorkSteamBrowser = ProxySettings.IsOnlyWorkSteamBrowser.Value;
                        httpProxyService.IsSystemProxy          = ProxySettings.EnableWindowsProxy.Value;
                        httpProxyService.IsProxyGOG             = ProxySettings.IsProxyGOG.Value;
                    }
                    else
                    {
                        httpProxyService.IsSystemProxy = true;
                    }

                    // macOS 上目前因权限问题仅支持 0.0.0.0(IPAddress.Any)
                    httpProxyService.ProxyIp = (!OperatingSystem2.IsMacOS && IPAddress2.TryParse(ProxySettings.SystemProxyIp.Value, out var ip)) ? ip : IPAddress.Any;

                    httpProxyService.Socks5ProxyEnable = ProxySettings.Socks5ProxyEnable.Value;
                    httpProxyService.Socks5ProxyPortId = ProxySettings.Socks5ProxyPortId.Value;
                    if (!ModelValidatorProvider.IsPortId(httpProxyService.Socks5ProxyPortId))
                    {
                        httpProxyService.Socks5ProxyPortId = ProxySettings.DefaultSocks5ProxyPortId;
                    }

                    //httpProxyService.HostProxyPortId = ProxySettings.HostProxyPortId;
                    httpProxyService.TwoLevelAgentEnable = ProxySettings.TwoLevelAgentEnable.Value;

                    httpProxyService.TwoLevelAgentProxyType = (ExternalProxyType)ProxySettings.TwoLevelAgentProxyType.Value;
                    if (!httpProxyService.TwoLevelAgentProxyType.IsDefined())
                    {
                        httpProxyService.TwoLevelAgentProxyType = IHttpProxyService.DefaultTwoLevelAgentProxyType;
                    }

                    httpProxyService.TwoLevelAgentIp     = IPAddress2.TryParse(ProxySettings.TwoLevelAgentIp.Value, out var ip_t) ? ip_t.ToString() : IPAddress.Loopback.ToString();
                    httpProxyService.TwoLevelAgentPortId = ProxySettings.TwoLevelAgentPortId.Value;
                    if (!ModelValidatorProvider.IsPortId(httpProxyService.TwoLevelAgentPortId))
                    {
                        httpProxyService.TwoLevelAgentPortId = ProxySettings.DefaultTwoLevelAgentPortId;
                    }
                    httpProxyService.TwoLevelAgentUserName = ProxySettings.TwoLevelAgentUserName.Value;
                    httpProxyService.TwoLevelAgentPassword = ProxySettings.TwoLevelAgentPassword.Value;

                    httpProxyService.ProxyDNS = IPAddress2.TryParse(ProxySettings.ProxyMasterDns.Value, out var dns) ? dns : null;

                    this.RaisePropertyChanged(nameof(EnableProxyDomains));
                    this.RaisePropertyChanged(nameof(EnableProxyScripts));

                    if (!httpProxyService.IsSystemProxy)
                    {
                        const ushort httpsPort = 443;
                        var inUse = httpProxyService.PortInUse(httpsPort);
                        if (inUse)
                        {
                            string?error_CommunityFix_StartProxyFaild443 = null;
                            if (OperatingSystem2.IsWindows)
                            {
                                var p = SocketHelper.GetProcessByTcpPort(httpsPort);
                                if (p != null)
                                {
                                    error_CommunityFix_StartProxyFaild443 = AppResources.CommunityFix_StartProxyFaild443___.Format(httpsPort, p.ProcessName, p.Id);
                                }
                            }
                            error_CommunityFix_StartProxyFaild443 ??= AppResources.CommunityFix_StartProxyFaild443_.Format(httpsPort);
                            Toast.Show(error_CommunityFix_StartProxyFaild443);
                            return;
                        }
                    }

                    var isRun = await httpProxyService.StartProxy();

                    if (isRun)
                    {
                        if (!httpProxyService.IsSystemProxy)
                        {
                            if (httpProxyService.ProxyDomains.Any_Nullable())
                            {
                                var localhost = IPAddress.Any.Equals(httpProxyService.ProxyIp) ? IPAddress.Loopback.ToString() : httpProxyService.ProxyIp.ToString();

                                var hosts = httpProxyService.ProxyDomains !.SelectMany(s =>
                                {
                                    if (s == null)
                                    {
                                        return(default !);
Example #7
0
        public InlineViewer([NotNull] InlineViewerArgs args,
                            [NotNull] IClipboardHandler clipboardHandler,
                            [NotNull] ISchedulerProvider schedulerProvider,
                            [NotNull] ISelectionMonitor selectionMonitor,
                            [NotNull] ILogger logger,
                            [NotNull] IThemeProvider themeProvider)
        {
            if (args == null)
            {
                throw new ArgumentNullException(nameof(args));
            }
            if (clipboardHandler == null)
            {
                throw new ArgumentNullException(nameof(clipboardHandler));
            }
            if (schedulerProvider == null)
            {
                throw new ArgumentNullException(nameof(schedulerProvider));
            }
            if (selectionMonitor == null)
            {
                throw new ArgumentNullException(nameof(selectionMonitor));
            }
            if (themeProvider == null)
            {
                throw new ArgumentNullException(nameof(themeProvider));
            }
            SelectionMonitor       = selectionMonitor;
            CopyToClipboardCommand = new Command(() => clipboardHandler.WriteToClipboard(selectionMonitor.GetSelectedText()));

            _isSettingScrollPosition = false;

            var lineProvider    = args.LineProvider;
            var selectedChanged = args.SelectedChanged;
            var pageSize        = this.WhenValueChanged(vm => vm.PageSize);

            //if use selection is null, tail the file
            var scrollSelected = selectedChanged
                                 .CombineLatest(lineProvider, pageSize, (proxy, lp, pge) => proxy == null ? new ScrollRequest(pge, 0) : new ScrollRequest(pge, proxy.Start))
                                 .DistinctUntilChanged();



            var horizonalScrollArgs = new ReplaySubject <TextScrollInfo>(1);

            HorizonalScrollChanged = hargs =>
            {
                horizonalScrollArgs.OnNext(hargs);
            };

            var scrollUser = _userScrollRequested
                             .Where(x => !_isSettingScrollPosition)
                             .Select(request => new ScrollRequest(ScrollReason.User, request.PageSize, request.FirstIndex));

            var scroller = scrollSelected.Merge(scrollUser)
                           .ObserveOn(schedulerProvider.Background)
                           .DistinctUntilChanged();


            var lineScroller = new LineScroller(lineProvider, scroller);

            Count = lineProvider.Select(lp => lp.Count).ForBinding();

            MaximumChars = lineScroller.MaximumLines()
                           .ObserveOn(schedulerProvider.MainThread)
                           .ForBinding();

            var proxyFactory = new LineProxyFactory(new TextFormatter(args.SearchMetadataCollection), new LineMatches(args.SearchMetadataCollection), horizonalScrollArgs.DistinctUntilChanged(), themeProvider);

            //load lines into observable collection
            var loader = lineScroller.Lines.Connect()
                         .Transform(proxyFactory.Create, new ParallelisationOptions(ParallelType.Ordered, 3))
                         .Sort(SortExpressionComparer <LineProxy> .Ascending(proxy => proxy))
                         .ObserveOn(schedulerProvider.MainThread)
                         .Bind(out _data)
                         .DisposeMany()
                         .LogErrors(logger)
                         .Subscribe();

            // track first visible index [required to set scroll extent]
            var firstIndexMonitor = lineScroller.Lines.Connect()
                                    .Buffer(TimeSpan.FromMilliseconds(250)).FlattenBufferResult()
                                    .ToCollection()
                                    .Select(lines => lines.Count == 0 ? 0 : lines.Select(l => l.Index).Max() - lines.Count + 1)
                                    .ObserveOn(schedulerProvider.MainThread)
                                    .Subscribe(first =>
            {
                try
                {
                    _isSettingScrollPosition = true;
                    FirstIndex = first;
                }
                finally
                {
                    _isSettingScrollPosition = false;
                }
            });

            _cleanUp = new CompositeDisposable(lineScroller,
                                               loader,
                                               Count,
                                               firstIndexMonitor,
                                               SelectionMonitor,
                                               MaximumChars,
                                               horizonalScrollArgs.SetAsComplete(),
                                               _userScrollRequested.SetAsComplete());
        }
        public SearchProxyCollection(ISearchMetadataCollection metadataCollection,
                                     Guid id,
                                     Action <SearchMetadata> changeScopeAction,
                                     ISchedulerProvider schedulerProvider,
                                     IColourProvider colourProvider,
                                     IIconProvider iconsProvider,
                                     ITextAssociationCollection textAssociationCollection,
                                     IThemeProvider themeProvider)
        {
            var proxyItems = metadataCollection.Metadata.Connect()
                             .WhereReasonsAre(ChangeReason.Add, ChangeReason.Remove) //ignore updates because we update from here
                             .Transform(meta =>
            {
                return(new SearchOptionsProxy(meta,
                                              changeScopeAction,
                                              colourProvider,
                                              themeProvider,
                                              new IconSelector(iconsProvider, schedulerProvider),
                                              m => metadataCollection.Remove(m.SearchText),
                                              iconsProvider.DefaultIconSelector,
                                              id));
            })
                             .SubscribeMany(so =>
            {
                //when a value changes, write the original value back to the metadata collection
                var anyPropertyHasChanged = so.WhenAnyPropertyChanged()
                                            .Select(_ => (SearchMetadata)so)
                                            .Subscribe(metadataCollection.AddorUpdate);

                //when an icon or colour has changed we need to record user choice so
                //the same choice can be used again
                var iconChanged       = so.WhenValueChanged(proxy => proxy.IconKind, false).ToUnit();
                var colourChanged     = so.WhenValueChanged(proxy => proxy.HighlightHue, false).ToUnit();
                var ignoreCaseChanged = so.WhenValueChanged(proxy => proxy.CaseSensitive, false).ToUnit();

                var textAssociationChanged = iconChanged.Merge(colourChanged).Merge(ignoreCaseChanged)
                                             .Throttle(TimeSpan.FromMilliseconds(250))
                                             .Select(_ => new TextAssociation(so.Text, so.CaseSensitive, so.UseRegex, so.HighlightHue.Swatch,
                                                                              so.IconKind.ToString(), so.HighlightHue.Name, DateTime.UtcNow))
                                             .Subscribe(textAssociationCollection.MarkAsChanged);

                return(new CompositeDisposable(anyPropertyHasChanged, textAssociationChanged));
            })
                             .AsObservableCache();

            Count = proxyItems.CountChanged.StartWith(0).ForBinding();

            var monitor = MonitorPositionalChanges().Subscribe(metadataCollection.Add);

            //load data onto grid
            var collection = new ObservableCollectionExtended <SearchOptionsProxy>();

            var includedLoader = proxyItems
                                 .Connect(proxy => !proxy.IsExclusion)
                                 .Sort(SortExpressionComparer <SearchOptionsProxy> .Ascending(proxy => proxy.Position))
                                 .ObserveOn(schedulerProvider.MainThread)
                                 //force reset for each new or removed item dues to a bug in the underlying dragablz control which inserts in an incorrect position
                                 .Bind(collection, new ObservableCollectionAdaptor <SearchOptionsProxy, string>(0))
                                 .DisposeMany()
                                 .Subscribe();

            ReadOnlyObservableCollection <SearchOptionsProxy> excluded;
            var excludedLoader = proxyItems
                                 .Connect(proxy => proxy.IsExclusion)
                                 .Sort(SortExpressionComparer <SearchOptionsProxy> .Ascending(proxy => proxy.Text))
                                 .ObserveOn(schedulerProvider.MainThread)
                                 //force reset for each new or removed item dues to a bug in the underlying dragablz control which inserts in an incorrect position
                                 .Bind(out excluded)
                                 .DisposeMany()
                                 .Subscribe();


            Excluded = excluded;
            Included = new ReadOnlyObservableCollection <SearchOptionsProxy>(collection);

            _cleanUp = new CompositeDisposable(proxyItems, includedLoader, excludedLoader, monitor);
        }
Example #9
0
        public SearchOptionsViewModel(ISearchMetadataCollection metadataCollection,
                                      ISearchMetadataFactory searchMetadataFactory,
                                      ISchedulerProvider schedulerProvider,
                                      IColourProvider colourProvider,
                                      IIconProvider iconsProvider,
                                      ITextAssociationCollection textAssociationCollection,
                                      SearchHints searchHints,
                                      IThemeProvider themeProvider)
        {
            SearchHints = searchHints;

            var proxyItems = metadataCollection.Metadata.Connect()
                             .WhereReasonsAre(ChangeReason.Add, ChangeReason.Remove) //ignore updates because we update from here
                             .Transform(meta =>
            {
                return(new SearchOptionsProxy(meta,
                                              colourProvider,
                                              themeProvider,
                                              new IconSelector(iconsProvider, schedulerProvider),
                                              m => metadataCollection.Remove(m.SearchText),
                                              iconsProvider.DefaultIconSelector,
                                              Id));
            })
                             .SubscribeMany(so =>
            {
                //when a value changes, write the original value back to the metadata collection
                var anyPropertyHasChanged = so.WhenAnyPropertyChanged()
                                            .Select(_ => (SearchMetadata)so)
                                            .Subscribe(metadataCollection.AddorUpdate);

                //when an icon or colour has changed we need to record user choice so
                //the same choice can be used again
                var iconChanged       = so.WhenValueChanged(proxy => proxy.IconKind, false).ToUnit();
                var colourChanged     = so.WhenValueChanged(proxy => proxy.HighlightHue, false).ToUnit();
                var ignoreCaseChanged = so.WhenValueChanged(proxy => proxy.IgnoreCase, false).ToUnit();

                var textAssociationChanged = iconChanged.Merge(colourChanged).Merge(ignoreCaseChanged)
                                             .Throttle(TimeSpan.FromMilliseconds(250))
                                             .Select(_ => new TextAssociation(so.Text, so.IgnoreCase, so.UseRegex, so.HighlightHue.Swatch, so.IconKind.ToString(), so.HighlightHue.Name, DateTime.UtcNow))
                                             .Subscribe(textAssociationCollection.MarkAsChanged);

                return(new CompositeDisposable(anyPropertyHasChanged, textAssociationChanged));
            })
                             .AsObservableCache();

            var monitor = MonitorPositionalChanges()
                          .Subscribe(metadataCollection.Add);


            //load data onto grid
            var collection = new ObservableCollectionExtended <SearchOptionsProxy>();

            var userOptions = proxyItems.Connect()
                              .Sort(SortExpressionComparer <SearchOptionsProxy> .Ascending(proxy => proxy.Position))
                              .ObserveOn(schedulerProvider.MainThread)
                              //force reset for each new or removed item dues to a bug in the underlying dragablz control which inserts in an incorrect position
                              .Bind(collection, new ObservableCollectionAdaptor <SearchOptionsProxy, string>(0))
                              .DisposeMany()
                              .Subscribe();

            Data = new ReadOnlyObservableCollection <SearchOptionsProxy>(collection);

            //command to add the current search to the tail collection
            var searchInvoker = SearchHints.SearchRequested
                                .ObserveOn(schedulerProvider.Background)
                                .Subscribe(request =>
            {
                var meta = searchMetadataFactory.Create(request.Text,
                                                        request.UseRegEx,
                                                        metadataCollection.NextIndex(),
                                                        false);
                metadataCollection.AddorUpdate(meta);
            });

            _cleanUp = new CompositeDisposable(searchInvoker,
                                               userOptions,
                                               searchInvoker,
                                               monitor,
                                               SearchHints);
        }
        protected override void OnParametersSet()
        {
            base.OnParametersSet();

            ViewModel.TitlesViews.Connect().Transform(t => t.Name).Sort(SortExpressionComparer <string> .Ascending(s => s)).ObserveOn(RxApp.MainThreadScheduler).Bind(out activeTitleGroup).Subscribe();
        }
Example #11
0
        public TailViewModel([NotNull] ILogger logger,
                             [NotNull] ISchedulerProvider schedulerProvider,
                             [NotNull] IFileWatcher fileWatcher,
                             [NotNull] ISelectionMonitor selectionMonitor,
                             [NotNull] IClipboardHandler clipboardHandler,
                             [NotNull] ISearchInfoCollection searchInfoCollection,
                             [NotNull] IInlineViewerFactory inlineViewerFactory,
                             [NotNull] GeneralOptionBindings generalOptionBindings,
                             [NotNull] ICombinedSearchMetadataCollection combinedSearchMetadataCollection,
                             [NotNull] IStateBucketService stateBucketService,
                             [NotNull] ITailViewStateRestorer restorer,
                             [NotNull] SearchHints searchHints,
                             [NotNull] ITailViewStateControllerFactory tailViewStateControllerFactory,
                             [NotNull] IThemeProvider themeProvider,
                             [NotNull] SearchCollection searchCollection,
                             [NotNull] ITextFormatter textFormatter,
                             [NotNull] ILineMatches lineMatches,
                             [NotNull] IObjectProvider objectProvider,
                             [NotNull] IDialogCoordinator dialogCoordinator)
        {
            if (logger == null)
            {
                throw new ArgumentNullException(nameof(logger));
            }
            if (schedulerProvider == null)
            {
                throw new ArgumentNullException(nameof(schedulerProvider));
            }
            if (fileWatcher == null)
            {
                throw new ArgumentNullException(nameof(fileWatcher));
            }
            if (clipboardHandler == null)
            {
                throw new ArgumentNullException(nameof(clipboardHandler));
            }
            if (searchInfoCollection == null)
            {
                throw new ArgumentNullException(nameof(searchInfoCollection));
            }
            if (inlineViewerFactory == null)
            {
                throw new ArgumentNullException(nameof(inlineViewerFactory));
            }
            if (stateBucketService == null)
            {
                throw new ArgumentNullException(nameof(stateBucketService));
            }
            if (themeProvider == null)
            {
                throw new ArgumentNullException(nameof(themeProvider));
            }
            if (textFormatter == null)
            {
                throw new ArgumentNullException(nameof(textFormatter));
            }
            if (lineMatches == null)
            {
                throw new ArgumentNullException(nameof(lineMatches));
            }
            if (objectProvider == null)
            {
                throw new ArgumentNullException(nameof(objectProvider));
            }
            if (dialogCoordinator == null)
            {
                throw new ArgumentNullException(nameof(dialogCoordinator));
            }
            if (combinedSearchMetadataCollection == null)
            {
                throw new ArgumentNullException(nameof(combinedSearchMetadataCollection));
            }

            Name                  = fileWatcher.FullName;
            SelectionMonitor      = selectionMonitor ?? throw new ArgumentNullException(nameof(selectionMonitor));
            GeneralOptionBindings = generalOptionBindings;
            SearchHints           = searchHints ?? throw new ArgumentNullException(nameof(searchHints));

            CopyToClipboardCommand     = new Command(() => clipboardHandler.WriteToClipboard(selectionMonitor.GetSelectedText()));
            OpenFileCommand            = new Command(() => Process.Start(fileWatcher.FullName));
            OpenFolderCommand          = new Command(() => Process.Start(fileWatcher.Folder));
            CopyPathToClipboardCommand = new Command(() => clipboardHandler.WriteToClipboard(fileWatcher.FullName));
            UnClearCommand             = new Command(fileWatcher.Reset);
            ClearCommand             = new Command(fileWatcher.Clear);
            KeyAutoTail              = new Command(() => { AutoTail = true; });
            OpenSearchOptionsCommand = new Command(async() =>
            {
                await Task.Run(() =>
                {
                    var content = objectProvider.Get <SearchOptionsViewModel>(new Argument <ICombinedSearchMetadataCollection>(combinedSearchMetadataCollection));
                    dialogCoordinator.Show(this, content, x => content.Dispose());
                });
            });

            var closeOnDeselect = this.WhenValueChanged(vm => vm.IsSelected, false)
                                  .Where(selected => !selected)
                                  .Subscribe(_ => dialogCoordinator.Close());

            SearchCollection         = searchCollection ?? throw new ArgumentNullException(nameof(searchCollection));
            SearchMetadataCollection = combinedSearchMetadataCollection.Local;

            var horizonalScrollArgs = new ReplaySubject <TextScrollInfo>(1);

            HorizonalScrollChanged = args => horizonalScrollArgs.OnNext(args);

            _tailViewStateControllerFactory = tailViewStateControllerFactory;

            //this deals with state when loading the system at start up and at shut-down
            _persister = new TailViewPersister(this, restorer);

            FileStatus = fileWatcher.Status.ForBinding();

            //command to add the current search to the tail collection
            var searchInvoker = SearchHints.SearchRequested.Subscribe(request => searchInfoCollection.Add(request.Text, request.UseRegEx));

            //An observable which acts as a scroll command
            var autoChanged = this.WhenValueChanged(vm => vm.AutoTail);
            var scroller    = _userScrollRequested.CombineLatest(autoChanged, (user, auto) =>
            {
                var mode = AutoTail ? ScrollReason.Tail : ScrollReason.User;
                return(new ScrollRequest(mode, user.PageSize, user.FirstIndex));
            })
                              .Do(x => logger.Info("Scrolling to {0}/{1}", x.FirstIndex, x.PageSize))
                              .DistinctUntilChanged();

            //User feedback to show file size
            FileSizeText = fileWatcher.Latest.Select(fn => fn.Size)
                           .Select(size => size.FormatWithAbbreviation())
                           .DistinctUntilChanged()
                           .ForBinding();


            //tailer is the main object used to tail, scroll and filter in a file
            var selectedProvider = SearchCollection.Latest.ObserveOn(schedulerProvider.Background);

            var lineScroller = new LineScroller(selectedProvider, scroller);

            MaximumChars = lineScroller.MaximumLines()
                           .ObserveOn(schedulerProvider.MainThread)
                           .ForBinding();

            var lineProxyFactory = new LineProxyFactory(textFormatter, lineMatches, horizonalScrollArgs.DistinctUntilChanged(), themeProvider);

            var loader = lineScroller.Lines.Connect()
                         .LogChanges(logger, "Received")
                         .Transform(lineProxyFactory.Create)
                         .LogChanges(logger, "Sorting")
                         .Sort(SortExpressionComparer <LineProxy> .Ascending(proxy => proxy))
                         .ObserveOn(schedulerProvider.MainThread)
                         .Bind(out _data, 100)
                         .LogChanges(logger, "Bound")
                         .DisposeMany()
                         .LogErrors(logger)
                         .Subscribe();

            //monitor matching lines and start index,
            Count       = searchInfoCollection.All.Select(latest => latest.Count).ForBinding();
            CountText   = searchInfoCollection.All.Select(latest => $"{latest.Count:##,###} lines").ForBinding();
            LatestCount = SearchCollection.Latest.Select(latest => latest.Count).ForBinding();

            ////track first visible index
            var firstIndexMonitor = lineScroller.Lines.Connect()
                                    .Buffer(TimeSpan.FromMilliseconds(25)).FlattenBufferResult()
                                    .ToCollection()
                                    .Select(lines => lines.Count == 0 ? 0 : lines.Select(l => l.Index).Max() - lines.Count + 1)
                                    .ObserveOn(schedulerProvider.MainThread)
                                    .Subscribe(first =>
            {
                FirstIndex = first;
            });

            //Create objects required for inline viewing
            var isUserDefinedChanged = SearchCollection.WhenValueChanged(sc => sc.Selected)
                                       .Where(selected => selected != null)
                                       .Select(selected => selected.IsUserDefined)
                                       .DistinctUntilChanged()
                                       .Replay(1)
                                       .RefCount();

            var showInline          = this.WhenValueChanged(vm => vm.ShowInline);
            var inlineViewerVisible = isUserDefinedChanged.CombineLatest(showInline, (userDefined, showInlne) => userDefined && showInlne);

            CanViewInline       = isUserDefinedChanged.ForBinding();
            InlineViewerVisible = inlineViewerVisible.ForBinding();

            //return an empty line provider unless user is viewing inline - this saves needless trips to the file
            var inline = searchInfoCollection.All.CombineLatest(inlineViewerVisible, (index, ud) => ud ? index : EmptyLineProvider.Instance);

            InlineViewer = inlineViewerFactory.Create(combinedSearchMetadataCollection, inline, this.WhenValueChanged(vm => vm.SelectedItem));

            _cleanUp = new CompositeDisposable(lineScroller,
                                               loader,
                                               firstIndexMonitor,
                                               FileStatus,
                                               Count,
                                               LatestCount,
                                               FileSizeText,
                                               CanViewInline,
                                               InlineViewer,
                                               InlineViewerVisible,
                                               SearchCollection,
                                               searchInfoCollection,
                                               searchHints,
                                               combinedSearchMetadataCollection,
                                               SelectionMonitor,
                                               closeOnDeselect,
                                               Disposable.Create(dialogCoordinator.Close),
                                               searchInvoker,
                                               MaximumChars,
                                               _stateMonitor,
                                               combinedSearchMetadataCollection,
                                               horizonalScrollArgs.SetAsComplete(),
                                               _userScrollRequested.SetAsComplete());
        }
Example #12
0
        public MovieListViewModel(
            NavigationManager navigationManager,
            ILocalStorageService localStorageService,
            ReduxStore <MovieSearchState> movieSearchStore)
        {
            _navigationManager   = navigationManager;
            _localStorageService = localStorageService;

            // Set initial value
            SearchText = movieSearchStore.State.SearchText;

            var source = new SourceCache <OmdbMovieSearchDto, string>(x => x.ImdbId)
                         .DisposeWith(CleanUp);

            source.Connect()
            .Sort(SortExpressionComparer <OmdbMovieSearchDto> .Ascending(p => p.Title), SortOptimisations.ComparesImmutableValuesOnly)
            .Bind(Movies)
            .Subscribe(_ => UpdateState())
            .DisposeWith(CleanUp);

            source.CountChanged
            .StartWith(0)
            .Select(x => x == 0)
            .ToPropertyEx(this, x => x.IsSourceEmpty)
            .DisposeWith(CleanUp);

            var searchTextObservable = this.WhenAnyValue(x => x.SearchText)
                                       .Skip(1)
                                       // Use throttle to prevent over requesting data
                                       .Throttle(TimeSpan.FromMilliseconds(250))
                                       .Publish();

            searchTextObservable
            .Where(string.IsNullOrEmpty)
            .Subscribe(_ => movieSearchStore.Dispatch(new ResetMovieSearchAction()))
            .DisposeWith(CleanUp);

            searchTextObservable
            .Where(x => !string.IsNullOrEmpty(x))
            .Subscribe(x => movieSearchStore.Dispatch(new PerformMovieSearchAction(x)))
            .DisposeWith(CleanUp);

            searchTextObservable.Connect();

            movieSearchStore
            .Select(MovieSearchSelectors.SelectIsSearching)
            .ToPropertyEx(this, x => x.IsSearching)
            .DisposeWith(CleanUp);

            movieSearchStore
            .Select(MovieSearchSelectors.SelectMovies)
            .Subscribe(x => source.Edit(list =>
            {
                list.Clear();
                list.AddOrUpdate(x);
            }))
            .DisposeWith(CleanUp);

            movieSearchStore
            .Select(MovieSearchSelectors.SelectSearchText)
            .Skip(1)
            .SelectMany(async x =>
            {
                await SaveSearchTextsAsync(x)
                .ConfigureAwait(false);

                return(Unit.Default);
            })
            .Subscribe()
            .DisposeWith(CleanUp);
        }
Example #13
0
        public SeasonFormViewModel(
            Season season,
            SeriesFormViewModel parent,
            IObservable <int> maxSequenceNumber,
            ResourceManager?resourceManager = null,
            IScheduler?scheduler            = null)
            : base(parent, maxSequenceNumber, resourceManager, scheduler)
        {
            this.Season = season;

            var canDeletePeriod = this.periodsSource.Connect()
                                  .Count()
                                  .Select(count => count > MinPeriodCount);

            this.periodsSource.Connect()
            .Sort(SortExpressionComparer <Period> .Ascending(period => period.StartYear)
                  .ThenByAscending(period => period.StartMonth)
                  .ThenByAscending(period => period.EndYear)
                  .ThenByAscending(period => period.EndMonth))
            .Transform(period => this.CreatePeriodForm(period, canDeletePeriod))
            .Bind(out this.periods)
            .DisposeMany()
            .Subscribe();

            this.CopyProperties();

            this.ChannelRule = this.ValidationRule(
                vm => vm.Channel, channel => !String.IsNullOrWhiteSpace(channel), "ChannelEmpty");

            this.PeriodsNonOverlapping =
                this.periods.ToObservableChangeSet()
                .AutoRefreshOnObservable(pvm => pvm.Changed)
                .Select(_ => this.AreAllPeriodsNonOverlapping());

            this.WhenAnyValue(vm => vm.CurrentPosterIndex)
            .Select(index => this.Season.Periods[index].PosterUrl)
            .BindTo(this, vm => vm.CurrentPosterUrl);

            var canAddPeriod = this.Periods.ToObservableChangeSet()
                               .AutoRefreshOnObservable(period => period.Valid)
                               .ToCollection()
                               .Select(periods => periods.Count < MaxPeriodCount && periods.All(period => !period.HasErrors))
                               .CombineLatest(this.PeriodsNonOverlapping, (a, b) => a && b);

            this.AddPeriod = ReactiveCommand.Create(this.OnAddPeriod, canAddPeriod);

            var canSwitchToNextPoster = this.WhenAnyValue(vm => vm.CurrentPosterIndex)
                                        .Merge(this.Save.Select(_ => this.CurrentPosterIndex))
                                        .Select(index =>
                                                index != this.Season.Periods.Count - 1 &&
                                                this.Season.Periods.Skip(index + 1).Any(period => period.PosterUrl != null));

            var canSwitchToPreviousPoster = this.WhenAnyValue(vm => vm.CurrentPosterIndex)
                                            .Merge(this.Save.Select(_ => this.CurrentPosterIndex))
                                            .Select(index =>
                                                    index != 0 &&
                                                    this.Season.Periods.Take(index).Any(period => period.PosterUrl != null));

            this.SwitchToNextPoster = ReactiveCommand.Create(
                () => this.SetCurrentPosterIndex(index => index + 1), canSwitchToNextPoster);

            this.SwitchToPreviousPoster = ReactiveCommand.Create(
                () => this.SetCurrentPosterIndex(index => index - 1), canSwitchToPreviousPoster);

            this.Save.Discard()
            .Merge(this.GoToSeries.Discard())
            .Delay(TimeSpan.FromMilliseconds(500), this.Scheduler)
            .Subscribe(() => this.CurrentPosterIndex = 0);

            this.CanAlwaysDelete();
            this.EnableChangeTracking();
        }
        public FileTailerViewModel(ILogger logger, ISchedulerProvider schedulerProvider, FileInfo fileInfo)
        {
            if (logger == null)
            {
                throw new ArgumentNullException(nameof(logger));
            }
            if (schedulerProvider == null)
            {
                throw new ArgumentNullException(nameof(schedulerProvider));
            }
            if (fileInfo == null)
            {
                throw new ArgumentNullException(nameof(fileInfo));
            }

            File     = fileInfo.FullName;
            AutoTail = true;

            var filterRequest = this.WhenValueChanged(vm => vm.SearchText).Throttle(TimeSpan.FromMilliseconds(125));
            var autoTail      = this.WhenValueChanged(vm => vm.AutoTail)
                                .CombineLatest(_userScrollRequested, (auto, user) =>
                                               auto
                        ? new ScrollRequest(user.Rows)
                        : new ScrollRequest(user.Rows, user.FirstIndex + 1))
                                .DistinctUntilChanged();

            var tailer = new FileTailer(fileInfo, filterRequest, autoTail);

            var lineCounter = tailer
                              .TotalLinesCount
                              .CombineLatest(tailer.MatchedLinesCount, (total, matched) =>
                                             total == matched
                        ? $"File has {total:#,###} lines"
                        : $"Showing {matched:#,###} of {total:#,###} lines")
                              .Subscribe(text => LineCountText = text);

            // load lines into observable collection
            var loader = tailer.Lines.Connect()
                         .Buffer(TimeSpan.FromMilliseconds(125)).FlattenBufferResult()
                         .Transform(line => new LineProxy(line))
                         .Sort(SortExpressionComparer <LineProxy> .Ascending(proxy => proxy.Number))
                         .ObserveOn(schedulerProvider.MainThread)
                         .Bind(out _data)
                         .Do(_ => AutoScroller.ScrollToEnd())
                         .Subscribe(a => logger.Info(a.Adds.ToString()), ex => logger.Error(ex, "Opps"));

            // monitor matching lines and start index
            // update local values so the virtual scroll panel can bind to them
            var matchedLinesMonitor = tailer.MatchedLinesCount
                                      .Subscribe(matched => MatchedLinesCount = matched);

            var firstIndexMonitor = tailer.Lines.Connect()
                                    .QueryWhenChanged(lines =>
            {
                // use zero based index rather than line number
                return(lines.Count == 0 ? 0 : lines.Select(l => l.Number).Min() - 1);
            }).Subscribe(first => FirstRow = first - 1);

            _cleanup = new CompositeDisposable(
                tailer,
                lineCounter,
                loader,
                matchedLinesMonitor,
                firstIndexMonitor,
                Disposable.Create(() => _userScrollRequested.OnCompleted()));
        }
Example #15
0
        public ViewModel()
        {
            this.WhenAnyValue(x => x.Foo.Bar.Baz)
            .Subscribe(x => Console.WriteLine("Hallo " + x?.ToString()));

            Console.WriteLine("Example 1");
            this.Foo.Bar.Baz = null;
            Console.WriteLine("Example 2a");
            this.Foo.Bar = new BarClass();
            Console.WriteLine("Example 2b");
            this.Foo.Bar = new BarClass();
            Console.WriteLine("Example 3");
            this.Foo.Bar = new BarClass()
            {
                Baz = "Something"
            };

            Console.WriteLine("Example 4");
            this.Foo = new FooClass();


            SourceList <String> sl = new SourceList <String>();

            sl.Add("One");
            sl.Add("Two");
            sl.Add("Two");
            sl.Add("Three");


            sl.Connect()
            .Transform(x => x)
            .Sort(SortExpressionComparer <String> .Ascending(t => t))
            .DistinctValues(x => x)
            .Bind(out ReadOnlyObservableCollection <String> sorted)
            .Subscribe();

            Console.WriteLine("=== Raw List ===");
            PrintList <String>(sl.Items);

            Console.WriteLine("=== Sorted ===");
            PrintList <String>(sorted);

            Console.WriteLine("===  ===");



            FooClass fo1 = new FooClass()
            {
                Bar = new BarClass("Hello ")
            };
            FooClass fo2 = new FooClass()
            {
                Bar = new BarClass("World ")
            };
            FooClass fo3 = new FooClass()
            {
                Bar = new BarClass("Out ")
            };
            FooClass fo4 = new FooClass()
            {
                Bar = new BarClass("There ")
            };
            FooClass fo5 = new FooClass()
            {
                Bar = new BarClass("!!!!!!")
            };

            sl2.Add(fo1);
            sl2.Add(fo2);
            sl2.Add(fo3);
            sl2.Add(fo4);


            sl2.Connect()
            .AutoRefresh(x => x.Bar.Baz)
            .Transform(x => x.Bar.Baz, true)
            //       .Sort(SortExpressionComparer<String>.Ascending(t => t))
            //       .DistinctValues(x => x)
            .Bind(out ReadOnlyObservableCollection <String> transformed)
            .Subscribe(x => { Console.WriteLine("CHANGE from Subscribe"); });

            Console.WriteLine("=== Start ===");

            ((INotifyCollectionChanged)transformed).CollectionChanged +=
                new NotifyCollectionChangedEventHandler((s, e) => Console.WriteLine("CHANGE from Event Handler"));


            Console.WriteLine("sl2: ");
            PrintList <FooClass>(sl2.Items);

            Console.WriteLine("transformed: ");
            PrintList <String>(transformed);


            Console.WriteLine("=== Send to Space ===");
            fo2.Bar.Baz = "Space";

            Console.WriteLine("sl2: ");
            PrintList <FooClass>(sl2.Items);

            Console.WriteLine("transformed: ");
            PrintList <String>(transformed);

            Console.WriteLine("=== Add !!!! ===");

            sl2.Add(fo5);

            Console.WriteLine("sl2: ");
            PrintList <FooClass>(sl2.Items);

            Console.WriteLine("transformed: ");
            PrintList <String>(transformed);

            Console.WriteLine("===  ===");

            Console.WriteLine("Finish");
            Console.ReadLine();
        }
Example #16
0
        public InstallerVM(MainWindowVM mainWindowVM)
        {
            if (Path.GetDirectoryName(Assembly.GetEntryAssembly().Location.ToLower()) == KnownFolders.Downloads.Path.ToLower())
            {
                MessageBox.Show(
                    "Wabbajack is running inside your Downloads folder. This folder is often highly monitored by antivirus software and these can often " +
                    "conflict with the operations Wabbajack needs to perform. Please move this executable outside of your Downloads folder and then restart the app.",
                    "Cannot run inside Downloads",
                    MessageBoxButton.OK,
                    MessageBoxImage.Error);
                Environment.Exit(1);
            }

            MWVM = mainWindowVM;

            ModListLocation = new FilePickerVM()
            {
                ExistCheckOption = FilePickerVM.CheckOptions.On,
                PathType         = FilePickerVM.PathTypeOptions.File,
                PromptTitle      = "Select a modlist to install"
            };

            // Swap to proper sub VM based on selected type
            _installer = this.WhenAny(x => x.TargetManager)
                         // Delay so the initial VM swap comes in immediately, subVM comes right after
                         .DelayInitial(TimeSpan.FromMilliseconds(50), RxApp.MainThreadScheduler)
                         .Select <ModManager?, ISubInstallerVM>(type =>
            {
                switch (type)
                {
                case ModManager.MO2:
                    return(new MO2InstallerVM(this));

                case ModManager.Vortex:
                    return(new VortexInstallerVM(this));

                default:
                    return(null);
                }
            })
                         // Unload old VM
                         .Pairwise()
                         .Do(pair =>
            {
                pair.Previous?.Unload();
            })
                         .Select(p => p.Current)
                         .ToProperty(this, nameof(Installer));

            // Load settings
            MWVM.Settings.SaveSignal
            .Subscribe(_ =>
            {
                MWVM.Settings.Installer.LastInstalledListLocation = ModListLocation.TargetPath;
            })
            .DisposeWith(CompositeDisposable);

            _modList = this.WhenAny(x => x.ModListLocation.TargetPath)
                       .ObserveOn(RxApp.TaskpoolScheduler)
                       .Select(modListPath =>
            {
                if (modListPath == null)
                {
                    return(default(ModListVM));
                }
                if (!File.Exists(modListPath))
                {
                    return(default(ModListVM));
                }
                return(new ModListVM(modListPath));
            })
                       .ObserveOnGuiThread()
                       .StartWith(default(ModListVM))
                       .ToProperty(this, nameof(ModList));
            _htmlReport = this.WhenAny(x => x.ModList)
                          .Select(modList => modList?.ReportHTML)
                          .ToProperty(this, nameof(HTMLReport));
            _installing = this.WhenAny(x => x.Installer.ActiveInstallation)
                          .Select(i => i != null)
                          .ObserveOnGuiThread()
                          .ToProperty(this, nameof(Installing));
            _TargetManager = this.WhenAny(x => x.ModList)
                             .Select(modList => modList?.ModManager)
                             .ToProperty(this, nameof(TargetManager));

            // Add additional error check on modlist
            ModListLocation.AdditionalError = this.WhenAny(x => x.ModList)
                                              .Select <ModListVM, IErrorResponse>(modList =>
            {
                if (modList == null)
                {
                    return(ErrorResponse.Fail("Modlist path resulted in a null object."));
                }
                if (modList.Error != null)
                {
                    return(ErrorResponse.Fail("Modlist is corrupt", modList.Error));
                }
                return(ErrorResponse.Success);
            });

            BackCommand = ReactiveCommand.Create(
                execute: () =>
            {
                StartedInstallation     = false;
                Completed               = null;
                mainWindowVM.ActivePane = mainWindowVM.ModeSelectionVM;
            },
                canExecute: this.WhenAny(x => x.Installing)
                .Select(x => !x));

            _percentCompleted = this.WhenAny(x => x.Installer.ActiveInstallation)
                                .StartWith(default(AInstaller))
                                .CombineLatest(
                this.WhenAny(x => x.Completed),
                (installer, completed) =>
            {
                if (installer == null)
                {
                    return(Observable.Return <float>(completed != null ? 1f : 0f));
                }
                return(installer.PercentCompleted.StartWith(0f));
            })
                                .Switch()
                                .Debounce(TimeSpan.FromMilliseconds(25))
                                .ToProperty(this, nameof(PercentCompleted));

            Slideshow = new SlideShow(this);

            // Set display items to modlist if configuring or complete,
            // or to the current slideshow data if installing
            _image = Observable.CombineLatest(
                this.WhenAny(x => x.ModList.Error),
                this.WhenAny(x => x.ModList)
                .Select(x => x?.ImageObservable ?? Observable.Empty <BitmapImage>())
                .Switch()
                .StartWith(WabbajackLogo),
                this.WhenAny(x => x.Slideshow.Image)
                .StartWith(default(BitmapImage)),
                this.WhenAny(x => x.Installing),
                resultSelector: (err, modList, slideshow, installing) =>
            {
                if (err != null)
                {
                    return(WabbajackErrLogo);
                }
                var ret = installing ? slideshow : modList;
                return(ret ?? WabbajackLogo);
            })
                     .Select <BitmapImage, ImageSource>(x => x)
                     .ToProperty(this, nameof(Image));
            _titleText = Observable.CombineLatest(
                this.WhenAny(x => x.ModList.Name),
                this.WhenAny(x => x.Slideshow.TargetMod.ModName)
                .StartWith(default(string)),
                this.WhenAny(x => x.Installing),
                resultSelector: (modList, mod, installing) => installing ? mod : modList)
                         .ToProperty(this, nameof(TitleText));
            _authorText = Observable.CombineLatest(
                this.WhenAny(x => x.ModList.Author),
                this.WhenAny(x => x.Slideshow.TargetMod.ModAuthor)
                .StartWith(default(string)),
                this.WhenAny(x => x.Installing),
                resultSelector: (modList, mod, installing) => installing ? mod : modList)
                          .ToProperty(this, nameof(AuthorText));
            _description = Observable.CombineLatest(
                this.WhenAny(x => x.ModList.Description),
                this.WhenAny(x => x.Slideshow.TargetMod.ModDescription)
                .StartWith(default(string)),
                this.WhenAny(x => x.Installing),
                resultSelector: (modList, mod, installing) => installing ? mod : modList)
                           .ToProperty(this, nameof(Description));
            _modListName = Observable.CombineLatest(
                this.WhenAny(x => x.ModList.Error)
                .Select(x => x != null),
                this.WhenAny(x => x.ModList)
                .Select(x => x?.Name),
                resultSelector: (err, name) =>
            {
                if (err)
                {
                    return("Corrupted Modlist");
                }
                return(name);
            })
                           .ToProperty(this, nameof(ModListName));

            // Define commands
            ShowReportCommand = ReactiveCommand.Create(ShowReport);
            OpenReadmeCommand = ReactiveCommand.Create(
                execute: () => this.ModList?.OpenReadmeWindow(),
                canExecute: this.WhenAny(x => x.ModList)
                .Select(modList => !string.IsNullOrEmpty(modList?.Readme))
                .ObserveOnGuiThread());
            VisitWebsiteCommand = ReactiveCommand.Create(
                execute: () => Process.Start(ModList.Website),
                canExecute: this.WhenAny(x => x.ModList.Website)
                .Select(x => x?.StartsWith("https://") ?? false)
                .ObserveOnGuiThread());

            _progressTitle = Observable.CombineLatest(
                this.WhenAny(x => x.Installing),
                this.WhenAny(x => x.StartedInstallation),
                resultSelector: (installing, started) =>
            {
                if (!installing)
                {
                    return("Configuring");
                }
                return(started ? "Installing" : "Installed");
            })
                             .ToProperty(this, nameof(ProgressTitle));

            Dictionary <int, CPUDisplayVM> cpuDisplays = new Dictionary <int, CPUDisplayVM>();

            // Compile progress updates and populate ObservableCollection
            this.WhenAny(x => x.Installer.ActiveInstallation)
            .SelectMany(c => c?.QueueStatus ?? Observable.Empty <CPUStatus>())
            .ObserveOn(RxApp.TaskpoolScheduler)
            // Attach start times to incoming CPU items
            .Scan(
                new CPUDisplayVM(),
                (_, cpu) =>
            {
                var ret = cpuDisplays.TryCreate(cpu.ID);
                ret.AbsorbStatus(cpu);
                return(ret);
            })
            .ToObservableChangeSet(x => x.Status.ID)
            .Batch(TimeSpan.FromMilliseconds(250), RxApp.TaskpoolScheduler)
            .EnsureUniqueChanges()
            .Filter(i => i.Status.IsWorking && i.Status.ID != WorkQueue.UnassignedCpuId)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Sort(SortExpressionComparer <CPUDisplayVM> .Ascending(s => s.StartTime))
            .Bind(StatusList)
            .Subscribe()
            .DisposeWith(CompositeDisposable);

            BeginCommand = ReactiveCommand.CreateFromTask(
                canExecute: this.WhenAny(x => x.Installer.CanInstall)
                .Switch(),
                execute: async() =>
            {
                try
                {
                    await this.Installer.Install();
                    Completed = ErrorResponse.Success;
                    try
                    {
                        this.ModList?.OpenReadmeWindow();
                    }
                    catch (Exception ex)
                    {
                        Utils.Error(ex);
                    }
                }
                catch (Exception ex)
                {
                    while (ex.InnerException != null)
                    {
                        ex = ex.InnerException;
                    }
                    Utils.Log(ex.StackTrace);
                    Utils.Log(ex.ToString());
                    Utils.Log($"{ex.Message} - Can't continue");
                    Completed = ErrorResponse.Fail(ex);
                }
            });

            // When sub installer begins an install, mark state variable
            BeginCommand.StartingExecution()
            .Subscribe(_ =>
            {
                StartedInstallation = true;
            })
            .DisposeWith(CompositeDisposable);

            // Listen for user interventions, and compile a dynamic list of all unhandled ones
            var activeInterventions = this.WhenAny(x => x.Installer.ActiveInstallation)
                                      .SelectMany(c => c?.LogMessages ?? Observable.Empty <IStatusMessage>())
                                      .WhereCastable <IStatusMessage, IUserIntervention>()
                                      .ToObservableChangeSet()
                                      .AutoRefresh(i => i.Handled)
                                      .Filter(i => !i.Handled)
                                      .AsObservableList();

            // Find the top intervention /w no CPU ID to be marked as "global"
            _ActiveGlobalUserIntervention = activeInterventions.Connect()
                                            .Filter(x => x.CpuID == WorkQueue.UnassignedCpuId)
                                            .QueryWhenChanged(query => query.FirstOrDefault())
                                            .ObserveOnGuiThread()
                                            .ToProperty(this, nameof(ActiveGlobalUserIntervention));

            CloseWhenCompleteCommand = ReactiveCommand.Create(
                canExecute: this.WhenAny(x => x.Completed)
                .Select(x => x != null),
                execute: () =>
            {
                MWVM.ShutdownApplication();
            });

            GoToInstallCommand = ReactiveCommand.Create(
                canExecute: Observable.CombineLatest(
                    this.WhenAny(x => x.Completed)
                    .Select(x => x != null),
                    this.WhenAny(x => x.Installer.SupportsAfterInstallNavigation),
                    resultSelector: (complete, supports) => complete && supports),
                execute: () =>
            {
                Installer.AfterInstallNavigation();
            });
        }
Example #17
0
        public static void Main(string[] args)
        {
            var FemaleSex = new Sex("Female", 0);
            var MaleSex   = new Sex("Male", 0);

            var myList = new SourceList <Person>();

            myList.Edit(people =>
            {
                people.Add(new Person("Alex", 32, "Male"));
                people.Add(new Person("Sveta", 24, "Female"));
                people.Add(new Person("Yura", 63, "Male"));
            });

            myList.Add(new Person("Luda", 56, "Female"));

            var people = myList
                         .Connect()
//				.Filter(person => person.Age < 50)
                         .Sort(SortExpressionComparer <Person> .Ascending(person => person.Age))
                         //.GroupOn(person => person.Sex)
                         .Subscribe(changeSet =>
            {
                foreach (var change in changeSet)
                {
                    if (change.Type == ChangeType.Range)
                    {
                        foreach (var itemChange in change.Range)
                        {
                            if (change.Reason == ListChangeReason.AddRange)
                            {
                                if (itemChange.Sex == "Female")
                                {
                                    FemaleSex.PeopleCount++;
                                }
                                else
                                {
                                    MaleSex.PeopleCount++;
                                }
                            }
                        }
                    }
                    else
                    {
                        if (change.Reason == ListChangeReason.Add)
                        {
                            if (change.Item.Current.Sex == "Female")
                            {
                                FemaleSex.PeopleCount++;
                            }
                            else
                            {
                                MaleSex.PeopleCount++;
                            }
                        }
                        else if (change.Reason == ListChangeReason.Remove)
                        {
                            if (change.Item.Current.Sex == "Female")
                            {
                                FemaleSex.PeopleCount--;
                            }
                            else
                            {
                                MaleSex.PeopleCount--;
                            }
                        }
                    }
                }
            });


            // Updates
            myList.Add(new Person("Valera", 35, "Male"));
            myList.Add(new Person("Snejka", 5, "Female"));
            myList.Add(new Person("Diana", 23, "Female"));
            myList.Add(new Person("Tanya", 21, "Female"));
            myList.Remove(myList.Items.Where(person => person.Name == "Snejka").FirstOrDefault());


            Console.WriteLine($"{FemaleSex.Description} = {FemaleSex.PeopleCount}");
            Console.WriteLine($"{MaleSex.Description} = {MaleSex.PeopleCount}");



//			foreach(var personGroup in people.Items)
//			{
//				Console.WriteLine($"{personGroup.GroupKey}:");
//				foreach(var person in personGroup.List.Items)
//					Console.WriteLine($"\t{person.Name} - {person.Age}");
//			}
        }
Example #18
0
        IObservable <Unit> SetupFilteringAnimals()
        {
            ReadOnlyObservableCollection <Animal> filteredAnimals;
            SourceList <Animal> animalList = Animal.CreateMeSomeAnimalsPlease();

            IObservable <Func <Animal, bool> > dynamicFilter =
                // ReactiveUI connecting to the DepedencyProperty
                this.WhenAnyValue(x => x.tbFilterText.Text)
                // Debounce
                .Throttle(TimeSpan.FromMilliseconds(250))
                .Select(CreatePredicate);

            IObservable <IComparer <Animal> > dynamicSort =
                this.WhenAnyValue(x => x.cbSortByName.IsChecked)
                .Select(x => x ?? false)
                .Select(isChecked => isChecked ?
                        SortExpressionComparer <Animal> .Ascending(i => i.Name)
                        : SortExpressionComparer <Animal> .Ascending(i => animalList.Items.IndexOf(i))
                        );

            var returnValue =
                animalList
                .Connect()
                .Filter(dynamicFilter)    // accepts any observable
                .Sort(dynamicSort)
                .ObserveOnDispatcher()
                // side effect
                .Bind(out filteredAnimals)
                .Publish();

            returnValue.Connect();


            // Create filtered source to watch for changes on
            var filteredAnimalsChanged =
                filteredAnimals
                .ToObservableChangeSet()
                .Publish()
                .RefCount();


            var calculateAverage =
                // Watch for property Changed events
                filteredAnimalsChanged
                .WhenPropertyChanged(x => x.AnimalRating).ToUnit()

                // watch for list changed
                .Merge(filteredAnimalsChanged.ToUnit())
                .Do(_ => UpdateAverage())
                .ToUnit();


            lvFilteredAnimals.ItemsSource = filteredAnimals;
            return(returnValue.ToUnit().Merge(calculateAverage));



            Func <Animal, bool> CreatePredicate(string text)
            {
                if (text == null || text.Length < 3)
                {
                    return(animal => true);
                }

                text = text.ToLower();
                return(animal => animal.Name.ToLower().Contains(text) ||
                       animal.Type.ToLower().Contains(text) ||
                       animal.Family.ToString().ToLower().Contains(text));
            }

            void UpdateAverage()
            {
                // There is a better way
                var filterBy = filteredAnimals.Where(x => x.AnimalRating > 0).ToArray();

                if (!filterBy.Any())
                {
                    tbAverageRating.Text = "Unknown";
                    return;
                }

                tbAverageRating.Text =
                    filterBy.Average(x => x.AnimalRating)
                    .ToString();
            }
        }
Example #19
0
 private IComparer <EntryModel> GetSorting(Func <EntryModel, IComparable> f)
 {
     return(SortExpressionComparer <EntryModel> .Ascending(f));
 }
Example #20
0
        /// <summary>
        /// Creates a new <see cref="ElementsViewModel"/>.
        /// </summary>
        public ElementsViewModel()
        {
            this.NewElement = ReactiveCommand.CreateFromTask(this.CreateElementAsync);

            this.CreateAttackingMatchup = ReactiveCommand.CreateFromTask(this.CreateAttackingMatchupAsync);

            this.CreateDefendingMatchup = ReactiveCommand.CreateFromTask(this.CreateDefendingMatchupAsync);

            App.Metadata.WhenAnyValue(x => x.CurrentProject)
            .Subscribe(x =>
            {
                if (x is null)
                {
                    return;
                }
                SaveableObject.SaveableObjects.Connect()
                .WhenPropertyChanged(p => p.IsSaved)
                .Select(p =>
                {
                    return(SaveableObject.SaveableObjects.Items.All(y =>
                    {
                        return !(y is Element || y is ElementMatchup) || y.IsSaved;
                    }));
                })
                .ToPropertyEx(this, x => x.AreElementsSaved);
            });

            this.WhenAnyValue(x => x.AreElementsSaved)
            .Select(x =>
            {
                return($"Elements{(x ? string.Empty : "*")}");
            })
            .ToPropertyEx(this, x => x.Header);

            App.Metadata.WhenAnyValue(x => x.CurrentProject)
            .Subscribe(x =>
            {
                if (x is null)
                {
                    return;
                }

                // Connect to Elements
                IObservable <ISortedChangeSet <Element, int> >?elements = App.Metadata.CurrentProject?.Elements.Connect()
                                                                          .Sort(SortExpressionComparer <Element> .Ascending(x => x.Name));

                // Elements Binding
                elements.ObserveOn(RxApp.MainThreadScheduler).Bind(out this.elements).Subscribe();

                // Connect to Element Matchups
                IObservable <ISortedChangeSet <ElementMatchup, int> >?elementMatchups =
                    App.Metadata.CurrentProject?.ElementMatchups.Connect()
                    .AutoRefresh(x => x.Multiplier)
                    .AutoRefreshOnObservable(x => this.WhenAnyValue(x => x.SelectedElement))
                    .Sort(SortExpressionComparer <ElementMatchup> .Ascending(x => x.DefendingElement.Name));

                // Element Matchups Binding
                elementMatchups.ObserveOn(RxApp.MainThreadScheduler)
                .Bind(out this.elementMatchups)
                .Subscribe();

                // Attacking Matchups Binding
                elementMatchups.Filter(x =>
                {
                    return(x.AttackingElement == this.SelectedElement);
                })
                .ObserveOn(RxApp.MainThreadScheduler)
                .Bind(out this.attackingMatchups)
                .Subscribe();

                // Defending Matchups Binding
                elementMatchups.Filter(x =>
                {
                    return(x.DefendingElement == this.SelectedElement);
                })
                .ObserveOn(RxApp.MainThreadScheduler)
                .Bind(out this.defendingMatchups)
                .Subscribe();

                // Offensive Rating Binding
                elementMatchups.Select(x => this.GetOffensiveRating())
                .BindTo(this, x => x.OffensiveRating);

                elements.Select(x => this.GetOffensiveRating())
                .BindTo(this, x => x.OffensiveRating);

                // Defensive Rating Binding
                elementMatchups.Select(x => this.GetDefensiveRating())
                .BindTo(this, x => x.DefensiveRating);

                elements.Select(x => this.GetDefensiveRating())
                .BindTo(this, x => x.DefensiveRating);
            });
        }
        private ShellViewModel()
        {
            FilePath = new BehaviorSubject <string>(@"Test.mrpd");
            this.WhenActivated(d =>
            {
                TestCommand = ReactiveCommand.Create(() =>
                {
                    TestName = "Test";
                });

                (LoadFileCommand = ReactiveCommand.Create(LoadFile)).DisposeWith(d);
                (UpCommand = ReactiveCommand.Create(Up, this.WhenAnyValue(s => s.SelectedNodeIndex).Select(i => i > 0))).DisposeWith(d);
                (CreateNodeCommand = ReactiveCommand.Create(CreateNode)).DisposeWith(d);
                (_deleteNodeCommand = ReactiveCommand.Create <string>(DeleteNode)).DisposeWith(d);
                (_enterNodeCommand = ReactiveCommand.Create <string>(EnterNode)).DisposeWith(d);
                (_startRenameNodeCommand = ReactiveCommand.Create <string>(StartRenameNode)).DisposeWith(d);
                (_endRenameNodeCommand = ReactiveCommand.Create <(string, string)>(EndRenameNode)).DisposeWith(d);
                (_deleteDataCommand = ReactiveCommand.Create <string>(DeleteData)).DisposeWith(d);
                NodeNameList.Connect().ObserveOnDispatcher(DispatcherPriority.Background).Bind(out _nodeNames).Subscribe().DisposeWith(d);
                NodeItemViewModelCache.Connect().Sort(SortExpressionComparer <ItemViewModelBase> .Ascending(i => i.Name)).Concat(DataItemViewModelCache.Connect().Sort(SortExpressionComparer <ItemViewModelBase> .Ascending(i => i.Name))).Bind(out _itemViewModels).Subscribe().DisposeWith(d);
                this.WhenAnyValue(s => s.SelectedNodeIndex).Skip(1).Subscribe(SelectedNodeIndexChanged).DisposeWith(d);
                FilePath.Subscribe(FilePathChanged).DisposeWith(d);
                FilePath.Select(f => f != null).ToProperty(this, s => s.HasFile, out _hasFile).DisposeWith(d);

                (SaveCommand = ReactiveCommand.Create(async() =>
                {
                    await this.ShowProgressAsync("", "正在保存...");
                })).DisposeWith(d);
            });
        }
Example #22
0
        public MainWindowVM(RunMode mode, string source, MainWindow mainWindow)
        {
            this.Mode       = mode;
            this.MainWindow = mainWindow;
            this._Installer = new Lazy <InstallerVM>(() => new InstallerVM(this));
            this._Compiler  = new Lazy <CompilerVM>(() => new CompilerVM(this, source));

            // Set up logging
            _logSubj
            .ToObservableChangeSet()
            .Buffer(TimeSpan.FromMilliseconds(250))
            .Where(l => l.Count > 0)
            .FlattenBufferResult()
            .Top(5000)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Bind(this.Log)
            .Subscribe()
            .DisposeWith(this.CompositeDisposable);
            Utils.SetLoggerFn(s => _logSubj.OnNext(s));
            Utils.SetStatusFn((msg, progress) => WorkQueue.Report(msg, progress));

            // Wire mode to drive the active pane.
            // Note:  This is currently made into a derivative property driven by mode,
            // but it can be easily changed into a normal property that can be set from anywhere if needed
            this._ActivePane = this.WhenAny(x => x.Mode)
                               .Select <RunMode, ViewModel>(m =>
            {
                switch (m)
                {
                case RunMode.Compile:
                    return(this._Compiler.Value);

                case RunMode.Install:
                    return(this._Installer.Value);

                default:
                    return(default);
                }
            })
                               .ToProperty(this, nameof(this.ActivePane));
            this.WhenAny(x => x.ActivePane)
            .ObserveOn(RxApp.TaskpoolScheduler)
            .WhereCastable <ViewModel, InstallerVM>()
            .Subscribe(vm => vm.ModListPath = source)
            .DisposeWith(this.CompositeDisposable);

            // Initialize work queue
            WorkQueue.Init(
                report_function: (id, msg, progress) => this._statusSubject.OnNext(new CPUStatus()
            {
                ID = id, Msg = msg, Progress = progress
            }),
                report_queue_size: (max, current) => this.SetQueueSize(max, current));

            // Compile progress updates and populate ObservableCollection
            this._statusSubject
            .ObserveOn(RxApp.TaskpoolScheduler)
            .ToObservableChangeSet(x => x.ID)
            .Batch(TimeSpan.FromMilliseconds(250))
            .EnsureUniqueChanges()
            .ObserveOn(RxApp.MainThreadScheduler)
            .Sort(SortExpressionComparer <CPUStatus> .Ascending(s => s.ID), SortOptimisations.ComparesImmutableValuesOnly)
            .Bind(this.StatusList)
            .Subscribe()
            .DisposeWith(this.CompositeDisposable);
        }
Example #23
0
        public Indexer([NotNull] IObservable <FileSegmentCollection> fileSegments,
                       int compression = 10,
                       int tailSize    = 1000000,
                       int sizeOfFileAtWhichThereIsAbsolutelyNoPointInIndexing = 250000000,
                       Encoding encoding    = null,
                       IScheduler scheduler = null)
        {
            if (fileSegments == null)
            {
                throw new ArgumentNullException(nameof(fileSegments));
            }

            //TODO: When File segment has got smaller => roll-over [do something about it]

            scheduler = scheduler ?? Scheduler.Default;

            var shared = fileSegments.Replay(1).RefCount();

            //1. Get information from segment info
            var infoSubscriber = shared.Select(segments => segments.Info)
                                 .Subscribe(info =>
            {
                Info = info;

                if (Encoding == null || info.Name != Info.Name)
                {
                    Encoding = encoding ?? info.GetEncoding();
                }
            });


            //2. create  a resulting index object from the collection of index fragments
            Result = _indicies
                     .Connect()
                     .Sort(SortExpressionComparer <Index> .Ascending(si => si.Start))
                     .ToCollection()
                     .Scan((IndexCollection)null, (previous, notification) => new IndexCollection(notification, previous, Info, Encoding))
                     .Replay(1).RefCount();


            //3. Scan the tail so results can be returned quickly
            var tailScanner = shared.Select(segments => segments.Tail)
                              .DistinctUntilChanged()
                              .Scan((Index)null, (previous, current) =>
            {
                if (previous == null)
                {
                    var initial = Scan(current.Start, -1, 1);
                    return(initial ?? new Index(0, 0, 0, 0, IndexType.Tail));
                }
                var latest = Scan(previous.End, -1, 1);
                return(latest == null ? null : new Index(latest, previous));
            })
                              .Where(tail => tail != null)
                              .Replay(1).RefCount();

            //4. estimate =
            var tailSubscriber = tailScanner.Subscribe(tail =>
            {
                _indicies.Edit(innerList =>
                {
                    var existing = innerList.FirstOrDefault(si => si.Type == IndexType.Tail);
                    if (existing != null)
                    {
                        innerList.Remove(existing);
                    }
                    innerList.Add(tail);
                });
            });

            //Scan the remainer of the file
            var headSubscriber = tailScanner.FirstAsync()
                                 .Subscribe(tail =>
            {
                if (tail.Start == 0)
                {
                    return;
                }

                //Need iterate one at a time through the
                var estimateLines = EstimateNumberOfLines(tail, Info);
                var estimate      = new Index(0, tail.Start, compression, estimateLines, IndexType.Page);
                _indicies.Add(estimate);

                //keep it as an estimate for files over 250 meg [for now]
                if (tail.Start > sizeOfFileAtWhichThereIsAbsolutelyNoPointInIndexing)
                {
                    return;
                }

                //todo: index first and last segment for large sized file

                scheduler.Schedule(() =>
                {
                    var actual = Scan(0, tail.Start, compression);
                    _indicies.Edit(innerList =>
                    {
                        innerList.Remove(estimate);
                        innerList.Add(actual);
                    });
                });
            });

            _cleanUp = new CompositeDisposable(infoSubscriber, _indicies, tailSubscriber, tailSubscriber, headSubscriber);
        }
Example #24
0
        public void RebuildGrid()
        {
            Monik?.ApplicationVerbose("Matrix.RebuildGrid started");

            MainGrid.Children.Clear();

            if (Rows == null || Columns == null ||
                Rows.Count == 0 || Columns.Count == 0)
            {
                Monik?.ApplicationVerbose("Matrix.RebuildGrid skip func");
                return;
            }

            var columns     = Columns.ToList();
            int columnCount = Columns.Count;
            var rows        = Rows.ToList();
            int rowCount    = Rows.Count;

            //////////////////
            // 1. Fill columns
            //////////////////
            MainGrid.ColumnDefinitions.Clear();
            // rows header
            MainGrid.ColumnDefinitions.Add(
                new ColumnDefinition {
                Width = new GridLength(30, GridUnitType.Pixel)
            });

            // columns
            for (int i = 0; i < columnCount; i++)
            {
                var it = columns[i];
                Monik?.ApplicationVerbose($"Matrix.RebuildGrid add column {it.Id}::{it.Name}::{it.Order}");

                var cd = new ColumnDefinition();
                cd.DataContext = it;
                cd.Width       = new GridLength(it.Size / 10.0, GridUnitType.Star);
                MainGrid.ColumnDefinitions.Add(cd);

                PropertyDescriptor pd = DependencyPropertyDescriptor.FromProperty(ColumnDefinition.WidthProperty, typeof(ColumnDefinition));
                pd.AddValueChanged(cd, new EventHandler(ColumnWidthPropertyChanged));

                ContentControl cc = new ContentControl();
                cc.Content         = it;
                cc.MouseMove      += Head_MouseMove;
                cc.ContextMenu     = HeadContextMenu;
                cc.ContentTemplate = (DataTemplate)this.Resources["DefaultHorizontalHeaderTemplate"];
                MainGrid.Children.Add(cc);

                // Update number of Cards in Column
                CardsObservable
                .Filter(x => x.ColumnDeterminant == it.Id)
                .ToCollection()
                .Subscribe(x => it.CurNumberOfCards = x.Count());

                // dont draw excess splitter
                if (i < columnCount - 1)
                {
                    MainGrid.Children.Add(BuildVerticalSpliter(i, rowCount));
                }

                Grid.SetColumn(cc, i + 1);
                Grid.SetRow(cc, 0);
            }

            ///////////////
            // 2. Fill rows
            ///////////////
            MainGrid.RowDefinitions.Clear();
            // columns header
            MainGrid.RowDefinitions.Add(
                new RowDefinition {
                Height = new GridLength(30, GridUnitType.Pixel)
            });

            // rows
            VerticalHeaders.Clear();
            for (int i = 0; i < rowCount; i++)
            {
                var it = rows[i];
                Monik?.ApplicationVerbose($"Matrix.RebuildGrid add row {it.Id}::{it.Name}::{it.Order}");

                var rd = new RowDefinition();
                rd.DataContext = it;
                rd.Height      = new GridLength(it.Size / 10.0, GridUnitType.Star);
                MainGrid.RowDefinitions.Add(rd);

                PropertyDescriptor pd = DependencyPropertyDescriptor.FromProperty(RowDefinition.HeightProperty, typeof(RowDefinition));
                pd.AddValueChanged(rd, new EventHandler(RowWidthPropertyChanged));

                ContentControl cc = new ContentControl();
                VerticalHeaders.Add(cc);
                cc.Content         = it;
                cc.MouseMove      += Head_MouseMove;
                cc.ContextMenu     = HeadContextMenu;
                cc.ContentTemplate = (DataTemplate)this.Resources["DefaulVerticalHeaderTemplate"];
                MainGrid.Children.Add(cc);

                // Update number of Cards in Row
                CardsObservable
                .Filter(x => x.RowDeterminant == it.Id)
                .ToCollection()
                .Subscribe(x => it.CurNumberOfCards = x.Count());

                // dont draw excess splitter
                if (i < rowCount - 1)
                {
                    MainGrid.Children.Add(BuildHorizontalSpliter(i, columnCount));
                }
                Grid.SetColumn(cc, 0);
                Grid.SetRow(cc, i + 1);
                Canvas.SetZIndex(cc, System.Int32.MaxValue);
            }

            ////////////////////////
            // 3. Fill Intersections
            ////////////////////////
            for (int i = 0; i < Columns.Count; i++)
            {
                for (int j = 0; j < Rows.Count; j++)
                {
                    int colDet = columns[i].Id;
                    int rowDet = rows[j].Id;

                    CardsObservable
                    .Filter(x => x.ColumnDeterminant == colDet && x.RowDeterminant == rowDet)
                    .Sort(SortExpressionComparer <ICard> .Ascending(c => c.Order))
                    .ObserveOnDispatcher()
                    .Bind(out ReadOnlyObservableCollection <ICard> intersectionCards)
                    .Subscribe();

                    Intersection cell = new Intersection(this)
                    {
                        DataContext       = this,
                        ColumnDeterminant = colDet,
                        RowDeterminant    = rowDet,
                        SelfCards         = intersectionCards
                    };

                    MainGrid.Children.Add(cell);
                    Grid.SetColumn(cell, i + 1);
                    Grid.SetColumnSpan(cell, 1);
                    Grid.SetRow(cell, j + 1);
                    Grid.SetRowSpan(cell, 1);
                }
            }
            SwimLanePropertyChanged(this, null);
            Monik?.ApplicationVerbose("Matrix.RebuildGrid finished");
        }
        //IEnumerable<MenuItemViewModel> GetMenuItems()
        //{
        //    //yield return new MenuItemViewModel(nameof(AppResources.CommunityFix_EnableScriptService));
        //    yield return new MenuItemViewModel(nameof(AppResources.ScriptStore))
        //    {
        //        IconKey = "JavaScriptDrawing",
        //        Command = ScriptStoreCommand
        //    };
        //    yield return new MenuItemViewModel(nameof(AppResources.Script_AllEnable))
        //    {
        //        IconKey = "JavaScriptDrawing",
        //        Command = AllEnableScriptCommand,
        //    };
        //    yield return new MenuItemViewModel();
        //    if (OnlySteamBrowser != null) yield return OnlySteamBrowser;
        //}

        public ProxyScriptManagePageViewModel()
        {
            IconKey = nameof(ProxyScriptManagePageViewModel);

            if (!IApplication.IsDesktopPlatform)
            {
                return;
            }

            ScriptStoreCommand       = ReactiveCommand.Create(OpenScriptStoreWindow);
            AllEnableScriptCommand   = ReactiveCommand.Create(AllEnableScript);
            AddNewScriptButton_Click = ReactiveCommand.CreateFromTask(async() =>
            {
                FilePicker2.FilePickerFileType?fileTypes;
                if (IApplication.IsDesktopPlatform)
                {
                    fileTypes = new ValueTuple <string, string[]>[] {
                        ("JavaScript Files", new[] { FileEx.JS, }),
                        ("Text Files", new[] { FileEx.TXT, }),
                        //("All Files", new[] { "*", }),
                    };
                }
                else if (OperatingSystem2.IsAndroid)
                {
                    fileTypes = new[] { MediaTypeNames.TXT, MediaTypeNames.JS };
                }
                else
                {
                    fileTypes = null;
                }
                await FilePicker2.PickAsync(ProxyService.Current.AddNewScript, fileTypes);
            });

            //EnableScriptAutoUpdateCommand = ReactiveCommand.Create(() =>
            //{
            //    ScriptAutoUpdate?.CheckmarkChange(ProxySettings.IsAutoCheckScriptUpdate.Value = !ProxySettings.IsAutoCheckScriptUpdate.Value);
            //});
            //OnlySteamBrowserCommand = ReactiveCommand.Create(() =>
            //{
            //    OnlySteamBrowser?.CheckmarkChange(ProxySettings.IsOnlyWorkSteamBrowser.Value = !ProxySettings.IsOnlyWorkSteamBrowser.Value);
            //});

            //ScriptAutoUpdate = new MenuItemViewModel(nameof(AppResources.Script_AutoUpdate))
            //{
            //    Command = EnableScriptAutoUpdateCommand,
            //};
            //OnlySteamBrowser = new(nameof(AppResources.CommunityFix_OnlySteamBrowser))
            //{
            //    Command = OnlySteamBrowserCommand,
            //};
            //MenuItems = new ObservableCollection<MenuItemViewModel>(GetMenuItems());

            //ScriptAutoUpdate?.CheckmarkChange(ProxySettings.IsAutoCheckScriptUpdate.Value);
            //OnlySteamBrowser?.CheckmarkChange(ProxySettings.IsOnlyWorkSteamBrowser.Value);

            var scriptFilter = this.WhenAnyValue(x => x.SearchText).Select(ScriptFilter);

            ProxyService.Current.ProxyScripts
            .Connect()
            .Filter(scriptFilter)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Sort(SortExpressionComparer <ScriptDTO> .Ascending(x => x.Order).ThenBy(x => x.Name))
            .Bind(out _ProxyScripts)
            .Subscribe(_ => this.RaisePropertyChanged(nameof(IsProxyScriptsEmpty)));
        }
Example #26
0
        public void DoesNotThrow2()
        {
            var cache      = new SourceCache <Data, int>(d => d.Id);
            var disposable = cache.Connect().Sort(new BehaviorSubject <IComparer <Data> >(SortExpressionComparer <Data> .Ascending(d => d.Id))).Subscribe();

            disposable.Dispose();
        }
        protected override void Initialize()
        {
            base.Initialize();

            ForceCreateUserRolesFilterCommand = ReactiveCommand
                                                .Create <string>(x => ForceCreateUserRolesFilter = x)
                                                .DisposeWith(Disposables);

            LockUsersCommand = ReactiveCommand
                               .CreateFromTask <IList>(LockUsers,
                                                       this.WhenAny(
                                                           x => x.SelectedItemsIds,
                                                           x => x.Value != null && x.Value.Count > 0))
                               .DisposeWith(Disposables);

            RolesFilterCommand = ReactiveCommand
                                 .Create <string>(filter => RolesFilter = filter)
                                 .DisposeWith(Disposables);
            RoleCheckedCommand = ReactiveCommand
                                 .Create <SelectedUserRoleViewModel>(RoleChecked)
                                 .DisposeWith(Disposables);

            var rolesChangedObservable = this.WhenAnyValue(x => x.IsChangedRoles);

            ApplyRolesCommand = ReactiveCommand
                                .CreateFromTask(ApplyRoles, rolesChangedObservable)
                                .DisposeWith(Disposables);
            ResetRolesCommand = ReactiveCommand
                                .CreateFromTask(ResetRoles, rolesChangedObservable)
                                .DisposeWith(Disposables);

            ForceChangePasswordCommand = ReactiveCommand
                                         .CreateFromTask(ForceResetPassword, this.WhenHaveOnlyOneSelectedItem())
                                         .DisposeWith(Disposables);
            ForceChangePhoneCommand = ReactiveCommand
                                      .CreateFromTask(ForceChangePhone)
                                      .DisposeWith(Disposables);
            ForceChangeEmailCommand = ReactiveCommand
                                      .CreateFromTask(ForceChangeEmail)
                                      .DisposeWith(Disposables);

            // Permissions

            SubscribeToPermissions(
                _domain0.Model.UserPermissions,
                (permissionId, items) => items
                .Where(x => !x.RoleId.HasValue && x.Id.Value == permissionId)
                .Select(x => x.UserId))
            .DisposeWith(Disposables);

            // Roles

            var dynamicForceCreateUserRolesFilter = this
                                                    .WhenAnyValue(x => x.ForceCreateUserRolesFilter)
                                                    .Select(Filters.CreateRolesPredicate);

            _domain0.Model.Roles.Connect()
            .Filter(dynamicForceCreateUserRolesFilter)
            .Transform(x => new ForceCreateUserRoleViewModel {
                Role = x
            })
            .Sort(SortExpressionComparer <ForceCreateUserRoleViewModel> .Ascending(x => x.Role.Id))
            .ObserveOnDispatcher()
            .Bind(out _forceCreateUserRoles)
            .Subscribe()
            .DisposeWith(Disposables);

            var dynamicRolesFilter = this
                                     .WhenAnyValue(x => x.RolesFilter)
                                     .Select(Filters.CreateRolesPredicate);

            var sourceUserRoles = _domain0.Model.UserRoles
                                  .Connect()
                                  .ToCollection();
            var sourceRoles = _domain0.Model.Roles
                              .Connect()
                              .Filter(dynamicRolesFilter)
                              .ToCollection();
            var sourceSelected = this
                                 .WhenAnyValue(x => x.SelectedItemsIds);

            Observable.CombineLatest(
                sourceUserRoles,
                sourceRoles,
                sourceSelected,
                (userRoles, roles, selectedIds) => selectedIds.Count > 0
                        ? new { userRoles, roles, selectedIds }
                        : null)
            .Throttle(TimeSpan.FromSeconds(.1))
            .Synchronize()
            .Select(o => o?.roles
                    .Select(r =>
            {
                var roleId  = r.Id.Value;
                var userIds = o.userRoles
                              .Where(x => x.Id.Value == roleId)
                              .Select(x => x.UserId)
                              .Distinct();
                var groupSelectedIds = o.selectedIds
                                       .Intersect(userIds)
                                       .ToList();
                var count = groupSelectedIds.Count;
                var total = o.selectedIds.Count;
                return(new SelectedUserRoleViewModel(count, total)
                {
                    Item = r,
                    ParentIds = groupSelectedIds
                });
            })
                    .OrderByDescending(x => x.Count)
                    .ThenBy(x => x.Item.Name)
                    .ThenBy(x => x.Id)
                    .ToList())
            .ObserveOn(RxApp.MainThreadScheduler)
            .Subscribe(x =>
            {
                SelectedUserRoles = x;
                IsChangedRoles    = false;
            })
            .DisposeWith(Disposables);

            // Environments

            _domain0.Model.Environments.Connect()
            .Sort(SortExpressionComparer <Environment> .Ascending(x => x.Id))
            .ObserveOnDispatcher()
            .Bind(out _environments)
            .Subscribe()
            .DisposeWith(Disposables);

            // Locales

            var dynamicLocaleFilter = this
                                      .WhenAnyValue(x => x.Environment)
                                      .Select(Filters.CreateEnvironmentPredicate);

            _domain0.Model.MessageTemplates.Connect()
            .Filter(dynamicLocaleFilter)
            .Group(x => x.Locale)
            .Transform(x => x.Key)
            .Sort(SortExpressionComparer <string> .Ascending(x => x))
            .ObserveOnDispatcher()
            .Bind(out _locales)
            .Subscribe()
            .DisposeWith(Disposables);
        }
Example #28
0
        public InlineViewer([NotNull] InlineViewerArgs args,
                            [NotNull] IClipboardHandler clipboardHandler,
                            [NotNull] ISchedulerProvider schedulerProvider,
                            [NotNull] ISelectionMonitor selectionMonitor)
        {
            if (args == null)
            {
                throw new ArgumentNullException(nameof(args));
            }
            if (clipboardHandler == null)
            {
                throw new ArgumentNullException(nameof(clipboardHandler));
            }
            if (schedulerProvider == null)
            {
                throw new ArgumentNullException(nameof(schedulerProvider));
            }
            if (selectionMonitor == null)
            {
                throw new ArgumentNullException(nameof(selectionMonitor));
            }
            SelectionMonitor       = selectionMonitor;
            CopyToClipboardCommand = new Command(() => clipboardHandler.WriteToClipboard(selectionMonitor.GetSelectedText()));

            _isSettingScrollPosition = false;

            var lineProvider    = args.LineProvider;
            var selectedChanged = args.SelectedChanged;
            var pageSize        = this.WhenValueChanged(vm => vm.PageSize);
            var scrollSelected  = selectedChanged.Where(proxy => proxy != null)
                                  .CombineLatest(lineProvider, pageSize, (proxy, lp, pge) => new ScrollRequest(pge, proxy.Start));

            var scrollUser = _userScrollRequested
                             .Where(x => !_isSettingScrollPosition)
                             .Select(request => new ScrollRequest(ScrollReason.User, request.PageSize, request.FirstIndex));

            var scroller = scrollSelected.Merge(scrollUser)
                           .ObserveOn(schedulerProvider.Background)
                           .DistinctUntilChanged();

            var lineScroller = new LineScroller(lineProvider, scroller);

            Count = lineProvider.Select(lp => lp.Count).ForBinding();

            //load lines into observable collection
            var loader = lineScroller.Lines.Connect()
                         .Transform(args.LineProxyFactory.Create)
                         .Sort(SortExpressionComparer <LineProxy> .Ascending(proxy => proxy))
                         .ObserveOn(schedulerProvider.MainThread)
                         .Bind(out _data)
                         .DisposeMany()
                         .Subscribe();

            // track first visible index[required to set scroll extent]
            var firstIndexMonitor = lineScroller.Lines.Connect()
                                    .Buffer(TimeSpan.FromMilliseconds(250)).FlattenBufferResult()
                                    .ToCollection()
                                    .Select(lines => lines.Count == 0 ? 0 : lines.Select(l => l.Index).Max() - lines.Count + 1)
                                    .ObserveOn(schedulerProvider.MainThread)
                                    .Subscribe(first =>
            {
                try
                {
                    _isSettingScrollPosition = true;
                    FirstIndex = first;
                }
                finally
                {
                    _isSettingScrollPosition = false;
                }
            });

            _cleanUp = new CompositeDisposable(lineScroller,
                                               loader,
                                               Count,
                                               firstIndexMonitor,
                                               SelectionMonitor,
                                               Disposable.Create(() =>
            {
                _userScrollRequested.OnCompleted();
            }));
        }
Example #29
0
        public CompilerVM(MainWindowVM mainWindowVM)
        {
            MWVM = mainWindowVM;

            OutputLocation = new FilePickerVM()
            {
                ExistCheckOption = FilePickerVM.CheckOptions.IfPathNotEmpty,
                PathType         = FilePickerVM.PathTypeOptions.Folder,
                PromptTitle      = "Select the folder to place the resulting modlist.wabbajack file",
            };

            // Load settings
            CompilerSettings settings = MWVM.Settings.Compiler;

            SelectedCompilerType      = settings.LastCompiledModManager;
            OutputLocation.TargetPath = settings.OutputLocation;
            MWVM.Settings.SaveSignal
            .Subscribe(_ =>
            {
                settings.LastCompiledModManager = SelectedCompilerType;
                settings.OutputLocation         = OutputLocation.TargetPath;
            })
            .DisposeWith(CompositeDisposable);

            // Swap to proper sub VM based on selected type
            _compiler = this.WhenAny(x => x.SelectedCompilerType)
                        // Delay so the initial VM swap comes in immediately, subVM comes right after
                        .DelayInitial(TimeSpan.FromMilliseconds(50), RxApp.MainThreadScheduler)
                        .Select <ModManager, ISubCompilerVM>(type =>
            {
                switch (type)
                {
                case ModManager.MO2:
                    return(new MO2CompilerVM(this));

                case ModManager.Vortex:
                    return(new VortexCompilerVM(this));

                default:
                    return(null);
                }
            })
                        // Unload old VM
                        .Pairwise()
                        .Do(pair =>
            {
                pair.Previous?.Unload();
            })
                        .Select(p => p.Current)
                        .ToProperty(this, nameof(Compiler));

            // Let sub VM determine what settings we're displaying and when
            _currentModlistSettings = this.WhenAny(x => x.Compiler.ModlistSettings)
                                      .ToProperty(this, nameof(CurrentModlistSettings));

            _image = this.WhenAny(x => x.CurrentModlistSettings.ImagePath.TargetPath)
                     // Throttle so that it only loads image after any sets of swaps have completed
                     .Throttle(TimeSpan.FromMilliseconds(50), RxApp.MainThreadScheduler)
                     .DistinctUntilChanged()
                     .Select(path =>
            {
                if (string.IsNullOrWhiteSpace(path))
                {
                    return(UIUtils.BitmapImageFromResource("Resources/Wabba_Mouth_No_Text.png"));
                }
                if (UIUtils.TryGetBitmapImageFromFile(path, out var image))
                {
                    return(image);
                }
                return(null);
            })
                     .ToProperty(this, nameof(Image));

            _compiling = this.WhenAny(x => x.Compiler.ActiveCompilation)
                         .Select(compilation => compilation != null)
                         .ObserveOnGuiThread()
                         .ToProperty(this, nameof(Compiling));

            BackCommand = ReactiveCommand.Create(
                execute: () =>
            {
                mainWindowVM.ActivePane = mainWindowVM.ModeSelectionVM;
                StartedCompilation      = false;
                Completed = null;
            },
                canExecute: this.WhenAny(x => x.Compiling)
                .Select(x => !x));

            // Compile progress updates and populate ObservableCollection
            Dictionary <int, CPUDisplayVM> cpuDisplays = new Dictionary <int, CPUDisplayVM>();

            this.WhenAny(x => x.Compiler.ActiveCompilation)
            .SelectMany(c => c?.QueueStatus ?? Observable.Empty <CPUStatus>())
            .ObserveOn(RxApp.TaskpoolScheduler)
            // Attach start times to incoming CPU items
            .Scan(
                new CPUDisplayVM(),
                (_, cpu) =>
            {
                var ret = cpuDisplays.TryCreate(cpu.ID);
                ret.AbsorbStatus(cpu);
                return(ret);
            })
            .ToObservableChangeSet(x => x.Status.ID)
            .Batch(TimeSpan.FromMilliseconds(250), RxApp.TaskpoolScheduler)
            .EnsureUniqueChanges()
            .Filter(i => i.Status.IsWorking && i.Status.ID != WorkQueue.UnassignedCpuId)
            .ObserveOn(RxApp.MainThreadScheduler)
            .Sort(SortExpressionComparer <CPUDisplayVM> .Ascending(s => s.StartTime))
            .Bind(StatusList)
            .Subscribe()
            .DisposeWith(CompositeDisposable);

            _percentCompleted = this.WhenAny(x => x.Compiler.ActiveCompilation)
                                .StartWith(default(ACompiler))
                                .CombineLatest(
                this.WhenAny(x => x.Completed),
                (compiler, completed) =>
            {
                if (compiler == null)
                {
                    return(Observable.Return <float>(completed != null ? 1f : 0f));
                }
                return(compiler.PercentCompleted.StartWith(0));
            })
                                .Switch()
                                .Debounce(TimeSpan.FromMilliseconds(25))
                                .ToProperty(this, nameof(PercentCompleted));

            BeginCommand = ReactiveCommand.CreateFromTask(
                canExecute: this.WhenAny(x => x.Compiler.CanCompile)
                .Switch(),
                execute: async() =>
            {
                try
                {
                    await this.Compiler.Compile();
                    Completed = ErrorResponse.Success;
                }
                catch (Exception ex)
                {
                    Completed = ErrorResponse.Fail(ex);
                    while (ex.InnerException != null)
                    {
                        ex = ex.InnerException;
                    }
                    Utils.Error(ex, $"Compiler error");
                }
            });

            // When sub compiler begins a compile, mark state variable
            BeginCommand.StartingExecution()
            .Subscribe(_ =>
            {
                StartedCompilation = true;
            })
            .DisposeWith(CompositeDisposable);

            // Listen for user interventions, and compile a dynamic list of all unhandled ones
            var activeInterventions = this.WhenAny(x => x.Compiler.ActiveCompilation)
                                      .SelectMany(c => c?.LogMessages ?? Observable.Empty <IStatusMessage>())
                                      .WhereCastable <IStatusMessage, IUserIntervention>()
                                      .ToObservableChangeSet()
                                      .AutoRefresh(i => i.Handled)
                                      .Filter(i => !i.Handled)
                                      .AsObservableList();

            // Find the top intervention /w no CPU ID to be marked as "global"
            _ActiveGlobalUserIntervention = activeInterventions.Connect()
                                            .Filter(x => x.CpuID == WorkQueue.UnassignedCpuId)
                                            .QueryWhenChanged(query => query.FirstOrDefault())
                                            .ObserveOnGuiThread()
                                            .ToProperty(this, nameof(ActiveGlobalUserIntervention));

            CloseWhenCompleteCommand = ReactiveCommand.Create(
                canExecute: this.WhenAny(x => x.Completed)
                .Select(x => x != null),
                execute: () =>
            {
                MWVM.ShutdownApplication();
            });

            GoToModlistCommand = ReactiveCommand.Create(
                canExecute: this.WhenAny(x => x.Completed)
                .Select(x => x != null),
                execute: () =>
            {
                if (string.IsNullOrWhiteSpace(OutputLocation.TargetPath))
                {
                    Process.Start("explorer.exe", Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location));
                }
                else
                {
                    Process.Start("explorer.exe", OutputLocation.TargetPath);
                }
            });
        }