From 52887aacf04e2f98de33e7caf21d2226924a0535 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Wed, 11 Nov 2020 18:36:01 +0800 Subject: [PATCH] Batch process ui change with interval 50ms --- Flow.Launcher/ViewModel/MainViewModel.cs | 46 +++++++-- Flow.Launcher/ViewModel/ResultsForUpdate.cs | 2 +- Flow.Launcher/ViewModel/ResultsViewModel.cs | 107 ++++++++++---------- 3 files changed, 93 insertions(+), 62 deletions(-) diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index ac2cc79d5..0a1ef8d81 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -106,13 +106,25 @@ namespace Flow.Launcher.ViewModel { _resultsUpdateQueue = new BlockingCollection(); - Task.Run(() => + Task.Run(async () => { while (true) { - var resultToUpdate = _resultsUpdateQueue.Take(); - if (!resultToUpdate.Token.IsCancellationRequested) - UpdateResultView(resultToUpdate.Results, resultToUpdate.Metadata, resultToUpdate.Query); + List queue = new List() { _resultsUpdateQueue.Take() }; + await Task.Delay(50); + + while (_resultsUpdateQueue.TryTake(out var resultsForUpdate)) + { + queue.Add(resultsForUpdate); + } + + //foreach (var update in queue) + //{ + // UpdateResultView(update.Results, update.Metadata, update.Query); + //} + + UpdateResultView(queue.Where(r => !r.Token.IsCancellationRequested)); + } }); } @@ -412,7 +424,7 @@ namespace Flow.Launcher.ViewModel if (query != null) { // handle the exclusiveness of plugin using action keyword - RemoveOldQueryResults(query); + // RemoveOldQueryResults(query); _lastQuery = query; Task.Delay(200, currentCancellationToken).ContinueWith(_ => @@ -443,7 +455,7 @@ namespace Flow.Launcher.ViewModel { // nothing to do here } - + // this should happen once after all queries are done so progress bar should continue // until the end of all querying @@ -459,6 +471,7 @@ namespace Flow.Launcher.ViewModel { Results.Clear(); Results.Visbility = Visibility.Collapsed; + } } @@ -683,6 +696,23 @@ namespace Flow.Launcher.ViewModel } } + public void UpdateResultView(IEnumerable resultsForUpdates) + { + foreach (var result in resultsForUpdates.SelectMany(u => u.Results)) + { + if (_topMostRecord.IsTopMost(result)) + { + result.Score = int.MaxValue; + } + else + { + result.Score += _userSelectedRecord.GetSelectedCount(result) * 5; + } + } + + Results.AddResults(resultsForUpdates); + } + /// /// To avoid deadlock, this method should not called from main thread /// @@ -705,10 +735,6 @@ namespace Flow.Launcher.ViewModel Results.AddResults(list, metadata.ID); } - if (Results.Visbility != Visibility.Visible && list.Count > 0) - { - Results.Visbility = Visibility.Visible; - } } #endregion diff --git a/Flow.Launcher/ViewModel/ResultsForUpdate.cs b/Flow.Launcher/ViewModel/ResultsForUpdate.cs index 29f626285..2257d35b0 100644 --- a/Flow.Launcher/ViewModel/ResultsForUpdate.cs +++ b/Flow.Launcher/ViewModel/ResultsForUpdate.cs @@ -6,7 +6,7 @@ using System.Threading; namespace Flow.Launcher.ViewModel { - class ResultsForUpdate + public class ResultsForUpdate { public List Results { get; } diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs index ac435c494..d06a390c5 100644 --- a/Flow.Launcher/ViewModel/ResultsViewModel.cs +++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Collections.Specialized; using System.Linq; using System.Windows; using System.Windows.Controls; @@ -115,19 +116,20 @@ namespace Flow.Launcher.ViewModel public void Clear() { - Results.Clear(); + Results.RemoveAll(); } public void RemoveResultsExcept(PluginMetadata metadata) { - Results.RemoveAll(r => r.Result.PluginID != metadata.ID); + //Results.RemoveAll(r => r.Result.PluginID != metadata.ID); } public void RemoveResultsFor(PluginMetadata metadata) { - Results.RemoveAll(r => r.Result.PluginID == metadata.ID); + //Results.RemoveAll(r => r.Result.PluginID == metadata.ID); } + /// /// To avoid deadlock, this method should not called from main thread /// @@ -138,16 +140,44 @@ namespace Flow.Launcher.ViewModel // update UI in one run, so it can avoid UI flickering Results.Update(newResults); - if (Results.Count > 0) + if (Visbility != Visibility.Visible && Results.Count > 0) { Margin = new Thickness { Top = 8 }; SelectedIndex = 0; + Visbility = Visibility.Visible; } else { Margin = new Thickness { Top = 0 }; + Visbility = Visibility.Collapsed; } } + /// + /// To avoid deadlock, this method should not called from main thread + /// + public void AddResults(IEnumerable resultsForUpdates) + { + var newResults = NewResults(resultsForUpdates); + lock (_collectionLock) + { + Results.Update(newResults); + } + + switch (Visbility) + { + case Visibility.Collapsed when Results.Count > 0: + Margin = new Thickness { Top = 8 }; + SelectedIndex = 0; + Visbility = Visibility.Visible; + break; + case Visibility.Visible when Results.Count == 0: + Margin = new Thickness { Top = 0 }; + Visbility = Visibility.Collapsed; + break; + + } + } + private List NewResults(List newRawResults, string resultId) { @@ -165,8 +195,25 @@ namespace Flow.Launcher.ViewModel .Take(MaxResults * 2) .ToList(); } + + private List NewResults(IEnumerable resultsForUpdates) + { + if (!resultsForUpdates.Any()) + return Results.ToList(); + + var results = Results as IEnumerable; + + return results.Where(r => !resultsForUpdates.Any(u => u.Metadata.ID == r.Result.PluginID)) + .Concat(resultsForUpdates + .SelectMany(u => u.Results) + .Select(r => new ResultViewModel(r, _settings))) + .OrderByDescending(rv => rv.Result.Score) + .Take(MaxResults * 2) + .ToList(); + } #endregion + #region FormattedText Dependency Property public static readonly DependencyProperty FormattedTextProperty = DependencyProperty.RegisterAttached( "FormattedText", @@ -198,20 +245,12 @@ namespace Flow.Launcher.ViewModel } #endregion - public class ResultCollection : ObservableCollection + public class ResultCollection : ObservableCollection, INotifyCollectionChanged { - - public void RemoveAll(Predicate predicate) + public event NotifyCollectionChangedEventHandler CollectionChanged; + public void RemoveAll() { - CheckReentrancy(); - - for (int i = Count - 1; i >= 0; i--) - { - if (predicate(this[i])) - { - RemoveAt(i); - } - } + ClearItems(); } /// @@ -226,44 +265,10 @@ namespace Flow.Launcher.ViewModel { Add(item); } + CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); - - return; - int newCount = newItems.Count; - int oldCount = Items.Count; - int location = newCount > oldCount ? oldCount : newCount; - - for (int i = 0; i < location; i++) - { - ResultViewModel oldResult = this[i]; - ResultViewModel newResult = newItems[i]; - if (!oldResult.Equals(newResult)) - { // result is not the same update it in the current index - this[i] = newResult; - } - else if (oldResult.Result.Score != newResult.Result.Score) - { - this[i].Result.Score = newResult.Result.Score; - } - } - - - if (newCount >= oldCount) - { - for (int i = oldCount; i < newCount; i++) - { - Add(newItems[i]); - } - } - else - { - for (int i = oldCount - 1; i >= newCount; i--) - { - RemoveAt(i); - } - } } } }