mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Move WebSearch to Async model
This commit is contained in:
parent
d0d938b92a
commit
a4edbc2cb9
5 changed files with 52 additions and 52 deletions
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
|
|
@ -13,14 +14,12 @@ using Flow.Launcher.Plugin.SharedCommands;
|
||||||
|
|
||||||
namespace Flow.Launcher.Plugin.WebSearch
|
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 PluginInitContext _context;
|
||||||
|
|
||||||
private readonly Settings _settings;
|
private readonly Settings _settings;
|
||||||
private readonly SettingsViewModel _viewModel;
|
private readonly SettingsViewModel _viewModel;
|
||||||
private CancellationTokenSource _updateSource;
|
|
||||||
private CancellationToken _updateToken;
|
|
||||||
|
|
||||||
internal const string Images = "Images";
|
internal const string Images = "Images";
|
||||||
internal static string DefaultImagesDirectory;
|
internal static string DefaultImagesDirectory;
|
||||||
|
|
@ -33,7 +32,7 @@ namespace Flow.Launcher.Plugin.WebSearch
|
||||||
_viewModel.Save();
|
_viewModel.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Result> Query(Query query)
|
public async Task<List<Result>> QueryAsync(Query query, CancellationToken token)
|
||||||
{
|
{
|
||||||
if (FilesFolders.IsLocationPathString(query.Search))
|
if (FilesFolders.IsLocationPathString(query.Search))
|
||||||
return new List<Result>();
|
return new List<Result>();
|
||||||
|
|
@ -41,11 +40,7 @@ namespace Flow.Launcher.Plugin.WebSearch
|
||||||
var searchSourceList = new List<SearchSource>();
|
var searchSourceList = new List<SearchSource>();
|
||||||
var results = new List<Result>();
|
var results = new List<Result>();
|
||||||
|
|
||||||
_updateSource?.Cancel();
|
_settings.SearchSources.Where(o => (o.ActionKeyword == query.ActionKeyword || o.ActionKeyword == SearchSourceGlobalPluginWildCardSign)
|
||||||
_updateSource = new CancellationTokenSource();
|
|
||||||
_updateToken = _updateSource.Token;
|
|
||||||
|
|
||||||
_settings.SearchSources.Where(o => (o.ActionKeyword == query.ActionKeyword || o.ActionKeyword == SearchSourceGlobalPluginWildCardSign)
|
|
||||||
&& o.Enabled)
|
&& o.Enabled)
|
||||||
.ToList()
|
.ToList()
|
||||||
.ForEach(x => searchSourceList.Add(x));
|
.ForEach(x => searchSourceList.Add(x));
|
||||||
|
|
@ -94,49 +89,45 @@ namespace Flow.Launcher.Plugin.WebSearch
|
||||||
};
|
};
|
||||||
|
|
||||||
results.Add(result);
|
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;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateResultsFromSuggestion(List<Result> results, string keyword, string subtitle,
|
private async Task UpdateResultsFromSuggestionAsync(List<Result> results, string keyword, string subtitle,
|
||||||
SearchSource searchSource, Query query)
|
SearchSource searchSource, Query query, CancellationToken token)
|
||||||
{
|
{
|
||||||
if (_settings.EnableSuggestion)
|
if (_settings.EnableSuggestion)
|
||||||
{
|
{
|
||||||
const int waittime = 300;
|
var suggestions = await SuggestionsAsync(keyword, subtitle, searchSource, token).ConfigureAwait(false);
|
||||||
var task = Task.Run(async () =>
|
results.AddRange(suggestions);
|
||||||
{
|
|
||||||
var suggestions = await Suggestions(keyword, subtitle, searchSource);
|
|
||||||
results.AddRange(suggestions);
|
|
||||||
}, _updateToken);
|
|
||||||
|
|
||||||
if (!task.Wait(waittime))
|
token.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
ResultsUpdated?.Invoke(this, new ResultUpdatedEventArgs
|
||||||
{
|
{
|
||||||
task.ContinueWith(_ => ResultsUpdated?.Invoke(this, new ResultUpdatedEventArgs
|
Results = results,
|
||||||
{
|
Query = query
|
||||||
Results = results,
|
});
|
||||||
Query = query
|
|
||||||
}), _updateToken);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<IEnumerable<Result>> Suggestions(string keyword, string subtitle, SearchSource searchSource)
|
private async Task<IEnumerable<Result>> SuggestionsAsync(string keyword, string subtitle, SearchSource searchSource, CancellationToken token)
|
||||||
{
|
{
|
||||||
var source = _settings.SelectedSuggestion;
|
var source = _settings.SelectedSuggestion;
|
||||||
if (source != null)
|
if (source != null)
|
||||||
{
|
{
|
||||||
var suggestions = await source.Suggestions(keyword);
|
var suggestions = await source.Suggestions(keyword, token);
|
||||||
var resultsFromSuggestion = suggestions.Select(o => new Result
|
var resultsFromSuggestion = suggestions.Select(o => new Result
|
||||||
{
|
{
|
||||||
Title = o,
|
Title = o,
|
||||||
|
|
@ -169,19 +160,24 @@ namespace Flow.Launcher.Plugin.WebSearch
|
||||||
_settings = _viewModel.Settings;
|
_settings = _viewModel.Settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Init(PluginInitContext context)
|
public Task InitAsync(PluginInitContext context)
|
||||||
{
|
{
|
||||||
_context = context;
|
return Task.Run(Init);
|
||||||
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
|
void Init()
|
||||||
var name = Path.GetFileNameWithoutExtension(_context.CurrentPluginMetadata.ExecuteFileName);
|
{
|
||||||
CustomImagesDirectory = Path.Combine(DataLocation.PluginSettingsDirectory, name, "CustomIcons");
|
_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
|
#region ISettingProvider Members
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ using Newtonsoft.Json.Linq;
|
||||||
using Flow.Launcher.Infrastructure.Http;
|
using Flow.Launcher.Infrastructure.Http;
|
||||||
using Flow.Launcher.Infrastructure.Logger;
|
using Flow.Launcher.Infrastructure.Logger;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
|
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\\((.*)\\)");
|
private readonly Regex _reg = new Regex("window.baidu.sug\\((.*)\\)");
|
||||||
|
|
||||||
public override async Task<List<string>> Suggestions(string query)
|
public override async Task<List<string>> Suggestions(string query, CancellationToken token)
|
||||||
{
|
{
|
||||||
string result;
|
string result;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const string api = "http://suggestion.baidu.com/su?json=1&wd=";
|
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)
|
catch (HttpRequestException e)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -9,19 +9,20 @@ using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
|
namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
|
||||||
{
|
{
|
||||||
class Bing : SuggestionSource
|
class Bing : SuggestionSource
|
||||||
{
|
{
|
||||||
public override async Task<List<string>> Suggestions(string query)
|
public override async Task<List<string>> Suggestions(string query, CancellationToken token)
|
||||||
{
|
{
|
||||||
Stream resultStream;
|
Stream resultStream;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const string api = "https://api.bing.com/qsonhs.aspx?q=";
|
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)
|
catch (HttpRequestException e)
|
||||||
{
|
{
|
||||||
|
|
@ -29,7 +30,7 @@ namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
|
||||||
return new List<string>();
|
return new List<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resultStream.Length == 0) return new List<string>();
|
if (resultStream.Length == 0) return new List<string>(); // this handles the cancellation
|
||||||
|
|
||||||
JsonElement json;
|
JsonElement json;
|
||||||
try
|
try
|
||||||
|
|
|
||||||
|
|
@ -8,18 +8,19 @@ using Newtonsoft.Json.Linq;
|
||||||
using Flow.Launcher.Infrastructure.Http;
|
using Flow.Launcher.Infrastructure.Http;
|
||||||
using Flow.Launcher.Infrastructure.Logger;
|
using Flow.Launcher.Infrastructure.Logger;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
|
namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
|
||||||
{
|
{
|
||||||
public class Google : SuggestionSource
|
public class Google : SuggestionSource
|
||||||
{
|
{
|
||||||
public override async Task<List<string>> Suggestions(string query)
|
public override async Task<List<string>> Suggestions(string query, CancellationToken token)
|
||||||
{
|
{
|
||||||
string result;
|
string result;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const string api = "https://www.google.com/complete/search?output=chrome&q=";
|
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)
|
catch (HttpRequestException e)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
|
namespace Flow.Launcher.Plugin.WebSearch.SuggestionSources
|
||||||
{
|
{
|
||||||
public abstract class SuggestionSource
|
public abstract class SuggestionSource
|
||||||
{
|
{
|
||||||
public abstract Task<List<string>> Suggestions(string query);
|
public abstract Task<List<string>> Suggestions(string query, CancellationToken token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue