diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index 49fe680f1c8..c95a8ce7b23 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -291,5 +291,12 @@ public interface IPublicAPI /// /// public bool IsGameModeOn(); + + /// + /// Reloads the query. + /// This method should run + /// + /// Choose the first result after reload if true; keep the last selected result if false. Default is true. + public void ReQuery(bool reselect = true); } } diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index 36309a22a4f..b49bf39d3c5 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -315,6 +315,8 @@ public bool IsGameModeOn() public void RegisterGlobalKeyboardCallback(Func callback) => _globalKeyboardHandlers.Add(callback); public void RemoveGlobalKeyboardCallback(Func callback) => _globalKeyboardHandlers.Remove(callback); + public void ReQuery(bool reselect = true) => _mainVM.ReQuery(reselect); + #endregion #region Private Methods diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index aa300ea31e9..b6483a56ee3 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -210,7 +210,7 @@ private void LoadHistory() } [RelayCommand] - private void ReQuery() + public void ReQuery() { if (SelectedIsFromQueryResults()) { @@ -218,6 +218,14 @@ private void ReQuery() } } + public void ReQuery(bool reselect) + { + if (SelectedIsFromQueryResults()) + { + QueryResults(isReQuery: true, reSelect: reselect); + } + } + [RelayCommand] private void LoadContextMenu() { @@ -775,7 +783,7 @@ private void QueryHistory() private readonly IReadOnlyList _emptyResult = new List(); - private async void QueryResults(bool isReQuery = false) + private async void QueryResults(bool isReQuery = false, bool reSelect = true) { _updateSource?.Cancel(); @@ -850,7 +858,7 @@ private async void QueryResults(bool isReQuery = false) var tasks = plugins.Select(plugin => plugin.Metadata.Disabled switch { - false => QueryTask(plugin), + false => QueryTask(plugin, reSelect), true => Task.CompletedTask }).ToArray(); @@ -878,7 +886,7 @@ private async void QueryResults(bool isReQuery = false) } // Local function - async Task QueryTask(PluginPair plugin) + async Task QueryTask(PluginPair plugin, bool reSelect = true) { // Since it is wrapped within a ThreadPool Thread, the synchronous context is null // Task.Yield will force it to run in ThreadPool @@ -892,7 +900,7 @@ async Task QueryTask(PluginPair plugin) results ??= _emptyResult; if (!_resultsUpdateChannelWriter.TryWrite(new ResultsForUpdate(results, plugin.Metadata, query, - currentCancellationToken))) + currentCancellationToken, reSelect))) { Log.Error("MainViewModel", "Unable to add item to Result Update Queue"); } @@ -1133,7 +1141,7 @@ public void Save() /// /// To avoid deadlock, this method should not called from main thread /// - public void UpdateResultView(IEnumerable resultsForUpdates) + public void UpdateResultView(ICollection resultsForUpdates) { if (!resultsForUpdates.Any()) return; @@ -1172,7 +1180,10 @@ public void UpdateResultView(IEnumerable resultsForUpdates) } } - Results.AddResults(resultsForUpdates, token); + // it should be the same for all results + bool reSelect = resultsForUpdates.First().ReSelectFirstResult; + + Results.AddResults(resultsForUpdates, token, reSelect); } #endregion diff --git a/Flow.Launcher/ViewModel/ResultsForUpdate.cs b/Flow.Launcher/ViewModel/ResultsForUpdate.cs index 4cb5b1a952c..bc0be0de81e 100644 --- a/Flow.Launcher/ViewModel/ResultsForUpdate.cs +++ b/Flow.Launcher/ViewModel/ResultsForUpdate.cs @@ -4,23 +4,13 @@ namespace Flow.Launcher.ViewModel { - public struct ResultsForUpdate + public record struct ResultsForUpdate( + IReadOnlyList Results, + PluginMetadata Metadata, + Query Query, + CancellationToken Token, + bool ReSelectFirstResult = true) { - public IReadOnlyList Results { get; } - - public PluginMetadata Metadata { get; } - public string ID { get; } - - public Query Query { get; } - public CancellationToken Token { get; } - - public ResultsForUpdate(IReadOnlyList results, PluginMetadata metadata, Query query, CancellationToken token) - { - Results = results; - Metadata = metadata; - Query = query; - Token = token; - ID = metadata.ID; - } + public string ID { get; } = Metadata.ID; } } diff --git a/Flow.Launcher/ViewModel/ResultsViewModel.cs b/Flow.Launcher/ViewModel/ResultsViewModel.cs index bb07ce085e8..d02dc9bd582 100644 --- a/Flow.Launcher/ViewModel/ResultsViewModel.cs +++ b/Flow.Launcher/ViewModel/ResultsViewModel.cs @@ -147,23 +147,23 @@ public void AddResults(List newRawResults, string resultId) /// /// To avoid deadlock, this method should not called from main thread /// - public void AddResults(IEnumerable resultsForUpdates, CancellationToken token) + public void AddResults(IEnumerable resultsForUpdates, CancellationToken token, bool reselect = true) { var newResults = NewResults(resultsForUpdates); if (token.IsCancellationRequested) return; - UpdateResults(newResults, token); + UpdateResults(newResults, token, reselect); } - private void UpdateResults(List newResults, CancellationToken token = default) + private void UpdateResults(List newResults, CancellationToken token = default, bool reselect = true) { lock (_collectionLock) { // update UI in one run, so it can avoid UI flickering Results.Update(newResults, token); - if (Results.Any()) + if (reselect && Results.Any()) SelectedItem = Results[0]; }