From c5167cb5e526b0ca3eae3867291e26b49df283e0 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Fri, 28 May 2021 08:44:06 +1000 Subject: [PATCH 1/2] fix duplicate query searches from same global action keywords --- Flow.Launcher.Core/Plugin/PluginManager.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index e2c009ee3aa..1f068303f9d 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -118,7 +118,9 @@ public static async Task InitializePlugins(IPublicAPI api) _contextMenuPlugins = GetPluginsForInterface(); foreach (var plugin in AllPlugins) { - foreach (var actionKeyword in plugin.Metadata.ActionKeywords) + // set distinct on each plugin's action keywords helps only firing global(*) and action keywords once where a plugin + // has multiple global and action keywords because we will only add them here once. + foreach (var actionKeyword in plugin.Metadata.ActionKeywords.Distinct()) { switch (actionKeyword) { From efc45c76ac41227a18697d4cb25b9ec762394cbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=98=E9=9F=AC=20=E5=BC=A0?= Date: Fri, 28 May 2021 17:06:58 +0800 Subject: [PATCH 2/2] Use HashSet storing GlobalPlugins Use HashSet instead of List to avoid duplicate global plugin --- Flow.Launcher.Core/Plugin/PluginManager.cs | 10 ++++------ Flow.Launcher/ViewModel/MainViewModel.cs | 21 ++++++++------------- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index 1f068303f9d..94ceb242e5c 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -21,8 +21,8 @@ public static class PluginManager private static IEnumerable _contextMenuPlugins; public static List AllPlugins { get; private set; } - public static readonly List GlobalPlugins = new List(); - public static readonly Dictionary NonGlobalPlugins = new Dictionary(); + public static readonly HashSet GlobalPlugins = new(); + public static readonly Dictionary NonGlobalPlugins = new (); public static IPublicAPI API { private set; get; } @@ -143,7 +143,7 @@ public static async Task InitializePlugins(IPublicAPI api) } } - public static List ValidPluginsForQuery(Query query) + public static ICollection ValidPluginsForQuery(Query query) { if (NonGlobalPlugins.ContainsKey(query.ActionKeyword)) { @@ -285,9 +285,7 @@ public static void RemoveActionKeyword(string id, string oldActionkeyword) if (oldActionkeyword == Query.GlobalPluginWildcardSign && // Plugins may have multiple ActionKeywords that are global, eg. WebSearch plugin.Metadata.ActionKeywords - .Where(x => x == Query.GlobalPluginWildcardSign) - .ToList() - .Count == 1) + .Count(x => x == Query.GlobalPluginWildcardSign) == 1) { GlobalPlugins.Remove(plugin); } diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 56ab0ff1d4f..abe8d681b54 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -494,21 +494,16 @@ private void QueryResults() } }, currentCancellationToken); - Task[] tasks = new Task[plugins.Count]; - try + // plugins is ICollection, meaning LINQ will get the Count and preallocate Array + + Task[] tasks = plugins.Select(plugin => plugin.Metadata.Disabled switch { - for (var i = 0; i < plugins.Count; i++) - { - if (!plugins[i].Metadata.Disabled) - { - tasks[i] = QueryTask(plugins[i]); - } - else - { - tasks[i] = Task.CompletedTask; // Avoid Null - } - } + false => QueryTask(plugin), + true => Task.CompletedTask + }).ToArray(); + try + { // Check the code, WhenAll will translate all type of IEnumerable or Collection to Array, so make an array at first await Task.WhenAll(tasks); }