Change UI rendering logic

Co-authored-by: Bao-Qian <bao.github@outlook.com>
This commit is contained in:
弘韬 张 2020-11-10 17:13:45 +08:00
parent c254c93255
commit 9d21649622
4 changed files with 92 additions and 59 deletions

View file

@ -42,7 +42,7 @@
<ColumnDefinition Width="0" />
</Grid.ColumnDefinitions>
<Image x:Name="ImageIcon" Width="32" Height="32" HorizontalAlignment="Left"
Source="{Binding Image ,IsAsync=True}" />
Source="{Binding Image}" />
<Grid Margin="5 0 5 0" Grid.Column="1" HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition />

View file

@ -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<ResultsForUpdate> _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<ResultsForUpdate>();
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));
}
});
}

View file

@ -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<Result> Results { get; }
public PluginMetadata Metadata { get; }
public string ID { get; }
public Query Query { get; }
public CancellationToken Token { get; }
public ResultsForUpdate(List<Result> results, string resultID, CancellationToken token)
{
Results = results;
ID = resultID;
Token = token;
}
public ResultsForUpdate(List<Result> results, PluginMetadata metadata, Query query, CancellationToken token)
{
Results = results;
Metadata = metadata;
Query = query;
Token = token;
ID = metadata.ID;
}
}
}

View file

@ -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
/// </summary>
public void AddResults(List<Result> 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<ResultViewModel> NewResults(List<Result> newRawResults, string resultId)
{
var results = Results.ToList();
if (newRawResults.Count == 0)
return Results.ToList();
var results = Results as IEnumerable<ResultViewModel>;
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
/// <param name="newItems"></param>
public void Update(List<ResultViewModel> newItems)
{
ClearItems();
foreach (var item in newItems)
{
Add(item);
}
return;
int newCount = newItems.Count;
int oldCount = Items.Count;
int location = newCount > oldCount ? oldCount : newCount;