diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs
index 1d160983a..702741590 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/QueryConstructor.cs
@@ -1,4 +1,6 @@
using System;
+using System.Collections.Generic;
+using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.Search.Interop;
@@ -74,7 +76,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
///
/// Search will be performed on all folders and files based on user's search keywords.
///
- public string FilesAndFolders(ReadOnlySpan userSearchString)
+ public string FilesAndFolders(ReadOnlySpan userSearchString, IEnumerable allowedResultTypes = null)
{
if (userSearchString.IsWhiteSpace())
userSearchString = "*";
@@ -82,8 +84,50 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
// Remove any special characters that might cause issues with the query
var replacedSearchString = ReplaceSpecialCharacterWithTwoSideWhiteSpace(userSearchString);
+ // Build the type filter constraint
+ var typeFilterConstraint = BuildTypeFilterConstraint(allowedResultTypes);
+
// Generate SQL from constructed parameters, converting the userSearchString from AQS->WHERE clause
- return $"{CreateBaseQuery().GenerateSQLFromUserQuery(replacedSearchString)} AND {RestrictionsForAllFilesAndFoldersSearch} ORDER BY {OrderIdentifier}";
+ var baseQuery = $"{CreateBaseQuery().GenerateSQLFromUserQuery(replacedSearchString)} AND {RestrictionsForAllFilesAndFoldersSearch}";
+
+ // Append type filter if present
+ if (!string.IsNullOrEmpty(typeFilterConstraint))
+ baseQuery += $" AND {typeFilterConstraint}";
+
+ return $"{baseQuery} ORDER BY {OrderIdentifier}";
+ }
+
+ ///
+ /// Build WHERE clause constraint to filter by result types (File, Folder, Volume).
+ ///
+ ///
+ /// System.ItemType values:
+ /// - ".directory" for folders
+ /// - Specific file extensions (e.g., ".txt", ".pdf") for files
+ /// - Drive volumes are identified by their path structure
+ ///
+ private static string BuildTypeFilterConstraint(IEnumerable allowedResultTypes)
+ {
+ if (allowedResultTypes == null)
+ return null;
+
+ var typesList = allowedResultTypes as IList ?? allowedResultTypes.ToList();
+
+ // No filtering needed if empty or all types are allowed
+ // TODO: what if more types are added in the future?
+ if (typesList.Count == 0 || typesList.Count == 3)
+ return null;
+
+ var hasFile = typesList.Contains(ResultType.File);
+ var hasFolder = typesList.Contains(ResultType.Folder) || typesList.Contains(ResultType.Volume); // Folder and volume are merged in Folder action keyword so treat them as same
+
+ if (hasFolder)
+ return "System.ItemType = '.directory'";
+
+ if (hasFile)
+ return "System.ItemType <> '.directory'";
+
+ return null;
}
///
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexSearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexSearchManager.cs
index 0201fa3b7..98207275e 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexSearchManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexSearchManager.cs
@@ -45,13 +45,14 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
private IAsyncEnumerable WindowsIndexFilesAndFoldersSearchAsync(
ReadOnlySpan querySearchString,
+ IEnumerable allowedResultTypes = null,
CancellationToken token = default)
{
try
{
return WindowsIndex.WindowsIndexSearchAsync(
QueryConstructor.CreateQueryHelper().ConnectionString,
- QueryConstructor.FilesAndFolders(querySearchString),
+ QueryConstructor.FilesAndFolders(querySearchString, allowedResultTypes),
token);
}
catch (COMException)
@@ -85,8 +86,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
public IAsyncEnumerable SearchAsync(string search, CancellationToken token, IEnumerable allowedResultTypes = null)
{
- // TODO: result type filter
- return WindowsIndexFilesAndFoldersSearchAsync(search, token: token);
+ return WindowsIndexFilesAndFoldersSearchAsync(search, allowedResultTypes, token);
}
public IAsyncEnumerable ContentSearchAsync(string plainSearch, string contentSearch, CancellationToken token)