mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-07 11:46:30 +02:00
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:
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
Reference in New Issue
Block a user