File search now has filters (#42141)

Closes #39260

Search for all files & folders, folders only, or files only.

Enjoy.


https://github.com/user-attachments/assets/43ba93f5-dfc5-4e73-8414-547cf99dcfcf
This commit is contained in:
Michael Jolley
2025-10-24 19:16:21 -05:00
committed by GitHub
parent 6e5ad11bc3
commit 20188bda9b
5 changed files with 114 additions and 10 deletions

View File

@@ -6,7 +6,7 @@ using Microsoft.CommandPalette.Extensions.Toolkit;
namespace Microsoft.CmdPal.Ext.Indexer; namespace Microsoft.CmdPal.Ext.Indexer;
internal sealed class Icons internal static class Icons
{ {
internal static IconInfo FileExplorerSegoeIcon { get; } = new("\uEC50"); internal static IconInfo FileExplorerSegoeIcon { get; } = new("\uEC50");
@@ -19,4 +19,8 @@ internal sealed class Icons
internal static IconInfo DocumentIcon { get; } = new("\uE8A5"); // Document internal static IconInfo DocumentIcon { get; } = new("\uE8A5"); // Document
internal static IconInfo FolderOpenIcon { get; } = new("\uE838"); // FolderOpen internal static IconInfo FolderOpenIcon { get; } = new("\uE838"); // FolderOpen
internal static IconInfo FilesIcon { get; } = new("\uF571"); // PrintAllPages
internal static IconInfo FilterIcon { get; } = new("\uE71C"); // Filter
} }

View File

@@ -0,0 +1,27 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.CmdPal.Ext.Indexer.Properties;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
namespace Microsoft.CmdPal.Ext.Indexer.Indexer;
internal sealed partial class SearchFilters : Filters
{
public SearchFilters()
{
CurrentFilterId = "all";
}
public override IFilterItem[] GetFilters()
{
return [
new Filter() { Id = "all", Name = Resources.Indexer_Filter_All, Icon = Icons.FilterIcon },
new Separator(),
new Filter() { Id = "folders", Name = Resources.Indexer_Filter_Folders_Only, Icon = Icons.FolderOpenIcon },
new Filter() { Id = "files", Name = Resources.Indexer_Filter_Files_Only, Icon = Icons.FilesIcon },
];
}
}

View File

@@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Text.Encodings.Web; using System.Text.Encodings.Web;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.CmdPal.Ext.Indexer.Indexer;
using Microsoft.CmdPal.Ext.Indexer.Properties; using Microsoft.CmdPal.Ext.Indexer.Properties;
using Microsoft.CommandPalette.Extensions; using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit; using Microsoft.CommandPalette.Extensions.Toolkit;
@@ -36,6 +37,11 @@ internal sealed partial class IndexerPage : DynamicListPage, IDisposable
PlaceholderText = Resources.Indexer_PlaceholderText; PlaceholderText = Resources.Indexer_PlaceholderText;
_searchEngine = new(); _searchEngine = new();
_queryCookie = 10; _queryCookie = 10;
var filters = new SearchFilters();
filters.PropChanged += Filters_PropChanged;
Filters = filters;
CreateEmptyContent(); CreateEmptyContent();
} }
@@ -49,6 +55,11 @@ internal sealed partial class IndexerPage : DynamicListPage, IDisposable
initialQuery = query; initialQuery = query;
SearchText = query; SearchText = query;
disposeSearchEngine = false; disposeSearchEngine = false;
var filters = new SearchFilters();
filters.PropChanged += Filters_PropChanged;
Filters = filters;
CreateEmptyContent(); CreateEmptyContent();
} }
@@ -79,30 +90,56 @@ internal sealed partial class IndexerPage : DynamicListPage, IDisposable
{ {
// {20D04FE0-3AEA-1069-A2D8-08002B30309D} is CLSID for "This PC" // {20D04FE0-3AEA-1069-A2D8-08002B30309D} is CLSID for "This PC"
const string template = "search-ms:query={0}&crumb=location:::{{20D04FE0-3AEA-1069-A2D8-08002B30309D}}"; const string template = "search-ms:query={0}&crumb=location:::{{20D04FE0-3AEA-1069-A2D8-08002B30309D}}";
var encodedSearchText = UrlEncoder.Default.Encode(SearchText); var fullSearchText = FullSearchString(SearchText);
var encodedSearchText = UrlEncoder.Default.Encode(fullSearchText);
var command = string.Format(CultureInfo.CurrentCulture, template, encodedSearchText); var command = string.Format(CultureInfo.CurrentCulture, template, encodedSearchText);
ShellHelpers.OpenInShell(command); ShellHelpers.OpenInShell(command);
} }
public override ICommandItem EmptyContent => _isEmptyQuery ? _noSearchEmptyContent : _nothingFoundEmptyContent; public override ICommandItem EmptyContent => _isEmptyQuery ? _noSearchEmptyContent : _nothingFoundEmptyContent;
private void Filters_PropChanged(object sender, IPropChangedEventArgs args)
{
PerformSearch(SearchText);
}
public override void UpdateSearchText(string oldSearch, string newSearch) public override void UpdateSearchText(string oldSearch, string newSearch)
{ {
if (oldSearch != newSearch && newSearch != initialQuery) if (oldSearch != newSearch && newSearch != initialQuery)
{ {
_ = Task.Run(() => PerformSearch(newSearch);
{
_isEmptyQuery = string.IsNullOrWhiteSpace(newSearch);
Query(newSearch);
LoadMore();
OnPropertyChanged(nameof(EmptyContent));
initialQuery = null;
});
} }
} }
private void PerformSearch(string newSearch)
{
var actualSearch = FullSearchString(newSearch);
_ = Task.Run(() =>
{
_isEmptyQuery = string.IsNullOrWhiteSpace(actualSearch);
Query(actualSearch);
LoadMore();
OnPropertyChanged(nameof(EmptyContent));
initialQuery = null;
});
}
public override IListItem[] GetItems() => [.. _indexerListItems]; public override IListItem[] GetItems() => [.. _indexerListItems];
private string FullSearchString(string query)
{
switch (Filters.CurrentFilterId)
{
case "folders":
return $"{query} kind:folders";
case "files":
return $"{query} kind:NOT folders";
case "all":
default:
return query;
}
}
public override void LoadMore() public override void LoadMore()
{ {
IsLoading = true; IsLoading = true;

View File

@@ -177,6 +177,33 @@ namespace Microsoft.CmdPal.Ext.Indexer.Properties {
} }
} }
/// <summary>
/// Looks up a localized string similar to Files and folders.
/// </summary>
internal static string Indexer_Filter_All {
get {
return ResourceManager.GetString("Indexer_Filter_All", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Files.
/// </summary>
internal static string Indexer_Filter_Files_Only {
get {
return ResourceManager.GetString("Indexer_Filter_Files_Only", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Folders.
/// </summary>
internal static string Indexer_Filter_Folders_Only {
get {
return ResourceManager.GetString("Indexer_Filter_Folders_Only", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Find file from path. /// Looks up a localized string similar to Find file from path.
/// </summary> /// </summary>

View File

@@ -196,4 +196,13 @@ You can try searching all files on this PC or adjust your indexing settings.</va
<data name="Indexer_Command_SearchAllFiles" xml:space="preserve"> <data name="Indexer_Command_SearchAllFiles" xml:space="preserve">
<value>Search all files</value> <value>Search all files</value>
</data> </data>
<data name="Indexer_Filter_All" xml:space="preserve">
<value>Files and folders</value>
</data>
<data name="Indexer_Filter_Folders_Only" xml:space="preserve">
<value>Folders</value>
</data>
<data name="Indexer_Filter_Files_Only" xml:space="preserve">
<value>Files</value>
</data>
</root> </root>