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;