Esempio n. 1
0
        public LineScroller(FileInfo file,
                            IObservable <ILineProvider> latest,
                            IObservable <ScrollRequest> scrollRequest,
                            ILogger logger,
                            IScheduler scheduler = null)
        {
            if (file == null)
            {
                throw new ArgumentNullException(nameof(file));
            }
            if (latest == null)
            {
                throw new ArgumentNullException(nameof(latest));
            }
            if (logger == null)
            {
                throw new ArgumentNullException(nameof(logger));
            }

            logger.Info($"Constructing file tailer for {file.FullName}");

            var lines = new SourceList <Line>();

            Lines = lines.AsObservableList();

            var locker = new object();

            scrollRequest = scrollRequest.Synchronize(locker);


            var aggregator = latest.CombineLatest(scrollRequest, (currentLines, scroll) => currentLines.ReadLines(scroll).ToArray())
                             .Subscribe(currentPage =>
            {
                var previous = lines.Items.ToArray();
                var added    = currentPage.Except(previous, Line.TextStartComparer).ToArray();
                var removed  = previous.Except(currentPage, Line.TextStartComparer).ToArray();

                lines.Edit(innerList =>
                {
                    if (removed.Any())
                    {
                        innerList.RemoveMany(removed);
                    }
                    if (added.Any())
                    {
                        innerList.AddRange(added);
                    }
                });
            });

            _cleanUp = new CompositeDisposable(Lines, lines, aggregator);
        }
Esempio n. 2
0
        public OcsSession()
        {
            _ocs     = new SourceList <AnalysisData>();
            _nnMean  = new SourceList <AnalysisData>();
            _sdNn    = new SourceList <AnalysisData>();
            _meanEda = new SourceList <AnalysisData>();
            _peakEda = new SourceList <AnalysisData>();

            Ocs     = _ocs.AsObservableList();
            NnMean  = _nnMean.AsObservableList();
            SdNn    = _sdNn.AsObservableList();
            MeanEda = _meanEda.AsObservableList();
            PeakEda = _peakEda.AsObservableList();
        }
Esempio n. 3
0
        public DialogSelectNeuronsViewModel(string message, string avatarUrl, bool allowMultiSelect, INeuronQueryService neuronQueryService = null) :
            base(message)
        {
            this.avatarUrl          = avatarUrl;
            this.AllowMultiSelect   = allowMultiSelect;
            this.neuronQueryService = neuronQueryService ?? Locator.Current.GetService <INeuronQueryService>();
            var list = new SourceList <Neuron>();

            this.ReloadCommand    = ReactiveCommand.Create(async() => await this.OnReloadClicked(list));
            this.SelectCommand    = ReactiveCommand.Create(this.OnSelectedClicked);
            this.UserDialogResult = null;

            this.cleanUp = list.AsObservableList().Connect()
                           .Bind(out this.neurons)
                           .DisposeMany()
                           .Subscribe();
        }
Esempio n. 4
0
        public void TheLightIsChangedWhenThereIsAMatch(string processName, string windowName)
        {
            var activeProcessesService = Substitute.For <IActiveProcessesService>();

            var procs = new SourceList <string>();

            procs.Add(processName);
            activeProcessesService.ProcessNames.Returns(procs.AsObservableList());

            var windows = new SourceList <string>();

            windows.Add(windowName);
            activeProcessesService.ProcessNames.Returns(windows.AsObservableList());

            var phillipsHueService = Substitute.For <IPhillipsHueService>();

            var lights = new SourceList <Light>();
            var light  = new Light()
            {
                Id   = "5",
                Name = "Office Door",
            };

            lights.Add(light);
            phillipsHueService.Lights.Returns(lights.AsObservableList());


            var sut = new OnAirServiceBuilder()
                      .WithActiveProcessesService(activeProcessesService)
                      .WithPhillipsHueService(phillipsHueService)
                      .Build();

            // user interface is updated
            sut.IsOnAir.ShouldBeTrue();

            // the correct light is turned on
            phillipsHueService.Received().SendCommandAsync(
                Arg.Is <LightCommand>(x => x.On.Value == true),
                Arg.Is <IEnumerable <string> >(x => x.Contains(light.Id)));

            // TODO: assert that the light is set to the correct color
        }
Esempio n. 5
0
        public LineScroller([NotNull] IObservable <ILineProvider> latest, [NotNull] IObservable <ScrollRequest> scrollRequest)
        {
            if (latest == null)
            {
                throw new ArgumentNullException(nameof(latest));
            }
            if (scrollRequest == null)
            {
                throw new ArgumentNullException(nameof(scrollRequest));
            }

            var lines = new SourceList <Line>();

            Lines = lines.AsObservableList();

            var locker = new object();

            scrollRequest = scrollRequest.Synchronize(locker);
            latest        = latest.Synchronize(locker);

            var aggregator = latest.CombineLatest(scrollRequest, (currentLines, scroll) => currentLines.ReadLines(scroll).ToArray())
                             .Subscribe(currentPage =>
            {
                var previous = lines.Items.ToArray();
                var added    = currentPage.Except(previous, Line.TextStartComparer).ToArray();
                var removed  = previous.Except(currentPage, Line.TextStartComparer).ToArray();

                lines.Edit(innerList =>
                {
                    if (removed.Any())
                    {
                        innerList.RemoveMany(removed);
                    }
                    if (added.Any())
                    {
                        innerList.AddRange(added);
                    }
                });
            });

            _cleanUp = new CompositeDisposable(Lines, lines, aggregator);
        }
Esempio n. 6
0
        public EmpaticaSession()
        {
            _acceleration = new SourceList <Acceleration>();
            _batteryLevel = new SourceList <BatteryLevel>();
            _bvp          = new SourceList <Bvp>();
            _gsr          = new SourceList <Gsr>();
            _hr           = new SourceList <Hr>();
            _ibi          = new SourceList <Ibi>();
            _tag          = new SourceList <Tag>();
            _temperature  = new SourceList <Temperature>();

            Acceleration = _acceleration.AsObservableList();
            BatteryLevel = _batteryLevel.AsObservableList();
            Bvp          = _bvp.AsObservableList();
            Gsr          = _gsr.AsObservableList();
            Hr           = _hr.AsObservableList();
            Ibi          = _ibi.AsObservableList();
            Tag          = _tag.AsObservableList();
            Temperature  = _temperature.AsObservableList();
        }
Esempio n. 7
0
        public UserFileService(IAppFolderService appFolderService,
                               IFileService fileService,
                               IFileSystemWatcherService fileSystemWatcherService,
                               IEncryptionService encryptionService)
        {
            _appFolderService         = appFolderService;
            _fileService              = fileService;
            _fileSystemWatcherService = fileSystemWatcherService;
            _encryptionService        = encryptionService;

            _appFolderPath = _appFolderService.GetAppFolderPath();

            string localFolderName  = FileLocation.Local.FolderName();
            string roamedFolderName = FileLocation.Roamed.FolderName();

            var localFolderTask  = CreateUserFolderAsync(localFolderName);
            var roamedFolderTask = CreateUserFolderAsync(roamedFolderName);

            FilesList = _filesList.AsObservableList();

            Initialization = InitializeFileList();
        }
Esempio n. 8
0
        public FileTailer(FileInfo file,
                IObservable<FileSearchResult> filter,
                IObservable<ScrollRequest> scrollRequest,
                ILogger logger,
                IScheduler scheduler = null)
        {
            if (file == null) throw new ArgumentNullException(nameof(file));
            if (filter == null) throw new ArgumentNullException(nameof(filter));
            if (logger == null) throw new ArgumentNullException(nameof(logger));

            logger.Info($"Constructing file tailer for {file.FullName}");

            var lines = new SourceList<Line>();
            Lines = lines.AsObservableList();

            var isBusy = new Subject<bool>();
            IsSearching = isBusy.AsObservable();

            var locker = new object();
            scrollRequest = scrollRequest.Synchronize(locker);

            var fileWatcher = file.WatchFile(scheduler: scheduler)
                            .DistinctUntilChanged()
                            .TakeWhile(notification => notification.Exists).Repeat()
                            .Replay(1).RefCount();

            var indexer = fileWatcher.Index().Replay(1).RefCount();

            //compare latest lines and latest filter and only take the filtered results it is not empty
            var latestLines = indexer.Cast<ILineProvider>().Synchronize(locker);
            var latestFilter = filter.Cast<ILineProvider>().Synchronize(locker);
            var latest = latestLines.CombineLatest(latestFilter, (l, f) => f.IsEmpty ? l : f);

            MatchedLines = latest.Select(provider => provider.Count);
            TotalLines = latestLines.Select(x => x.Count);
            FileSize = fileWatcher.Select(notification => notification.Size);
            IsLoading = indexer.Take(1).Select(_ => false).StartWith(true);

            var aggregator = latest.CombineLatest(scrollRequest, (currentLines, scroll) =>
            {
                return currentLines.ReadLines(scroll).ToArray();
            })
            .Subscribe(currentPage =>
            {
                var previous = lines.Items.ToArray();
                var added = currentPage.Except(previous).ToArray();
                var removed = previous.Except(currentPage).ToArray();

                lines.Edit(innerList =>
                {
                    if (removed.Any()) innerList.RemoveMany(removed);
                    if (added.Any()) innerList.AddRange(added);
                });

            });

            //var aggregator = latest.CombineLatest(scrollRequest, (currentLines, scroll) =>
            //{
            //    //TODO: Read entire page, the check which lines should be added and which shold be removed
            //    //as part of that work, get the maximum inded [this is the head!]

            //    //   Debug.WriteLine($"{scroll.Mode}, {scroll.FirstIndex}, {scroll.PageSize}");

            //    var currentPage = currentLines.GetIndicies(scroll).ToArray();

            //    var previous = lines.Items.Select(l => l.LineInfo).ToArray();
            //    var removed = previous.Except(currentPage, LineInfo.LineIndexComparer).ToArray();
            //    var added = currentPage.Except(previous, LineInfo.LineIndexComparer).ToArray();
            //    //calculated added and removed lines
            //    var removedLines = lines.Items.Where(l => removed.Contains(l.LineInfo)).ToArray();

            //    Func<long, DateTime?> isTail = l =>
            //    {
            //        //account for time with tail (i.e. add time to ILineProvider.TailStartsAt )
            //        var tail = currentLines.TailStartsAt;
            //        var onTail = tail != -1 && l >= tail;
            //        return onTail ? DateTime.Now : (DateTime?)null;
            //    };

            //    //Console.WriteLine();
            //    //finally we can load the line from the file todo: Add encdoing back in
            //    var newLines = file.ReadLine(added, (lineIndex, text, position) => new Line(lineIndex, text, isTail(position)), Encoding.UTF8).ToArray();

            //    return new { NewLines = newLines, OldLines = removedLines };
            //})
            //.Where(fn => fn.NewLines.Length + fn.OldLines.Length > 0)
            //.Subscribe(changes =>
            //{
            //    //update observable list
            //    lines.Edit(innerList =>
            //{
            //    if (changes.OldLines.Any()) innerList.RemoveMany(changes.OldLines);
            //    if (changes.NewLines.Any()) innerList.AddRange(changes.NewLines);
            //});
            //});

            _cleanUp = new CompositeDisposable(Lines, lines, aggregator, Disposable.Create(() => isBusy.OnCompleted()));
        }
Esempio n. 9
0
        public FileTailer(FileInfo file, 
            IObservable<string> textToMatch,
            IObservable<ScrollRequest> scrollRequest,
            IScheduler scheduler=null)
        {
            if (file == null) throw new ArgumentNullException(nameof(file));
            if (textToMatch == null) throw new ArgumentNullException(nameof(textToMatch));

            //create list of lines which contain the observable text
               var matchedLines = textToMatch
                    .Select(searchText =>
                    {
                        Func<string, bool> predicate = null;
                        if (!string.IsNullOrEmpty(searchText))
                            predicate = s => s.Contains(searchText, StringComparison.OrdinalIgnoreCase);

                        return file.WatchFile(scheduler:scheduler ?? Scheduler.Default)
                                    .TakeWhile(notification => notification.Exists)
                                    .Repeat()
                                    .ScanFile(predicate);

                    }).Switch()
                    .Replay(1).RefCount();

            MatchedLines = matchedLines.Select(x => x.MatchingLines.Length);

            TotalLines = matchedLines.Select(x => x.TotalLines);

            //todo: plug in file missing or error into the screen

            var lines = new SourceList<Line>();
            Lines = lines.AsObservableList();

            //this is the beast! Dynamically combine lines requested by the consumer
            //with the lines which exist in the file. This enables proper virtualisation of the file
            var scroller = matchedLines
                .CombineLatest(scrollRequest, (scanResult, request) => new {scanResult , request })
                .Subscribe(x =>
                {
                    var mode = x.request.Mode;
                    var pageSize = x.request.PageSize;
                    var endOfTail = x.scanResult.EndOfTail;
                    var isInitial = x.scanResult.Index==0;
                    var allLines = x.scanResult.MatchingLines;
                    var previousPage = lines.Items.Select(l => new LineIndex(l.Number, l.Index)).ToArray();

                    //Otherwise take the page size and start index from the request
                    var currentPage = (mode == ScrollingMode.Tail
                        ? allLines.Skip(allLines.Length-pageSize).Take(pageSize).ToArray()
                        : allLines.Skip(x.request.FirstIndex).Take(pageSize)).ToArray();

                    var added = currentPage.Except(previousPage).ToArray();
                    var removed = previousPage.Except(currentPage).Select(li=>li.Line).ToArray();

                    if (added.Length + removed.Length == 0) return;

                    try
                    {
                        var addedLines = file.ReadLines(added, (lineIndex, text) =>
                        {
                            var isEndOfTail = !isInitial && lineIndex.Line > endOfTail;
                            return new Line(lineIndex.Line, lineIndex.Index, text, isEndOfTail ? DateTime.Now : (DateTime?)null);
                        }).ToArray();

                        //get old lines from the current collection
                        var removedLines = lines.Items.Where(l => removed.Contains(l.Number)).ToArray();

                        //finally relect changes in the list
                        lines.Edit(innerList =>
                        {
                            innerList.RemoveMany(removedLines);
                            innerList.AddRange(addedLines);
                        });
                    }
                    catch (Exception)
                    {
                        //Very small chance of an error here but if one is causght the next successful read will recify this
                        //TODO: 1. Feedback to user that steaming has stopped
                        //TODO: 2. Place the ReadLines(..) method with the select of an observable
                    }

                });
            _cleanUp = new CompositeDisposable(Lines, scroller, lines);
        }
 public ParentDynamic()
 {
     Children           = new SourceList <Person>();
     ChildrenObservable = Children.AsObservableList();
 }
 public ParentDynamic(int id, IEnumerable <Person> children)
 {
     Children = new SourceList <Person>();
     Children.AddRange(children);
     ChildrenObservable = Children.AsObservableList();
 }
Esempio n. 12
0
        public FileTailer(FileInfo file, IObservable <string> textToMatch, IObservable <ScrollRequest> scrollRequest)
        {
            if (file == null)
            {
                throw new ArgumentNullException(nameof(file));
            }
            if (textToMatch == null)
            {
                throw new ArgumentNullException(nameof(textToMatch));
            }
            if (scrollRequest == null)
            {
                throw new ArgumentNullException(nameof(scrollRequest));
            }

            // create list of lines which contain the observable text
            var matchedLines = textToMatch
                               .Select(searchText =>
            {
                Func <string, bool> predicate = null;
                if (!string.IsNullOrEmpty(searchText))
                {
                    // TODO: for now we use case insensitive search but we need to update it later on
                    predicate = s => s.Contains(searchText, StringComparison.OrdinalIgnoreCase);
                }

                // todo: probably not the most efficient implementation to start reading the file all over again but works for now
                return(file.WatchFile().ScanFile(predicate));
            })
                               .Switch()
                               .Replay(1) // we use a replay here because we want to create a hot observable that all the subscribers share a single instance of
                               .RefCount();

            MatchedLinesCount = matchedLines.Select(x => x.MatchingLines.Length);

            // count of lines
            TotalLinesCount = matchedLines.Select(x => x.TotalLines);

            var lines = new SourceList <Line>(); // this is where the DynamicData magic happens!

            Lines = lines.AsObservableList();    // convert the sourceList to observableList

            // Dynamically combine lines requested by the consumer with the lines which exist in the file. This enables
            // proper virtualization of the file
            var scroller = matchedLines
                           .CombineLatest(scrollRequest, (matched, request) => new { matched, request })
                           .Subscribe(x =>
            {
                var mode     = x.request.Mode;
                var pageSize = x.request.PageSize;

                var endOfTail    = x.matched.EndOfTail;
                var isInitial    = x.matched.Index == 0;
                var allLines     = x.matched.MatchingLines;
                var previousPage = lines.Items.Select(l => l.Number).ToArray();

                // if tailing, take the end only
                // otherwise take the page size and start index from the request
                var currentPage = (mode == ScrollingMode.Tail
                        ? allLines.Skip(allLines.Length - pageSize).ToArray()
                        : allLines.Skip(x.request.FirstIndex - 1).Take(pageSize)).ToArray();

                var added   = currentPage.Except(previousPage).ToArray();
                var removed = previousPage.Except(currentPage).ToArray();

                // read new lines from the file
                var addedLines = file.ReadLines(added, i => !isInitial && i > endOfTail).ToArray();
                // get old lines from the current collection
                var removedLines = lines.Items.Where(l => removed.Contains(l.Number)).ToArray();

                // finally relect changes in the list
                lines.Edit(innerList =>
                {
                    innerList.RemoveMany(removedLines);
                    innerList.AddRange(addedLines);
                });
            });

            _cleanup = new CompositeDisposable(Lines, scroller, lines);
        }
Esempio n. 13
0
        public FileTailer(FileInfo file, 
            IObservable<string> textToMatch,
            IObservable<ScrollRequest> scrollRequest,
            IScheduler scheduler=null)
        {
            if (file == null) throw new ArgumentNullException(nameof(file));
            if (textToMatch == null) throw new ArgumentNullException(nameof(textToMatch));

            var lines = new SourceList<Line>();
            Lines = lines.AsObservableList();

            var locker = new object();
            scrollRequest = scrollRequest.Synchronize(locker);

            var metronome = Observable
                    .Interval(TimeSpan.FromMilliseconds(250), scheduler ?? Scheduler.Default)
                    .ToUnit()
                    .Replay().RefCount();

            //temp mess for a few days
            var indexer = file.WatchFile(metronome)
                            .TakeWhile(notification => notification.Exists)
                            .Repeat()
                            .Index()
                            .Synchronize(locker)
                            .Replay(1).RefCount();

            var matcher = textToMatch.Select(searchText =>
            {
                if (string.IsNullOrEmpty(searchText) || searchText.Length < 3)
                    return Observable.Return(LineMatches.None);

                return file.WatchFile(metronome)
                    .TakeWhile(notification => notification.Exists)
                    .Repeat()
                    .Match(s => s.Contains(searchText, StringComparison.OrdinalIgnoreCase));

            }).Switch()
            .Synchronize(locker)
            .Replay(1).RefCount();

            //count matching lines (all if no filter is specified)
            MatchedLines = indexer.CombineLatest(matcher, (indicies, matches) => matches == LineMatches.None ? indicies.Count : matches.Count);

            //count total line
            TotalLines = indexer.Select(x => x.Count);

            FileSize = file.WatchFile(metronome).Select(notification => notification.Size);

            var aggregator = indexer.CombineLatest(matcher, scrollRequest,(idx, mtch, scroll) => new CombinedResult(scroll, mtch, idx))
                .Select(result =>
                {
                    var scroll = result.Scroll;
                    var indicies = result.Incidies;
                    var matched = result.MatchedLines;

                    IEnumerable<LineIndex> indices;
                    if (result.MatchedLines.ChangedReason == LineMatchChangedReason.None)
                    {
                        indices = scroll.Mode == ScrollingMode.Tail
                            ? indicies.GetTail(scroll)
                            : indicies.GetFromIndex(scroll);
                    }
                    else
                    {
                        indices = scroll.Mode == ScrollingMode.Tail
                            ? indicies.GetTail(scroll, matched)
                            : indicies.GetFromIndex(scroll, matched);
                    }

                    var currentPage = indices.ToArray();
                    var previous = lines.Items.Select(l => l.LineIndex).ToArray();
                    var removed = previous.Except(currentPage).ToArray();
                    var removedLines = lines.Items.Where(l=> removed.Contains(l.LineIndex)).ToArray();

                    var added = currentPage.Except(previous).ToArray();
                    //finally we can load the line from the file
                    var newLines =  file.ReadLines(added, (lineIndex, text) =>
                    {
                        var isEndOfTail = indicies.ChangedReason != LinesChangedReason.Loaded && lineIndex.Line > indicies.TailStartsAt;

                        return new Line(lineIndex, text, isEndOfTail ? DateTime.Now : (DateTime?) null);
                    }, indicies.Encoding).ToArray();

                    return new { NewLines = newLines, OldLines = removedLines };
                })
                .RetryWithBackOff((Exception error, int attempts) =>
                {
                    //todo: plug in file missing or error into the screen
                    return TimeSpan.FromSeconds(1);
                 })
                 .Where(fn=> fn.NewLines.Length + fn.OldLines.Length > 0)
                .Subscribe(changes =>
                {
                    //update observable list
                    lines.Edit(innerList =>
                    {
                        if (changes.OldLines.Any()) innerList.RemoveMany(changes.OldLines);
                        if (changes.NewLines.Any())  innerList.AddRange(changes.NewLines);
                    });
                });
            _cleanUp = new CompositeDisposable(Lines, lines, aggregator);
        }
Esempio n. 14
0
        public FileTailer(FileInfo file,
                          IObservable <string> textToMatch,
                          IObservable <ScrollRequest> scrollRequest,
                          IScheduler scheduler = null)
        {
            if (file == null)
            {
                throw new ArgumentNullException(nameof(file));
            }
            if (textToMatch == null)
            {
                throw new ArgumentNullException(nameof(textToMatch));
            }

            //create list of lines which contain the observable text
            var matchedLines = textToMatch
                               .Select(searchText =>
            {
                Func <string, bool> predicate = null;
                if (!string.IsNullOrEmpty(searchText))
                {
                    predicate = s => s.Contains(searchText, StringComparison.OrdinalIgnoreCase);
                }

                return(file.WatchFile(scheduler: scheduler ?? Scheduler.Default)
                       .TakeWhile(notification => notification.Exists)
                       .Repeat()
                       .ScanFile(predicate));
            }).Switch()
                               .Replay(1).RefCount();

            MatchedLines = matchedLines.Select(x => x.MatchingLines.Length);

            TotalLines = matchedLines.Select(x => x.TotalLines);

            //todo: plug in file missing or error into the screen

            var lines = new SourceList <Line>();

            Lines = lines.AsObservableList();

            //this is the beast! Dynamically combine lines requested by the consumer
            //with the lines which exist in the file. This enables proper virtualisation of the file
            var scroller = matchedLines
                           .CombineLatest(scrollRequest, (scanResult, request) => new { scanResult, request })
                           .Subscribe(x =>
            {
                var mode         = x.request.Mode;
                var pageSize     = x.request.PageSize;
                var endOfTail    = x.scanResult.EndOfTail;
                var isInitial    = x.scanResult.Index == 0;
                var allLines     = x.scanResult.MatchingLines;
                var previousPage = lines.Items.Select(l => new LineIndex(l.Number, l.Index)).ToArray();

                //Otherwise take the page size and start index from the request
                var currentPage = (mode == ScrollingMode.Tail
                        ? allLines.Skip(allLines.Length - pageSize).Take(pageSize).ToArray()
                        : allLines.Skip(x.request.FirstIndex).Take(pageSize)).ToArray();

                var added   = currentPage.Except(previousPage).ToArray();
                var removed = previousPage.Except(currentPage).Select(li => li.Line).ToArray();

                if (added.Length + removed.Length == 0)
                {
                    return;
                }


                try
                {
                    var addedLines = file.ReadLines(added, (lineIndex, text) =>
                    {
                        var isEndOfTail = !isInitial && lineIndex.Line > endOfTail;
                        return(new Line(lineIndex.Line, lineIndex.Index, text, isEndOfTail ? DateTime.Now : (DateTime?)null));
                    }).ToArray();

                    //get old lines from the current collection
                    var removedLines = lines.Items.Where(l => removed.Contains(l.Number)).ToArray();

                    //finally relect changes in the list
                    lines.Edit(innerList =>
                    {
                        innerList.RemoveMany(removedLines);
                        innerList.AddRange(addedLines);
                    });
                }
                catch (Exception)
                {
                    //Very small chance of an error here but if one is causght the next successful read will recify this
                    //TODO: 1. Feedback to user that steaming has stopped
                    //TODO: 2. Place the ReadLines(..) method with the select of an observable
                }
            });

            _cleanUp = new CompositeDisposable(Lines, scroller, lines);
        }
Esempio n. 15
0
 public IObservableList <User> GetUsersStream()
 {
     return(_usersSource.AsObservableList());
 }
Esempio n. 16
0
        public FileTailer(FileInfo file, 
            IObservable<string> textToMatch,
            IObservable<ScrollRequest> scrollRequest,
            IScheduler scheduler=null)
        {
            if (file == null) throw new ArgumentNullException(nameof(file));
            if (textToMatch == null) throw new ArgumentNullException(nameof(textToMatch));

            var lines = new SourceList<Line>();
            Lines = lines.AsObservableList();

            var matcher = textToMatch.Select(searchText =>
            {
                if (string.IsNullOrEmpty(searchText) || searchText.Length < 3)
                    return Observable.Return(LineMatches.None);

                return file.WatchFile(scheduler: scheduler)
                    .TakeWhile(notification => notification.Exists)
                    .Repeat()
                    .Match(s => s.Contains(searchText, StringComparison.OrdinalIgnoreCase));

            }).Switch()
            .Replay(1).RefCount();

            //temp mess for a few days
            var indexer = file.WatchFile(scheduler: scheduler)
                                .TakeWhile(notification => notification.Exists)
                                .Repeat()
                                .Index()
                                .Replay(1).RefCount();

            //count matching lines (all if no filter is specified)
            MatchedLines = indexer.CombineLatest(matcher, (indicies, matches) => matches == LineMatches.None ? indicies.Count : matches.Count);

            //count total line
            TotalLines = indexer.Select(x => x.Count);

            //todo: plug in file missing or error into the screen

            var locker = new object();
            var theBeast = indexer.Synchronize(locker)
                .CombineLatest(matcher.Synchronize(locker), scrollRequest.Synchronize(locker),(idx, mtch, scroll) => new CombinedResult(scroll, mtch, idx))
                .Select(result =>
                {
                    var scroll = result.Scroll;
                    var allLines = result.Incidies;
                    var matched = result.MatchedLines;

                    IEnumerable<LineIndex> indices;
                    if (result.MatchedLines.ChangedReason == LineMatchChangedReason.None)
                    {
                        indices = scroll.Mode == ScrollingMode.Tail
                            ? allLines.GetTail(scroll)
                            : allLines.GetFromIndex(scroll);
                    }
                    else
                    {
                        indices = scroll.Mode == ScrollingMode.Tail
                            ? allLines.GetTail(scroll, matched)
                            : allLines.GetFromIndex(scroll, matched);
                    }

                    return  file.ReadLines(indices, (lineIndex, text) =>
                    {
                        var isEndOfTail = allLines.ChangedReason != LinesChangedReason.Loaded && lineIndex.Line > allLines.TailStartsAt;
                        return new Line(lineIndex.Line, lineIndex.Index, text,isEndOfTail ? DateTime.Now : (DateTime?) null);
                    }).ToArray();
                })
                //.RetryWithBackOff((error, attempts) =>
                //{
                //    //TODO: Log
                //    return TimeSpan.FromSeconds(1);
                //})
                .Subscribe(newPage =>
                {
                    //update observable list
                    lines.Edit(innerList =>
                    {

                        var removed = innerList.Except(newPage).ToArray();
                        var added = newPage.Except(innerList).ToArray();

                        if (removed.Any()) innerList.RemoveMany(removed);
                        if (added.Any())  innerList.AddRange(added);
                    });

                });

            ////this is the beast! Dynamically combine lines requested by the consumer
            ////with the lines which exist in the file. This enables proper virtualisation of the file
            //var scroller = matchedLines
            //    .CombineLatest(scrollRequest, (scanResult, request) => new {scanResult , request })
            //    .Subscribe(x =>
            //    {
            //        var mode = x.request.Mode;
            //        var pageSize = x.request.PageSize;
            //        var endOfTail = x.scanResult.EndOfTail;
            //        var isInitial = x.scanResult.Index==0;
            //        var allLines = x.scanResult.MatchingLines;
            //        var previousPage = lines.Items.Select(l => new LineIndex(l.Number, l.Index, 0, 0)).ToArray();

            //        //Otherwise take the page size and start index from the request
            //        var currentPage = (mode == ScrollingMode.Tail
            //            ? allLines.Skip(allLines.Length-pageSize).Take(pageSize).ToArray()
            //            : allLines.Skip(x.request.FirstIndex).Take(pageSize)).ToArray();

            //        var added = currentPage.Except(previousPage).ToArray();
            //        var removed = previousPage.Except(currentPage).Select(li=>li.Line).ToArray();

            //        if (added.Length + removed.Length == 0) return;

            //        try
            //        {
            //            var addedLines = file.ReadLines(added, (lineIndex, text) =>
            //            {
            //                var isEndOfTail = !isInitial && lineIndex.Line > endOfTail;
            //                return new Line(lineIndex.Line, lineIndex.Index, text, isEndOfTail ? DateTime.Now : (DateTime?)null);
            //            }).ToArray();

            //            //get old lines from the current collection
            //            var removedLines = lines.Items.Where(l => removed.Contains(l.Number)).ToArray();

            //            //finally relect changes in the list
            //            lines.Edit(innerList =>
            //            {
            //                innerList.RemoveMany(removedLines);
            //                innerList.AddRange(addedLines);
            //            });
            //        }
            //        catch (Exception)
            //        {
            //            //Very small chance of an error here but if one is causght the next successful read will recify this
            //            //TODO: 1. Feedback to user that steaming has stopped
            //            //TODO: 2. Place the ReadLines(..) method with the select of an observable
            //        }

            //    });
            _cleanUp = new CompositeDisposable(Lines, lines);
        }