Use new model to clear results & Fix clear existing results when using IResultUpdate (#3588)

This commit is contained in:
Jack Ye 2025-06-02 11:16:22 +08:00 committed by GitHub
parent a68c69bb06
commit a06cb43540
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 63 additions and 33 deletions

View file

@ -16,7 +16,8 @@ namespace Flow.Launcher.Core.Plugin
Search = string.Empty,
RawQuery = string.Empty,
SearchTerms = Array.Empty<string>(),
ActionKeyword = string.Empty
ActionKeyword = string.Empty,
IsHomeQuery = true
};
}
@ -53,7 +54,8 @@ namespace Flow.Launcher.Core.Plugin
Search = search,
RawQuery = rawQuery,
SearchTerms = searchTerms,
ActionKeyword = actionKeyword
ActionKeyword = actionKeyword,
IsHomeQuery = false
};
}
}

View file

@ -21,6 +21,11 @@ namespace Flow.Launcher.Plugin
/// </summary>
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>
/// Search part of a query.
/// This will not include action keyword if exclusive plugin gets it, otherwise it should be same as RawQuery.

View file

@ -101,7 +101,7 @@ namespace Flow.Launcher
private void ThemeManager_ActualApplicationThemeChanged(ModernWpf.ThemeManager sender, object args)
{
_theme.RefreshFrameAsync();
_ = _theme.RefreshFrameAsync();
}
private void OnSourceInitialized(object sender, EventArgs e)

View file

@ -216,7 +216,26 @@ namespace Flow.Launcher.ViewModel
while (channelReader.TryRead(out var item))
{
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;
}
}
UpdateResultView(queue.Values);
@ -268,6 +287,8 @@ namespace Flow.Launcher.ViewModel
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,
token)))
{
@ -1262,7 +1283,7 @@ namespace Flow.Launcher.ViewModel
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();
@ -1436,13 +1457,8 @@ namespace Flow.Launcher.ViewModel
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,
token, reSelect, shouldClearExistingResults)))
token, reSelect)))
{
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");
// 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,
token, reSelect, shouldClearExistingResults)))
token, reSelect)))
{
App.API.LogError(ClassName, "Unable to add item to Result Update Queue");
}
@ -1865,6 +1876,7 @@ namespace Flow.Launcher.ViewModel
{
if (!resultsForUpdates.Any())
return;
CancellationToken token;
try

View file

@ -10,7 +10,7 @@ namespace Flow.Launcher.ViewModel
Query Query,
CancellationToken Token,
bool ReSelectFirstResult = true,
bool shouldClearExistingResults = false)
bool ShouldClearExistingResults = false)
{
public string ID { get; } = Metadata.ID;
}

View file

@ -17,6 +17,8 @@ namespace Flow.Launcher.ViewModel
{
#region Private Fields
private readonly string ClassName = nameof(ResultsViewModel);
public ResultCollection Results { get; }
private readonly object _collectionLock = new();
@ -187,11 +189,9 @@ namespace Flow.Launcher.ViewModel
/// </summary>
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);
if (token.IsCancellationRequested)
return;
UpdateResults(newResults, reselect, token);
}
@ -240,16 +240,20 @@ namespace Flow.Launcher.ViewModel
private List<ResultViewModel> NewResults(ICollection<ResultsForUpdate> resultsForUpdates)
{
if (!resultsForUpdates.Any())
{
App.API.LogDebug(ClassName, "No results for updates, returning existing results");
return Results;
}
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();
}
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))
.Concat(newResults)
.OrderByDescending(rv => rv.Result.Score)
@ -293,8 +297,6 @@ namespace Flow.Launcher.ViewModel
{
private long editTime = 0;
private CancellationToken _token;
public event NotifyCollectionChangedEventHandler CollectionChanged;
protected void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
@ -302,12 +304,12 @@ namespace Flow.Launcher.ViewModel
CollectionChanged?.Invoke(this, e);
}
public void BulkAddAll(List<ResultViewModel> resultViews)
private void BulkAddAll(List<ResultViewModel> resultViews, CancellationToken token = default)
{
AddRange(resultViews);
// can return because the list will be cleared next time updated, which include a reset event
if (_token.IsCancellationRequested)
if (token.IsCancellationRequested)
return;
// manually update event
@ -315,12 +317,12 @@ namespace Flow.Launcher.ViewModel
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++)
{
var item = Items[i];
if (_token.IsCancellationRequested)
if (token.IsCancellationRequested)
return;
Add(item);
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, i));
@ -342,21 +344,30 @@ namespace Flow.Launcher.ViewModel
/// <param name="newItems"></param>
public void Update(List<ResultViewModel> newItems, CancellationToken token = default)
{
_token = token;
if (Count == 0 && newItems.Count == 0 || _token.IsCancellationRequested)
// Since NewResults may need to clear existing results, so we cannot check token cancellation here
if (Count == 0 && newItems.Count == 0)
return;
if (editTime < 10 || newItems.Count < 30)
{
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++;
return;
}
else
{
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)
{
Capacity = newItems.Count;