Refactor Explorer Code to fit the new architecture

1. Rename some method in QueryConstructor.cs by removing prefix and suffix
2. Split the logic of checking '>' to outer SearchManager.cs
3. Use IAsyncEnumerable for potential future improvement.
This commit is contained in:
Hongtao Zhang 2022-09-10 10:45:41 -05:00
parent 193ea552dd
commit 000c45bfa8
No known key found for this signature in database
GPG key ID: 75F655B91C7AC9BB
16 changed files with 155 additions and 128 deletions

View file

@ -73,7 +73,7 @@ namespace Flow.Launcher.Test.Plugins
var queryConstructor = new QueryConstructor(new Settings());
//When
var queryString = queryConstructor.QueryForTopLevelDirectorySearch(folderPath);
var queryString = queryConstructor.Directory(folderPath);
// Then
Assert.IsTrue(queryString == expectedString,
@ -93,7 +93,7 @@ namespace Flow.Launcher.Test.Plugins
var queryConstructor = new QueryConstructor(new Settings());
//When
var queryString = queryConstructor.QueryForTopLevelDirectorySearch(userSearchString);
var queryString = queryConstructor.Directory(userSearchString);
// Then
Assert.IsTrue(queryString == expectedString,
@ -125,7 +125,7 @@ namespace Flow.Launcher.Test.Plugins
public void GivenWindowsIndexSearch_WhenSearchAllFoldersAndFiles_ThenQueryWhereRestrictionsShouldUseScopeString(string expectedString)
{
//When
var resultString = QueryConstructor.QueryWhereRestrictionsForAllFilesAndFoldersSearch;
var resultString = QueryConstructor.RestrictionsForAllFilesAndFoldersSearch;
// Then
Assert.IsTrue(resultString == expectedString,
@ -142,7 +142,7 @@ namespace Flow.Launcher.Test.Plugins
{
// Given
var queryConstructor = new QueryConstructor(new Settings());
var baseQuery = queryConstructor.CreateBaseQuery();
var baseQuery = queryConstructor.BaseQueryHelper;
// system running this test could have different locale than the hard-coded 1033 LCID en-US.
var queryKeywordLocale = baseQuery.QueryKeywordLocale;
@ -151,7 +151,7 @@ namespace Flow.Launcher.Test.Plugins
//When
var resultString = queryConstructor.QueryForAllFilesAndFolders(userSearchString);
var resultString = queryConstructor.FilesAndFolders(userSearchString);
// Then
Assert.IsTrue(resultString == expectedString,
@ -169,7 +169,7 @@ namespace Flow.Launcher.Test.Plugins
var queryConstructor = new QueryConstructor(new Settings());
//When
var resultString = queryConstructor.QueryWhereRestrictionsForFileContentSearch(querySearchString);
var resultString = QueryConstructor.RestrictionsForFileContentSearch(querySearchString);
// Then
Assert.IsTrue(resultString == expectedString,
@ -187,7 +187,7 @@ namespace Flow.Launcher.Test.Plugins
var queryConstructor = new QueryConstructor(new Settings());
//When
var resultString = queryConstructor.QueryForFileContentSearch(userSearchString);
var resultString = queryConstructor.FileContent(userSearchString);
// Then
Assert.IsTrue(resultString == expectedString,

View file

@ -51,4 +51,8 @@
<ProjectReference Include="..\..\Flow.Launcher.Infrastructure\Flow.Launcher.Infrastructure.csproj" />
<ProjectReference Include="..\..\Flow.Launcher.Plugin\Flow.Launcher.Plugin.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Search\IIndexProvider.cs" />
</ItemGroup>
</Project>

View file

@ -90,4 +90,4 @@ namespace Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo
return results.OrderBy(r=>r.Type).ThenBy(r=>r.FullPath);
}
}
}
}

View file

@ -193,4 +193,4 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything
}
}
}
}
}

View file

@ -3,10 +3,11 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Flow.Launcher.Plugin.Explorer.Search.IProvider;
namespace Flow.Launcher.Plugin.Explorer.Search.Everything
{
public class EverythingSearchManager : IIndexProvider, IContentIndexProvider, IPathEnumerable
public class EverythingSearchManager : IIndexProvider, IContentIndexProvider, IPathIndexProvider
{
private Settings Settings { get; }
@ -48,4 +49,4 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything
token);
}
}
}
}

View file

@ -1,12 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace Flow.Launcher.Plugin.Explorer.Search
{
public interface IPathEnumerable
{
public IAsyncEnumerable<SearchResult> EnumerateAsync(string path, string search, bool recursive, CancellationToken token);
}
}

View file

@ -1,11 +1,10 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace Flow.Launcher.Plugin.Explorer.Search
namespace Flow.Launcher.Plugin.Explorer.Search.IProvider
{
public interface IContentIndexProvider
{
public IAsyncEnumerable<SearchResult> ContentSearchAsync(string plainSearch, string contentSearch, CancellationToken token = default);
}
}
}

View file

@ -1,11 +1,10 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace Flow.Launcher.Plugin.Explorer.Search
namespace Flow.Launcher.Plugin.Explorer.Search.IProvider
{
public interface IIndexProvider
{
public IAsyncEnumerable<SearchResult> SearchAsync(string search, CancellationToken token);
}
}
}

View file

@ -0,0 +1,10 @@
using System.Collections.Generic;
using System.Threading;
namespace Flow.Launcher.Plugin.Explorer.Search.IProvider
{
public interface IPathIndexProvider
{
public IAsyncEnumerable<SearchResult> EnumerateAsync(string path, string search, bool recursive, CancellationToken token);
}
}

View file

@ -210,4 +210,4 @@ namespace Flow.Launcher.Plugin.Explorer.Search
Folder,
File
}
}
}

View file

@ -55,30 +55,39 @@ namespace Flow.Launcher.Plugin.Explorer.Search
results.UnionWith(quickAccessLinks);
}
IAsyncEnumerable<SearchResult> searchResults;
if (ActionKeywordMatch(query, Settings.ActionKeyword.FileContentSearchActionKeyword))
{
// A backdoor to prevent everything to do content search
if (Settings.ContentIndexProvider is EverythingSearchManager && !Settings.EnableEverythingContentSearch)
{
return EverythingContentSearchResult(query);
}
searchResults = Settings.ContentIndexProvider.ContentSearchAsync("", query.Search, token);
}
else
{
searchResults = Settings.IndexProvider.SearchAsync(query.Search, token);
return new List<Result>();
}
IAsyncEnumerable<SearchResult> searchResults = null;
if (ActionKeywordMatch(query, Settings.ActionKeyword.PathSearchActionKeyword) ||
ActionKeywordMatch(query, Settings.ActionKeyword.SearchActionKeyword))
bool isPathSearch = query.Search.IsLocationPathString();
switch (isPathSearch)
{
results.UnionWith(await PathSearchAsync(query, token).ConfigureAwait(false));
case true
when (ActionKeywordMatch(query, Settings.ActionKeyword.PathSearchActionKeyword)
|| ActionKeywordMatch(query, Settings.ActionKeyword.SearchActionKeyword)):
results.UnionWith(await PathSearchAsync(query, token).ConfigureAwait(false));
return results.ToList();
break;
case false when ActionKeywordMatch(query, Settings.ActionKeyword.FileContentSearchActionKeyword):
{
// A backdoor to prevent everything to do content search
if (Settings.ContentIndexProvider is EverythingSearchManager && !Settings.EnableEverythingContentSearch)
{
return EverythingContentSearchResult(query);
}
searchResults = Settings.ContentIndexProvider.ContentSearchAsync("", query.Search, token);
break;
}
case false:
searchResults = Settings.IndexProvider.SearchAsync(query.Search, token);
break;
}
if (searchResults == null)
{
return results.ToList();
@ -154,7 +163,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search
if (!FilesFolders.ReturnPreviousDirectoryIfIncompleteString(locationPath).LocationExists())
return results.ToList();
var useIndexSearch = Settings.IndexSearchEngine is Settings.IndexSearchEngineOption.WindowsIndex
var useIndexSearch = Settings.IndexSearchEngine is Settings.IndexSearchEngineOption.WindowsIndex
&& UseWindowsIndexForDirectorySearch(locationPath);
results.Add(ResultManager.CreateOpenCurrentFolderResult(locationPath, useIndexSearch));
@ -172,7 +181,8 @@ namespace Flow.Launcher.Plugin.Explorer.Search
query.Search[..recursiveIndicatorIndex],
query.Search[(recursiveIndicatorIndex + 1)..],
true,
token).ToListAsync(cancellationToken: token)
token)
.ToListAsync(cancellationToken: token)
.ConfigureAwait(false);
}
@ -207,7 +217,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search
}
public static bool IsFileContentSearch(string actionKeyword) => actionKeyword == Settings.FileContentSearchActionKeyword;
private bool UseWindowsIndexForDirectorySearch(string locationPath)
{

View file

@ -2,13 +2,14 @@
namespace Flow.Launcher.Plugin.Explorer.Search
{
public struct SearchResult
public record struct SearchResult
{
public string FullPath { get; init; }
public ResultType Type { get; init; }
public int Score { get; init; }
public bool WindowsIndexed { get; init; }
public bool ShowIndexState { get; init; }
}
}
}

View file

@ -4,21 +4,25 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
{
public class QueryConstructor
{
private readonly Settings settings;
private Settings Settings { get; }
private const string SystemIndex = "SystemIndex";
public CSearchQueryHelper BaseQueryHelper { get; }
public QueryConstructor(Settings settings)
{
this.settings = settings;
Settings = settings;
BaseQueryHelper = CreateBaseQuery();
}
public CSearchQueryHelper CreateBaseQuery()
private CSearchQueryHelper CreateBaseQuery()
{
var baseQuery = CreateQueryHelper();
// Set the number of results we want. Don't set this property if all results are needed.
baseQuery.QueryMaxResults = settings.MaxResult;
baseQuery.QueryMaxResults = Settings.MaxResult;
// Set list of columns we want to display, getting the path presently
baseQuery.QuerySelectColumns = "System.FileName, System.ItemUrl, System.ItemType";
@ -32,7 +36,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
return baseQuery;
}
internal CSearchQueryHelper CreateQueryHelper()
internal static CSearchQueryHelper CreateQueryHelper()
{
// This uses the Microsoft.Search.Interop assembly
var manager = new CSearchManager();
@ -42,18 +46,19 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
// Get the ISearchQueryHelper which will help us to translate AQS --> SQL necessary to query the indexer
var queryHelper = catalogManager.GetQueryHelper();
return queryHelper;
}
private static string TopLevelDirectoryConstraint(string path) => $"directory='file:{path}'";
private static string RecursiveDirectoryConstraint(string path) => $"scope='file:{path}'";
///<summary>
/// Set the required WHERE clause restriction to search on the first level of a specified directory.
///</summary>
public string QueryWhereRestrictionsForTopLevelDirectorySearch(string path)
{
var searchDepth = $"directory='file:";
return QueryWhereRestrictionsFromLocationPath(path, searchDepth);
return QueryWhereRestrictionsFromLocationPath(path, "directory='file:");
}
///<summary>
@ -61,9 +66,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
///</summary>
public string QueryWhereRestrictionsForTopLevelDirectoryAllFilesAndFoldersSearch(string path)
{
var searchDepth = $"scope='file:";
return QueryWhereRestrictionsFromLocationPath(path, searchDepth);
return QueryWhereRestrictionsFromLocationPath(path, "directory='scope:");
}
private string QueryWhereRestrictionsFromLocationPath(string path, string searchDepth)
@ -73,70 +76,72 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
var indexOfSeparator = path.LastIndexOf(Constants.DirectorySeperator);
var itemName = path.Substring(indexOfSeparator + 1);
var itemName = path[(indexOfSeparator + 1)..];
if (itemName.StartsWith(Constants.AllFilesFolderSearchWildcard))
itemName = itemName.Substring(1);
itemName = itemName[1..];
var previousLevelDirectory = path.Substring(0, indexOfSeparator);
if (string.IsNullOrEmpty(itemName))
return $"{searchDepth}{previousLevelDirectory}'";
return $"(System.FileName LIKE '{itemName}%' OR CONTAINS(System.FileName,'\"{itemName}*\"',1033)) AND {searchDepth}{previousLevelDirectory}'";
return $"(System.FileName LIKE '{itemName}%' OR CONTAINS({FileName},'\"{itemName}*\"',1033)) AND {searchDepth}{previousLevelDirectory}'";
}
///<summary>
/// Search will be performed on all folders and files on the first level of a specified directory.
///</summary>
public string QueryForTopLevelDirectorySearch(string path)
public string Directory(string path, string searchString = "", bool recursive = false)
{
string query = "SELECT TOP " + settings.MaxResult + $" {CreateBaseQuery().QuerySelectColumns} FROM {SystemIndex} WHERE ";
var queryConstraint = searchString is "" ? "" : $"AND ({FileName} LIKE '{searchString}%' OR CONTAINS({FileName},'\"{searchString}*\"'))";
if (path.LastIndexOf(Constants.AllFilesFolderSearchWildcard) > path.LastIndexOf(Constants.DirectorySeperator))
return query + QueryWhereRestrictionsForTopLevelDirectoryAllFilesAndFoldersSearch(path) + QueryOrderByFileNameRestriction;
var scopeConstraint = recursive
? RecursiveDirectoryConstraint(path)
: TopLevelDirectoryConstraint(path);
return query + QueryWhereRestrictionsForTopLevelDirectorySearch(path) + QueryOrderByFileNameRestriction;
string query = $"SELECT TOP {Settings.MaxResult} {BaseQueryHelper.QuerySelectColumns} FROM {SystemIndex} WHERE {scopeConstraint} {queryConstraint} ORDER BY {FileName}";
return query;
}
///<summary>
/// Search will be performed on all folders and files based on user's search keywords.
///</summary>
public string QueryForAllFilesAndFolders(string userSearchString)
public string FilesAndFolders(string userSearchString)
{
if (string.IsNullOrEmpty(userSearchString))
userSearchString = "*";
// Generate SQL from constructed parameters, converting the userSearchString from AQS->WHERE clause
return CreateBaseQuery().GenerateSQLFromUserQuery(userSearchString) + " AND " + QueryWhereRestrictionsForAllFilesAndFoldersSearch
+ QueryOrderByFileNameRestriction;
return $"{BaseQueryHelper.GenerateSQLFromUserQuery(userSearchString)} AND {RestrictionsForAllFilesAndFoldersSearch} ORDER BY {FileName}";
}
///<summary>
/// Set the required WHERE clause restriction to search for all files and folders.
///</summary>
public const string QueryWhereRestrictionsForAllFilesAndFoldersSearch = "scope='file:'";
public const string RestrictionsForAllFilesAndFoldersSearch = "scope='file:'";
public const string QueryOrderByFileNameRestriction = " ORDER BY System.FileName";
/// <summary>
/// Order identifier: file name
/// </summary>
public const string FileName = "System.FileName";
///<summary>
/// Search will be performed on all indexed file contents for the specified search keywords.
///</summary>
public string QueryForFileContentSearch(string userSearchString)
public string FileContent(string userSearchString)
{
string query = "SELECT TOP " + settings.MaxResult + $" {CreateBaseQuery().QuerySelectColumns} FROM {SystemIndex} WHERE ";
string query =
$"SELECT TOP {Settings.MaxResult} {BaseQueryHelper.QuerySelectColumns} FROM {SystemIndex} WHERE {RestrictionsForFileContentSearch(userSearchString)} AND {RestrictionsForAllFilesAndFoldersSearch} ORDER BY {FileName}";
return query + QueryWhereRestrictionsForFileContentSearch(userSearchString) + " AND " + QueryWhereRestrictionsForAllFilesAndFoldersSearch
+ QueryOrderByFileNameRestriction;
return query;
}
///<summary>
/// Set the required WHERE clause restriction to search within file content.
///</summary>
public string QueryWhereRestrictionsForFileContentSearch(string searchQuery)
{
return $"FREETEXT('{searchQuery}')";
}
public static string RestrictionsForFileContentSearch(string searchQuery) => $"FREETEXT('{searchQuery}')";
}
}

View file

@ -18,7 +18,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
{
// Reserved keywords in oleDB
private const string ReservedStringPattern = @"^[`\@\#\^,\&\/\\\$\%_;\[\]]+$";
private static Regex _reservedPatternMatcher = new(@"^[`\@\#\^,\&\/\\\$\%_;\[\]]+$", RegexOptions.Compiled);
private static async IAsyncEnumerable<SearchResult> ExecuteWindowsIndexSearchAsync(string indexQueryString, string connectionString, [EnumeratorCancellation] CancellationToken token)
{
@ -28,31 +28,42 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
await using var command = new OleDbCommand(indexQueryString, conn);
// Results return as an OleDbDataReader.
await using var dataReaderResults = await command.ExecuteReaderAsync(token) as OleDbDataReader;
OleDbDataReader dataReaderAttempt;
try
{
dataReaderAttempt = await command.ExecuteReaderAsync(token) as OleDbDataReader;
}
catch (OleDbException e)
{
Log.Exception($"|WindowsIndex.ExecuteWindowsIndexSearchAsync|Failed to execute windows index search query: {indexQueryString}", e);
yield break;
}
await using var dataReader = dataReaderAttempt;
token.ThrowIfCancellationRequested();
if (dataReaderResults is not { HasRows: true })
if (dataReader is not { HasRows: true })
{
yield break;
}
while (await dataReaderResults.ReadAsync(token))
while (await dataReader.ReadAsync(token))
{
token.ThrowIfCancellationRequested();
if (dataReaderResults.GetValue(0) == DBNull.Value || dataReaderResults.GetValue(1) == DBNull.Value)
if (dataReader.GetValue(0) == DBNull.Value || dataReader.GetValue(1) == DBNull.Value)
{
continue;
}
// # is URI syntax for the fragment component, need to be encoded so LocalPath returns complete path
var encodedFragmentPath = dataReaderResults
var encodedFragmentPath = dataReader
.GetString(1)
.Replace("#", "%23", StringComparison.OrdinalIgnoreCase);
var path = new Uri(encodedFragmentPath).LocalPath;
yield return new SearchResult()
yield return new SearchResult
{
FullPath = path,
Type = dataReaderResults.GetString(2) == "Directory" ? ResultType.Folder : ResultType.File,
Type = dataReader.GetString(2) == "Directory" ? ResultType.Folder : ResultType.File,
WindowsIndexed = true
};
}
@ -60,22 +71,18 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
// Initial ordering, this order can be updated later by UpdateResultView.MainViewModel based on history of user selection.
}
internal static IAsyncEnumerable<SearchResult> WindowsIndexSearchAsync(string searchString,
Func<CSearchQueryHelper> createQueryHelper,
Func<string, string> constructQuery,
IEnumerable<AccessLink> exclusionList,
internal static IAsyncEnumerable<SearchResult> WindowsIndexSearchAsync(string connectionString,
string search,
CancellationToken token)
{
var regexMatch = Regex.Match(searchString, ReservedStringPattern);
if (regexMatch.Success)
return AsyncEnumerable.Empty<SearchResult>();
var constructedQuery = constructQuery(searchString);
return ExecuteWindowsIndexSearchAsync(constructedQuery, createQueryHelper().ConnectionString, token);
return _reservedPatternMatcher.IsMatch(search)
? AsyncEnumerable.Empty<SearchResult>()
: ExecuteWindowsIndexSearchAsync(search, connectionString, token);
}
// TODO: Move to General Search Manager
private static void RemoveResultsInExclusionList(List<SearchResult> results, IReadOnlyList<AccessLink> exclusionList, CancellationToken token)
{
var indexExclusionListCount = exclusionList.Count;
@ -102,6 +109,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
}
}
// TODO: Use a custom exception to handle this
private static List<Result> ResultForWindexSearchOff(string rawQuery)
{
var api = SearchManager.Context.API;
@ -160,4 +168,4 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
#endif
}
}
}
}

View file

@ -2,19 +2,24 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Flow.Launcher.Plugin.Explorer.Search.IProvider;
using Microsoft.Search.Interop;
namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
{
public class WindowsIndexSearchManager : IIndexProvider, IContentIndexProvider, IPathEnumerable
public class WindowsIndexSearchManager : IIndexProvider, IContentIndexProvider, IPathIndexProvider
{
private Settings Settings { get; }
private QueryConstructor QueryConstructor { get; }
private CSearchQueryHelper QueryHelper { get; }
public WindowsIndexSearchManager(Settings settings)
{
Settings = settings;
QueryConstructor = new QueryConstructor(Settings);
QueryHelper = QueryConstructor.CreateQueryHelper();
}
private IAsyncEnumerable<SearchResult> WindowsIndexFileContentSearchAsync(string querySearchString,
CancellationToken token)
{
@ -22,39 +27,35 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
return AsyncEnumerable.Empty<SearchResult>();
return WindowsIndex.WindowsIndexSearchAsync(
querySearchString,
QueryConstructor.CreateQueryHelper,
QueryConstructor.QueryForFileContentSearch,
Settings.IndexSearchExcludedSubdirectoryPaths,
QueryHelper.ConnectionString,
QueryConstructor.FileContent(querySearchString),
token);
}
private IAsyncEnumerable<SearchResult> WindowsIndexFilesAndFoldersSearchAsync(string querySearchString,
CancellationToken token)
CancellationToken token = default)
{
return WindowsIndex.WindowsIndexSearchAsync(
querySearchString,
QueryConstructor.CreateQueryHelper,
QueryConstructor.QueryForAllFilesAndFolders,
Settings.IndexSearchExcludedSubdirectoryPaths,
QueryHelper.ConnectionString,
QueryConstructor.FilesAndFolders(querySearchString),
token);
}
private IAsyncEnumerable<SearchResult> WindowsIndexTopLevelFolderSearchAsync(string path,string search,
private IAsyncEnumerable<SearchResult> WindowsIndexTopLevelFolderSearchAsync(string search,
string path,
bool recursive,
CancellationToken token)
{
var queryConstructor = new QueryConstructor(Settings);
return WindowsIndex.WindowsIndexSearchAsync(
path,
queryConstructor.CreateQueryHelper,
queryConstructor.QueryForTopLevelDirectorySearch,
Settings.IndexSearchExcludedSubdirectoryPaths,
QueryConstructor.CreateQueryHelper().ConnectionString,
queryConstructor.Directory(path, search, recursive),
token);
}
public IAsyncEnumerable<SearchResult> SearchAsync(string search, CancellationToken token)
{
return WindowsIndexFilesAndFoldersSearchAsync(search, token);
return WindowsIndexFilesAndFoldersSearchAsync(search, token: token);
}
public IAsyncEnumerable<SearchResult> ContentSearchAsync(string plainSearch, string contentSearch, CancellationToken token)
{
@ -62,7 +63,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
}
public IAsyncEnumerable<SearchResult> EnumerateAsync(string path, string search, bool recursive, CancellationToken token)
{
return recursive ? WindowsIndexFilesAndFoldersSearchAsync(search, token) : WindowsIndexTopLevelFolderSearchAsync(path, search, token);
return WindowsIndexTopLevelFolderSearchAsync(search, path, recursive, token);
}
}
}
}

View file

@ -9,6 +9,7 @@ using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text.Json.Serialization;
using Flow.Launcher.Plugin.Explorer.Search.IProvider;
namespace Flow.Launcher.Plugin.Explorer
{
@ -65,7 +66,7 @@ namespace Flow.Launcher.Plugin.Explorer
#region SearchEngine
public PathEnumerationEngineOption PathEnumerationEngine { get; set; }
public PathEnumerationEngineOption PathEnumerationEngine { get; set; } = PathEnumerationEngineOption.WindowsIndex;
private EverythingSearchManager EverythingManagerInstance => _everythingManagerInstance ??= new EverythingSearchManager(this);
private WindowsIndexSearchManager WindowsIndexSearchManager => _windowsIndexSearchManager ??= new WindowsIndexSearchManager(this);
@ -81,7 +82,7 @@ namespace Flow.Launcher.Plugin.Explorer
};
[JsonIgnore]
public IPathEnumerable PathEnumerator => PathEnumerationEngine switch
public IPathIndexProvider PathEnumerator => PathEnumerationEngine switch
{
PathEnumerationEngineOption.Everything => EverythingManagerInstance,
PathEnumerationEngineOption.WindowsIndex => WindowsIndexSearchManager,
@ -192,4 +193,4 @@ namespace Flow.Launcher.Plugin.Explorer
_ => throw new ArgumentOutOfRangeException(nameof(actionKeyword), actionKeyword, "ActionKeyword enabled status not defined")
};
}
}
}