mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Change UI rendering logic
Co-authored-by: Bao-Qian <bao.github@outlook.com>
This commit is contained in:
parent
c254c93255
commit
9d21649622
4 changed files with 92 additions and 59 deletions
|
|
@ -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 />
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
36
Flow.Launcher/ViewModel/ResultsForUpdate.cs
Normal file
36
Flow.Launcher/ViewModel/ResultsForUpdate.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue