diff --git a/Flow.Launcher.Infrastructure/UserSettings/PluginSettings.cs b/Flow.Launcher.Infrastructure/UserSettings/PluginSettings.cs index 4c47ca425d2..ccd9beb868a 100644 --- a/Flow.Launcher.Infrastructure/UserSettings/PluginSettings.cs +++ b/Flow.Launcher.Infrastructure/UserSettings/PluginSettings.cs @@ -15,6 +15,16 @@ public void UpdatePluginSettings(List metadatas) if (Plugins.ContainsKey(metadata.ID)) { var settings = Plugins[metadata.ID]; + + // TODO: Remove. This is one off for 1.2.0 release. + // Introduced a new action keyword in Explorer, so need to update plugin setting in the UserData folder. + // This kind of plugin meta update should be handled by a dedicated method trigger by version bump. + if (metadata.ID == "572be03c74c642baae319fc283e561a8" && metadata.ActionKeywords.Count != settings.ActionKeywords.Count) + settings.ActionKeywords = metadata.ActionKeywords; + + if (string.IsNullOrEmpty(settings.Version)) + settings.Version = metadata.Version; + if (settings.ActionKeywords?.Count > 0) { metadata.ActionKeywords = settings.ActionKeywords; @@ -28,6 +38,7 @@ public void UpdatePluginSettings(List metadatas) { ID = metadata.ID, Name = metadata.Name, + Version = metadata.Version, ActionKeywords = metadata.ActionKeywords, Disabled = metadata.Disabled }; @@ -39,6 +50,7 @@ public class Plugin { public string ID { get; set; } public string Name { get; set; } + public string Version { get; set; } public List ActionKeywords { get; set; } // a reference of the action keywords from plugin manager /// diff --git a/Flow.Launcher.Test/Plugins/ExplorerTest.cs b/Flow.Launcher.Test/Plugins/ExplorerTest.cs index 0a1dece4fc3..0298a4d998b 100644 --- a/Flow.Launcher.Test/Plugins/ExplorerTest.cs +++ b/Flow.Launcher.Test/Plugins/ExplorerTest.cs @@ -184,6 +184,55 @@ public void GivenTopLevelDirectorySearch_WhenIndexSearchNotRequired_ThenSearchMe $"Actual number of results is {results.Count} {Environment.NewLine}"); } + [TestCase(@"some words", @"FREETEXT('some words')")] + public void GivenWindowsIndexSearch_WhenQueryWhereRestrictionsIsForFileContentSearch_ThenShouldReturnFreeTextString( + string querySearchString, string expectedString) + { + // Given + var queryConstructor = new QueryConstructor(new Settings()); + + //When + var resultString = queryConstructor.QueryWhereRestrictionsForFileContentSearch(querySearchString); + + // Then + Assert.IsTrue(resultString == expectedString, + $"Expected QueryWhereRestrictions string: {expectedString}{Environment.NewLine} " + + $"Actual string was: {resultString}{Environment.NewLine}"); + } + + [TestCase("some words", "SELECT TOP 100 System.FileName, System.ItemPathDisplay, System.ItemType " + + "FROM SystemIndex WHERE FREETEXT('some words') AND scope='file:'")] + public void GivenWindowsIndexSearch_WhenSearchForFileContent_ThenQueryShouldUseExpectedString( + string userSearchString, string expectedString) + { + // Given + var queryConstructor = new QueryConstructor(new Settings()); + + //When + var resultString = queryConstructor.QueryForFileContentSearch(userSearchString); + + // Then + Assert.IsTrue(resultString == expectedString, + $"Expected query string: {expectedString}{Environment.NewLine} " + + $"Actual string was: {resultString}{Environment.NewLine}"); + } + + public void GivenQuery_WhenActionKeywordForFileContentSearchExists_ThenFileContentSearchRequiredShouldReturnTrue() + { + // Given + var query = new Query { ActionKeyword = "doc:", Search = "search term" }; + + var searchManager = new SearchManager(new Settings(), new PluginInitContext()); + + // When + var result = searchManager.IsFileContentSearch(query.ActionKeyword); + + // Then + Assert.IsTrue(result, + $"Expected True for file content search. {Environment.NewLine} " + + $"Actual result was: {result}{Environment.NewLine}"); + } + [TestCase(@"c:\\", false)] [TestCase(@"i:\", true)] [TestCase(@"\c:\", false)] diff --git a/Flow.Launcher/Languages/en.xaml b/Flow.Launcher/Languages/en.xaml index 069071f39dc..adb49b65dee 100644 --- a/Flow.Launcher/Languages/en.xaml +++ b/Flow.Launcher/Languages/en.xaml @@ -111,7 +111,7 @@ Done Can't find specified plugin New Action Keyword can't be empty - New Action Keywords have been assigned to another plugin, please assign other new action keyword + This new Action Keyword is already assigned to another plugin, please choose a different one Success Use * if you don't want to specify an action keyword diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj b/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj index bd2a047eb46..efa5339b4d9 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Flow.Launcher.Plugin.Explorer.csproj @@ -104,6 +104,7 @@ + diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml index 01bd1a60fa1..b7710d3324b 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml @@ -1,8 +1,9 @@ - + Please make a selection first Please select a folder link Are you sure you want to delete {0}? Are you sure you want to permanently delete this {0}? @@ -13,10 +14,12 @@ Delete Edit Add + Customise Action Keywords Quick Folder Access Paths Index Search Excluded Paths Indexing Options - + Search Activation: + File Content Search: Explorer diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs index f814962ba76..6c0d186f169 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs @@ -36,12 +36,15 @@ internal List Search(Query query) var quickFolderLinks = quickFolderAccess.FolderList(query, settings.QuickFolderAccessLinks, context); - if (quickFolderLinks.Count > 0) + if (quickFolderLinks.Count > 0 && query.ActionKeyword == settings.SearchActionKeyword) return quickFolderLinks; if (string.IsNullOrEmpty(querySearch)) return results; + if (IsFileContentSearch(query.ActionKeyword)) + return WindowsIndexFileContentSearch(query, querySearch); + var isEnvironmentVariable = EnvironmentVariables.IsEnvironmentVariableSearch(querySearch); if (isEnvironmentVariable) @@ -74,6 +77,24 @@ internal List Search(Query query) return results; } + private List WindowsIndexFileContentSearch(Query query, string querySearchString) + { + var queryConstructor = new QueryConstructor(settings); + + if (string.IsNullOrEmpty(querySearchString)) + return new List(); + + return indexSearch.WindowsIndexSearch(querySearchString, + queryConstructor.CreateQueryHelper().ConnectionString, + queryConstructor.QueryForFileContentSearch, + query); + } + + public bool IsFileContentSearch(string actionKeyword) + { + return actionKeyword == settings.FileContentSearchActionKeyword; + } + private List DirectoryInfoClassSearch(Query query, string querySearch) { var directoryInfoSearch = new DirectoryInfoSearch(context); diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs index f4480eea7a0..393c1514dd5 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs @@ -117,5 +117,23 @@ public string QueryWhereRestrictionsForAllFilesAndFoldersSearch() { return $"scope='file:'"; } + + /// + /// Search will be performed on all indexed file contents for the specified search keywords. + /// + public string QueryForFileContentSearch(string userSearchString) + { + string query = "SELECT TOP " + settings.MaxResult + $" {CreateBaseQuery().QuerySelectColumns} FROM {SystemIndex} WHERE "; + + return query + QueryWhereRestrictionsForFileContentSearch(userSearchString) + " AND " + QueryWhereRestrictionsForAllFilesAndFoldersSearch(); + } + + /// + /// Set the required WHERE clause restriction to search within file content. + /// + public string QueryWhereRestrictionsForFileContentSearch(string searchQuery) + { + return $"FREETEXT('{searchQuery}')"; + } } } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs index d4bfdbbfcab..4e62b3cba2a 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs @@ -17,5 +17,11 @@ public class Settings [JsonProperty] public List IndexSearchExcludedSubdirectoryPaths { get; set; } = new List(); + + [JsonProperty] + public string SearchActionKeyword { get; set; } = Query.GlobalPluginWildcardSign; + + [JsonProperty] + public string FileContentSearchActionKeyword { get; set; } = "doc:"; } } \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs index a5e81716a63..e14a6ebb54e 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs +++ b/Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs @@ -1,4 +1,5 @@ -using Flow.Launcher.Infrastructure.Storage; +using Flow.Launcher.Core.Plugin; +using Flow.Launcher.Infrastructure.Storage; using Flow.Launcher.Plugin.Explorer.Search; using Flow.Launcher.Plugin.Explorer.Search.FolderLinks; using System.Diagnostics; @@ -40,5 +41,18 @@ internal void OpenWindowsIndexingOptions() Process.Start(psi); } + + internal void UpdateActionKeyword(string newActionKeyword, string oldActionKeyword) + { + PluginManager.ReplaceActionKeyword(Context.CurrentPluginMetadata.ID, oldActionKeyword, newActionKeyword); + + if (Settings.FileContentSearchActionKeyword == oldActionKeyword) + Settings.FileContentSearchActionKeyword = newActionKeyword; + + if (Settings.SearchActionKeyword == oldActionKeyword) + Settings.SearchActionKeyword = newActionKeyword; + } + + internal bool IsActionKeywordAlreadyAssigned(string newActionKeyword) => PluginManager.ActionKeywordRegistered(newActionKeyword); } } diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml new file mode 100644 index 00000000000..0e1c7e87265 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Explorer/Views/ActionKeywordSetting.xaml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + +