From c979609de7db53ac987156e05e206f3df826a932 Mon Sep 17 00:00:00 2001 From: 01Dri Date: Wed, 29 Oct 2025 20:39:44 -0300 Subject: [PATCH 01/21] new keywords in settings --- Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs index 8d62531cd62..8c787796055 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs @@ -58,6 +58,15 @@ public class Settings public bool QuickAccessKeywordEnabled { get; set; } + + public string FolderSearchActionKeyword { get; set; } = Query.GlobalPluginWildcardSign; + + public bool FolderSearchKeywordEnabled { get; set; } + + public string FileSearchActionKeyword { get; set; } = Query.GlobalPluginWildcardSign; + + public bool FileSearchKeywordEnabled { get; set; } + public bool WarnWindowsSearchServiceOff { get; set; } = true; public bool ShowFileSizeInPreviewPanel { get; set; } = true; @@ -160,7 +169,10 @@ internal enum ActionKeyword PathSearchActionKeyword, FileContentSearchActionKeyword, IndexSearchActionKeyword, - QuickAccessActionKeyword + QuickAccessActionKeyword, + FolderSearchActionKeyword, + FileSearchActionKeyword, + } internal string GetActionKeyword(ActionKeyword actionKeyword) => actionKeyword switch From 531e8c70715157b7c942fc899d87be2d88d5c30b Mon Sep 17 00:00:00 2001 From: 01Dri Date: Wed, 29 Oct 2025 20:50:59 -0300 Subject: [PATCH 02/21] settings keywords --- Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml | 2 ++ Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs | 8 ++++++++ .../ViewModels/SettingsViewModel.cs | 6 +++++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml index c40040df5be..45c0d72acd9 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml @@ -58,6 +58,8 @@ File Content Search: Index Search: Quick Access: + Folder Search: + File Search: Current Action Keyword Done Enabled diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs index 8c787796055..b5ea760dc20 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs @@ -182,6 +182,8 @@ internal enum ActionKeyword ActionKeyword.FileContentSearchActionKeyword => FileContentSearchActionKeyword, ActionKeyword.IndexSearchActionKeyword => IndexSearchActionKeyword, ActionKeyword.QuickAccessActionKeyword => QuickAccessActionKeyword, + ActionKeyword.FolderSearchActionKeyword => FolderSearchActionKeyword, + ActionKeyword.FileSearchActionKeyword => FileSearchActionKeyword, _ => throw new ArgumentOutOfRangeException(nameof(actionKeyword), actionKeyword, "ActionKeyWord property not found") }; @@ -192,6 +194,8 @@ internal enum ActionKeyword ActionKeyword.FileContentSearchActionKeyword => FileContentSearchActionKeyword = keyword, ActionKeyword.IndexSearchActionKeyword => IndexSearchActionKeyword = keyword, ActionKeyword.QuickAccessActionKeyword => QuickAccessActionKeyword = keyword, + ActionKeyword.FolderSearchActionKeyword => FolderSearchActionKeyword = keyword, + ActionKeyword.FileSearchActionKeyword => FileSearchActionKeyword = keyword, _ => throw new ArgumentOutOfRangeException(nameof(actionKeyword), actionKeyword, "ActionKeyWord property not found") }; @@ -202,6 +206,8 @@ internal enum ActionKeyword ActionKeyword.IndexSearchActionKeyword => IndexSearchKeywordEnabled, ActionKeyword.FileContentSearchActionKeyword => FileContentSearchKeywordEnabled, ActionKeyword.QuickAccessActionKeyword => QuickAccessKeywordEnabled, + ActionKeyword.FolderSearchActionKeyword => FolderSearchKeywordEnabled, + ActionKeyword.FileSearchActionKeyword => FileSearchKeywordEnabled, _ => throw new ArgumentOutOfRangeException(nameof(actionKeyword), actionKeyword, "ActionKeyword enabled status not defined") }; @@ -212,6 +218,8 @@ internal enum ActionKeyword ActionKeyword.IndexSearchActionKeyword => IndexSearchKeywordEnabled = enable, ActionKeyword.FileContentSearchActionKeyword => FileContentSearchKeywordEnabled = enable, ActionKeyword.QuickAccessActionKeyword => QuickAccessKeywordEnabled = enable, + ActionKeyword.FolderSearchActionKeyword => FolderSearchKeywordEnabled = enable, + ActionKeyword.FileSearchActionKeyword => FileSearchKeywordEnabled = enable, _ => throw new ArgumentOutOfRangeException(nameof(actionKeyword), actionKeyword, "ActionKeyword enabled status not defined") }; } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs index 2d46c6307cc..956c84db2c6 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs @@ -279,7 +279,11 @@ private void InitializeActionKeywordModels() new(Settings.ActionKeyword.IndexSearchActionKeyword, "plugin_explorer_actionkeywordview_indexsearch"), new(Settings.ActionKeyword.QuickAccessActionKeyword, - "plugin_explorer_actionkeywordview_quickaccess") + "plugin_explorer_actionkeywordview_quickaccess"), + new(Settings.ActionKeyword.FolderSearchActionKeyword, + "plugin_explorer_actionkeywordview_foldersearch"), + new(Settings.ActionKeyword.FileSearchActionKeyword, + "plugin_explorer_actionkeywordview_filesearch") }; } From dbe7d520cd5329706f57c65cb339aec5532750d8 Mon Sep 17 00:00:00 2001 From: 01Dri Date: Thu, 30 Oct 2025 00:16:25 -0300 Subject: [PATCH 03/21] ActionKeywordConfiguration --- .../Search/ActionKeywordConfiguration.cs | 25 +++ .../Search/SearchManager.cs | 170 ++++++++++++------ .../Flow.Launcher.Plugin.Explorer/Settings.cs | 2 +- 3 files changed, 140 insertions(+), 57 deletions(-) create mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/ActionKeywordConfiguration.cs diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/ActionKeywordConfiguration.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/ActionKeywordConfiguration.cs new file mode 100644 index 00000000000..926a7c01870 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/ActionKeywordConfiguration.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Flow.Launcher.Plugin.Explorer.Search; +public class ActionKeywordConfiguration +{ + public string Keyword { get; } + + public Settings.ActionKeyword Type { get; } + + public bool Enable { get; } + + public ActionKeywordConfiguration(string keyword, Settings.ActionKeyword type, bool enable) + { + Keyword = keyword; + Type = type; + Enable = enable; + } + + public bool IsActive(Settings.ActionKeyword type) + => Type == type && Enable; +} diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs index d7b0690828a..c5a30ccde93 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs @@ -1,13 +1,16 @@ -using Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo; -using Flow.Launcher.Plugin.Explorer.Search.Everything; -using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks; -using Flow.Launcher.Plugin.SharedCommands; -using System; +using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using System.Windows; using Flow.Launcher.Plugin.Explorer.Exceptions; +using Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo; +using Flow.Launcher.Plugin.Explorer.Search.Everything; +using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks; +using Flow.Launcher.Plugin.SharedCommands; +using static Flow.Launcher.Plugin.Explorer.Settings; using Path = System.IO.Path; namespace Flow.Launcher.Plugin.Explorer.Search @@ -24,6 +27,7 @@ public SearchManager(Settings settings, PluginInitContext context) Settings = settings; } + /// /// Note: A path that ends with "\" and one that doesn't will not be regarded as equal. /// @@ -47,45 +51,46 @@ public int GetHashCode(Result obj) internal async Task> SearchAsync(Query query, CancellationToken token) { var results = new HashSet(PathEqualityComparator.Instance); - - // This allows the user to type the below action keywords and see/search the list of quick folder links - if (ActionKeywordMatch(query, Settings.ActionKeyword.SearchActionKeyword) - || ActionKeywordMatch(query, Settings.ActionKeyword.QuickAccessActionKeyword) - || ActionKeywordMatch(query, Settings.ActionKeyword.PathSearchActionKeyword) - || ActionKeywordMatch(query, Settings.ActionKeyword.IndexSearchActionKeyword) - || ActionKeywordMatch(query, Settings.ActionKeyword.FileContentSearchActionKeyword)) + var actionKeywordConfigurations = GetActionKeywordConfigurations(); + var keywordStr = query.ActionKeyword.Length == 0 ? Query.GlobalPluginWildcardSign : query.ActionKeyword; + if (string.IsNullOrEmpty(keywordStr)) { - if (string.IsNullOrEmpty(query.Search) && ActionKeywordMatch(query, Settings.ActionKeyword.QuickAccessActionKeyword)) - return QuickAccess.AccessLinkListAll(query, Settings.QuickAccessLinks); + return new List(); } - else + bool isPathSearch = query.Search.IsLocationPathString() + || EnvironmentVariables.IsEnvironmentVariableSearch(query.Search) + || EnvironmentVariables.HasEnvironmentVar(query.Search); + + var actionKeywordConfiguration = actionKeywordConfigurations.FirstOrDefault(x => x.Keyword == keywordStr && x.Enable); + if (actionKeywordConfiguration == null && !isPathSearch) { - // No action keyword matched- plugin should not handle this query, return empty results. return new List(); } - IAsyncEnumerable searchResults; + if (actionKeywordConfiguration == null && isPathSearch) + { + actionKeywordConfiguration = + new ActionKeywordConfiguration(keywordStr, ActionKeyword.PathSearchActionKeyword, true); + } - bool isPathSearch = query.Search.IsLocationPathString() - || EnvironmentVariables.IsEnvironmentVariableSearch(query.Search) - || EnvironmentVariables.HasEnvironmentVar(query.Search); + if (string.IsNullOrEmpty(query.Search) + && actionKeywordConfiguration!.IsActive(ActionKeyword.QuickAccessActionKeyword)) + { + return QuickAccess.AccessLinkListAll(query, Settings.QuickAccessLinks); + } + + IAsyncEnumerable searchResults; string engineName; - switch (isPathSearch) + switch (actionKeywordConfiguration!.IsActive(ActionKeyword.PathSearchActionKeyword) + || actionKeywordConfiguration.IsActive(ActionKeyword.SearchActionKeyword)) { - case true - when ActionKeywordMatch(query, Settings.ActionKeyword.PathSearchActionKeyword) - || ActionKeywordMatch(query, Settings.ActionKeyword.SearchActionKeyword): - + case true: results.UnionWith(await PathSearchAsync(query, token).ConfigureAwait(false)); - return results.ToList(); - case false - when ActionKeywordMatch(query, Settings.ActionKeyword.FileContentSearchActionKeyword): - - // Intentionally require enabling of Everything's content search due to its slowness + when actionKeywordConfiguration.IsActive(ActionKeyword.FileContentSearchActionKeyword): if (Settings.ContentIndexProvider is EverythingSearchManager && !Settings.EnableEverythingContentSearch) return EverythingContentSearchResult(query); @@ -93,18 +98,22 @@ when ActionKeywordMatch(query, Settings.ActionKeyword.FileContentSearchActionKey engineName = Enum.GetName(Settings.ContentSearchEngine); break; + case false - when ActionKeywordMatch(query, Settings.ActionKeyword.IndexSearchActionKeyword) - || ActionKeywordMatch(query, Settings.ActionKeyword.SearchActionKeyword): + when actionKeywordConfiguration.IsActive(ActionKeyword.IndexSearchActionKeyword) + || actionKeywordConfiguration.IsActive(ActionKeyword.SearchActionKeyword) + || actionKeywordConfiguration.IsActive(ActionKeyword.FolderSearchActionKeyword) + || actionKeywordConfiguration.IsActive(ActionKeyword.FileSearchActionKeyword): searchResults = Settings.IndexProvider.SearchAsync(query.Search, token); engineName = Enum.GetName(Settings.IndexSearchEngine); break; - case true or false - when ActionKeywordMatch(query, Settings.ActionKeyword.QuickAccessActionKeyword): + case false + when actionKeywordConfiguration.IsActive(ActionKeyword.QuickAccessActionKeyword): return QuickAccess.AccessLinkListMatched(query, Settings.QuickAccessLinks); + default: return results.ToList(); } @@ -115,11 +124,14 @@ when ActionKeywordMatch(query, Settings.ActionKeyword.QuickAccessActionKeyword): try { await foreach (var search in searchResults.WithCancellation(token).ConfigureAwait(false)) - if (search.Type == ResultType.File && IsExcludedFile(search)) { + { + if (ShouldSkip(actionKeywordConfiguration, search)) + { continue; - } else { - results.Add(ResultManager.CreateResult(query, search)); } + results.Add(ResultManager.CreateResult(query, search)); + + } } catch (OperationCanceledException) { @@ -140,25 +152,6 @@ when ActionKeywordMatch(query, Settings.ActionKeyword.QuickAccessActionKeyword): return results.ToList(); } - private bool ActionKeywordMatch(Query query, Settings.ActionKeyword allowedActionKeyword) - { - var keyword = query.ActionKeyword.Length == 0 ? Query.GlobalPluginWildcardSign : query.ActionKeyword; - - return allowedActionKeyword switch - { - Settings.ActionKeyword.SearchActionKeyword => Settings.SearchActionKeywordEnabled && - keyword == Settings.SearchActionKeyword, - Settings.ActionKeyword.PathSearchActionKeyword => Settings.PathSearchKeywordEnabled && - keyword == Settings.PathSearchActionKeyword, - Settings.ActionKeyword.FileContentSearchActionKeyword => Settings.FileContentSearchKeywordEnabled && - keyword == Settings.FileContentSearchActionKeyword, - Settings.ActionKeyword.IndexSearchActionKeyword => Settings.IndexSearchKeywordEnabled && - keyword == Settings.IndexSearchActionKeyword, - Settings.ActionKeyword.QuickAccessActionKeyword => Settings.QuickAccessKeywordEnabled && - keyword == Settings.QuickAccessActionKeyword, - _ => throw new ArgumentOutOfRangeException(nameof(allowedActionKeyword), allowedActionKeyword, "actionKeyword out of range") - }; - } private List EverythingContentSearchResult(Query query) { @@ -280,5 +273,70 @@ private bool IsExcludedFile(SearchResult result) return excludedFileTypes.Contains(fileExtension, StringComparer.OrdinalIgnoreCase); } + + private bool ShouldSkip(ActionKeywordConfiguration actionKeywordConfiguration, SearchResult search) + { + if (search.Type == ResultType.File && IsExcludedFile(search)) + return true; + + if (actionKeywordConfiguration.IsActive(ActionKeyword.FolderSearchActionKeyword) + && search.Type != ResultType.Folder) + { + return true; + } + + if (actionKeywordConfiguration.IsActive(ActionKeyword.FileSearchActionKeyword) + && search.Type != ResultType.File) + { + return true; + } + + return false; + } + + + private List GetActionKeywordConfigurations() + { + return new List() + { + new( + Settings.FolderSearchActionKeyword, + ActionKeyword.FolderSearchActionKeyword, + Settings.FolderSearchKeywordEnabled + ), + new( + Settings.FileSearchActionKeyword, + ActionKeyword.FileSearchActionKeyword, + Settings.FileSearchKeywordEnabled + ), + new( + Settings.PathSearchActionKeyword, + ActionKeyword.PathSearchActionKeyword, + Settings.PathSearchKeywordEnabled + ), + new( + Settings.SearchActionKeyword, + ActionKeyword.SearchActionKeyword, + Settings.SearchActionKeywordEnabled + ), + new( + Settings.QuickAccessActionKeyword, + ActionKeyword.QuickAccessActionKeyword, + Settings.QuickAccessKeywordEnabled + ), + new( + Settings.IndexSearchActionKeyword, + ActionKeyword.IndexSearchActionKeyword, + Settings.IndexSearchKeywordEnabled + ), + new( + Settings.FileContentSearchActionKeyword, + ActionKeyword.FileContentSearchActionKeyword, + Settings.FileContentSearchKeywordEnabled + ), + }; + } + } + } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs index b5ea760dc20..0e31d23c0ac 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs @@ -163,7 +163,7 @@ public enum ContentIndexSearchEngineOption #endregion - internal enum ActionKeyword + public enum ActionKeyword { SearchActionKeyword, PathSearchActionKeyword, From e0a99c5099993e28dcab2c9457f3a1a4d72a5c13 Mon Sep 17 00:00:00 2001 From: 01Dri Date: Sat, 1 Nov 2025 20:55:55 -0300 Subject: [PATCH 04/21] adjust --- .../Search/SearchManager.cs | 50 ++----------------- .../Flow.Launcher.Plugin.Explorer/Settings.cs | 27 ++++++++-- 2 files changed, 26 insertions(+), 51 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs index c5a30ccde93..2917f93093f 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs @@ -51,7 +51,6 @@ public int GetHashCode(Result obj) internal async Task> SearchAsync(Query query, CancellationToken token) { var results = new HashSet(PathEqualityComparator.Instance); - var actionKeywordConfigurations = GetActionKeywordConfigurations(); var keywordStr = query.ActionKeyword.Length == 0 ? Query.GlobalPluginWildcardSign : query.ActionKeyword; if (string.IsNullOrEmpty(keywordStr)) { @@ -60,8 +59,8 @@ internal async Task> SearchAsync(Query query, CancellationToken tok bool isPathSearch = query.Search.IsLocationPathString() || EnvironmentVariables.IsEnvironmentVariableSearch(query.Search) || EnvironmentVariables.HasEnvironmentVar(query.Search); + var actionKeywordConfiguration = Settings.GetActionKeywordConfiguration(keywordStr); - var actionKeywordConfiguration = actionKeywordConfigurations.FirstOrDefault(x => x.Keyword == keywordStr && x.Enable); if (actionKeywordConfiguration == null && !isPathSearch) { return new List(); @@ -72,6 +71,7 @@ internal async Task> SearchAsync(Query query, CancellationToken tok actionKeywordConfiguration = new ActionKeywordConfiguration(keywordStr, ActionKeyword.PathSearchActionKeyword, true); } + // This allows the user to type the below action keywords and see/search the list of quick folder links if (string.IsNullOrEmpty(query.Search) && actionKeywordConfiguration!.IsActive(ActionKeyword.QuickAccessActionKeyword)) @@ -90,6 +90,7 @@ internal async Task> SearchAsync(Query query, CancellationToken tok results.UnionWith(await PathSearchAsync(query, token).ConfigureAwait(false)); return results.ToList(); case false + // Intentionally require enabling of Everything's content search due to its slowness when actionKeywordConfiguration.IsActive(ActionKeyword.FileContentSearchActionKeyword): if (Settings.ContentIndexProvider is EverythingSearchManager && !Settings.EnableEverythingContentSearch) return EverythingContentSearchResult(query); @@ -109,7 +110,7 @@ when actionKeywordConfiguration.IsActive(ActionKeyword.IndexSearchActionKeyword) engineName = Enum.GetName(Settings.IndexSearchEngine); break; - case false + case false when actionKeywordConfiguration.IsActive(ActionKeyword.QuickAccessActionKeyword): return QuickAccess.AccessLinkListMatched(query, Settings.QuickAccessLinks); @@ -294,49 +295,6 @@ private bool ShouldSkip(ActionKeywordConfiguration actionKeywordConfiguration, S return false; } - - private List GetActionKeywordConfigurations() - { - return new List() - { - new( - Settings.FolderSearchActionKeyword, - ActionKeyword.FolderSearchActionKeyword, - Settings.FolderSearchKeywordEnabled - ), - new( - Settings.FileSearchActionKeyword, - ActionKeyword.FileSearchActionKeyword, - Settings.FileSearchKeywordEnabled - ), - new( - Settings.PathSearchActionKeyword, - ActionKeyword.PathSearchActionKeyword, - Settings.PathSearchKeywordEnabled - ), - new( - Settings.SearchActionKeyword, - ActionKeyword.SearchActionKeyword, - Settings.SearchActionKeywordEnabled - ), - new( - Settings.QuickAccessActionKeyword, - ActionKeyword.QuickAccessActionKeyword, - Settings.QuickAccessKeywordEnabled - ), - new( - Settings.IndexSearchActionKeyword, - ActionKeyword.IndexSearchActionKeyword, - Settings.IndexSearchKeywordEnabled - ), - new( - Settings.FileContentSearchActionKeyword, - ActionKeyword.FileContentSearchActionKeyword, - Settings.FileContentSearchKeywordEnabled - ), - }; - } - } } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs index 0e31d23c0ac..dbd74ca42d3 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs @@ -1,12 +1,13 @@ -using Flow.Launcher.Plugin.Explorer.Search; -using Flow.Launcher.Plugin.Explorer.Search.Everything; -using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks; -using Flow.Launcher.Plugin.Explorer.Search.WindowsIndex; -using System; +using System; +using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Text.Json.Serialization; +using Flow.Launcher.Plugin.Explorer.Search; +using Flow.Launcher.Plugin.Explorer.Search.Everything; using Flow.Launcher.Plugin.Explorer.Search.IProvider; +using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks; +using Flow.Launcher.Plugin.Explorer.Search.WindowsIndex; namespace Flow.Launcher.Plugin.Explorer { @@ -222,5 +223,21 @@ public enum ActionKeyword ActionKeyword.FileSearchActionKeyword => FileSearchKeywordEnabled = enable, _ => throw new ArgumentOutOfRangeException(nameof(actionKeyword), actionKeyword, "ActionKeyword enabled status not defined") }; + + public ActionKeywordConfiguration GetActionKeywordConfiguration(string actionKeywordStr) + { + if (string.IsNullOrEmpty(actionKeywordStr)) return null; + foreach (ActionKeyword action in Enum.GetValues(typeof(ActionKeyword))) + { + var keywordStr = GetActionKeyword(action); + if (string.IsNullOrEmpty(keywordStr)) continue; + if (keywordStr == actionKeywordStr) + { + return new ActionKeywordConfiguration(keywordStr, action, GetActionKeywordEnabled(action)); + } + } + return null; + } + } } From 9209b93a5e7766165300f5db3d3a9e85b0c12cd7 Mon Sep 17 00:00:00 2001 From: 01Dri Date: Sun, 2 Nov 2025 00:35:42 -0300 Subject: [PATCH 05/21] up --- .../Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs index 2917f93093f..6e5c7615462 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs @@ -52,13 +52,11 @@ internal async Task> SearchAsync(Query query, CancellationToken tok { var results = new HashSet(PathEqualityComparator.Instance); var keywordStr = query.ActionKeyword.Length == 0 ? Query.GlobalPluginWildcardSign : query.ActionKeyword; - if (string.IsNullOrEmpty(keywordStr)) - { - return new List(); - } bool isPathSearch = query.Search.IsLocationPathString() || EnvironmentVariables.IsEnvironmentVariableSearch(query.Search) || EnvironmentVariables.HasEnvironmentVar(query.Search); + + var actionKeywordConfiguration = Settings.GetActionKeywordConfiguration(keywordStr); if (actionKeywordConfiguration == null && !isPathSearch) From d2dd16bcfb72c39a67ca15a4ae9dd9da656f79b3 Mon Sep 17 00:00:00 2001 From: 01Dri Date: Sun, 2 Nov 2025 03:38:39 -0300 Subject: [PATCH 06/21] up --- .../Search/SearchManager.cs | 23 +++++-------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs index 6e5c7615462..bc2112aa5c8 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs @@ -56,7 +56,6 @@ internal async Task> SearchAsync(Query query, CancellationToken tok || EnvironmentVariables.IsEnvironmentVariableSearch(query.Search) || EnvironmentVariables.HasEnvironmentVar(query.Search); - var actionKeywordConfiguration = Settings.GetActionKeywordConfiguration(keywordStr); if (actionKeywordConfiguration == null && !isPathSearch) @@ -97,31 +96,21 @@ when actionKeywordConfiguration.IsActive(ActionKeyword.FileContentSearchActionKe engineName = Enum.GetName(Settings.ContentSearchEngine); break; - - case false - when actionKeywordConfiguration.IsActive(ActionKeyword.IndexSearchActionKeyword) - || actionKeywordConfiguration.IsActive(ActionKeyword.SearchActionKeyword) - || actionKeywordConfiguration.IsActive(ActionKeyword.FolderSearchActionKeyword) - || actionKeywordConfiguration.IsActive(ActionKeyword.FileSearchActionKeyword): - - searchResults = Settings.IndexProvider.SearchAsync(query.Search, token); - engineName = Enum.GetName(Settings.IndexSearchEngine); - break; - - case false + case false when actionKeywordConfiguration.IsActive(ActionKeyword.QuickAccessActionKeyword): return QuickAccess.AccessLinkListMatched(query, Settings.QuickAccessLinks); default: - return results.ToList(); + searchResults = Settings.IndexProvider.SearchAsync(query.Search, token); + engineName = Enum.GetName(Settings.IndexSearchEngine); + break; } - // Merge Quick Access Link results for non-path searches. - results.UnionWith(QuickAccess.AccessLinkListMatched(query, Settings.QuickAccessLinks)); - try { + results.UnionWith(QuickAccess.AccessLinkListMatched(query, Settings.QuickAccessLinks)); + await foreach (var search in searchResults.WithCancellation(token).ConfigureAwait(false)) { if (ShouldSkip(actionKeywordConfiguration, search)) From fbb26e9932741bd11a000c98f0114eec2f4f823a Mon Sep 17 00:00:00 2001 From: 01Dri Date: Sun, 2 Nov 2025 03:46:19 -0300 Subject: [PATCH 07/21] switch case adjust --- Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs index bc2112aa5c8..73cb04574f1 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs @@ -80,8 +80,7 @@ internal async Task> SearchAsync(Query query, CancellationToken tok string engineName; - switch (actionKeywordConfiguration!.IsActive(ActionKeyword.PathSearchActionKeyword) - || actionKeywordConfiguration.IsActive(ActionKeyword.SearchActionKeyword)) + switch (actionKeywordConfiguration!.IsActive(ActionKeyword.PathSearchActionKeyword)) { case true: results.UnionWith(await PathSearchAsync(query, token).ConfigureAwait(false)); From c90de6fa8a5589d93c5bf8700a7d5efb2073b950 Mon Sep 17 00:00:00 2001 From: 01Dri Date: Sun, 2 Nov 2025 16:30:29 -0300 Subject: [PATCH 08/21] code quality --- ...onfiguration.cs => ActionKeywordActive.cs} | 14 +++--- .../Search/SearchManager.cs | 43 ++++++++++++------- .../Flow.Launcher.Plugin.Explorer/Settings.cs | 7 +-- .../ViewModels/SettingsViewModel.cs | 2 +- 4 files changed, 40 insertions(+), 26 deletions(-) rename Plugins/Flow.Launcher.Plugin.Explorer/Search/{ActionKeywordConfiguration.cs => ActionKeywordActive.cs} (52%) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/ActionKeywordConfiguration.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/ActionKeywordActive.cs similarity index 52% rename from Plugins/Flow.Launcher.Plugin.Explorer/Search/ActionKeywordConfiguration.cs rename to Plugins/Flow.Launcher.Plugin.Explorer/Search/ActionKeywordActive.cs index 926a7c01870..1fb5ee13987 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/ActionKeywordConfiguration.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/ActionKeywordActive.cs @@ -3,23 +3,25 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using static Flow.Launcher.Plugin.Explorer.Settings; namespace Flow.Launcher.Plugin.Explorer.Search; -public class ActionKeywordConfiguration +public class ActionKeywordActive { public string Keyword { get; } public Settings.ActionKeyword Type { get; } - public bool Enable { get; } - public ActionKeywordConfiguration(string keyword, Settings.ActionKeyword type, bool enable) + public ActionKeywordActive(string keyword, Settings.ActionKeyword type) { Keyword = keyword; Type = type; - Enable = enable; } - public bool IsActive(Settings.ActionKeyword type) - => Type == type && Enable; + public bool Equals(ActionKeyword type) + { + return Type == type; + } + } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs index 73cb04574f1..f922a781ab5 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs @@ -56,22 +56,23 @@ internal async Task> SearchAsync(Query query, CancellationToken tok || EnvironmentVariables.IsEnvironmentVariableSearch(query.Search) || EnvironmentVariables.HasEnvironmentVar(query.Search); - var actionKeywordConfiguration = Settings.GetActionKeywordConfiguration(keywordStr); + var activeActionKeyword = Settings.GetActiveActionKeyword(keywordStr); - if (actionKeywordConfiguration == null && !isPathSearch) + if (activeActionKeyword == null && !isPathSearch) { - return new List(); + MergeQuickAccessInResultsIfQueryMatch(results, query); + return results.ToList(); } - if (actionKeywordConfiguration == null && isPathSearch) + if (activeActionKeyword == null && isPathSearch) { - actionKeywordConfiguration = - new ActionKeywordConfiguration(keywordStr, ActionKeyword.PathSearchActionKeyword, true); + activeActionKeyword = + new ActionKeywordActive(keywordStr, ActionKeyword.PathSearchActionKeyword); } // This allows the user to type the below action keywords and see/search the list of quick folder links if (string.IsNullOrEmpty(query.Search) - && actionKeywordConfiguration!.IsActive(ActionKeyword.QuickAccessActionKeyword)) + && activeActionKeyword!.Equals(ActionKeyword.QuickAccessActionKeyword)) { return QuickAccess.AccessLinkListAll(query, Settings.QuickAccessLinks); } @@ -80,14 +81,14 @@ internal async Task> SearchAsync(Query query, CancellationToken tok string engineName; - switch (actionKeywordConfiguration!.IsActive(ActionKeyword.PathSearchActionKeyword)) + switch (activeActionKeyword!.Equals(ActionKeyword.PathSearchActionKeyword)) { case true: results.UnionWith(await PathSearchAsync(query, token).ConfigureAwait(false)); return results.ToList(); case false // Intentionally require enabling of Everything's content search due to its slowness - when actionKeywordConfiguration.IsActive(ActionKeyword.FileContentSearchActionKeyword): + when activeActionKeyword.Equals(ActionKeyword.FileContentSearchActionKeyword): if (Settings.ContentIndexProvider is EverythingSearchManager && !Settings.EnableEverythingContentSearch) return EverythingContentSearchResult(query); @@ -96,7 +97,7 @@ when actionKeywordConfiguration.IsActive(ActionKeyword.FileContentSearchActionKe break; case false - when actionKeywordConfiguration.IsActive(ActionKeyword.QuickAccessActionKeyword): + when activeActionKeyword.Equals(ActionKeyword.QuickAccessActionKeyword): return QuickAccess.AccessLinkListMatched(query, Settings.QuickAccessLinks); @@ -106,13 +107,13 @@ when actionKeywordConfiguration.IsActive(ActionKeyword.QuickAccessActionKeyword) break; } + // Merge Quick Access Link results for non-path searches. + MergeQuickAccessInResultsIfQueryMatch(results, query); try { - results.UnionWith(QuickAccess.AccessLinkListMatched(query, Settings.QuickAccessLinks)); - await foreach (var search in searchResults.WithCancellation(token).ConfigureAwait(false)) { - if (ShouldSkip(actionKeywordConfiguration, search)) + if (ShouldSkip(activeActionKeyword, search)) { continue; } @@ -261,18 +262,18 @@ private bool IsExcludedFile(SearchResult result) return excludedFileTypes.Contains(fileExtension, StringComparer.OrdinalIgnoreCase); } - private bool ShouldSkip(ActionKeywordConfiguration actionKeywordConfiguration, SearchResult search) + private bool ShouldSkip(ActionKeywordActive actionKeywordActive, SearchResult search) { if (search.Type == ResultType.File && IsExcludedFile(search)) return true; - if (actionKeywordConfiguration.IsActive(ActionKeyword.FolderSearchActionKeyword) + if (actionKeywordActive.Equals(ActionKeyword.FolderSearchActionKeyword) && search.Type != ResultType.Folder) { return true; } - if (actionKeywordConfiguration.IsActive(ActionKeyword.FileSearchActionKeyword) + if (actionKeywordActive.Equals(ActionKeyword.FileSearchActionKeyword) && search.Type != ResultType.File) { return true; @@ -281,6 +282,16 @@ private bool ShouldSkip(ActionKeywordConfiguration actionKeywordConfiguration, S return false; } + private void MergeQuickAccessInResultsIfQueryMatch(HashSet results, Query query) + { + var quickAccessMatched = QuickAccess.AccessLinkListMatched(query, Settings.QuickAccessLinks); + if (quickAccessMatched != null && quickAccessMatched.Any()) + { + results.UnionWith(quickAccessMatched); + } + + } + } } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs index dbd74ca42d3..8da51b41ae3 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs @@ -224,16 +224,17 @@ public enum ActionKeyword _ => throw new ArgumentOutOfRangeException(nameof(actionKeyword), actionKeyword, "ActionKeyword enabled status not defined") }; - public ActionKeywordConfiguration GetActionKeywordConfiguration(string actionKeywordStr) + public ActionKeywordActive GetActiveActionKeyword(string actionKeywordStr) { if (string.IsNullOrEmpty(actionKeywordStr)) return null; foreach (ActionKeyword action in Enum.GetValues(typeof(ActionKeyword))) { var keywordStr = GetActionKeyword(action); if (string.IsNullOrEmpty(keywordStr)) continue; - if (keywordStr == actionKeywordStr) + var isEnabled = GetActionKeywordEnabled(action); + if (keywordStr == actionKeywordStr && isEnabled) { - return new ActionKeywordConfiguration(keywordStr, action, GetActionKeywordEnabled(action)); + return new ActionKeywordActive(keywordStr, action); } } return null; diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs index 956c84db2c6..c4ca3f85310 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs @@ -469,7 +469,7 @@ private void ShowUnselectedMessage() private static string? PromptUserSelectPath(ResultType type, string? initialDirectory = null) { - string? path = null; + string? path = null; if (type is ResultType.Folder) { From 20959dc0dac387767f2675322647339d1eae8b37 Mon Sep 17 00:00:00 2001 From: 01Dri Date: Sun, 2 Nov 2025 17:10:24 -0300 Subject: [PATCH 09/21] code quality --- .../Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs index f922a781ab5..926b60c735c 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs @@ -285,13 +285,8 @@ private bool ShouldSkip(ActionKeywordActive actionKeywordActive, SearchResult se private void MergeQuickAccessInResultsIfQueryMatch(HashSet results, Query query) { var quickAccessMatched = QuickAccess.AccessLinkListMatched(query, Settings.QuickAccessLinks); - if (quickAccessMatched != null && quickAccessMatched.Any()) - { - results.UnionWith(quickAccessMatched); - } - + if (quickAccessMatched != null && quickAccessMatched.Any()) results.UnionWith(quickAccessMatched); } - } } From 4107b87aeb41143b0c7f589018295400d5cc5379 Mon Sep 17 00:00:00 2001 From: 01Dri Date: Sun, 2 Nov 2025 23:40:39 -0300 Subject: [PATCH 10/21] code quality --- .../Search/ActionKeywordActive.cs | 27 ------------------- .../Search/SearchManager.cs | 11 +++----- .../Flow.Launcher.Plugin.Explorer/Settings.cs | 7 ++--- 3 files changed, 6 insertions(+), 39 deletions(-) delete mode 100644 Plugins/Flow.Launcher.Plugin.Explorer/Search/ActionKeywordActive.cs diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/ActionKeywordActive.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/ActionKeywordActive.cs deleted file mode 100644 index 1fb5ee13987..00000000000 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/ActionKeywordActive.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using static Flow.Launcher.Plugin.Explorer.Settings; - -namespace Flow.Launcher.Plugin.Explorer.Search; -public class ActionKeywordActive -{ - public string Keyword { get; } - - public Settings.ActionKeyword Type { get; } - - - public ActionKeywordActive(string keyword, Settings.ActionKeyword type) - { - Keyword = keyword; - Type = type; - } - - public bool Equals(ActionKeyword type) - { - return Type == type; - } - -} diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs index 926b60c735c..463d39be1c3 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs @@ -64,11 +64,8 @@ internal async Task> SearchAsync(Query query, CancellationToken tok return results.ToList(); } - if (activeActionKeyword == null && isPathSearch) - { - activeActionKeyword = - new ActionKeywordActive(keywordStr, ActionKeyword.PathSearchActionKeyword); - } + if (activeActionKeyword == null && isPathSearch) activeActionKeyword = ActionKeyword.PathSearchActionKeyword; + // This allows the user to type the below action keywords and see/search the list of quick folder links if (string.IsNullOrEmpty(query.Search) @@ -113,7 +110,7 @@ when activeActionKeyword.Equals(ActionKeyword.QuickAccessActionKeyword): { await foreach (var search in searchResults.WithCancellation(token).ConfigureAwait(false)) { - if (ShouldSkip(activeActionKeyword, search)) + if (ShouldSkip(activeActionKeyword!.Value, search)) { continue; } @@ -262,7 +259,7 @@ private bool IsExcludedFile(SearchResult result) return excludedFileTypes.Contains(fileExtension, StringComparer.OrdinalIgnoreCase); } - private bool ShouldSkip(ActionKeywordActive actionKeywordActive, SearchResult search) + private bool ShouldSkip(ActionKeyword actionKeywordActive, SearchResult search) { if (search.Type == ResultType.File && IsExcludedFile(search)) return true; diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs index 8da51b41ae3..0b02c374bc5 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs @@ -224,7 +224,7 @@ public enum ActionKeyword _ => throw new ArgumentOutOfRangeException(nameof(actionKeyword), actionKeyword, "ActionKeyword enabled status not defined") }; - public ActionKeywordActive GetActiveActionKeyword(string actionKeywordStr) + public ActionKeyword? GetActiveActionKeyword(string actionKeywordStr) { if (string.IsNullOrEmpty(actionKeywordStr)) return null; foreach (ActionKeyword action in Enum.GetValues(typeof(ActionKeyword))) @@ -232,10 +232,7 @@ public ActionKeywordActive GetActiveActionKeyword(string actionKeywordStr) var keywordStr = GetActionKeyword(action); if (string.IsNullOrEmpty(keywordStr)) continue; var isEnabled = GetActionKeywordEnabled(action); - if (keywordStr == actionKeywordStr && isEnabled) - { - return new ActionKeywordActive(keywordStr, action); - } + if (keywordStr == actionKeywordStr && isEnabled) return action; } return null; } From 30dbdb80807b0d44714c6518e37fd54d38a87268 Mon Sep 17 00:00:00 2001 From: 01Dri Date: Tue, 4 Nov 2025 21:25:22 -0300 Subject: [PATCH 11/21] Option to exclude quick access from results --- .../Languages/en.xaml | 1 + .../Search/SearchManager.cs | 10 +++++++--- .../Flow.Launcher.Plugin.Explorer/Settings.cs | 2 ++ .../Views/ExplorerSettings.xaml | 16 +++++++++++++--- 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml index 45c0d72acd9..43a34c8a6e5 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml @@ -32,6 +32,7 @@ Add General Setting Customise Action Keywords + Exclude Quick Access results when using action keywords Customise Quick Access Quick Access Links Everything Setting diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs index 463d39be1c3..9192d663966 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs @@ -60,7 +60,7 @@ internal async Task> SearchAsync(Query query, CancellationToken tok if (activeActionKeyword == null && !isPathSearch) { - MergeQuickAccessInResultsIfQueryMatch(results, query); + MergeQuickAccessInResultsIfQueryMatch(results, query, activeActionKeyword); return results.ToList(); } @@ -105,7 +105,7 @@ when activeActionKeyword.Equals(ActionKeyword.QuickAccessActionKeyword): } // Merge Quick Access Link results for non-path searches. - MergeQuickAccessInResultsIfQueryMatch(results, query); + MergeQuickAccessInResultsIfQueryMatch(results, query, activeActionKeyword); try { await foreach (var search in searchResults.WithCancellation(token).ConfigureAwait(false)) @@ -279,8 +279,12 @@ private bool ShouldSkip(ActionKeyword actionKeywordActive, SearchResult search) return false; } - private void MergeQuickAccessInResultsIfQueryMatch(HashSet results, Query query) + private void MergeQuickAccessInResultsIfQueryMatch(HashSet results, Query query, ActionKeyword? activeActionKeyword) { + if (activeActionKeyword != null && activeActionKeyword != ActionKeyword.QuickAccessActionKeyword) + { + if (Settings.ExcludeQuickAccessFromActionKeywords) return; + } var quickAccessMatched = QuickAccess.AccessLinkListMatched(query, Settings.QuickAccessLinks); if (quickAccessMatched != null && quickAccessMatched.Any()) results.UnionWith(quickAccessMatched); } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs index 0b02c374bc5..766b92c935a 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs @@ -68,6 +68,8 @@ public class Settings public bool FileSearchKeywordEnabled { get; set; } + public bool ExcludeQuickAccessFromActionKeywords { get; set; } = false; + public bool WarnWindowsSearchServiceOff { get; set; } = true; public bool ShowFileSizeInPreviewPanel { get; set; } = true; diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml index 79000e70055..b7d4138a5ac 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml @@ -674,17 +674,27 @@ + - + - + + @@ -695,7 +705,7 @@ Date: Tue, 4 Nov 2025 23:29:44 -0300 Subject: [PATCH 12/21] code quality --- Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs index 9192d663966..8816a2c198f 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs @@ -60,8 +60,7 @@ internal async Task> SearchAsync(Query query, CancellationToken tok if (activeActionKeyword == null && !isPathSearch) { - MergeQuickAccessInResultsIfQueryMatch(results, query, activeActionKeyword); - return results.ToList(); + return new List(); } if (activeActionKeyword == null && isPathSearch) activeActionKeyword = ActionKeyword.PathSearchActionKeyword; From 4e5378b97a30c71aa8bcc9f01167cd33567ad17c Mon Sep 17 00:00:00 2001 From: 01Dri Date: Tue, 4 Nov 2025 23:31:20 -0300 Subject: [PATCH 13/21] code quality --- Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs index 8816a2c198f..31c73eb8a82 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs @@ -285,7 +285,7 @@ private void MergeQuickAccessInResultsIfQueryMatch(HashSet results, Quer if (Settings.ExcludeQuickAccessFromActionKeywords) return; } var quickAccessMatched = QuickAccess.AccessLinkListMatched(query, Settings.QuickAccessLinks); - if (quickAccessMatched != null && quickAccessMatched.Any()) results.UnionWith(quickAccessMatched); + if (quickAccessMatched != null && quickAccessMatched.Count > 0) results.UnionWith(quickAccessMatched); } } From dbf44917565ed57d67c0755992c61bce7dd606e8 Mon Sep 17 00:00:00 2001 From: Jack Ye Date: Sun, 9 Nov 2025 12:56:14 +0800 Subject: [PATCH 14/21] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs index 766b92c935a..e135ba8a55c 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs @@ -175,7 +175,6 @@ public enum ActionKeyword QuickAccessActionKeyword, FolderSearchActionKeyword, FileSearchActionKeyword, - } internal string GetActionKeyword(ActionKeyword actionKeyword) => actionKeyword switch From 945a3d60916d0b8fc862e2f4c6edf4005fc58281 Mon Sep 17 00:00:00 2001 From: Jack Ye Date: Sun, 9 Nov 2025 13:11:03 +0800 Subject: [PATCH 15/21] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml index b7d4138a5ac..40aaf2bf07d 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ExplorerSettings.xaml @@ -676,7 +676,7 @@ - + From b67a6085b251ac9f7f53e29434b3c92707a00178 Mon Sep 17 00:00:00 2001 From: Jack Ye Date: Sun, 9 Nov 2025 13:11:59 +0800 Subject: [PATCH 16/21] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../ViewModels/SettingsViewModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs index c4ca3f85310..956c84db2c6 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs @@ -469,7 +469,7 @@ private void ShowUnselectedMessage() private static string? PromptUserSelectPath(ResultType type, string? initialDirectory = null) { - string? path = null; + string? path = null; if (type is ResultType.Folder) { From dcf4b46f7a17ec512c838853d74bbe3c3f50bc21 Mon Sep 17 00:00:00 2001 From: Jack Ye Date: Sun, 9 Nov 2025 13:12:32 +0800 Subject: [PATCH 17/21] Simplify logic Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs index 31c73eb8a82..f2bbd339825 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs @@ -280,10 +280,10 @@ private bool ShouldSkip(ActionKeyword actionKeywordActive, SearchResult search) private void MergeQuickAccessInResultsIfQueryMatch(HashSet results, Query query, ActionKeyword? activeActionKeyword) { - if (activeActionKeyword != null && activeActionKeyword != ActionKeyword.QuickAccessActionKeyword) - { - if (Settings.ExcludeQuickAccessFromActionKeywords) return; - } + if (activeActionKeyword != null + && activeActionKeyword != ActionKeyword.QuickAccessActionKeyword + && Settings.ExcludeQuickAccessFromActionKeywords) + return; var quickAccessMatched = QuickAccess.AccessLinkListMatched(query, Settings.QuickAccessLinks); if (quickAccessMatched != null && quickAccessMatched.Count > 0) results.UnionWith(quickAccessMatched); } From 1d60cb70912b4f5897a1b50f6fc064098c63e04f Mon Sep 17 00:00:00 2001 From: Jack Ye Date: Sun, 9 Nov 2025 13:12:45 +0800 Subject: [PATCH 18/21] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs index f2bbd339825..eefb30f691d 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs @@ -92,7 +92,7 @@ when activeActionKeyword.Equals(ActionKeyword.FileContentSearchActionKeyword): engineName = Enum.GetName(Settings.ContentSearchEngine); break; - case false + case false when activeActionKeyword.Equals(ActionKeyword.QuickAccessActionKeyword): return QuickAccess.AccessLinkListMatched(query, Settings.QuickAccessLinks); From 558967df4d9d84f38c0811a843bb1e4ab4eb3b8a Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sun, 9 Nov 2025 13:15:14 +0800 Subject: [PATCH 19/21] Code cleanup --- .../Search/SearchManager.cs | 9 ++------- Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs | 3 +-- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs index eefb30f691d..73ea14062df 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs @@ -1,10 +1,8 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; -using System.Windows; using Flow.Launcher.Plugin.Explorer.Exceptions; using Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo; using Flow.Launcher.Plugin.Explorer.Search.Everything; @@ -27,7 +25,6 @@ public SearchManager(Settings settings, PluginInitContext context) Settings = settings; } - /// /// Note: A path that ends with "\" and one that doesn't will not be regarded as equal. /// @@ -136,7 +133,6 @@ when activeActionKeyword.Equals(ActionKeyword.QuickAccessActionKeyword): return results.ToList(); } - private List EverythingContentSearchResult(Query query) { return new List() @@ -230,7 +226,7 @@ private async Task> PathSearchAsync(Query query, CancellationToken public static bool UseIndexSearch(string path) { - if (Main.Settings.IndexSearchEngine is not Settings.IndexSearchEngineOption.WindowsIndex) + if (Main.Settings.IndexSearchEngine is not IndexSearchEngineOption.WindowsIndex) return false; // Check if the path is using windows index search @@ -252,7 +248,7 @@ private bool UseWindowsIndexForDirectorySearch(string locationPath) private bool IsExcludedFile(SearchResult result) { - string[] excludedFileTypes = Settings.ExcludedFileTypes.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + string[] excludedFileTypes = Settings.ExcludedFileTypes.Split([','], StringSplitOptions.RemoveEmptyEntries); string fileExtension = Path.GetExtension(result.FullPath).TrimStart('.'); return excludedFileTypes.Contains(fileExtension, StringComparer.OrdinalIgnoreCase); @@ -288,5 +284,4 @@ private void MergeQuickAccessInResultsIfQueryMatch(HashSet results, Quer if (quickAccessMatched != null && quickAccessMatched.Count > 0) results.UnionWith(quickAccessMatched); } } - } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs index e135ba8a55c..b4eda373797 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs @@ -228,7 +228,7 @@ public enum ActionKeyword public ActionKeyword? GetActiveActionKeyword(string actionKeywordStr) { if (string.IsNullOrEmpty(actionKeywordStr)) return null; - foreach (ActionKeyword action in Enum.GetValues(typeof(ActionKeyword))) + foreach (var action in Enum.GetValues()) { var keywordStr = GetActionKeyword(action); if (string.IsNullOrEmpty(keywordStr)) continue; @@ -237,6 +237,5 @@ public enum ActionKeyword } return null; } - } } From 24d212f918525bcd5ee6ebe46958decc945c1e89 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sun, 9 Nov 2025 13:20:04 +0800 Subject: [PATCH 20/21] Code cleanup --- .../Search/SearchManager.cs | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs index 73ea14062df..4cee36a8b40 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs @@ -57,7 +57,7 @@ internal async Task> SearchAsync(Query query, CancellationToken tok if (activeActionKeyword == null && !isPathSearch) { - return new List(); + return []; } if (activeActionKeyword == null && isPathSearch) activeActionKeyword = ActionKeyword.PathSearchActionKeyword; @@ -78,7 +78,7 @@ internal async Task> SearchAsync(Query query, CancellationToken tok { case true: results.UnionWith(await PathSearchAsync(query, token).ConfigureAwait(false)); - return results.ToList(); + return [.. results]; case false // Intentionally require enabling of Everything's content search due to its slowness when activeActionKeyword.Equals(ActionKeyword.FileContentSearchActionKeyword): @@ -111,12 +111,11 @@ when activeActionKeyword.Equals(ActionKeyword.QuickAccessActionKeyword): continue; } results.Add(ResultManager.CreateResult(query, search)); - } } catch (OperationCanceledException) { - return new List(); + return []; } catch (EngineNotAvailableException) { @@ -130,13 +129,13 @@ when activeActionKeyword.Equals(ActionKeyword.QuickAccessActionKeyword): results.RemoveWhere(r => Settings.IndexSearchExcludedSubdirectoryPaths.Any( excludedPath => FilesFolders.PathContains(excludedPath.Path, r.SubTitle, allowEqual: true))); - return results.ToList(); + return [.. results]; } private List EverythingContentSearchResult(Query query) { - return new List() - { + return + [ new() { Title = Localize.flowlauncher_plugin_everything_enable_content_search(), @@ -149,7 +148,7 @@ private List EverythingContentSearchResult(Query query) return false; } } - }; + ]; } private async Task> PathSearchAsync(Query query, CancellationToken token = default) @@ -170,7 +169,7 @@ private async Task> PathSearchAsync(Query query, CancellationToken // Check that actual location exists, otherwise directory search will throw directory not found exception if (!FilesFolders.ReturnPreviousDirectoryIfIncompleteString(path).LocationExists()) - return results.ToList(); + return [.. results]; var useIndexSearch = Settings.IndexSearchEngine is Settings.IndexSearchEngineOption.WindowsIndex && UseWindowsIndexForDirectorySearch(path); @@ -182,7 +181,7 @@ private async Task> PathSearchAsync(Query query, CancellationToken : ResultManager.CreateOpenCurrentFolderResult(retrievedDirectoryPath, query.ActionKeyword, useIndexSearch)); if (token.IsCancellationRequested) - return new List(); + return []; IAsyncEnumerable directoryResult; @@ -204,7 +203,7 @@ private async Task> PathSearchAsync(Query query, CancellationToken } if (token.IsCancellationRequested) - return new List(); + return []; try { @@ -219,7 +218,7 @@ private async Task> PathSearchAsync(Query query, CancellationToken } - return results.ToList(); + return [.. results]; } public bool IsFileContentSearch(string actionKeyword) => actionKeyword == Settings.FileContentSearchActionKeyword; From 592f60a3578a27ae097689a363d4138884746340 Mon Sep 17 00:00:00 2001 From: Jack251970 <1160210343@qq.com> Date: Sun, 9 Nov 2025 13:38:10 +0800 Subject: [PATCH 21/21] Code cleanup --- .../Search/SearchManager.cs | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs index 4cee36a8b40..235994cbacf 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs @@ -48,24 +48,26 @@ public int GetHashCode(Result obj) internal async Task> SearchAsync(Query query, CancellationToken token) { var results = new HashSet(PathEqualityComparator.Instance); - var keywordStr = query.ActionKeyword.Length == 0 ? Query.GlobalPluginWildcardSign : query.ActionKeyword; - bool isPathSearch = query.Search.IsLocationPathString() - || EnvironmentVariables.IsEnvironmentVariableSearch(query.Search) - || EnvironmentVariables.HasEnvironmentVar(query.Search); + var keyword = query.ActionKeyword.Length == 0 ? Query.GlobalPluginWildcardSign : query.ActionKeyword; + var isPathSearch = query.Search.IsLocationPathString() + || EnvironmentVariables.IsEnvironmentVariableSearch(query.Search) + || EnvironmentVariables.HasEnvironmentVar(query.Search); - var activeActionKeyword = Settings.GetActiveActionKeyword(keywordStr); + // If action keyword is enabled and matched, get the active action keyword. + var activeActionKeyword = Settings.GetActiveActionKeyword(keyword); + // No action keyword matched - plugin should not handle this query, return empty results. if (activeActionKeyword == null && !isPathSearch) { return []; } + // If no action keyword matched but the query is a path search, set active action keyword to path search. if (activeActionKeyword == null && isPathSearch) activeActionKeyword = ActionKeyword.PathSearchActionKeyword; // This allows the user to type the below action keywords and see/search the list of quick folder links - if (string.IsNullOrEmpty(query.Search) - && activeActionKeyword!.Equals(ActionKeyword.QuickAccessActionKeyword)) + && activeActionKeyword.Equals(ActionKeyword.QuickAccessActionKeyword)) { return QuickAccess.AccessLinkListAll(query, Settings.QuickAccessLinks); } @@ -74,11 +76,12 @@ internal async Task> SearchAsync(Query query, CancellationToken tok string engineName; - switch (activeActionKeyword!.Equals(ActionKeyword.PathSearchActionKeyword)) + switch (activeActionKeyword.Equals(ActionKeyword.PathSearchActionKeyword)) { case true: results.UnionWith(await PathSearchAsync(query, token).ConfigureAwait(false)); return [.. results]; + case false // Intentionally require enabling of Everything's content search due to its slowness when activeActionKeyword.Equals(ActionKeyword.FileContentSearchActionKeyword): @@ -93,7 +96,6 @@ when activeActionKeyword.Equals(ActionKeyword.FileContentSearchActionKeyword): when activeActionKeyword.Equals(ActionKeyword.QuickAccessActionKeyword): return QuickAccess.AccessLinkListMatched(query, Settings.QuickAccessLinks); - default: searchResults = Settings.IndexProvider.SearchAsync(query.Search, token); engineName = Enum.GetName(Settings.IndexSearchEngine); @@ -255,15 +257,20 @@ private bool IsExcludedFile(SearchResult result) private bool ShouldSkip(ActionKeyword actionKeywordActive, SearchResult search) { + // Is excluded file type if (search.Type == ResultType.File && IsExcludedFile(search)) + { return true; + } + // Action keyword specific filtering for folders if (actionKeywordActive.Equals(ActionKeyword.FolderSearchActionKeyword) && search.Type != ResultType.Folder) { return true; } + // Action keyword specific filtering for files if (actionKeywordActive.Equals(ActionKeyword.FileSearchActionKeyword) && search.Type != ResultType.File) { @@ -278,7 +285,10 @@ private void MergeQuickAccessInResultsIfQueryMatch(HashSet results, Quer if (activeActionKeyword != null && activeActionKeyword != ActionKeyword.QuickAccessActionKeyword && Settings.ExcludeQuickAccessFromActionKeywords) + { return; + } + var quickAccessMatched = QuickAccess.AccessLinkListMatched(query, Settings.QuickAccessLinks); if (quickAccessMatched != null && quickAccessMatched.Count > 0) results.UnionWith(quickAccessMatched); }