From 6e4d9a5e61c577ae684c29f6513e22b2bb339a1a Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 21 Feb 2025 11:10:16 +0800 Subject: [PATCH 01/24] Remove useless blank lines --- Flow.Launcher.Core/Plugin/PluginManager.cs | 1 - Flow.Launcher.Plugin/Query.cs | 1 - Flow.Launcher/ViewModel/MainViewModel.cs | 2 -- 3 files changed, 4 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index 5c4eaa1dadc..b1f397ea2d1 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -229,7 +229,6 @@ public static ICollection ValidPluginsForQuery(Query query) if (!NonGlobalPlugins.ContainsKey(query.ActionKeyword)) return GlobalPlugins; - var plugin = NonGlobalPlugins[query.ActionKeyword]; return new List { diff --git a/Flow.Launcher.Plugin/Query.cs b/Flow.Launcher.Plugin/Query.cs index e182491c2f0..ab3c8cfeb09 100644 --- a/Flow.Launcher.Plugin/Query.cs +++ b/Flow.Launcher.Plugin/Query.cs @@ -43,7 +43,6 @@ public Query() { } /// public const string ActionKeywordSeparator = ";"; - /// /// Wildcard action keyword. Plugins using this value will be queried on every search. /// diff --git a/Flow.Launcher/ViewModel/MainViewModel.cs b/Flow.Launcher/ViewModel/MainViewModel.cs index 5c3251bfc7e..07547136792 100644 --- a/Flow.Launcher/ViewModel/MainViewModel.cs +++ b/Flow.Launcher/ViewModel/MainViewModel.cs @@ -1118,7 +1118,6 @@ private async void QueryResults(bool isReQuery = false, bool reSelect = true) SearchIconVisibility = Visibility.Visible; } - if (query.ActionKeyword == Plugin.Query.GlobalPluginWildcardSign) { // Wait 45 millisecond for query change in global query @@ -1145,7 +1144,6 @@ private async void QueryResults(bool isReQuery = false, bool reSelect = true) 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 From 8f6bed45e4f9305110f2ffc9aac47f827c7d84b4 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 21 Feb 2025 12:23:31 +0800 Subject: [PATCH 02/24] Remove useless * keywords --- Plugins/Flow.Launcher.Plugin.Explorer/plugin.json | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/plugin.json b/Plugins/Flow.Launcher.Plugin.Explorer/plugin.json index 4eb6bb83bda..89eaa657db4 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.Explorer/plugin.json @@ -2,10 +2,7 @@ "ID": "572be03c74c642baae319fc283e561a8", "ActionKeywords": [ "*", - "doc:", - "*", - "*", - "*" + "doc:" ], "Name": "Explorer", "Description": "Find and manage files and folders via Windows Search or Everything", From e1f1b97b7e158d015f122e02f393e6d72ae08697 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 21 Feb 2025 12:27:38 +0800 Subject: [PATCH 03/24] Support allow modify action keywords & WebSearch does not let user change its keywords --- Flow.Launcher.Plugin/PluginMetadata.cs | 2 ++ Flow.Launcher/ViewModel/PluginViewModel.cs | 2 +- Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Flow.Launcher.Plugin/PluginMetadata.cs b/Flow.Launcher.Plugin/PluginMetadata.cs index b4e06913e32..14a7202038b 100644 --- a/Flow.Launcher.Plugin/PluginMetadata.cs +++ b/Flow.Launcher.Plugin/PluginMetadata.cs @@ -34,6 +34,8 @@ internal set public List ActionKeywords { get; set; } + public bool AllowModifyActionKeywords { get; set; } = true; + public string IcoPath { get; set;} public override string ToString() diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs index a46b98d64b6..4b628f96e6c 100644 --- a/Flow.Launcher/ViewModel/PluginViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginViewModel.cs @@ -100,7 +100,7 @@ public Control SettingControl : null; private ImageSource _image = ImageLoader.MissingImage; - public Visibility ActionKeywordsVisibility => PluginPair.Metadata.ActionKeywords.Count == 1 ? Visibility.Visible : Visibility.Collapsed; + public Visibility ActionKeywordsVisibility => PluginPair.Metadata.AllowModifyActionKeywords ? Visibility.Visible : Visibility.Collapsed; public string InitilizaTime => PluginPair.Metadata.InitTime + "ms"; public string QueryTime => PluginPair.Metadata.AvgQueryTime + "ms"; public string Version => InternationalizationManager.Instance.GetTranslation("plugin_query_version") + " " + PluginPair.Metadata.Version; diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json b/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json index 6b6792ad399..1fc9967fcdb 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json @@ -23,6 +23,7 @@ "yahoo", "bd" ], + "AllowModifyActionKeywords": false, "Name": "Web Searches", "Description": "Provide the web search ability", "Author": "qianlifeng", From abfeee1423a011229ec6cd9dd7e85dddc2a90ac6 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 21 Feb 2025 12:59:56 +0800 Subject: [PATCH 04/24] Support multiple action keywords --- Flow.Launcher.Core/Plugin/PluginManager.cs | 29 +++++++++++++++++----- Flow.Launcher.Plugin/Query.cs | 4 +-- Flow.Launcher/ActionKeywords.xaml.cs | 15 +++++++---- Flow.Launcher/ViewModel/PluginViewModel.cs | 7 +++--- 4 files changed, 39 insertions(+), 16 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index b1f397ea2d1..8c62c2f02ac 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -340,7 +340,12 @@ public static List GetContextMenusForPlugin(Result result) return results; } - public static bool ActionKeywordRegistered(string actionKeyword) + public static bool ActionKeywordRegistered(IReadOnlyList actionKeywords) + { + return actionKeywords.Any(ActionKeywordRegistered); + } + + private static bool ActionKeywordRegistered(string actionKeyword) { // this method is only checking for action keywords (defined as not '*') registration // hence the actionKeyword != Query.GlobalPluginWildcardSign logic @@ -385,19 +390,31 @@ public static void RemoveActionKeyword(string id, string oldActionkeyword) if (oldActionkeyword != Query.GlobalPluginWildcardSign) NonGlobalPlugins.Remove(oldActionkeyword); - plugin.Metadata.ActionKeywords.Remove(oldActionkeyword); } - public static void ReplaceActionKeyword(string id, string oldActionKeyword, string newActionKeyword) + public static void ReplaceActionKeyword(string id, IReadOnlyList oldActionKeyword, IReadOnlyList newActionKeyword) { - if (oldActionKeyword != newActionKeyword) + if (CheckActionKeywordChanged(oldActionKeyword, newActionKeyword)) { - AddActionKeyword(id, newActionKeyword); - RemoveActionKeyword(id, oldActionKeyword); + foreach (var actionKeyword in newActionKeyword) + { + AddActionKeyword(id, actionKeyword); + } + foreach (var actionKeyword in oldActionKeyword) + { + RemoveActionKeyword(id, actionKeyword); + } } } + private static bool CheckActionKeywordChanged(IReadOnlyList oldActionKeyword, IReadOnlyList newActionKeyword) + { + if (oldActionKeyword.Count != newActionKeyword.Count) + return true; + return oldActionKeyword.Where((t, i) => t != newActionKeyword[i]).Any(); + } + private static string GetContainingFolderPathAfterUnzip(string unzippedParentFolderPath) { var unzippedFolderCount = Directory.GetDirectories(unzippedParentFolderPath).Length; diff --git a/Flow.Launcher.Plugin/Query.cs b/Flow.Launcher.Plugin/Query.cs index ab3c8cfeb09..15b2dd171f5 100644 --- a/Flow.Launcher.Plugin/Query.cs +++ b/Flow.Launcher.Plugin/Query.cs @@ -39,9 +39,9 @@ public Query() { } public const string TermSeparator = " "; /// - /// User can set multiple action keywords seperated by ';' + /// User can set multiple action keywords seperated by whitespace /// - public const string ActionKeywordSeparator = ";"; + public const string ActionKeywordSeparator = TermSeparator; /// /// Wildcard action keyword. Plugins using this value will be queried on every search. diff --git a/Flow.Launcher/ActionKeywords.xaml.cs b/Flow.Launcher/ActionKeywords.xaml.cs index ba47a4ded22..4a6bd10a85f 100644 --- a/Flow.Launcher/ActionKeywords.xaml.cs +++ b/Flow.Launcher/ActionKeywords.xaml.cs @@ -3,6 +3,7 @@ using Flow.Launcher.Plugin; using Flow.Launcher.ViewModel; using Flow.Launcher.Core; +using System.Linq; namespace Flow.Launcher { @@ -32,13 +33,17 @@ private void BtnCancel_OnClick(object sender, RoutedEventArgs e) private void btnDone_OnClick(object sender, RoutedEventArgs _) { - var oldActionKeyword = plugin.Metadata.ActionKeywords[0]; - var newActionKeyword = tbAction.Text.Trim(); - newActionKeyword = newActionKeyword.Length > 0 ? newActionKeyword : "*"; + var oldActionKeywords = plugin.Metadata.ActionKeywords; + + var newActionKeywords = tbAction.Text.Split(Query.ActionKeywordSeparator).ToList(); + newActionKeywords.RemoveAll(string.IsNullOrEmpty); + newActionKeywords = newActionKeywords.Distinct().ToList(); + + newActionKeywords = newActionKeywords.Count > 0 ? newActionKeywords : new() { Query.GlobalPluginWildcardSign }; - if (!PluginViewModel.IsActionKeywordRegistered(newActionKeyword)) + if (!PluginViewModel.IsActionKeywordRegistered(newActionKeywords)) { - pluginViewModel.ChangeActionKeyword(newActionKeyword, oldActionKeyword); + pluginViewModel.ChangeActionKeyword(newActionKeywords, oldActionKeywords); Close(); } else diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs index 4b628f96e6c..748490c4727 100644 --- a/Flow.Launcher/ViewModel/PluginViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginViewModel.cs @@ -8,6 +8,7 @@ using CommunityToolkit.Mvvm.Input; using Flow.Launcher.Core.Resource; using Flow.Launcher.Resources.Controls; +using System.Collections.Generic; namespace Flow.Launcher.ViewModel { @@ -109,9 +110,9 @@ public Control SettingControl public int Priority => PluginPair.Metadata.Priority; public Infrastructure.UserSettings.Plugin PluginSettingsObject { get; set; } - public void ChangeActionKeyword(string newActionKeyword, string oldActionKeyword) + public void ChangeActionKeyword(IReadOnlyList newActionKeywords, IReadOnlyList oldActionKeywords) { - PluginManager.ReplaceActionKeyword(PluginPair.Metadata.ID, oldActionKeyword, newActionKeyword); + PluginManager.ReplaceActionKeyword(PluginPair.Metadata.ID, oldActionKeywords, newActionKeywords); OnPropertyChanged(nameof(ActionKeywordsText)); } @@ -150,7 +151,7 @@ private void OpenDeletePluginWindow() PluginManager.API.ShowMainWindow(); } - public static bool IsActionKeywordRegistered(string newActionKeyword) => PluginManager.ActionKeywordRegistered(newActionKeyword); + public static bool IsActionKeywordRegistered(IReadOnlyList newActionKeywords) => PluginManager.ActionKeywordRegistered(newActionKeywords); [RelayCommand] private void SetActionKeywords() From d9ba38b3221174996201f8df2b1a93a9000e00e5 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 21 Feb 2025 13:09:19 +0800 Subject: [PATCH 05/24] Fix issue that plugin cannot update ActionKeyword after changing its action keywords --- Flow.Launcher.Core/Plugin/PluginManager.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index 8c62c2f02ac..e4ecf0f40e4 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -405,6 +405,17 @@ public static void ReplaceActionKeyword(string id, IReadOnlyList oldActi { RemoveActionKeyword(id, actionKeyword); } + + // Update action keyword in plugin metadata + var plugin = GetPluginForId(id); + if (newActionKeyword.Count > 0) + { + plugin.Metadata.ActionKeyword = newActionKeyword[0]; + } + else + { + plugin.Metadata.ActionKeyword = string.Empty; + } } } From f999b97de1e2a57dd11a7b8fe1ab39194936b865 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 21 Feb 2025 13:25:31 +0800 Subject: [PATCH 06/24] Fix build issue --- Flow.Launcher.Core/Plugin/PluginManager.cs | 46 +++++++++++++++---- .../SearchSourceSetting.xaml.cs | 4 +- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index e4ecf0f40e4..c8f78767c4d 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -342,10 +342,17 @@ public static List GetContextMenusForPlugin(Result result) public static bool ActionKeywordRegistered(IReadOnlyList actionKeywords) { - return actionKeywords.Any(ActionKeywordRegistered); + foreach (var actionKeyword in actionKeywords) + { + if (ActionKeywordRegistered(actionKeyword)) + { + return true; + } + } + return false; } - private static bool ActionKeywordRegistered(string actionKeyword) + public static bool ActionKeywordRegistered(string actionKeyword) { // this method is only checking for action keywords (defined as not '*') registration // hence the actionKeyword != Query.GlobalPluginWildcardSign logic @@ -369,6 +376,7 @@ public static void AddActionKeyword(string id, string newActionKeyword) NonGlobalPlugins[newActionKeyword] = plugin; } + // Update action keywords in plugin metadata plugin.Metadata.ActionKeywords.Add(newActionKeyword); } @@ -390,27 +398,28 @@ public static void RemoveActionKeyword(string id, string oldActionkeyword) if (oldActionkeyword != Query.GlobalPluginWildcardSign) NonGlobalPlugins.Remove(oldActionkeyword); + // Update action keywords in plugin metadata plugin.Metadata.ActionKeywords.Remove(oldActionkeyword); } - public static void ReplaceActionKeyword(string id, IReadOnlyList oldActionKeyword, IReadOnlyList newActionKeyword) + public static void ReplaceActionKeyword(string id, IReadOnlyList oldActionKeywords, IReadOnlyList newActionKeywords) { - if (CheckActionKeywordChanged(oldActionKeyword, newActionKeyword)) + if (CheckActionKeywordChanged(oldActionKeywords, newActionKeywords)) { - foreach (var actionKeyword in newActionKeyword) + foreach (var actionKeyword in newActionKeywords) { AddActionKeyword(id, actionKeyword); } - foreach (var actionKeyword in oldActionKeyword) + foreach (var actionKeyword in oldActionKeywords) { RemoveActionKeyword(id, actionKeyword); } // Update action keyword in plugin metadata var plugin = GetPluginForId(id); - if (newActionKeyword.Count > 0) + if (newActionKeywords.Count > 0) { - plugin.Metadata.ActionKeyword = newActionKeyword[0]; + plugin.Metadata.ActionKeyword = newActionKeywords[0]; } else { @@ -426,6 +435,27 @@ private static bool CheckActionKeywordChanged(IReadOnlyList oldActionKey return oldActionKeyword.Where((t, i) => t != newActionKeyword[i]).Any(); } + public static void ReplaceActionKeyword(string id, string oldActionKeyword, string newActionKeyword) + { + if (oldActionKeyword != newActionKeyword) + { + AddActionKeyword(id, newActionKeyword); + RemoveActionKeyword(id, oldActionKeyword); + + // Update action keyword in plugin metadata + var plugin = GetPluginForId(id); + var newActionKeywords = plugin.Metadata.ActionKeywords; + if (newActionKeywords.Count > 0) + { + plugin.Metadata.ActionKeyword = newActionKeywords[0]; + } + else + { + plugin.Metadata.ActionKeyword = string.Empty; + } + } + } + private static string GetContainingFolderPathAfterUnzip(string unzippedParentFolderPath) { var unzippedFolderCount = Directory.GetDirectories(unzippedParentFolderPath).Length; diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml.cs index a3e5630c22e..f79176f991b 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml.cs @@ -80,7 +80,7 @@ private void OnConfirmButtonClick(object sender, RoutedEventArgs e) private void AddSearchSource() { var keyword = _searchSource.ActionKeyword; - if (!PluginManager.ActionKeywordRegistered(keyword)) + if (!_context.API.ActionKeywordAssigned(keyword)) { var id = _context.CurrentPluginMetadata.ID; PluginManager.AddActionKeyword(id, keyword); @@ -100,7 +100,7 @@ private void EditSearchSource() { var newKeyword = _searchSource.ActionKeyword; var oldKeyword = _oldSearchSource.ActionKeyword; - if (!PluginManager.ActionKeywordRegistered(newKeyword) || oldKeyword == newKeyword) + if (!_context.API.ActionKeywordAssigned(newKeyword) || oldKeyword == newKeyword) { var id = _context.CurrentPluginMetadata.ID; PluginManager.ReplaceActionKeyword(id, oldKeyword, newKeyword); From 37ad5aa09bb1336ee3db27a913e6d2a51cc314c4 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 21 Feb 2025 13:31:46 +0800 Subject: [PATCH 07/24] Fix issue that ActionKeywordRegistered will not exclude old action key --- Flow.Launcher.Core/Plugin/PluginManager.cs | 12 +++++++++--- Flow.Launcher/ActionKeywords.xaml.cs | 3 ++- Flow.Launcher/ViewModel/PluginViewModel.cs | 2 -- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index c8f78767c4d..d0e6fcab02f 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -340,11 +340,11 @@ public static List GetContextMenusForPlugin(Result result) return results; } - public static bool ActionKeywordRegistered(IReadOnlyList actionKeywords) + public static bool ActionKeywordRegistered(IReadOnlyList newActionKeywords, IReadOnlyList oldActionKeywords) { - foreach (var actionKeyword in actionKeywords) + foreach (var actionKeyword in newActionKeywords) { - if (ActionKeywordRegistered(actionKeyword)) + if (ActionKeywordRegistered(actionKeyword, oldActionKeywords)) { return true; } @@ -352,6 +352,12 @@ public static bool ActionKeywordRegistered(IReadOnlyList actionKeywords) return false; } + private static bool ActionKeywordRegistered(string actionKeyword, IReadOnlyList oldActionKeywords) + { + if (oldActionKeywords.Contains(actionKeyword)) return false; + return ActionKeywordRegistered(actionKeyword); + } + public static bool ActionKeywordRegistered(string actionKeyword) { // this method is only checking for action keywords (defined as not '*') registration diff --git a/Flow.Launcher/ActionKeywords.xaml.cs b/Flow.Launcher/ActionKeywords.xaml.cs index 4a6bd10a85f..af6dcfe90d7 100644 --- a/Flow.Launcher/ActionKeywords.xaml.cs +++ b/Flow.Launcher/ActionKeywords.xaml.cs @@ -4,6 +4,7 @@ using Flow.Launcher.ViewModel; using Flow.Launcher.Core; using System.Linq; +using Flow.Launcher.Core.Plugin; namespace Flow.Launcher { @@ -41,7 +42,7 @@ private void btnDone_OnClick(object sender, RoutedEventArgs _) newActionKeywords = newActionKeywords.Count > 0 ? newActionKeywords : new() { Query.GlobalPluginWildcardSign }; - if (!PluginViewModel.IsActionKeywordRegistered(newActionKeywords)) + if (!PluginManager.ActionKeywordRegistered(newActionKeywords, oldActionKeywords)) { pluginViewModel.ChangeActionKeyword(newActionKeywords, oldActionKeywords); Close(); diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs index 748490c4727..63263c768a8 100644 --- a/Flow.Launcher/ViewModel/PluginViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginViewModel.cs @@ -151,8 +151,6 @@ private void OpenDeletePluginWindow() PluginManager.API.ShowMainWindow(); } - public static bool IsActionKeywordRegistered(IReadOnlyList newActionKeywords) => PluginManager.ActionKeywordRegistered(newActionKeywords); - [RelayCommand] private void SetActionKeywords() { From 300d64d66165e4cc302dcf58ce8fe908323135be Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 21 Feb 2025 13:43:53 +0800 Subject: [PATCH 08/24] Remove action keyword first --- Flow.Launcher.Core/Plugin/PluginManager.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index d0e6fcab02f..18519c85d14 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -412,13 +412,15 @@ public static void ReplaceActionKeyword(string id, IReadOnlyList oldActi { if (CheckActionKeywordChanged(oldActionKeywords, newActionKeywords)) { - foreach (var actionKeyword in newActionKeywords) + // Fix collection modified while iterating exception + var oldActionKeywordsClone = oldActionKeywords.ToList(); + foreach (var actionKeyword in oldActionKeywordsClone) { - AddActionKeyword(id, actionKeyword); + RemoveActionKeyword(id, actionKeyword); } - foreach (var actionKeyword in oldActionKeywords) + foreach (var actionKeyword in newActionKeywords) { - RemoveActionKeyword(id, actionKeyword); + AddActionKeyword(id, actionKeyword); } // Update action keyword in plugin metadata @@ -445,8 +447,8 @@ public static void ReplaceActionKeyword(string id, string oldActionKeyword, stri { if (oldActionKeyword != newActionKeyword) { - AddActionKeyword(id, newActionKeyword); RemoveActionKeyword(id, oldActionKeyword); + AddActionKeyword(id, newActionKeyword); // Update action keyword in plugin metadata var plugin = GetPluginForId(id); From cab3eb78fd827283e7511511fba1bce1e8bf58cd Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 21 Feb 2025 13:45:02 +0800 Subject: [PATCH 09/24] Update string resource --- Flow.Launcher/Languages/en.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 4c465d61f52..282d0fb4723 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -335,7 +335,7 @@ This new Action Keyword is already assigned to another plugin, please choose a different one Success Completed successfully - Enter the action keyword you like to use to start the plugin. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. + Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. Custom Query Hotkey From 414684ce43b78452a544dcb12cef8abd1af9e5ee Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Fri, 21 Feb 2025 13:50:44 +0800 Subject: [PATCH 10/24] Replace action keyword function with api --- .../Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml.cs | 2 +- Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml.cs index f79176f991b..fa53e5f5a05 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml.cs @@ -83,7 +83,7 @@ private void AddSearchSource() if (!_context.API.ActionKeywordAssigned(keyword)) { var id = _context.CurrentPluginMetadata.ID; - PluginManager.AddActionKeyword(id, keyword); + _context.API.AddActionKeyword(id, keyword); _searchSources.Add(_searchSource); diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml.cs index 739bc9d6be6..5efe46a9d43 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml.cs @@ -40,7 +40,7 @@ private void OnDeleteSearchSearchClick(object sender, RoutedEventArgs e) if (result == MessageBoxResult.Yes) { var id = _context.CurrentPluginMetadata.ID; - PluginManager.RemoveActionKeyword(id, selected.ActionKeyword); + _context.API.RemoveActionKeyword(id, selected.ActionKeyword); _settings.SearchSources.Remove(selected); } } From 463293214b08e49a9a0f0d9be33aea04aecdee98 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sun, 23 Feb 2025 12:32:06 +0800 Subject: [PATCH 11/24] Revert "Remove useless * keywords" and do not let users change action keywords of Explorer --- Plugins/Flow.Launcher.Plugin.Explorer/plugin.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/plugin.json b/Plugins/Flow.Launcher.Plugin.Explorer/plugin.json index 89eaa657db4..7b067f5761e 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.Explorer/plugin.json @@ -2,8 +2,12 @@ "ID": "572be03c74c642baae319fc283e561a8", "ActionKeywords": [ "*", - "doc:" + "doc:", + "*", + "*", + "*" ], + "AllowModifyActionKeywords": false, "Name": "Explorer", "Description": "Find and manage files and folders via Windows Search or Everything", "Author": "Jeremy Wu", From 87febda78f7842ff018fe0718492e850ce164414 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sun, 23 Feb 2025 12:49:21 +0800 Subject: [PATCH 12/24] Add ReplaceActionKeyword api function --- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 9 ++++++++- Flow.Launcher/PublicAPIInstance.cs | 4 +++- .../Flow.Launcher.Plugin.WebSearch.csproj | 1 - .../SearchSourceSetting.xaml.cs | 3 +-- .../SettingsControl.xaml.cs | 1 - 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index 8376fd07ba7..da6bb598bd1 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -151,7 +151,6 @@ public interface IPublicAPI /// public void RemoveGlobalKeyboardCallback(Func callback); - /// /// Fuzzy Search the string with the given query. This is the core search mechanism Flow uses /// @@ -334,5 +333,13 @@ public interface IPublicAPI /// When user closes the progress box manually by button or esc key, this action will be called. /// A progress box interface. public Task ShowProgressBoxAsync(string caption, Func, Task> reportProgressAsync, Action forceClosed = null); + + /// + /// Replace ActionKeyword for specific plugin + /// + /// ID for plugin that needs to remove action keyword + /// The actionkeyword that is supposed to be removed + /// The actionkeyword that is supposed to be added + public void ReplaceActionKeyword(string pluginId, string oldActionKeyword, string newActionKeyword); } } diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index 7706a64ba9d..b6f3b0d27b3 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -26,6 +26,7 @@ using System.Diagnostics; using System.Collections.Specialized; using Flow.Launcher.Core; +using Flow.Launcher.Infrastructure.UserSettings; namespace Flow.Launcher { @@ -311,7 +312,6 @@ public bool IsGameModeOn() return _mainVM.GameModeStatus; } - private readonly List> _globalKeyboardHandlers = new(); public void RegisterGlobalKeyboardCallback(Func callback) => _globalKeyboardHandlers.Add(callback); @@ -326,6 +326,8 @@ public MessageBoxResult ShowMsgBox(string messageBoxText, string caption = "", M public Task ShowProgressBoxAsync(string caption, Func, Task> reportProgressAsync, Action forceClosed = null) => ProgressBoxEx.ShowAsync(caption, reportProgressAsync, forceClosed); + public void ReplaceActionKeyword(string pluginId, string oldActionKeyword, string newActionKeyword) => PluginManager.ReplaceActionKeyword(pluginId, oldActionKeyword, newActionKeyword); + #endregion #region Private Methods diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj b/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj index 55d69d5260c..c2d0a46a094 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/Flow.Launcher.Plugin.WebSearch.csproj @@ -51,7 +51,6 @@ - diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml.cs index fa53e5f5a05..d3d18d0d244 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using System.Windows; using Microsoft.Win32; -using Flow.Launcher.Core.Plugin; namespace Flow.Launcher.Plugin.WebSearch { @@ -103,7 +102,7 @@ private void EditSearchSource() if (!_context.API.ActionKeywordAssigned(newKeyword) || oldKeyword == newKeyword) { var id = _context.CurrentPluginMetadata.ID; - PluginManager.ReplaceActionKeyword(id, oldKeyword, newKeyword); + _context.API.ReplaceActionKeyword(id, oldKeyword, newKeyword); var index = _searchSources.IndexOf(_oldSearchSource); _searchSources[index] = _searchSource; diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml.cs index 5efe46a9d43..e53f4ec7517 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SettingsControl.xaml.cs @@ -1,6 +1,5 @@ using System.Windows; using System.Windows.Controls; -using Flow.Launcher.Core.Plugin; using System.ComponentModel; using System.Windows.Data; From 34cb078602f3c04ff428123415ac55e97e9b9daf Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sun, 23 Feb 2025 14:06:58 +0800 Subject: [PATCH 13/24] Check old action keyword out of PluginManager --- Flow.Launcher.Core/Plugin/PluginManager.cs | 18 ------------------ Flow.Launcher/ActionKeywords.xaml.cs | 22 +++++++++++++++++++++- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index 18519c85d14..9a37f6fe5cc 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -340,24 +340,6 @@ public static List GetContextMenusForPlugin(Result result) return results; } - public static bool ActionKeywordRegistered(IReadOnlyList newActionKeywords, IReadOnlyList oldActionKeywords) - { - foreach (var actionKeyword in newActionKeywords) - { - if (ActionKeywordRegistered(actionKeyword, oldActionKeywords)) - { - return true; - } - } - return false; - } - - private static bool ActionKeywordRegistered(string actionKeyword, IReadOnlyList oldActionKeywords) - { - if (oldActionKeywords.Contains(actionKeyword)) return false; - return ActionKeywordRegistered(actionKeyword); - } - public static bool ActionKeywordRegistered(string actionKeyword) { // this method is only checking for action keywords (defined as not '*') registration diff --git a/Flow.Launcher/ActionKeywords.xaml.cs b/Flow.Launcher/ActionKeywords.xaml.cs index af6dcfe90d7..b0e4edbc175 100644 --- a/Flow.Launcher/ActionKeywords.xaml.cs +++ b/Flow.Launcher/ActionKeywords.xaml.cs @@ -5,6 +5,7 @@ using Flow.Launcher.Core; using System.Linq; using Flow.Launcher.Core.Plugin; +using System.Collections.Generic; namespace Flow.Launcher { @@ -42,7 +43,7 @@ private void btnDone_OnClick(object sender, RoutedEventArgs _) newActionKeywords = newActionKeywords.Count > 0 ? newActionKeywords : new() { Query.GlobalPluginWildcardSign }; - if (!PluginManager.ActionKeywordRegistered(newActionKeywords, oldActionKeywords)) + if (!ActionKeywordRegistered(newActionKeywords, oldActionKeywords)) { pluginViewModel.ChangeActionKeyword(newActionKeywords, oldActionKeywords); Close(); @@ -53,5 +54,24 @@ private void btnDone_OnClick(object sender, RoutedEventArgs _) MessageBoxEx.Show(msg); } } + + private static bool ActionKeywordRegistered(IReadOnlyList newActionKeywords, IReadOnlyList oldActionKeywords) + { + foreach (var actionKeyword in newActionKeywords) + { + // We need to check if this new action keyword is from the old action keywords because + // we have not changed action keyword yet so PluginManager still has the old action keywords + if (oldActionKeywords.Contains(actionKeyword)) + { + continue; + } + + if (PluginManager.ActionKeywordRegistered(actionKeyword)) + { + return true; + } + } + return false; + } } } From 4ebc19a82d1dbe8f40f434989d182e5049c76d04 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sun, 23 Feb 2025 19:42:43 +0800 Subject: [PATCH 14/24] Check action keywords without order --- Flow.Launcher.Core/Plugin/PluginManager.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index 9a37f6fe5cc..54f6506d92c 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -418,11 +418,15 @@ public static void ReplaceActionKeyword(string id, IReadOnlyList oldActi } } - private static bool CheckActionKeywordChanged(IReadOnlyList oldActionKeyword, IReadOnlyList newActionKeyword) + private static bool CheckActionKeywordChanged(IReadOnlyList oldActionKeywords, IReadOnlyList newActionKeywords) { - if (oldActionKeyword.Count != newActionKeyword.Count) + if (oldActionKeywords.Count != newActionKeywords.Count) return true; - return oldActionKeyword.Where((t, i) => t != newActionKeyword[i]).Any(); + + var sortedOldActionKeywords = oldActionKeywords.OrderBy(s => s).ToList(); + var sortedNewActionKeywords = newActionKeywords.OrderBy(s => s).ToList(); + + return !sortedOldActionKeywords.SequenceEqual(sortedNewActionKeywords); } public static void ReplaceActionKeyword(string id, string oldActionKeyword, string newActionKeyword) From 5d67eef57bbce11c496e60b190b3469df09ba489 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sun, 23 Feb 2025 19:43:25 +0800 Subject: [PATCH 15/24] Improve code quality --- Flow.Launcher/ActionKeywords.xaml.cs | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/Flow.Launcher/ActionKeywords.xaml.cs b/Flow.Launcher/ActionKeywords.xaml.cs index b0e4edbc175..6ea1dae5079 100644 --- a/Flow.Launcher/ActionKeywords.xaml.cs +++ b/Flow.Launcher/ActionKeywords.xaml.cs @@ -42,8 +42,8 @@ private void btnDone_OnClick(object sender, RoutedEventArgs _) newActionKeywords = newActionKeywords.Distinct().ToList(); newActionKeywords = newActionKeywords.Count > 0 ? newActionKeywords : new() { Query.GlobalPluginWildcardSign }; - - if (!ActionKeywordRegistered(newActionKeywords, oldActionKeywords)) + + if (!newActionKeywords.Except(oldActionKeywords).Any(PluginManager.ActionKeywordRegistered)) { pluginViewModel.ChangeActionKeyword(newActionKeywords, oldActionKeywords); Close(); @@ -54,24 +54,5 @@ private void btnDone_OnClick(object sender, RoutedEventArgs _) MessageBoxEx.Show(msg); } } - - private static bool ActionKeywordRegistered(IReadOnlyList newActionKeywords, IReadOnlyList oldActionKeywords) - { - foreach (var actionKeyword in newActionKeywords) - { - // We need to check if this new action keyword is from the old action keywords because - // we have not changed action keyword yet so PluginManager still has the old action keywords - if (oldActionKeywords.Contains(actionKeyword)) - { - continue; - } - - if (PluginManager.ActionKeywordRegistered(actionKeyword)) - { - return true; - } - } - return false; - } } } From 38402848aa8b5695d7f0b52e888ea793940d4ed1 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sun, 23 Feb 2025 23:06:15 +0800 Subject: [PATCH 16/24] Improve code quality for project references --- .../Flow.Launcher.Plugin.Calculator.csproj | 2 ++ .../Flow.Launcher.Plugin.PluginsManager.csproj | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj b/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj index 1b985acf9b1..92719fa54c2 100644 --- a/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj +++ b/Plugins/Flow.Launcher.Plugin.Calculator/Flow.Launcher.Plugin.Calculator.csproj @@ -43,6 +43,8 @@ + + diff --git a/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj b/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj index b438305d627..c33c428890b 100644 --- a/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj +++ b/Plugins/Flow.Launcher.Plugin.PluginsManager/Flow.Launcher.Plugin.PluginsManager.csproj @@ -19,7 +19,7 @@ - + From 6e763f0c3b0da96e81da29d48dd5c408fd1d68b6 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 24 Feb 2025 09:53:00 +0800 Subject: [PATCH 17/24] Remove ReplaceActionKeyword api function & Add action keyword same noticification --- Flow.Launcher.Core/Plugin/PluginManager.cs | 72 ++++--------------- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 12 +--- Flow.Launcher/ActionKeywords.xaml.cs | 39 +++++++++- Flow.Launcher/Languages/en.xaml | 1 + Flow.Launcher/PublicAPIInstance.cs | 2 - Flow.Launcher/ViewModel/PluginViewModel.cs | 4 +- .../SearchSourceSetting.xaml.cs | 4 +- 7 files changed, 57 insertions(+), 77 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index 54f6506d92c..a32f1d68229 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -364,8 +364,16 @@ public static void AddActionKeyword(string id, string newActionKeyword) NonGlobalPlugins[newActionKeyword] = plugin; } - // Update action keywords in plugin metadata + // Update action keywords and action keyword in plugin metadata plugin.Metadata.ActionKeywords.Add(newActionKeyword); + if (plugin.Metadata.ActionKeywords.Count > 0) + { + plugin.Metadata.ActionKeyword = plugin.Metadata.ActionKeywords[0]; + } + else + { + plugin.Metadata.ActionKeyword = string.Empty; + } } /// @@ -386,67 +394,15 @@ public static void RemoveActionKeyword(string id, string oldActionkeyword) if (oldActionkeyword != Query.GlobalPluginWildcardSign) NonGlobalPlugins.Remove(oldActionkeyword); - // Update action keywords in plugin metadata + // Update action keywords and action keyword in plugin metadata plugin.Metadata.ActionKeywords.Remove(oldActionkeyword); - } - - public static void ReplaceActionKeyword(string id, IReadOnlyList oldActionKeywords, IReadOnlyList newActionKeywords) - { - if (CheckActionKeywordChanged(oldActionKeywords, newActionKeywords)) + if (plugin.Metadata.ActionKeywords.Count > 0) { - // Fix collection modified while iterating exception - var oldActionKeywordsClone = oldActionKeywords.ToList(); - foreach (var actionKeyword in oldActionKeywordsClone) - { - RemoveActionKeyword(id, actionKeyword); - } - foreach (var actionKeyword in newActionKeywords) - { - AddActionKeyword(id, actionKeyword); - } - - // Update action keyword in plugin metadata - var plugin = GetPluginForId(id); - if (newActionKeywords.Count > 0) - { - plugin.Metadata.ActionKeyword = newActionKeywords[0]; - } - else - { - plugin.Metadata.ActionKeyword = string.Empty; - } + plugin.Metadata.ActionKeyword = plugin.Metadata.ActionKeywords[0]; } - } - - private static bool CheckActionKeywordChanged(IReadOnlyList oldActionKeywords, IReadOnlyList newActionKeywords) - { - if (oldActionKeywords.Count != newActionKeywords.Count) - return true; - - var sortedOldActionKeywords = oldActionKeywords.OrderBy(s => s).ToList(); - var sortedNewActionKeywords = newActionKeywords.OrderBy(s => s).ToList(); - - return !sortedOldActionKeywords.SequenceEqual(sortedNewActionKeywords); - } - - public static void ReplaceActionKeyword(string id, string oldActionKeyword, string newActionKeyword) - { - if (oldActionKeyword != newActionKeyword) + else { - RemoveActionKeyword(id, oldActionKeyword); - AddActionKeyword(id, newActionKeyword); - - // Update action keyword in plugin metadata - var plugin = GetPluginForId(id); - var newActionKeywords = plugin.Metadata.ActionKeywords; - if (newActionKeywords.Count > 0) - { - plugin.Metadata.ActionKeyword = newActionKeywords[0]; - } - else - { - plugin.Metadata.ActionKeyword = string.Empty; - } + plugin.Metadata.ActionKeyword = string.Empty; } } diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index da6bb598bd1..4d424dc0ba9 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -189,14 +189,14 @@ public interface IPublicAPI Task HttpDownloadAsync([NotNull] string url, [NotNull] string filePath, Action reportProgress = null, CancellationToken token = default); /// - /// Add ActionKeyword for specific plugin + /// Add ActionKeyword and update action keyword metadata for specific plugin /// /// ID for plugin that needs to add action keyword /// The actionkeyword that is supposed to be added void AddActionKeyword(string pluginId, string newActionKeyword); /// - /// Remove ActionKeyword for specific plugin + /// Remove ActionKeyword and update action keyword metadata for specific plugin /// /// ID for plugin that needs to remove action keyword /// The actionkeyword that is supposed to be removed @@ -333,13 +333,5 @@ public interface IPublicAPI /// When user closes the progress box manually by button or esc key, this action will be called. /// A progress box interface. public Task ShowProgressBoxAsync(string caption, Func, Task> reportProgressAsync, Action forceClosed = null); - - /// - /// Replace ActionKeyword for specific plugin - /// - /// ID for plugin that needs to remove action keyword - /// The actionkeyword that is supposed to be removed - /// The actionkeyword that is supposed to be added - public void ReplaceActionKeyword(string pluginId, string oldActionKeyword, string newActionKeyword); } } diff --git a/Flow.Launcher/ActionKeywords.xaml.cs b/Flow.Launcher/ActionKeywords.xaml.cs index 6ea1dae5079..10f3cf4e977 100644 --- a/Flow.Launcher/ActionKeywords.xaml.cs +++ b/Flow.Launcher/ActionKeywords.xaml.cs @@ -45,8 +45,24 @@ private void btnDone_OnClick(object sender, RoutedEventArgs _) if (!newActionKeywords.Except(oldActionKeywords).Any(PluginManager.ActionKeywordRegistered)) { - pluginViewModel.ChangeActionKeyword(newActionKeywords, oldActionKeywords); - Close(); + if (oldActionKeywords.Count != newActionKeywords.Count) + { + ReplaceActionKeyword(plugin.Metadata.ID, oldActionKeywords, newActionKeywords); + } + + var sortedOldActionKeywords = oldActionKeywords.OrderBy(s => s).ToList(); + var sortedNewActionKeywords = newActionKeywords.OrderBy(s => s).ToList(); + + if (sortedOldActionKeywords.SequenceEqual(sortedNewActionKeywords)) + { + // User just changes the sequence of action keywords + var msg = translater.GetTranslation("newActionKeywordsSameAsOld"); + MessageBoxEx.Show(msg); + } + else + { + ReplaceActionKeyword(plugin.Metadata.ID, oldActionKeywords, newActionKeywords); + } } else { @@ -54,5 +70,24 @@ private void btnDone_OnClick(object sender, RoutedEventArgs _) MessageBoxEx.Show(msg); } } + + private void ReplaceActionKeyword(string id, IReadOnlyList oldActionKeywords, IReadOnlyList newActionKeywords) + { + // Because add & remove action keyword will change action keyword metadata, + // so we need to clone it to fix collection modified while iterating exception + var oldActionKeywordsClone = oldActionKeywords.ToList(); + foreach (var actionKeyword in oldActionKeywordsClone) + { + PluginManager.RemoveActionKeyword(id, actionKeyword); + } + foreach (var actionKeyword in newActionKeywords) + { + PluginManager.AddActionKeyword(id, actionKeyword); + } + + // Update action keywords text and close + pluginViewModel.OnActionKeywordsChanged(); + Close(); + } } } diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 282d0fb4723..b1575b252ee 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -333,6 +333,7 @@ Can't find specified plugin New Action Keyword can't be empty This new Action Keyword is already assigned to another plugin, please choose a different one + This new Action Keyword is the same as old, please choose a different one Success Completed successfully Enter the action keywords you like to use to start the plugin and use whitespace to divide them. Use * if you don't want to specify any, and the plugin will be triggered without any action keywords. diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index b6f3b0d27b3..248688f7681 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -326,8 +326,6 @@ public MessageBoxResult ShowMsgBox(string messageBoxText, string caption = "", M public Task ShowProgressBoxAsync(string caption, Func, Task> reportProgressAsync, Action forceClosed = null) => ProgressBoxEx.ShowAsync(caption, reportProgressAsync, forceClosed); - public void ReplaceActionKeyword(string pluginId, string oldActionKeyword, string newActionKeyword) => PluginManager.ReplaceActionKeyword(pluginId, oldActionKeyword, newActionKeyword); - #endregion #region Private Methods diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs index 63263c768a8..c726cc3431b 100644 --- a/Flow.Launcher/ViewModel/PluginViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginViewModel.cs @@ -110,9 +110,8 @@ public Control SettingControl public int Priority => PluginPair.Metadata.Priority; public Infrastructure.UserSettings.Plugin PluginSettingsObject { get; set; } - public void ChangeActionKeyword(IReadOnlyList newActionKeywords, IReadOnlyList oldActionKeywords) + public void OnActionKeywordsChanged() { - PluginManager.ReplaceActionKeyword(PluginPair.Metadata.ID, oldActionKeywords, newActionKeywords); OnPropertyChanged(nameof(ActionKeywordsText)); } @@ -158,5 +157,4 @@ private void SetActionKeywords() changeKeywordsWindow.ShowDialog(); } } - } diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml.cs b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml.cs index d3d18d0d244..58577dbc18a 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml.cs +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/SearchSourceSetting.xaml.cs @@ -15,7 +15,6 @@ public partial class SearchSourceSettingWindow private SearchSourceViewModel _viewModel; private string selectedNewIconImageFullPath; - public SearchSourceSettingWindow(IList sources, PluginInitContext context, SearchSource old) { _oldSearchSource = old; @@ -102,7 +101,8 @@ private void EditSearchSource() if (!_context.API.ActionKeywordAssigned(newKeyword) || oldKeyword == newKeyword) { var id = _context.CurrentPluginMetadata.ID; - _context.API.ReplaceActionKeyword(id, oldKeyword, newKeyword); + _context.API.RemoveActionKeyword(id, oldKeyword); + _context.API.AddActionKeyword(id, newKeyword); var index = _searchSources.IndexOf(_oldSearchSource); _searchSources[index] = _searchSource; From 2741366a3f3aa66da0c6d7c1f715752f9fbbe5de Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Mon, 24 Feb 2025 10:01:52 +0800 Subject: [PATCH 18/24] Improve code quality --- Flow.Launcher/ActionKeywords.xaml.cs | 25 +++++++++++----------- Flow.Launcher/ViewModel/PluginViewModel.cs | 2 -- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/Flow.Launcher/ActionKeywords.xaml.cs b/Flow.Launcher/ActionKeywords.xaml.cs index 10f3cf4e977..80a4abef126 100644 --- a/Flow.Launcher/ActionKeywords.xaml.cs +++ b/Flow.Launcher/ActionKeywords.xaml.cs @@ -4,7 +4,6 @@ using Flow.Launcher.ViewModel; using Flow.Launcher.Core; using System.Linq; -using Flow.Launcher.Core.Plugin; using System.Collections.Generic; namespace Flow.Launcher @@ -43,11 +42,14 @@ private void btnDone_OnClick(object sender, RoutedEventArgs _) newActionKeywords = newActionKeywords.Count > 0 ? newActionKeywords : new() { Query.GlobalPluginWildcardSign }; - if (!newActionKeywords.Except(oldActionKeywords).Any(PluginManager.ActionKeywordRegistered)) + var addedActionKeywords = newActionKeywords.Except(oldActionKeywords).ToList(); + var removedActionKeywords = oldActionKeywords.Except(newActionKeywords).ToList(); + if (!addedActionKeywords.Any(App.API.ActionKeywordAssigned)) { if (oldActionKeywords.Count != newActionKeywords.Count) { - ReplaceActionKeyword(plugin.Metadata.ID, oldActionKeywords, newActionKeywords); + ReplaceActionKeyword(plugin.Metadata.ID, removedActionKeywords, addedActionKeywords); + return; } var sortedOldActionKeywords = oldActionKeywords.OrderBy(s => s).ToList(); @@ -61,7 +63,7 @@ private void btnDone_OnClick(object sender, RoutedEventArgs _) } else { - ReplaceActionKeyword(plugin.Metadata.ID, oldActionKeywords, newActionKeywords); + ReplaceActionKeyword(plugin.Metadata.ID, removedActionKeywords, addedActionKeywords); } } else @@ -71,21 +73,18 @@ private void btnDone_OnClick(object sender, RoutedEventArgs _) } } - private void ReplaceActionKeyword(string id, IReadOnlyList oldActionKeywords, IReadOnlyList newActionKeywords) + private void ReplaceActionKeyword(string id, IReadOnlyList removedActionKeywords, IReadOnlyList addedActionKeywords) { - // Because add & remove action keyword will change action keyword metadata, - // so we need to clone it to fix collection modified while iterating exception - var oldActionKeywordsClone = oldActionKeywords.ToList(); - foreach (var actionKeyword in oldActionKeywordsClone) + foreach (var actionKeyword in removedActionKeywords) { - PluginManager.RemoveActionKeyword(id, actionKeyword); + App.API.RemoveActionKeyword(id, actionKeyword); } - foreach (var actionKeyword in newActionKeywords) + foreach (var actionKeyword in addedActionKeywords) { - PluginManager.AddActionKeyword(id, actionKeyword); + App.API.AddActionKeyword(id, actionKeyword); } - // Update action keywords text and close + // Update action keywords text and close window pluginViewModel.OnActionKeywordsChanged(); Close(); } diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs index c726cc3431b..9b717216aa6 100644 --- a/Flow.Launcher/ViewModel/PluginViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginViewModel.cs @@ -8,7 +8,6 @@ using CommunityToolkit.Mvvm.Input; using Flow.Launcher.Core.Resource; using Flow.Launcher.Resources.Controls; -using System.Collections.Generic; namespace Flow.Launcher.ViewModel { @@ -44,7 +43,6 @@ private string PluginManagerActionKeyword } } - private async void LoadIconAsync() { Image = await ImageLoader.LoadAsync(PluginPair.Metadata.IcoPath); From afce7022e92f7ad3053a8852384d480a74602195 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Tue, 25 Feb 2025 15:46:45 +0800 Subject: [PATCH 19/24] Improve documents --- Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index 4d424dc0ba9..36c29158543 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -190,6 +190,7 @@ public interface IPublicAPI /// /// Add ActionKeyword and update action keyword metadata for specific plugin + /// Before adding, please check if action keyword is already assigned by /// /// ID for plugin that needs to add action keyword /// The actionkeyword that is supposed to be added From f7b1190f9563e188fa4d733f1fa7d9b6c0b1c3cc Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Wed, 26 Feb 2025 22:03:26 +0800 Subject: [PATCH 20/24] Add global search panel --- Flow.Launcher/ActionKeywords.xaml.cs | 18 ++- Flow.Launcher/Languages/en.xaml | 1 + .../InstalledPluginDisplayKeyword.xaml | 106 ++++++++++++------ Flow.Launcher/ViewModel/PluginViewModel.cs | 17 +++ 4 files changed, 105 insertions(+), 37 deletions(-) diff --git a/Flow.Launcher/ActionKeywords.xaml.cs b/Flow.Launcher/ActionKeywords.xaml.cs index 80a4abef126..4b678f42df0 100644 --- a/Flow.Launcher/ActionKeywords.xaml.cs +++ b/Flow.Launcher/ActionKeywords.xaml.cs @@ -77,11 +77,25 @@ private void ReplaceActionKeyword(string id, IReadOnlyList removedAction { foreach (var actionKeyword in removedActionKeywords) { - App.API.RemoveActionKeyword(id, actionKeyword); + if (actionKeyword == Query.GlobalPluginWildcardSign) + { + pluginViewModel.GlobalSearch = false; + } + else + { + App.API.RemoveActionKeyword(id, actionKeyword); + } } foreach (var actionKeyword in addedActionKeywords) { - App.API.AddActionKeyword(id, actionKeyword); + if (actionKeyword == Query.GlobalPluginWildcardSign) + { + pluginViewModel.GlobalSearch = true; + } + else + { + App.API.AddActionKeyword(id, actionKeyword); + } } // Update action keywords text and close window diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index b1575b252ee..f2eeb2de5d8 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -114,6 +114,7 @@ Off Action keyword Setting Action keyword + Global search Current action keyword New action keyword Change Action Keywords diff --git a/Flow.Launcher/Resources/Controls/InstalledPluginDisplayKeyword.xaml b/Flow.Launcher/Resources/Controls/InstalledPluginDisplayKeyword.xaml index ff2f14c4b2d..197e9ddef76 100644 --- a/Flow.Launcher/Resources/Controls/InstalledPluginDisplayKeyword.xaml +++ b/Flow.Launcher/Resources/Controls/InstalledPluginDisplayKeyword.xaml @@ -4,44 +4,80 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:ui="http://schemas.modernwpf.com/2019" xmlns:viewModel="clr-namespace:Flow.Launcher.ViewModel" d:DataContext="{d:DesignInstance viewModel:PluginViewModel}" d:DesignHeight="300" d:DesignWidth="300" mc:Ignorable="d"> - - - -  - - -