diff --git a/Flow.Launcher.Core/Plugin/PluginAssemblyLoader.cs b/Flow.Launcher.Core/Plugin/PluginAssemblyLoader.cs index f473cbc656c..e18985fe7d2 100644 --- a/Flow.Launcher.Core/Plugin/PluginAssemblyLoader.cs +++ b/Flow.Launcher.Core/Plugin/PluginAssemblyLoader.cs @@ -49,10 +49,10 @@ protected override Assembly Load(AssemblyName assemblyName) return LoadFromAssemblyPath(assemblyPath); } - internal Type FromAssemblyGetTypeOfInterface(Assembly assembly, params Type[] types) + internal Type FromAssemblyGetTypeOfInterface(Assembly assembly, Type type) { var allTypes = assembly.ExportedTypes; - return allTypes.First(o => o.IsClass && !o.IsAbstract && o.GetInterfaces().Intersect(types).Any()); + return allTypes.First(o => o.IsClass && !o.IsAbstract && o.GetInterfaces().Any(t => t == type)); } internal bool ExistsInReferencedPackage(AssemblyName assemblyName) diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index 66eb0f0ec3c..8c9fd2eb964 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -97,16 +97,9 @@ public static async Task InitializePlugins(IPublicAPI api) { try { - var milliseconds = pair.Plugin switch - { - IAsyncPlugin plugin - => await Stopwatch.DebugAsync($"|PluginManager.InitializePlugins|Init method time cost for <{pair.Metadata.Name}>", - () => plugin.InitAsync(new PluginInitContext(pair.Metadata, API))), - IPlugin plugin - => Stopwatch.Debug($"|PluginManager.InitializePlugins|Init method time cost for <{pair.Metadata.Name}>", - () => plugin.Init(new PluginInitContext(pair.Metadata, API))), - _ => throw new ArgumentException(), - }; + var milliseconds = await Stopwatch.DebugAsync($"|PluginManager.InitializePlugins|Init method time cost for <{pair.Metadata.Name}>", + () => pair.Plugin.InitAsync(new PluginInitContext(pair.Metadata, API))); + pair.Metadata.InitTime += milliseconds; Log.Info( $"|PluginManager.InitializePlugins|Total init cost for <{pair.Metadata.Name}> is <{pair.Metadata.InitTime}ms>"); @@ -169,19 +162,9 @@ public static async Task> QueryForPlugin(PluginPair pair, Query que long milliseconds = -1L; - switch (pair.Plugin) - { - case IAsyncPlugin plugin: - milliseconds = await Stopwatch.DebugAsync($"|PluginManager.QueryForPlugin|Cost for {metadata.Name}", - async () => results = await plugin.QueryAsync(query, token).ConfigureAwait(false)); - break; - case IPlugin plugin: - await Task.Run(() => milliseconds = Stopwatch.Debug($"|PluginManager.QueryForPlugin|Cost for {metadata.Name}", - () => results = plugin.Query(query)), token).ConfigureAwait(false); - break; - default: - throw new ArgumentOutOfRangeException(); - } + milliseconds = await Stopwatch.DebugAsync($"|PluginManager.QueryForPlugin|Cost for {metadata.Name}", + async () => results = await pair.Plugin.QueryAsync(query, token).ConfigureAwait(false)); + token.ThrowIfCancellationRequested(); if (results == null) return results; @@ -199,7 +182,7 @@ public static async Task> QueryForPlugin(PluginPair pair, Query que } catch (Exception e) { - Log.Exception($"|PluginManager.QueryForPlugin|Exception for plugin <{pair.Metadata.Name}> when query <{query}>", e); + Log.Exception($"|PluginManager.QueryForPlugin|Exception for plugin <{pair.Metadata.Name}> when query <{query}>", e); } return results; diff --git a/Flow.Launcher.Core/Plugin/PluginsLoader.cs b/Flow.Launcher.Core/Plugin/PluginsLoader.cs index 2c75f963376..92aca810973 100644 --- a/Flow.Launcher.Core/Plugin/PluginsLoader.cs +++ b/Flow.Launcher.Core/Plugin/PluginsLoader.cs @@ -44,23 +44,23 @@ public static IEnumerable DotNetPlugins(List source) #if DEBUG var assemblyLoader = new PluginAssemblyLoader(metadata.ExecuteFilePath); var assembly = assemblyLoader.LoadAssemblyAndDependencies(); - var type = assemblyLoader.FromAssemblyGetTypeOfInterface(assembly, typeof(IPlugin), + var type = assemblyLoader.FromAssemblyGetTypeOfInterface(assembly, typeof(IAsyncPlugin)); - var plugin = Activator.CreateInstance(type); + var plugin = Activator.CreateInstance(type) as IAsyncPlugin; #else Assembly assembly = null; - object plugin = null; + IAsyncPlugin plugin = null; try { var assemblyLoader = new PluginAssemblyLoader(metadata.ExecuteFilePath); assembly = assemblyLoader.LoadAssemblyAndDependencies(); - var type = assemblyLoader.FromAssemblyGetTypeOfInterface(assembly, typeof(IPlugin), + var type = assemblyLoader.FromAssemblyGetTypeOfInterface(assembly, typeof(IAsyncPlugin)); - plugin = Activator.CreateInstance(type); + plugin = Activator.CreateInstance(type) as IAsyncPlugin; } catch (Exception e) when (assembly == null) { @@ -78,13 +78,13 @@ public static IEnumerable DotNetPlugins(List source) { Log.Exception($"|PluginsLoader.DotNetPlugins|The following plugin has errored and can not be loaded: <{metadata.Name}>", e); } - +#endif if (plugin == null) { erroredPlugins.Add(metadata.Name); return; } -#endif + plugins.Add(new PluginPair { Plugin = plugin, @@ -139,7 +139,7 @@ public static IEnumerable PythonPlugins(List source, } else { - Log.Error("PluginsLoader","Failed to set Python path despite the environment variable PATH is found", "PythonPlugins"); + Log.Error("PluginsLoader", "Failed to set Python path despite the environment variable PATH is found", "PythonPlugins"); } } } @@ -152,7 +152,7 @@ public static IEnumerable PythonPlugins(List source, } else { - Log.Error("PluginsLoader",$"Tried to automatically set from Settings.PythonDirectory " + + Log.Error("PluginsLoader", $"Tried to automatically set from Settings.PythonDirectory " + $"but can't find python executable in {path}", "PythonPlugins"); } } @@ -205,7 +205,7 @@ public static IEnumerable PythonPlugins(List source, } else { - Log.Error("PluginsLoader", + Log.Error("PluginsLoader", $"Failed to set Python path after Droplex install, {pythonPath} does not exist", "PythonPlugins"); } @@ -215,8 +215,8 @@ public static IEnumerable PythonPlugins(List source, if (string.IsNullOrEmpty(settings.PythonDirectory)) { MessageBox.Show("Unable to set Python executable path, please try from Flow's settings (scroll down to the bottom)."); - Log.Error("PluginsLoader", - $"Not able to successfully set Python path, the PythonDirectory variable is still an empty string.", + Log.Error("PluginsLoader", + $"Not able to successfully set Python path, the PythonDirectory variable is still an empty string.", "PythonPlugins"); return new List(); diff --git a/Flow.Launcher.Plugin/IPlugin.cs b/Flow.Launcher.Plugin/IPlugin.cs index 203dc9af736..bac93d090cd 100644 --- a/Flow.Launcher.Plugin/IPlugin.cs +++ b/Flow.Launcher.Plugin/IPlugin.cs @@ -1,4 +1,6 @@ using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; namespace Flow.Launcher.Plugin { @@ -9,7 +11,7 @@ namespace Flow.Launcher.Plugin /// or performaing CPU intense jobs (performing better with cancellation), please try the IAsyncPlugin interface /// /// - public interface IPlugin + public interface IPlugin : IAsyncPlugin { /// /// Querying when user's search changes @@ -27,5 +29,9 @@ public interface IPlugin /// /// void Init(PluginInitContext context); + + Task IAsyncPlugin.InitAsync(PluginInitContext context) => Task.Run(() => Init(context)); + + Task> IAsyncPlugin.QueryAsync(Query query, CancellationToken token) => Task.Run(() => Query(query)); } } diff --git a/Flow.Launcher.Plugin/PluginPair.cs b/Flow.Launcher.Plugin/PluginPair.cs index e8954b7a0ef..7bf6346910c 100644 --- a/Flow.Launcher.Plugin/PluginPair.cs +++ b/Flow.Launcher.Plugin/PluginPair.cs @@ -2,7 +2,7 @@ { public class PluginPair { - public object Plugin { get; internal set; } + public IAsyncPlugin Plugin { get; internal set; } public PluginMetadata Metadata { get; internal set; }