From 9d2164962292104aa9f33bdaef74fb8871208549 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Tue, 10 Nov 2020 17:13:45 +0800 Subject: [PATCH] Change UI rendering logic Co-authored-by: Bao-Qian --- Flow.Launcher/ResultListBox.xaml | 2 +- Flow.Launcher/ViewModel/MainViewModel.cs | 24 +++++- Flow.Launcher/ViewModel/ResultsForUpdate.cs | 36 +++++++++ Flow.Launcher/ViewModel/ResultsViewModel.cs | 89 ++++++++------------- 4 files changed, 92 insertions(+), 59 deletions(-) create mode 100644 Flow.Launcher/ViewModel/ResultsForUpdate.cs diff --git a/Flow.Launcher/ResultListBox.xaml b/Flow.Launcher/ResultListBox.xaml index 3280dc457..60d94a37b 100644 --- a/Flow.Launcher/ResultListBox.xaml +++ b/Flow.Launcher/ResultListBox.xaml @@ -42,7 +42,7 @@ + Source="{Binding Image}" /> diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index f18b74022..ac2cc79d5 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -21,6 +21,7 @@ using Flow.Launcher.Plugin.SharedCommands; using Flow.Launcher.Storage; using System.Windows.Media; using Flow.Launcher.Infrastructure.Image; +using System.Collections.Concurrent; namespace Flow.Launcher.ViewModel { @@ -47,6 +48,8 @@ namespace Flow.Launcher.ViewModel private bool _saved; private readonly Internationalization _translator = InternationalizationManager.Instance; + private BlockingCollection _resultsUpdateQueue; + #endregion @@ -76,6 +79,8 @@ namespace Flow.Launcher.ViewModel InitializeKeyCommands(); RegisterResultsUpdatedEvent(); + RegisterResultUpdate(); + SetHotkey(_settings.Hotkey, OnHotkey); SetCustomPluginHotkey(); SetOpenResultModifiers(); @@ -91,12 +96,27 @@ namespace Flow.Launcher.ViewModel Task.Run(() => { PluginManager.UpdatePluginMetadata(e.Results, pair.Metadata, e.Query); - UpdateResultView(e.Results, pair.Metadata, e.Query); + _resultsUpdateQueue.Add(new ResultsForUpdate(e.Results, pair.Metadata, e.Query, _updateToken)); }, _updateToken); }; } } + private void RegisterResultUpdate() + { + _resultsUpdateQueue = new BlockingCollection(); + + Task.Run(() => + { + while (true) + { + var resultToUpdate = _resultsUpdateQueue.Take(); + if (!resultToUpdate.Token.IsCancellationRequested) + UpdateResultView(resultToUpdate.Results, resultToUpdate.Metadata, resultToUpdate.Query); + } + }); + } + private void InitializeKeyCommands() { @@ -415,7 +435,7 @@ namespace Flow.Launcher.ViewModel if (!plugin.Metadata.Disabled) { var results = PluginManager.QueryForPlugin(plugin, query); - UpdateResultView(results, plugin.Metadata, query); + _resultsUpdateQueue.Add(new ResultsForUpdate(results, plugin.Metadata, query, _updateToken)); } }); } diff --git a/Flow.Launcher/ViewModel/ResultsForUpdate.cs b/Flow.Launcher/ViewModel/ResultsForUpdate.cs new file mode 100644 index 000000000..29f626285 --- /dev/null +++ b/Flow.Launcher/ViewModel/ResultsForUpdate.cs @@ -0,0 +1,36 @@ +using Flow.Launcher.Plugin; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; + +namespace Flow.Launcher.ViewModel +{ + class ResultsForUpdate + { + public List Results { get; } + + public PluginMetadata Metadata { get; } + public string ID { get; } + + public Query Query { get; } + public CancellationToken Token { get; } + + public ResultsForUpdate(List results, string resultID, CancellationToken token) + { + Results = results; + ID = resultID; + Token = token; + } + + + public ResultsForUpdate(List results, PluginMetadata metadata, Query query, CancellationToken token) + { + Results = results; + Metadata = metadata; + Query = query; + Token = token; + ID = metadata.ID; + } + } +} diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs index d30854180..ac435c494 100644 --- a/Flow.Launcher/ViewModel/ResultsViewModel.cs +++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs @@ -17,7 +17,6 @@ namespace Flow.Launcher.ViewModel public ResultCollection Results { get; } - private readonly object _addResultsLock = new object(); private readonly object _collectionLock = new object(); private readonly Settings _settings; private int MaxResults => _settings?.MaxResultsToShow ?? 6; @@ -134,70 +133,37 @@ namespace Flow.Launcher.ViewModel /// public void AddResults(List newRawResults, string resultId) { - lock (_addResultsLock) + var newResults = NewResults(newRawResults, resultId); + + // update UI in one run, so it can avoid UI flickering + Results.Update(newResults); + + if (Results.Count > 0) { - var newResults = NewResults(newRawResults, resultId); - - // update UI in one run, so it can avoid UI flickering - Results.Update(newResults); - - if (Results.Count > 0) - { - Margin = new Thickness { Top = 8 }; - SelectedIndex = 0; - } - else - { - Margin = new Thickness { Top = 0 }; - } + Margin = new Thickness { Top = 8 }; + SelectedIndex = 0; + } + else + { + Margin = new Thickness { Top = 0 }; } } private List NewResults(List newRawResults, string resultId) { - var results = Results.ToList(); + if (newRawResults.Count == 0) + return Results.ToList(); + + var results = Results as IEnumerable; + var newResults = newRawResults.Select(r => new ResultViewModel(r, _settings)).ToList(); - var oldResults = results.Where(r => r.Result.PluginID == resultId).ToList(); - // Find the same results in A (old results) and B (new newResults) - var sameResults = oldResults - .Where(t1 => newResults.Any(x => x.Result.Equals(t1.Result))) - .ToList(); - // remove result of relative complement of B in A - foreach (var result in oldResults.Except(sameResults)) - { - results.Remove(result); - } - - // update result with B's score and index position - foreach (var sameResult in sameResults) - { - int oldIndex = results.IndexOf(sameResult); - int oldScore = results[oldIndex].Result.Score; - var newResult = newResults[newResults.IndexOf(sameResult)]; - int newScore = newResult.Result.Score; - if (newScore != oldScore) - { - var oldResult = results[oldIndex]; - - oldResult.Result.Score = newScore; - oldResult.Result.OriginQuery = newResult.Result.OriginQuery; - - results.RemoveAt(oldIndex); - int newIndex = InsertIndexOf(newScore, results); - results.Insert(newIndex, oldResult); - } - } - - // insert result in relative complement of A in B - foreach (var result in newResults.Except(sameResults)) - { - int newIndex = InsertIndexOf(result.Result.Score, results); - results.Insert(newIndex, result); - } - - return results; + return results.Where(r => r.Result.PluginID != resultId) + .Concat(newResults) + .OrderByDescending(r => r.Result.Score) + .Take(MaxResults * 2) + .ToList(); } #endregion @@ -254,6 +220,17 @@ namespace Flow.Launcher.ViewModel /// public void Update(List newItems) { + ClearItems(); + + foreach (var item in newItems) + { + Add(item); + } + + + + return; + int newCount = newItems.Count; int oldCount = Items.Count; int location = newCount > oldCount ? oldCount : newCount;