mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Merge branch 'dev' into ExplorerDirectorySearchWithIndexFix
This commit is contained in:
commit
288baa5538
7 changed files with 46 additions and 48 deletions
|
|
@ -60,8 +60,8 @@ namespace Flow.Launcher.Test.Plugins
|
||||||
$"Actual: {result}{Environment.NewLine}");
|
$"Actual: {result}{Environment.NewLine}");
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("C:\\", "SELECT TOP 100 System.FileName, System.ItemUrl, System.ItemType FROM SystemIndex WHERE directory='file:C:\\'")]
|
[TestCase("C:\\", "SELECT TOP 100 System.FileName, System.ItemUrl, System.ItemType FROM SystemIndex WHERE directory='file:C:\\' ORDER BY System.FileName")]
|
||||||
[TestCase("C:\\SomeFolder\\", "SELECT TOP 100 System.FileName, System.ItemUrl, System.ItemType FROM SystemIndex WHERE directory='file:C:\\SomeFolder\\'")]
|
[TestCase("C:\\SomeFolder\\", "SELECT TOP 100 System.FileName, System.ItemUrl, System.ItemType FROM SystemIndex WHERE directory='file:C:\\SomeFolder\\' ORDER BY System.FileName")]
|
||||||
public void GivenWindowsIndexSearch_WhenSearchTypeIsTopLevelDirectorySearch_ThenQueryShouldUseExpectedString(string folderPath, string expectedString)
|
public void GivenWindowsIndexSearch_WhenSearchTypeIsTopLevelDirectorySearch_ThenQueryShouldUseExpectedString(string folderPath, string expectedString)
|
||||||
{
|
{
|
||||||
// Given
|
// Given
|
||||||
|
|
@ -79,7 +79,7 @@ namespace Flow.Launcher.Test.Plugins
|
||||||
[TestCase("C:\\SomeFolder\\flow.launcher.sln", "SELECT TOP 100 System.FileName, System.ItemUrl, System.ItemType " +
|
[TestCase("C:\\SomeFolder\\flow.launcher.sln", "SELECT TOP 100 System.FileName, System.ItemUrl, System.ItemType " +
|
||||||
"FROM SystemIndex WHERE (System.FileName LIKE 'flow.launcher.sln%' " +
|
"FROM SystemIndex WHERE (System.FileName LIKE 'flow.launcher.sln%' " +
|
||||||
"OR CONTAINS(System.FileName,'\"flow.launcher.sln*\"',1033))" +
|
"OR CONTAINS(System.FileName,'\"flow.launcher.sln*\"',1033))" +
|
||||||
" AND directory='file:C:\\SomeFolder'")]
|
" AND directory='file:C:\\SomeFolder' ORDER BY System.FileName")]
|
||||||
public void GivenWindowsIndexSearchTopLevelDirectory_WhenSearchingForSpecificItem_ThenQueryShouldUseExpectedString(
|
public void GivenWindowsIndexSearchTopLevelDirectory_WhenSearchingForSpecificItem_ThenQueryShouldUseExpectedString(
|
||||||
string userSearchString, string expectedString)
|
string userSearchString, string expectedString)
|
||||||
{
|
{
|
||||||
|
|
@ -116,11 +116,8 @@ namespace Flow.Launcher.Test.Plugins
|
||||||
[TestCase("scope='file:'")]
|
[TestCase("scope='file:'")]
|
||||||
public void GivenWindowsIndexSearch_WhenSearchAllFoldersAndFiles_ThenQueryWhereRestrictionsShouldUseScopeString(string expectedString)
|
public void GivenWindowsIndexSearch_WhenSearchAllFoldersAndFiles_ThenQueryWhereRestrictionsShouldUseScopeString(string expectedString)
|
||||||
{
|
{
|
||||||
// Given
|
|
||||||
var queryConstructor = new QueryConstructor(new Settings());
|
|
||||||
|
|
||||||
//When
|
//When
|
||||||
var resultString = queryConstructor.QueryWhereRestrictionsForAllFilesAndFoldersSearch();
|
var resultString = QueryConstructor.QueryWhereRestrictionsForAllFilesAndFoldersSearch;
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
Assert.IsTrue(resultString == expectedString,
|
Assert.IsTrue(resultString == expectedString,
|
||||||
|
|
@ -130,7 +127,7 @@ namespace Flow.Launcher.Test.Plugins
|
||||||
|
|
||||||
[TestCase("flow.launcher.sln", "SELECT TOP 100 \"System.FileName\", \"System.ItemUrl\", \"System.ItemType\" " +
|
[TestCase("flow.launcher.sln", "SELECT TOP 100 \"System.FileName\", \"System.ItemUrl\", \"System.ItemType\" " +
|
||||||
"FROM \"SystemIndex\" WHERE (System.FileName LIKE 'flow.launcher.sln%' " +
|
"FROM \"SystemIndex\" WHERE (System.FileName LIKE 'flow.launcher.sln%' " +
|
||||||
"OR CONTAINS(System.FileName,'\"flow.launcher.sln*\"',1033)) AND scope='file:'")]
|
"OR CONTAINS(System.FileName,'\"flow.launcher.sln*\"',1033)) AND scope='file:' ORDER BY System.FileName")]
|
||||||
public void GivenWindowsIndexSearch_WhenSearchAllFoldersAndFiles_ThenQueryShouldUseExpectedString(
|
public void GivenWindowsIndexSearch_WhenSearchAllFoldersAndFiles_ThenQueryShouldUseExpectedString(
|
||||||
string userSearchString, string expectedString)
|
string userSearchString, string expectedString)
|
||||||
{
|
{
|
||||||
|
|
@ -205,7 +202,7 @@ namespace Flow.Launcher.Test.Plugins
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("some words", "SELECT TOP 100 System.FileName, System.ItemUrl, System.ItemType " +
|
[TestCase("some words", "SELECT TOP 100 System.FileName, System.ItemUrl, System.ItemType " +
|
||||||
"FROM SystemIndex WHERE FREETEXT('some words') AND scope='file:'")]
|
"FROM SystemIndex WHERE FREETEXT('some words') AND scope='file:' ORDER BY System.FileName")]
|
||||||
public void GivenWindowsIndexSearch_WhenSearchForFileContent_ThenQueryShouldUseExpectedString(
|
public void GivenWindowsIndexSearch_WhenSearchForFileContent_ThenQueryShouldUseExpectedString(
|
||||||
string userSearchString, string expectedString)
|
string userSearchString, string expectedString)
|
||||||
{
|
{
|
||||||
|
|
@ -298,9 +295,9 @@ namespace Flow.Launcher.Test.Plugins
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("c:\\SomeFolder\\>", "scope='file:c:\\SomeFolder'")]
|
[TestCase("c:\\SomeFolder\\>", "scope='file:c:\\SomeFolder'")]
|
||||||
[TestCase("c:\\SomeFolder\\>SomeName", "(System.FileName LIKE 'SomeName%' " +
|
[TestCase("c:\\SomeFolder\\>SomeName", "(System.FileName LIKE 'SomeName%' "
|
||||||
"OR CONTAINS(System.FileName,'\"SomeName*\"',1033)) AND " +
|
+ "OR CONTAINS(System.FileName,'\"SomeName*\"',1033)) AND "
|
||||||
"scope='file:c:\\SomeFolder'")]
|
+ "scope='file:c:\\SomeFolder'")]
|
||||||
public void GivenWindowsIndexSearch_WhenSearchPatternHotKeyIsSearchAll_ThenQueryWhereRestrictionsShouldUseScopeString(string path, string expectedString)
|
public void GivenWindowsIndexSearch_WhenSearchPatternHotKeyIsSearchAll_ThenQueryWhereRestrictionsShouldUseScopeString(string path, string expectedString)
|
||||||
{
|
{
|
||||||
// Given
|
// Given
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
using Flow.Launcher.Infrastructure.Logger;
|
using Flow.Launcher.Infrastructure.Logger;
|
||||||
using Microsoft.Search.Interop;
|
using Microsoft.Search.Interop;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
@ -15,7 +15,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
|
||||||
private readonly ResultManager resultManager;
|
private readonly ResultManager resultManager;
|
||||||
|
|
||||||
// Reserved keywords in oleDB
|
// Reserved keywords in oleDB
|
||||||
private readonly string reservedStringPattern = @"^[\/\\\$\%_]+$";
|
private readonly string reservedStringPattern = @"^[`\@\#\^,\&\/\\\$\%_]+$";
|
||||||
|
|
||||||
internal IndexSearch(PluginInitContext context)
|
internal IndexSearch(PluginInitContext context)
|
||||||
{
|
{
|
||||||
|
|
@ -24,9 +24,8 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
|
||||||
|
|
||||||
internal async Task<List<Result>> ExecuteWindowsIndexSearchAsync(string indexQueryString, string connectionString, Query query, CancellationToken token)
|
internal async Task<List<Result>> ExecuteWindowsIndexSearchAsync(string indexQueryString, string connectionString, Query query, CancellationToken token)
|
||||||
{
|
{
|
||||||
var folderResults = new List<Result>();
|
|
||||||
var fileResults = new List<Result>();
|
|
||||||
var results = new List<Result>();
|
var results = new List<Result>();
|
||||||
|
var fileResults = new List<Result>();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -55,7 +54,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
|
||||||
|
|
||||||
if (dataReaderResults.GetString(2) == "Directory")
|
if (dataReaderResults.GetString(2) == "Directory")
|
||||||
{
|
{
|
||||||
folderResults.Add(resultManager.CreateFolderResult(
|
results.Add(resultManager.CreateFolderResult(
|
||||||
dataReaderResults.GetString(0),
|
dataReaderResults.GetString(0),
|
||||||
path,
|
path,
|
||||||
path,
|
path,
|
||||||
|
|
@ -83,8 +82,10 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
|
||||||
LogException("General error from performing index search", e);
|
LogException("General error from performing index search", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
results.AddRange(fileResults);
|
||||||
|
|
||||||
// Intial ordering, this order can be updated later by UpdateResultView.MainViewModel based on history of user selection.
|
// Intial ordering, this order can be updated later by UpdateResultView.MainViewModel based on history of user selection.
|
||||||
return results.Concat(folderResults.OrderBy(x => x.Title)).Concat(fileResults.OrderBy(x => x.Title)).ToList(); ;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal async Task<List<Result>> WindowsIndexSearchAsync(string searchString, string connectionString,
|
internal async Task<List<Result>> WindowsIndexSearchAsync(string searchString, string connectionString,
|
||||||
|
|
|
||||||
|
|
@ -81,11 +81,9 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
|
||||||
var previousLevelDirectory = path.Substring(0, indexOfSeparator);
|
var previousLevelDirectory = path.Substring(0, indexOfSeparator);
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(itemName))
|
if (string.IsNullOrEmpty(itemName))
|
||||||
return searchDepth + $"{previousLevelDirectory}'";
|
return $"{searchDepth}{previousLevelDirectory}'";
|
||||||
|
|
||||||
return $"(System.FileName LIKE '{itemName}%' " +
|
return $"(System.FileName LIKE '{itemName}%' OR CONTAINS(System.FileName,'\"{itemName}*\"',1033)) AND {searchDepth}{previousLevelDirectory}'";
|
||||||
$"OR CONTAINS(System.FileName,'\"{itemName}*\"',1033)) AND " +
|
|
||||||
searchDepth + $"{previousLevelDirectory}'";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///<summary>
|
///<summary>
|
||||||
|
|
@ -96,9 +94,9 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
|
||||||
string query = "SELECT TOP " + settings.MaxResult + $" {CreateBaseQuery().QuerySelectColumns} FROM {SystemIndex} WHERE ";
|
string query = "SELECT TOP " + settings.MaxResult + $" {CreateBaseQuery().QuerySelectColumns} FROM {SystemIndex} WHERE ";
|
||||||
|
|
||||||
if (path.LastIndexOf(Constants.AllFilesFolderSearchWildcard) > path.LastIndexOf(Constants.DirectorySeperator))
|
if (path.LastIndexOf(Constants.AllFilesFolderSearchWildcard) > path.LastIndexOf(Constants.DirectorySeperator))
|
||||||
return query + QueryWhereRestrictionsForTopLevelDirectoryAllFilesAndFoldersSearch(path);
|
return query + QueryWhereRestrictionsForTopLevelDirectoryAllFilesAndFoldersSearch(path) + QueryOrderByFileNameRestriction;
|
||||||
|
|
||||||
return query + QueryWhereRestrictionsForTopLevelDirectorySearch(path);
|
return query + QueryWhereRestrictionsForTopLevelDirectorySearch(path) + QueryOrderByFileNameRestriction;
|
||||||
}
|
}
|
||||||
|
|
||||||
///<summary>
|
///<summary>
|
||||||
|
|
@ -107,16 +105,17 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
|
||||||
public string QueryForAllFilesAndFolders(string userSearchString)
|
public string QueryForAllFilesAndFolders(string userSearchString)
|
||||||
{
|
{
|
||||||
// Generate SQL from constructed parameters, converting the userSearchString from AQS->WHERE clause
|
// Generate SQL from constructed parameters, converting the userSearchString from AQS->WHERE clause
|
||||||
return CreateBaseQuery().GenerateSQLFromUserQuery(userSearchString) + " AND " + QueryWhereRestrictionsForAllFilesAndFoldersSearch();
|
return CreateBaseQuery().GenerateSQLFromUserQuery(userSearchString) + " AND " + QueryWhereRestrictionsForAllFilesAndFoldersSearch
|
||||||
|
+ QueryOrderByFileNameRestriction;
|
||||||
}
|
}
|
||||||
|
|
||||||
///<summary>
|
///<summary>
|
||||||
/// Set the required WHERE clause restriction to search for all files and folders.
|
/// Set the required WHERE clause restriction to search for all files and folders.
|
||||||
///</summary>
|
///</summary>
|
||||||
public string QueryWhereRestrictionsForAllFilesAndFoldersSearch()
|
public const string QueryWhereRestrictionsForAllFilesAndFoldersSearch = "scope='file:'";
|
||||||
{
|
|
||||||
return $"scope='file:'";
|
public const string QueryOrderByFileNameRestriction = " ORDER BY System.FileName";
|
||||||
}
|
|
||||||
|
|
||||||
///<summary>
|
///<summary>
|
||||||
/// Search will be performed on all indexed file contents for the specified search keywords.
|
/// Search will be performed on all indexed file contents for the specified search keywords.
|
||||||
|
|
@ -125,7 +124,8 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
|
||||||
{
|
{
|
||||||
string query = "SELECT TOP " + settings.MaxResult + $" {CreateBaseQuery().QuerySelectColumns} FROM {SystemIndex} WHERE ";
|
string query = "SELECT TOP " + settings.MaxResult + $" {CreateBaseQuery().QuerySelectColumns} FROM {SystemIndex} WHERE ";
|
||||||
|
|
||||||
return query + QueryWhereRestrictionsForFileContentSearch(userSearchString) + " AND " + QueryWhereRestrictionsForAllFilesAndFoldersSearch();
|
return query + QueryWhereRestrictionsForFileContentSearch(userSearchString) + " AND " + QueryWhereRestrictionsForAllFilesAndFoldersSearch
|
||||||
|
+ QueryOrderByFileNameRestriction;
|
||||||
}
|
}
|
||||||
|
|
||||||
///<summary>
|
///<summary>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
using Flow.Launcher.Plugin.Explorer.Search;
|
using Flow.Launcher.Plugin.Explorer.Search;
|
||||||
using Flow.Launcher.Plugin.Explorer.Search.FolderLinks;
|
using Flow.Launcher.Plugin.Explorer.Search.FolderLinks;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
namespace Flow.Launcher.Plugin.Explorer
|
namespace Flow.Launcher.Plugin.Explorer
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
"Name": "Explorer",
|
"Name": "Explorer",
|
||||||
"Description": "Search and manage files and folders. Explorer utilises Windows Index Search",
|
"Description": "Search and manage files and folders. Explorer utilises Windows Index Search",
|
||||||
"Author": "Jeremy Wu",
|
"Author": "Jeremy Wu",
|
||||||
"Version": "1.3.0",
|
"Version": "1.4.0",
|
||||||
"Language": "csharp",
|
"Language": "csharp",
|
||||||
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
|
"Website": "https://github.com/Flow-Launcher/Flow.Launcher",
|
||||||
"ExecuteFileName": "Flow.Launcher.Plugin.Explorer.dll",
|
"ExecuteFileName": "Flow.Launcher.Plugin.Explorer.dll",
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,9 @@ namespace Flow.Launcher.Plugin.Program
|
||||||
|
|
||||||
public async Task<List<Result>> QueryAsync(Query query, CancellationToken token)
|
public async Task<List<Result>> QueryAsync(Query query, CancellationToken token)
|
||||||
{
|
{
|
||||||
|
if (IsStartupIndexProgramsRequired)
|
||||||
|
_ = IndexPrograms();
|
||||||
|
|
||||||
Win32[] win32;
|
Win32[] win32;
|
||||||
UWP.Application[] uwps;
|
UWP.Application[] uwps;
|
||||||
|
|
||||||
|
|
@ -147,7 +150,7 @@ namespace Flow.Launcher.Plugin.Program
|
||||||
|
|
||||||
var t2 = Task.Run(IndexUwpPrograms);
|
var t2 = Task.Run(IndexUwpPrograms);
|
||||||
|
|
||||||
await Task.WhenAll(t1, t2);
|
await Task.WhenAll(t1, t2).ConfigureAwait(false);
|
||||||
|
|
||||||
_settings.LastIndexTime = DateTime.Today;
|
_settings.LastIndexTime = DateTime.Today;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ namespace Flow.Launcher.Plugin.Program.Views
|
||||||
|
|
||||||
private void ViewRefresh()
|
private void ViewRefresh()
|
||||||
{
|
{
|
||||||
if(programSourceView.Items.Count == 0
|
if (programSourceView.Items.Count == 0
|
||||||
&& btnProgramSourceStatus.Visibility == Visibility.Visible
|
&& btnProgramSourceStatus.Visibility == Visibility.Visible
|
||||||
&& btnEditProgramSource.Visibility == Visibility.Visible)
|
&& btnEditProgramSource.Visibility == Visibility.Visible)
|
||||||
{
|
{
|
||||||
|
|
@ -70,21 +70,19 @@ namespace Flow.Launcher.Plugin.Program.Views
|
||||||
programSourceView.Items.Refresh();
|
programSourceView.Items.Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReIndexing()
|
private async void ReIndexing()
|
||||||
{
|
{
|
||||||
ViewRefresh();
|
ViewRefresh();
|
||||||
Task.Run(() =>
|
|
||||||
{
|
indexingPanel.Visibility = Visibility.Visible;
|
||||||
Dispatcher.Invoke(() => { indexingPanel.Visibility = Visibility.Visible; });
|
await Main.IndexPrograms();
|
||||||
Main.IndexPrograms();
|
indexingPanel.Visibility = Visibility.Hidden;
|
||||||
Dispatcher.Invoke(() => { indexingPanel.Visibility = Visibility.Hidden; });
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void btnAddProgramSource_OnClick(object sender, RoutedEventArgs e)
|
private void btnAddProgramSource_OnClick(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
var add = new AddProgramSource(context, _settings);
|
var add = new AddProgramSource(context, _settings);
|
||||||
if(add.ShowDialog() ?? false)
|
if (add.ShowDialog() ?? false)
|
||||||
{
|
{
|
||||||
ReIndexing();
|
ReIndexing();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue