mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Use new model to clear results & Fix clear existing results when using IResultUpdate (#3588)
This commit is contained in:
parent
a68c69bb06
commit
a06cb43540
6 changed files with 63 additions and 33 deletions
|
|
@ -16,7 +16,8 @@ namespace Flow.Launcher.Core.Plugin
|
||||||
Search = string.Empty,
|
Search = string.Empty,
|
||||||
RawQuery = string.Empty,
|
RawQuery = string.Empty,
|
||||||
SearchTerms = Array.Empty<string>(),
|
SearchTerms = Array.Empty<string>(),
|
||||||
ActionKeyword = string.Empty
|
ActionKeyword = string.Empty,
|
||||||
|
IsHomeQuery = true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -53,7 +54,8 @@ namespace Flow.Launcher.Core.Plugin
|
||||||
Search = search,
|
Search = search,
|
||||||
RawQuery = rawQuery,
|
RawQuery = rawQuery,
|
||||||
SearchTerms = searchTerms,
|
SearchTerms = searchTerms,
|
||||||
ActionKeyword = actionKeyword
|
ActionKeyword = actionKeyword,
|
||||||
|
IsHomeQuery = false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,11 @@ namespace Flow.Launcher.Plugin
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsReQuery { get; internal set; } = false;
|
public bool IsReQuery { get; internal set; } = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether the query is a home query.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsHomeQuery { get; internal init; } = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Search part of a query.
|
/// Search part of a query.
|
||||||
/// This will not include action keyword if exclusive plugin gets it, otherwise it should be same as RawQuery.
|
/// This will not include action keyword if exclusive plugin gets it, otherwise it should be same as RawQuery.
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ namespace Flow.Launcher
|
||||||
|
|
||||||
private void ThemeManager_ActualApplicationThemeChanged(ModernWpf.ThemeManager sender, object args)
|
private void ThemeManager_ActualApplicationThemeChanged(ModernWpf.ThemeManager sender, object args)
|
||||||
{
|
{
|
||||||
_theme.RefreshFrameAsync();
|
_ = _theme.RefreshFrameAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSourceInitialized(object sender, EventArgs e)
|
private void OnSourceInitialized(object sender, EventArgs e)
|
||||||
|
|
|
||||||
|
|
@ -216,7 +216,26 @@ namespace Flow.Launcher.ViewModel
|
||||||
while (channelReader.TryRead(out var item))
|
while (channelReader.TryRead(out var item))
|
||||||
{
|
{
|
||||||
if (!item.Token.IsCancellationRequested)
|
if (!item.Token.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
// Indicate if to clear existing results so to show only ones from plugins with action keywords
|
||||||
|
var query = item.Query;
|
||||||
|
var currentIsHomeQuery = query.IsHomeQuery;
|
||||||
|
var shouldClearExistingResults = ShouldClearExistingResultsForQuery(query, currentIsHomeQuery);
|
||||||
|
_lastQuery = item.Query;
|
||||||
|
_previousIsHomeQuery = currentIsHomeQuery;
|
||||||
|
|
||||||
|
// If the queue already has the item, we need to pass the shouldClearExistingResults flag
|
||||||
|
if (queue.TryGetValue(item.ID, out var existingItem))
|
||||||
|
{
|
||||||
|
item.ShouldClearExistingResults = shouldClearExistingResults || existingItem.ShouldClearExistingResults;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item.ShouldClearExistingResults = shouldClearExistingResults;
|
||||||
|
}
|
||||||
|
|
||||||
queue[item.ID] = item;
|
queue[item.ID] = item;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateResultView(queue.Values);
|
UpdateResultView(queue.Values);
|
||||||
|
|
@ -268,6 +287,8 @@ namespace Flow.Launcher.ViewModel
|
||||||
|
|
||||||
if (token.IsCancellationRequested) return;
|
if (token.IsCancellationRequested) return;
|
||||||
|
|
||||||
|
App.API.LogDebug(ClassName, $"Update results for plugin <{pair.Metadata.Name}>");
|
||||||
|
|
||||||
if (!_resultsUpdateChannelWriter.TryWrite(new ResultsForUpdate(resultsCopy, pair.Metadata, e.Query,
|
if (!_resultsUpdateChannelWriter.TryWrite(new ResultsForUpdate(resultsCopy, pair.Metadata, e.Query,
|
||||||
token)))
|
token)))
|
||||||
{
|
{
|
||||||
|
|
@ -1262,7 +1283,7 @@ namespace Flow.Launcher.ViewModel
|
||||||
|
|
||||||
App.API.LogDebug(ClassName, $"Start query with ActionKeyword <{query.ActionKeyword}> and RawQuery <{query.RawQuery}>");
|
App.API.LogDebug(ClassName, $"Start query with ActionKeyword <{query.ActionKeyword}> and RawQuery <{query.RawQuery}>");
|
||||||
|
|
||||||
var currentIsHomeQuery = query.RawQuery == string.Empty;
|
var currentIsHomeQuery = query.IsHomeQuery;
|
||||||
|
|
||||||
_updateSource?.Dispose();
|
_updateSource?.Dispose();
|
||||||
|
|
||||||
|
|
@ -1436,13 +1457,8 @@ namespace Flow.Launcher.ViewModel
|
||||||
|
|
||||||
App.API.LogDebug(ClassName, $"Update results for plugin <{plugin.Metadata.Name}>");
|
App.API.LogDebug(ClassName, $"Update results for plugin <{plugin.Metadata.Name}>");
|
||||||
|
|
||||||
// Indicate if to clear existing results so to show only ones from plugins with action keywords
|
|
||||||
var shouldClearExistingResults = ShouldClearExistingResultsForQuery(query, currentIsHomeQuery);
|
|
||||||
_lastQuery = query;
|
|
||||||
_previousIsHomeQuery = currentIsHomeQuery;
|
|
||||||
|
|
||||||
if (!_resultsUpdateChannelWriter.TryWrite(new ResultsForUpdate(resultsCopy, plugin.Metadata, query,
|
if (!_resultsUpdateChannelWriter.TryWrite(new ResultsForUpdate(resultsCopy, plugin.Metadata, query,
|
||||||
token, reSelect, shouldClearExistingResults)))
|
token, reSelect)))
|
||||||
{
|
{
|
||||||
App.API.LogError(ClassName, "Unable to add item to Result Update Queue");
|
App.API.LogError(ClassName, "Unable to add item to Result Update Queue");
|
||||||
}
|
}
|
||||||
|
|
@ -1459,13 +1475,8 @@ namespace Flow.Launcher.ViewModel
|
||||||
|
|
||||||
App.API.LogDebug(ClassName, $"Update results for history");
|
App.API.LogDebug(ClassName, $"Update results for history");
|
||||||
|
|
||||||
// Indicate if to clear existing results so to show only ones from plugins with action keywords
|
|
||||||
var shouldClearExistingResults = ShouldClearExistingResultsForQuery(query, currentIsHomeQuery);
|
|
||||||
_lastQuery = query;
|
|
||||||
_previousIsHomeQuery = currentIsHomeQuery;
|
|
||||||
|
|
||||||
if (!_resultsUpdateChannelWriter.TryWrite(new ResultsForUpdate(results, _historyMetadata, query,
|
if (!_resultsUpdateChannelWriter.TryWrite(new ResultsForUpdate(results, _historyMetadata, query,
|
||||||
token, reSelect, shouldClearExistingResults)))
|
token, reSelect)))
|
||||||
{
|
{
|
||||||
App.API.LogError(ClassName, "Unable to add item to Result Update Queue");
|
App.API.LogError(ClassName, "Unable to add item to Result Update Queue");
|
||||||
}
|
}
|
||||||
|
|
@ -1865,6 +1876,7 @@ namespace Flow.Launcher.ViewModel
|
||||||
{
|
{
|
||||||
if (!resultsForUpdates.Any())
|
if (!resultsForUpdates.Any())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CancellationToken token;
|
CancellationToken token;
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ namespace Flow.Launcher.ViewModel
|
||||||
Query Query,
|
Query Query,
|
||||||
CancellationToken Token,
|
CancellationToken Token,
|
||||||
bool ReSelectFirstResult = true,
|
bool ReSelectFirstResult = true,
|
||||||
bool shouldClearExistingResults = false)
|
bool ShouldClearExistingResults = false)
|
||||||
{
|
{
|
||||||
public string ID { get; } = Metadata.ID;
|
public string ID { get; } = Metadata.ID;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@ namespace Flow.Launcher.ViewModel
|
||||||
{
|
{
|
||||||
#region Private Fields
|
#region Private Fields
|
||||||
|
|
||||||
|
private readonly string ClassName = nameof(ResultsViewModel);
|
||||||
|
|
||||||
public ResultCollection Results { get; }
|
public ResultCollection Results { get; }
|
||||||
|
|
||||||
private readonly object _collectionLock = new();
|
private readonly object _collectionLock = new();
|
||||||
|
|
@ -187,11 +189,9 @@ namespace Flow.Launcher.ViewModel
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void AddResults(ICollection<ResultsForUpdate> resultsForUpdates, CancellationToken token, bool reselect = true)
|
public void AddResults(ICollection<ResultsForUpdate> resultsForUpdates, CancellationToken token, bool reselect = true)
|
||||||
{
|
{
|
||||||
|
// Since NewResults may need to clear existing results, do not check token cancellation after this point
|
||||||
var newResults = NewResults(resultsForUpdates);
|
var newResults = NewResults(resultsForUpdates);
|
||||||
|
|
||||||
if (token.IsCancellationRequested)
|
|
||||||
return;
|
|
||||||
|
|
||||||
UpdateResults(newResults, reselect, token);
|
UpdateResults(newResults, reselect, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -240,16 +240,20 @@ namespace Flow.Launcher.ViewModel
|
||||||
private List<ResultViewModel> NewResults(ICollection<ResultsForUpdate> resultsForUpdates)
|
private List<ResultViewModel> NewResults(ICollection<ResultsForUpdate> resultsForUpdates)
|
||||||
{
|
{
|
||||||
if (!resultsForUpdates.Any())
|
if (!resultsForUpdates.Any())
|
||||||
|
{
|
||||||
|
App.API.LogDebug(ClassName, "No results for updates, returning existing results");
|
||||||
return Results;
|
return Results;
|
||||||
|
}
|
||||||
|
|
||||||
var newResults = resultsForUpdates.SelectMany(u => u.Results, (u, r) => new ResultViewModel(r, _settings));
|
var newResults = resultsForUpdates.SelectMany(u => u.Results, (u, r) => new ResultViewModel(r, _settings));
|
||||||
|
|
||||||
if (resultsForUpdates.Any(x => x.shouldClearExistingResults))
|
if (resultsForUpdates.Any(x => x.ShouldClearExistingResults))
|
||||||
{
|
{
|
||||||
App.API.LogDebug("NewResults", $"Existing results are cleared for query");
|
App.API.LogDebug(ClassName, $"Existing results are cleared for query");
|
||||||
return newResults.OrderByDescending(rv => rv.Result.Score).ToList();
|
return newResults.OrderByDescending(rv => rv.Result.Score).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
App.API.LogDebug(ClassName, $"Keeping existing results for {resultsForUpdates.Count} queries");
|
||||||
return Results.Where(r => r?.Result != null && resultsForUpdates.All(u => u.ID != r.Result.PluginID))
|
return Results.Where(r => r?.Result != null && resultsForUpdates.All(u => u.ID != r.Result.PluginID))
|
||||||
.Concat(newResults)
|
.Concat(newResults)
|
||||||
.OrderByDescending(rv => rv.Result.Score)
|
.OrderByDescending(rv => rv.Result.Score)
|
||||||
|
|
@ -293,8 +297,6 @@ namespace Flow.Launcher.ViewModel
|
||||||
{
|
{
|
||||||
private long editTime = 0;
|
private long editTime = 0;
|
||||||
|
|
||||||
private CancellationToken _token;
|
|
||||||
|
|
||||||
public event NotifyCollectionChangedEventHandler CollectionChanged;
|
public event NotifyCollectionChangedEventHandler CollectionChanged;
|
||||||
|
|
||||||
protected void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
|
protected void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
|
||||||
|
|
@ -302,12 +304,12 @@ namespace Flow.Launcher.ViewModel
|
||||||
CollectionChanged?.Invoke(this, e);
|
CollectionChanged?.Invoke(this, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BulkAddAll(List<ResultViewModel> resultViews)
|
private void BulkAddAll(List<ResultViewModel> resultViews, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
AddRange(resultViews);
|
AddRange(resultViews);
|
||||||
|
|
||||||
// can return because the list will be cleared next time updated, which include a reset event
|
// can return because the list will be cleared next time updated, which include a reset event
|
||||||
if (_token.IsCancellationRequested)
|
if (token.IsCancellationRequested)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// manually update event
|
// manually update event
|
||||||
|
|
@ -315,12 +317,12 @@ namespace Flow.Launcher.ViewModel
|
||||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddAll(List<ResultViewModel> Items)
|
private void AddAll(List<ResultViewModel> Items, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < Items.Count; i++)
|
for (int i = 0; i < Items.Count; i++)
|
||||||
{
|
{
|
||||||
var item = Items[i];
|
var item = Items[i];
|
||||||
if (_token.IsCancellationRequested)
|
if (token.IsCancellationRequested)
|
||||||
return;
|
return;
|
||||||
Add(item);
|
Add(item);
|
||||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, i));
|
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, i));
|
||||||
|
|
@ -342,21 +344,30 @@ namespace Flow.Launcher.ViewModel
|
||||||
/// <param name="newItems"></param>
|
/// <param name="newItems"></param>
|
||||||
public void Update(List<ResultViewModel> newItems, CancellationToken token = default)
|
public void Update(List<ResultViewModel> newItems, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
_token = token;
|
// Since NewResults may need to clear existing results, so we cannot check token cancellation here
|
||||||
if (Count == 0 && newItems.Count == 0 || _token.IsCancellationRequested)
|
if (Count == 0 && newItems.Count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (editTime < 10 || newItems.Count < 30)
|
if (editTime < 10 || newItems.Count < 30)
|
||||||
{
|
{
|
||||||
if (Count != 0) RemoveAll(newItems.Count);
|
if (Count != 0) RemoveAll(newItems.Count);
|
||||||
AddAll(newItems);
|
|
||||||
|
// After results are removed, we need to check the token cancellation
|
||||||
|
// so that we will not add new items from the cancelled queries
|
||||||
|
if (token.IsCancellationRequested) return;
|
||||||
|
|
||||||
|
AddAll(newItems, token);
|
||||||
editTime++;
|
editTime++;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
BulkAddAll(newItems);
|
|
||||||
|
// After results are removed, we need to check the token cancellation
|
||||||
|
// so that we will not add new items from the cancelled queries
|
||||||
|
if (token.IsCancellationRequested) return;
|
||||||
|
|
||||||
|
BulkAddAll(newItems, token);
|
||||||
if (Capacity > 8000 && newItems.Count < 3000)
|
if (Capacity > 8000 && newItems.Count < 3000)
|
||||||
{
|
{
|
||||||
Capacity = newItems.Count;
|
Capacity = newItems.Count;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue