diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index 09711051e..b1396e207 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -231,7 +231,6 @@ namespace Flow.Launcher.Core.Plugin if (!NonGlobalPlugins.ContainsKey(query.ActionKeyword)) return GlobalPlugins; - var plugin = NonGlobalPlugins[query.ActionKeyword]; return new List { @@ -367,7 +366,16 @@ namespace Flow.Launcher.Core.Plugin NonGlobalPlugins[newActionKeyword] = plugin; } + // 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; + } } /// @@ -388,16 +396,15 @@ namespace Flow.Launcher.Core.Plugin if (oldActionkeyword != Query.GlobalPluginWildcardSign) NonGlobalPlugins.Remove(oldActionkeyword); - + // Update action keywords and action keyword in plugin metadata plugin.Metadata.ActionKeywords.Remove(oldActionkeyword); - } - - public static void ReplaceActionKeyword(string id, string oldActionKeyword, string newActionKeyword) - { - if (oldActionKeyword != newActionKeyword) + if (plugin.Metadata.ActionKeywords.Count > 0) { - AddActionKeyword(id, newActionKeyword); - RemoveActionKeyword(id, oldActionKeyword); + plugin.Metadata.ActionKeyword = plugin.Metadata.ActionKeywords[0]; + } + else + { + plugin.Metadata.ActionKeyword = string.Empty; } } diff --git a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs index 4c7af4cd4..f178ebb90 100644 --- a/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs +++ b/Flow.Launcher.Plugin/Interfaces/IPublicAPI.cs @@ -152,7 +152,6 @@ namespace Flow.Launcher.Plugin /// public void RemoveGlobalKeyboardCallback(Func callback); - /// /// Fuzzy Search the string with the given query. This is the core search mechanism Flow uses /// @@ -191,14 +190,15 @@ namespace Flow.Launcher.Plugin 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 + /// 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 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 diff --git a/Flow.Launcher.Plugin/PluginMetadata.cs b/Flow.Launcher.Plugin/PluginMetadata.cs index b4e06913e..91256298b 100644 --- a/Flow.Launcher.Plugin/PluginMetadata.cs +++ b/Flow.Launcher.Plugin/PluginMetadata.cs @@ -34,6 +34,8 @@ namespace Flow.Launcher.Plugin public List ActionKeywords { get; set; } + public bool HideActionKeywordPanel { get; set; } + public string IcoPath { get; set;} public override string ToString() diff --git a/Flow.Launcher.Plugin/Query.cs b/Flow.Launcher.Plugin/Query.cs index e182491c2..15b2dd171 100644 --- a/Flow.Launcher.Plugin/Query.cs +++ b/Flow.Launcher.Plugin/Query.cs @@ -39,10 +39,9 @@ namespace Flow.Launcher.Plugin 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 c3966e618..d403d4847 100644 --- a/Flow.Launcher/ActionKeywords.xaml.cs +++ b/Flow.Launcher/ActionKeywords.xaml.cs @@ -3,6 +3,8 @@ using Flow.Launcher.Core.Resource; using Flow.Launcher.Plugin; using Flow.Launcher.ViewModel; using Flow.Launcher.Core; +using System.Linq; +using System.Collections.Generic; namespace Flow.Launcher { @@ -32,14 +34,37 @@ namespace Flow.Launcher private void btnDone_OnClick(object sender, RoutedEventArgs _) { - var oldActionKeyword = plugin.Metadata.ActionKeywords[0]; - var newActionKeyword = tbAction.Text.Trim(); - newActionKeyword = newActionKeyword.Length > 0 ? newActionKeyword : "*"; - - if (!PluginViewModel.IsActionKeywordRegistered(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 }; + + var addedActionKeywords = newActionKeywords.Except(oldActionKeywords).ToList(); + var removedActionKeywords = oldActionKeywords.Except(newActionKeywords).ToList(); + if (!addedActionKeywords.Any(App.API.ActionKeywordAssigned)) { - pluginViewModel.ChangeActionKeyword(newActionKeyword, oldActionKeyword); - Close(); + if (oldActionKeywords.Count != newActionKeywords.Count) + { + ReplaceActionKeyword(plugin.Metadata.ID, removedActionKeywords, addedActionKeywords); + return; + } + + 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, removedActionKeywords, addedActionKeywords); + } } else { @@ -47,5 +72,21 @@ namespace Flow.Launcher App.API.ShowMsgBox(msg); } } + + private void ReplaceActionKeyword(string id, IReadOnlyList removedActionKeywords, IReadOnlyList addedActionKeywords) + { + foreach (var actionKeyword in removedActionKeywords) + { + App.API.RemoveActionKeyword(id, actionKeyword); + } + foreach (var actionKeyword in addedActionKeywords) + { + App.API.AddActionKeyword(id, actionKeyword); + } + + // Update action keywords text and close window + pluginViewModel.OnActionKeywordsChanged(); + Close(); + } } } diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 8bcfd9715..f0454b496 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -342,9 +342,10 @@ 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 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 diff --git a/Flow.Launcher/PublicAPIInstance.cs b/Flow.Launcher/PublicAPIInstance.cs index f367ac921..456f1ad47 100644 --- a/Flow.Launcher/PublicAPIInstance.cs +++ b/Flow.Launcher/PublicAPIInstance.cs @@ -331,7 +331,6 @@ namespace Flow.Launcher return _mainVM.GameModeStatus; } - private readonly List> _globalKeyboardHandlers = new(); public void RegisterGlobalKeyboardCallback(Func callback) => _globalKeyboardHandlers.Add(callback); diff --git a/Flow.Launcher/ViewModel/PluginViewModel.cs b/Flow.Launcher/ViewModel/PluginViewModel.cs index 209a81395..33d730604 100644 --- a/Flow.Launcher/ViewModel/PluginViewModel.cs +++ b/Flow.Launcher/ViewModel/PluginViewModel.cs @@ -43,7 +43,6 @@ namespace Flow.Launcher.ViewModel } } - private async void LoadIconAsync() { Image = await ImageLoader.LoadAsync(PluginPair.Metadata.IcoPath); @@ -100,7 +99,7 @@ namespace Flow.Launcher.ViewModel : null; private ImageSource _image = ImageLoader.MissingImage; - public Visibility ActionKeywordsVisibility => PluginPair.Metadata.ActionKeywords.Count == 1 ? Visibility.Visible : Visibility.Collapsed; + public Visibility ActionKeywordsVisibility => PluginPair.Metadata.HideActionKeywordPanel ? Visibility.Collapsed : Visibility.Visible; 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; @@ -109,9 +108,8 @@ namespace Flow.Launcher.ViewModel public int Priority => PluginPair.Metadata.Priority; public Infrastructure.UserSettings.Plugin PluginSettingsObject { get; set; } - public void ChangeActionKeyword(string newActionKeyword, string oldActionKeyword) + public void OnActionKeywordsChanged() { - PluginManager.ReplaceActionKeyword(PluginPair.Metadata.ID, oldActionKeyword, newActionKeyword); OnPropertyChanged(nameof(ActionKeywordsText)); } @@ -150,8 +148,6 @@ namespace Flow.Launcher.ViewModel App.API.ShowMainWindow(); } - public static bool IsActionKeywordRegistered(string newActionKeyword) => PluginManager.ActionKeywordRegistered(newActionKeyword); - [RelayCommand] private void SetActionKeywords() { 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 1b985acf9..9cdef365d 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,7 @@ + diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/plugin.json b/Plugins/Flow.Launcher.Plugin.Explorer/plugin.json index 4eb6bb83b..d2440ab61 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.Explorer/plugin.json @@ -7,6 +7,7 @@ "*", "*" ], + "HideActionKeywordPanel": true, "Name": "Explorer", "Description": "Find and manage files and folders via Windows Search or Everything", "Author": "Jeremy Wu", 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 b438305d6..c33c42889 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 @@ - + 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 55d69d526..c2d0a46a0 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 a3e5630c2..58577dbc1 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 { @@ -16,7 +15,6 @@ namespace Flow.Launcher.Plugin.WebSearch private SearchSourceViewModel _viewModel; private string selectedNewIconImageFullPath; - public SearchSourceSettingWindow(IList sources, PluginInitContext context, SearchSource old) { _oldSearchSource = old; @@ -80,10 +78,10 @@ namespace Flow.Launcher.Plugin.WebSearch 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); + _context.API.AddActionKeyword(id, keyword); _searchSources.Add(_searchSource); @@ -100,10 +98,11 @@ namespace Flow.Launcher.Plugin.WebSearch { 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); + _context.API.RemoveActionKeyword(id, oldKeyword); + _context.API.AddActionKeyword(id, 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 739bc9d6b..e53f4ec75 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; @@ -40,7 +39,7 @@ namespace Flow.Launcher.Plugin.WebSearch if (result == MessageBoxResult.Yes) { var id = _context.CurrentPluginMetadata.ID; - PluginManager.RemoveActionKeyword(id, selected.ActionKeyword); + _context.API.RemoveActionKeyword(id, selected.ActionKeyword); _settings.SearchSources.Remove(selected); } } diff --git a/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json b/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json index 6b6792ad3..20f6def70 100644 --- a/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.WebSearch/plugin.json @@ -23,6 +23,7 @@ "yahoo", "bd" ], + "HideActionKeywordPanel": true, "Name": "Web Searches", "Description": "Provide the web search ability", "Author": "qianlifeng",