diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Main.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/Main.cs index 3c4d4c67d..a573674ec 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Main.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; +using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using System.Windows.Controls; @@ -13,14 +14,12 @@ using Flow.Launcher.Plugin.SharedCommands; namespace Flow.Launcher.Plugin.WebSearch { - public class Main : IPlugin, ISettingProvider, IPluginI18n, ISavable, IResultUpdated + public class Main : IAsyncPlugin, ISettingProvider, IPluginI18n, ISavable, IResultUpdated { private PluginInitContext _context; private readonly Settings _settings; private readonly SettingsViewModel _viewModel; - private CancellationTokenSource _updateSource; - private CancellationToken _updateToken; internal const string Images = "Images"; internal static string DefaultImagesDirectory; @@ -33,7 +32,7 @@ namespace Flow.Launcher.Plugin.WebSearch _viewModel.Save(); } - public List Query(Query query) + public async Task> QueryAsync(Query query, CancellationToken token) { if (FilesFolders.IsLocationPathString(query.Search)) return new List(); @@ -41,11 +40,7 @@ namespace Flow.Launcher.Plugin.WebSearch var searchSourceList = new List(); var results = new List(); - _updateSource?.Cancel(); - _updateSource = new CancellationTokenSource(); - _updateToken = _updateSource.Token; - - _settings.SearchSources.Where(o => (o.ActionKeyword == query.ActionKeyword || o.ActionKeyword == SearchSourceGlobalPluginWildCardSign) + _settings.SearchSources.Where(o => (o.ActionKeyword == query.ActionKeyword || o.ActionKeyword == SearchSourceGlobalPluginWildCardSign) && o.Enabled) .ToList() .ForEach(x => searchSourceList.Add(x)); @@ -94,49 +89,45 @@ namespace Flow.Launcher.Plugin.WebSearch }; results.Add(result); - ResultsUpdated?.Invoke(this, new ResultUpdatedEventArgs - { - Results = results, - Query = query - }); - - UpdateResultsFromSuggestion(results, keyword, subtitle, searchSource, query); } + + ResultsUpdated?.Invoke(this, new ResultUpdatedEventArgs + { + Results = results, + Query = query + }); + + await UpdateResultsFromSuggestionAsync(results, keyword, subtitle, searchSource, query, token).ConfigureAwait(false); } } return results; } - private void UpdateResultsFromSuggestion(List results, string keyword, string subtitle, - SearchSource searchSource, Query query) + private async Task UpdateResultsFromSuggestionAsync(List results, string keyword, string subtitle, + SearchSource searchSource, Query query, CancellationToken token) { if (_settings.EnableSuggestion) { - const int waittime = 300; - var task = Task.Run(async () => - { - var suggestions = await Suggestions(keyword, subtitle, searchSource); - results.AddRange(suggestions); - }, _updateToken); + var suggestions = await SuggestionsAsync(keyword, subtitle, searchSource, token).ConfigureAwait(false); + results.AddRange(suggestions); - if (!task.Wait(waittime)) + token.ThrowIfCancellationRequested(); + + ResultsUpdated?.Invoke(this, new ResultUpdatedEventArgs { - task.ContinueWith(_ => ResultsUpdated?.Invoke(this, new ResultUpdatedEventArgs - { - Results = results, - Query = query - }), _updateToken); - } + Results = results, + Query = query + }); } } - private async Task> Suggestions(string keyword, string subtitle, SearchSource searchSource) + private async Task> SuggestionsAsync(string keyword, string subtitle, SearchSource searchSource, CancellationToken token) { var source = _settings.SelectedSuggestion; if (source != null) { - var suggestions = await source.Suggestions(keyword); + var suggestions = await source.Suggestions(keyword, token); var resultsFromSuggestion = suggestions.Select(o => new Result { Title = o, @@ -169,19 +160,24 @@ namespace Flow.Launcher.Plugin.WebSearch _settings = _viewModel.Settings; } - public void Init(PluginInitContext context) + public Task InitAsync(PluginInitContext context) { - _context = context; - var pluginDirectory = _context.CurrentPluginMetadata.PluginDirectory; - var bundledImagesDirectory = Path.Combine(pluginDirectory, Images); - - // Default images directory is in the WebSearch's application folder - DefaultImagesDirectory = Path.Combine(pluginDirectory, Images); - Helper.ValidateDataDirectory(bundledImagesDirectory, DefaultImagesDirectory); + return Task.Run(Init); - // Custom images directory is in the WebSearch's data location folder - var name = Path.GetFileNameWithoutExtension(_context.CurrentPluginMetadata.ExecuteFileName); - CustomImagesDirectory = Path.Combine(DataLocation.PluginSettingsDirectory, name, "CustomIcons"); + void Init() + { + _context = context; + var pluginDirectory = _context.CurrentPluginMetadata.PluginDirectory; + var bundledImagesDirectory = Path.Combine(pluginDirectory, Images); + + // Default images directory is in the WebSearch's application folder + DefaultImagesDirectory = Path.Combine(pluginDirectory, Images); + Helper.ValidateDataDirectory(bundledImagesDirectory, DefaultImagesDirectory); + + // Custom images directory is in the WebSearch's data location folder + var name = Path.GetFileNameWithoutExtension(_context.CurrentPluginMetadata.ExecuteFileName); + CustomImagesDirectory = Path.Combine(DataLocation.PluginSettingsDirectory, name, "CustomIcons"); + }; } #region ISettingProvider Members diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs index 6772acf82..0c6d95b4f 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Baidu.cs @@ -9,6 +9,7 @@ using Newtonsoft.Json.Linq; using Flow.Launcher.Infrastructure.Http; using Flow.Launcher.Infrastructure.Logger; using System.Net.Http; +using System.Threading; namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources { @@ -16,14 +17,14 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources { private readonly Regex _reg = new Regex("window.baidu.sug\\((.*)\\)"); - public override async Task> Suggestions(string query) + public override async Task> Suggestions(string query, CancellationToken token) { string result; try { const string api = "http://suggestion.baidu.com/su?json=1&wd="; - result = await Http.GetAsync(api + Uri.EscapeUriString(query)).ConfigureAwait(false); + result = await Http.GetAsync(api + Uri.EscapeUriString(query), token).ConfigureAwait(false); } catch (HttpRequestException e) { diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs index 9c4746711..991e45267 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Bing.cs @@ -9,19 +9,20 @@ using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Text.Json; using System.Linq; +using System.Threading; namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources { class Bing : SuggestionSource { - public override async Task> Suggestions(string query) + public override async Task> Suggestions(string query, CancellationToken token) { Stream resultStream; try { const string api = "https://api.bing.com/qsonhs.aspx?q="; - resultStream = await Http.GetStreamAsync(api + Uri.EscapeUriString(query)).ConfigureAwait(false); + resultStream = await Http.GetStreamAsync(api + Uri.EscapeUriString(query), token).ConfigureAwait(false); } catch (HttpRequestException e) { @@ -29,7 +30,7 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources return new List(); } - if (resultStream.Length == 0) return new List(); + if (resultStream.Length == 0) return new List(); // this handles the cancellation JsonElement json; try diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs index 5b9538091..d034679af 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/Google.cs @@ -8,18 +8,19 @@ using Newtonsoft.Json.Linq; using Flow.Launcher.Infrastructure.Http; using Flow.Launcher.Infrastructure.Logger; using System.Net.Http; +using System.Threading; namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources { public class Google : SuggestionSource { - public override async Task> Suggestions(string query) + public override async Task> Suggestions(string query, CancellationToken token) { string result; try { const string api = "https://www.google.com/complete/search?output=chrome&q="; - result = await Http.GetAsync(api + Uri.EscapeUriString(query)).ConfigureAwait(false); + result = await Http.GetAsync(api + Uri.EscapeUriString(query), token).ConfigureAwait(false); } catch (HttpRequestException e) { diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/SuggestionSource.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/SuggestionSource.cs index d6d89415f..bf444a2f7 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/SuggestionSource.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SuggestionSources/SuggestionSource.cs @@ -1,10 +1,11 @@ using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources { public abstract class SuggestionSource { - public abstract Task> Suggestions(string query); + public abstract Task> Suggestions(string query, CancellationToken token); } } \ No newline at end of file