Skip to content

Commit 1c39377

Browse files
authored
Merge pull request #260 from Flow-Launcher/dev
Release 1.7.0 | Plugin 1.4.0
2 parents b3eb82a + 1ec5023 commit 1c39377

File tree

135 files changed

+2753
-1968
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

135 files changed

+2753
-1968
lines changed
File renamed without changes.

Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
using System.Diagnostics;
44
using System.IO;
55
using System.Reflection;
6+
using System.Text.Json;
67
using System.Threading;
78
using System.Threading.Tasks;
89
using System.Windows.Forms;
9-
using Newtonsoft.Json;
1010
using Flow.Launcher.Infrastructure.Exception;
1111
using Flow.Launcher.Infrastructure.Logger;
1212
using Flow.Launcher.Plugin;
@@ -65,7 +65,7 @@ private List<Result> DeserializedResult(string output)
6565
{
6666
List<Result> results = new List<Result>();
6767

68-
JsonRPCQueryResponseModel queryResponseModel = JsonConvert.DeserializeObject<JsonRPCQueryResponseModel>(output);
68+
JsonRPCQueryResponseModel queryResponseModel = JsonSerializer.Deserialize<JsonRPCQueryResponseModel>(output);
6969
if (queryResponseModel.Result == null) return null;
7070

7171
foreach (JsonRPCResult result in queryResponseModel.Result)
@@ -84,7 +84,7 @@ private List<Result> DeserializedResult(string output)
8484
else
8585
{
8686
string actionReponse = ExecuteCallback(result1.JsonRPCAction);
87-
JsonRPCRequestModel jsonRpcRequestModel = JsonConvert.DeserializeObject<JsonRPCRequestModel>(actionReponse);
87+
JsonRPCRequestModel jsonRpcRequestModel = JsonSerializer.Deserialize<JsonRPCRequestModel>(actionReponse);
8888
if (jsonRpcRequestModel != null
8989
&& !String.IsNullOrEmpty(jsonRpcRequestModel.Method)
9090
&& jsonRpcRequestModel.Method.StartsWith("Flow.Launcher."))

Flow.Launcher.Core/Plugin/PluginAssemblyLoader.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ internal PluginAssemblyLoader(string assemblyFilePath)
2020
dependencyResolver = new AssemblyDependencyResolver(assemblyFilePath);
2121
assemblyName = new AssemblyName(Path.GetFileNameWithoutExtension(assemblyFilePath));
2222

23-
referencedPluginPackageDependencyResolver =
23+
referencedPluginPackageDependencyResolver =
2424
new AssemblyDependencyResolver(Path.Combine(Constant.ProgramDirectory, "Flow.Launcher.Plugin.dll"));
2525
}
2626

@@ -38,15 +38,15 @@ protected override Assembly Load(AssemblyName assemblyName)
3838
// that use Newtonsoft.Json
3939
if (assemblyPath == null || ExistsInReferencedPluginPackage(assemblyName))
4040
return null;
41-
41+
4242
return LoadFromAssemblyPath(assemblyPath);
4343
}
4444

45-
internal Type FromAssemblyGetTypeOfInterface(Assembly assembly, Type type)
45+
internal Type FromAssemblyGetTypeOfInterface(Assembly assembly, params Type[] types)
4646
{
4747
var allTypes = assembly.ExportedTypes;
4848

49-
return allTypes.First(o => o.IsClass && !o.IsAbstract && o.GetInterfaces().Contains(type));
49+
return allTypes.First(o => o.IsClass && !o.IsAbstract && o.GetInterfaces().Intersect(types).Any());
5050
}
5151

5252
internal bool ExistsInReferencedPluginPackage(AssemblyName assemblyName)

Flow.Launcher.Core/Plugin/PluginConfig.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
using System.Collections.Generic;
33
using System.Linq;
44
using System.IO;
5-
using Newtonsoft.Json;
65
using Flow.Launcher.Infrastructure;
76
using Flow.Launcher.Infrastructure.Logger;
87
using Flow.Launcher.Plugin;
8+
using System.Text.Json;
99

1010
namespace Flow.Launcher.Core.Plugin
1111
{
@@ -61,7 +61,7 @@ private static PluginMetadata GetPluginMetadata(string pluginDirectory)
6161
PluginMetadata metadata;
6262
try
6363
{
64-
metadata = JsonConvert.DeserializeObject<PluginMetadata>(File.ReadAllText(configPath));
64+
metadata = JsonSerializer.Deserialize<PluginMetadata>(File.ReadAllText(configPath));
6565
metadata.PluginDirectory = pluginDirectory;
6666
// for plugins which doesn't has ActionKeywords key
6767
metadata.ActionKeywords = metadata.ActionKeywords ?? new List<string> { metadata.ActionKeyword };

Flow.Launcher.Core/Plugin/PluginManager.cs

Lines changed: 79 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Collections.Generic;
44
using System.IO;
55
using System.Linq;
6+
using System.Threading;
67
using System.Threading.Tasks;
78
using Flow.Launcher.Infrastructure;
89
using Flow.Launcher.Infrastructure.Logger;
@@ -52,13 +53,14 @@ public static void Save()
5253
}
5354
}
5455

55-
public static void ReloadData()
56+
public static async Task ReloadData()
5657
{
57-
foreach(var plugin in AllPlugins)
58+
await Task.WhenAll(AllPlugins.Select(plugin => plugin.Plugin switch
5859
{
59-
var reloadablePlugin = plugin.Plugin as IReloadable;
60-
reloadablePlugin?.ReloadData();
61-
}
60+
IReloadable p => Task.Run(p.ReloadData),
61+
IAsyncReloadable p => p.ReloadDataAsync(),
62+
_ => Task.CompletedTask,
63+
}).ToArray());
6264
}
6365

6466
static PluginManager()
@@ -86,50 +88,62 @@ public static void LoadPlugins(PluginsSettings settings)
8688
/// Call initialize for all plugins
8789
/// </summary>
8890
/// <returns>return the list of failed to init plugins or null for none</returns>
89-
public static void InitializePlugins(IPublicAPI api)
91+
public static async Task InitializePlugins(IPublicAPI api)
9092
{
9193
API = api;
9294
var failedPlugins = new ConcurrentQueue<PluginPair>();
93-
Parallel.ForEach(AllPlugins, pair =>
95+
96+
var InitTasks = AllPlugins.Select(pair => Task.Run(async delegate
9497
{
9598
try
9699
{
97-
var milliseconds = Stopwatch.Debug($"|PluginManager.InitializePlugins|Init method time cost for <{pair.Metadata.Name}>", () =>
100+
var milliseconds = pair.Plugin switch
98101
{
99-
pair.Plugin.Init(new PluginInitContext
100-
{
101-
CurrentPluginMetadata = pair.Metadata,
102-
API = API
103-
});
104-
});
102+
IAsyncPlugin plugin
103+
=> await Stopwatch.DebugAsync($"|PluginManager.InitializePlugins|Init method time cost for <{pair.Metadata.Name}>",
104+
() => plugin.InitAsync(new PluginInitContext(pair.Metadata, API))),
105+
IPlugin plugin
106+
=> Stopwatch.Debug($"|PluginManager.InitializePlugins|Init method time cost for <{pair.Metadata.Name}>",
107+
() => plugin.Init(new PluginInitContext(pair.Metadata, API))),
108+
_ => throw new ArgumentException(),
109+
};
105110
pair.Metadata.InitTime += milliseconds;
106-
Log.Info($"|PluginManager.InitializePlugins|Total init cost for <{pair.Metadata.Name}> is <{pair.Metadata.InitTime}ms>");
111+
Log.Info(
112+
$"|PluginManager.InitializePlugins|Total init cost for <{pair.Metadata.Name}> is <{pair.Metadata.InitTime}ms>");
107113
}
108114
catch (Exception e)
109115
{
110116
Log.Exception(nameof(PluginManager), $"Fail to Init plugin: {pair.Metadata.Name}", e);
111-
pair.Metadata.Disabled = true;
117+
pair.Metadata.Disabled = true;
112118
failedPlugins.Enqueue(pair);
113119
}
114-
});
120+
}));
121+
122+
await Task.WhenAll(InitTasks);
115123

116124
_contextMenuPlugins = GetPluginsForInterface<IContextMenu>();
117125
foreach (var plugin in AllPlugins)
118126
{
119-
if (IsGlobalPlugin(plugin.Metadata))
120-
GlobalPlugins.Add(plugin);
121-
122-
// Plugins may have multiple ActionKeywords, eg. WebSearch
123-
plugin.Metadata.ActionKeywords
124-
.Where(x => x != Query.GlobalPluginWildcardSign)
125-
.ToList()
126-
.ForEach(x => NonGlobalPlugins[x] = plugin);
127+
foreach (var actionKeyword in plugin.Metadata.ActionKeywords)
128+
{
129+
switch (actionKeyword)
130+
{
131+
case Query.GlobalPluginWildcardSign:
132+
GlobalPlugins.Add(plugin);
133+
break;
134+
default:
135+
NonGlobalPlugins[actionKeyword] = plugin;
136+
break;
137+
}
138+
}
127139
}
128140

129141
if (failedPlugins.Any())
130142
{
131143
var failed = string.Join(",", failedPlugins.Select(x => x.Metadata.Name));
132-
API.ShowMsg($"Fail to Init Plugins", $"Plugins: {failed} - fail to load and would be disabled, please contact plugin creator for help", "", false);
144+
API.ShowMsg($"Fail to Init Plugins",
145+
$"Plugins: {failed} - fail to load and would be disabled, please contact plugin creator for help",
146+
"", false);
133147
}
134148
}
135149

@@ -146,24 +160,46 @@ public static List<PluginPair> ValidPluginsForQuery(Query query)
146160
}
147161
}
148162

149-
public static List<Result> QueryForPlugin(PluginPair pair, Query query)
163+
public static async Task<List<Result>> QueryForPlugin(PluginPair pair, Query query, CancellationToken token)
150164
{
151165
var results = new List<Result>();
152166
try
153167
{
154168
var metadata = pair.Metadata;
155-
var milliseconds = Stopwatch.Debug($"|PluginManager.QueryForPlugin|Cost for {metadata.Name}", () =>
169+
170+
long milliseconds = -1L;
171+
172+
switch (pair.Plugin)
156173
{
157-
results = pair.Plugin.Query(query) ?? new List<Result>();
158-
UpdatePluginMetadata(results, metadata, query);
159-
});
174+
case IAsyncPlugin plugin:
175+
milliseconds = await Stopwatch.DebugAsync($"|PluginManager.QueryForPlugin|Cost for {metadata.Name}",
176+
async () => results = await plugin.QueryAsync(query, token).ConfigureAwait(false));
177+
break;
178+
case IPlugin plugin:
179+
await Task.Run(() => milliseconds = Stopwatch.Debug($"|PluginManager.QueryForPlugin|Cost for {metadata.Name}",
180+
() => results = plugin.Query(query)), token).ConfigureAwait(false);
181+
break;
182+
default:
183+
throw new ArgumentOutOfRangeException();
184+
}
185+
token.ThrowIfCancellationRequested();
186+
UpdatePluginMetadata(results, metadata, query);
187+
160188
metadata.QueryCount += 1;
161-
metadata.AvgQueryTime = metadata.QueryCount == 1 ? milliseconds : (metadata.AvgQueryTime + milliseconds) / 2;
189+
metadata.AvgQueryTime =
190+
metadata.QueryCount == 1 ? milliseconds : (metadata.AvgQueryTime + milliseconds) / 2;
191+
token.ThrowIfCancellationRequested();
192+
}
193+
catch (OperationCanceledException)
194+
{
195+
// null will be fine since the results will only be added into queue if the token hasn't been cancelled
196+
return results = null;
162197
}
163198
catch (Exception e)
164199
{
165200
Log.Exception($"|PluginManager.QueryForPlugin|Exception for plugin <{pair.Metadata.Name}> when query <{query}>", e);
166201
}
202+
167203
return results;
168204
}
169205

@@ -182,11 +218,6 @@ public static void UpdatePluginMetadata(List<Result> results, PluginMetadata met
182218
}
183219
}
184220

185-
private static bool IsGlobalPlugin(PluginMetadata metadata)
186-
{
187-
return metadata.ActionKeywords.Contains(Query.GlobalPluginWildcardSign);
188-
}
189-
190221
/// <summary>
191222
/// get specified plugin, return null if not found
192223
/// </summary>
@@ -222,16 +253,19 @@ public static List<Result> GetContextMenusForPlugin(Result result)
222253
}
223254
catch (Exception e)
224255
{
225-
Log.Exception($"|PluginManager.GetContextMenusForPlugin|Can't load context menus for plugin <{pluginPair.Metadata.Name}>", e);
256+
Log.Exception(
257+
$"|PluginManager.GetContextMenusForPlugin|Can't load context menus for plugin <{pluginPair.Metadata.Name}>",
258+
e);
226259
}
227260
}
261+
228262
return results;
229263
}
230264

231265
public static bool ActionKeywordRegistered(string actionKeyword)
232266
{
233267
return actionKeyword != Query.GlobalPluginWildcardSign
234-
&& NonGlobalPlugins.ContainsKey(actionKeyword);
268+
&& NonGlobalPlugins.ContainsKey(actionKeyword);
235269
}
236270

237271
/// <summary>
@@ -249,6 +283,7 @@ public static void AddActionKeyword(string id, string newActionKeyword)
249283
{
250284
NonGlobalPlugins[newActionKeyword] = plugin;
251285
}
286+
252287
plugin.Metadata.ActionKeywords.Add(newActionKeyword);
253288
}
254289

@@ -262,16 +297,16 @@ public static void RemoveActionKeyword(string id, string oldActionkeyword)
262297
if (oldActionkeyword == Query.GlobalPluginWildcardSign
263298
&& // Plugins may have multiple ActionKeywords that are global, eg. WebSearch
264299
plugin.Metadata.ActionKeywords
265-
.Where(x => x == Query.GlobalPluginWildcardSign)
266-
.ToList()
267-
.Count == 1)
300+
.Where(x => x == Query.GlobalPluginWildcardSign)
301+
.ToList()
302+
.Count == 1)
268303
{
269304
GlobalPlugins.Remove(plugin);
270305
}
271-
306+
272307
if (oldActionkeyword != Query.GlobalPluginWildcardSign)
273308
NonGlobalPlugins.Remove(oldActionkeyword);
274-
309+
275310

276311
plugin.Metadata.ActionKeywords.Remove(oldActionkeyword);
277312
}

0 commit comments

Comments
 (0)