mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-08 04:07:40 +02:00
Rename the [Ee]xts dir to ext (#38852)
**WARNING:** This PR will probably blow up all in-flight PRs at some point in the early days of CmdPal, two of us created seperate `Exts` and `exts` dirs. Depending on what the casing was on the branch that you checked one of those out from, it'd get stuck like that on your PC forever. Windows didn't care, so we never noticed. But GitHub does care, and now browsing the source on GitHub is basically impossible. Closes #38081
This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
// 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 System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.CmdPal.Ext.Indexer.Data;
|
||||
using Microsoft.CmdPal.Ext.Indexer.Properties;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using Windows.Storage.Streams;
|
||||
|
||||
#nullable enable
|
||||
namespace Microsoft.CmdPal.Ext.Indexer;
|
||||
|
||||
/// <summary>
|
||||
/// This is almost more of just a sample than anything.
|
||||
/// This is one singular page for switching.
|
||||
/// </summary>
|
||||
public sealed partial class DirectoryExplorePage : DynamicListPage
|
||||
{
|
||||
private string _path;
|
||||
private List<ExploreListItem>? _directoryContents;
|
||||
private List<ExploreListItem>? _filteredContents;
|
||||
|
||||
public DirectoryExplorePage(string path)
|
||||
{
|
||||
_path = path;
|
||||
Icon = Icons.FileExplorer;
|
||||
Name = Resources.Indexer_Command_Browse;
|
||||
Title = path;
|
||||
}
|
||||
|
||||
public override void UpdateSearchText(string oldSearch, string newSearch)
|
||||
{
|
||||
if (_directoryContents == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(newSearch))
|
||||
{
|
||||
if (_filteredContents != null)
|
||||
{
|
||||
_filteredContents = null;
|
||||
RaiseItemsChanged(-1);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Need to break this out the manual way so that the compiler can know
|
||||
// this is an ExploreListItem
|
||||
var filteredResults = ListHelpers.FilterList(
|
||||
_directoryContents,
|
||||
newSearch,
|
||||
(s, i) => ListHelpers.ScoreListItem(s, i));
|
||||
|
||||
if (_filteredContents != null)
|
||||
{
|
||||
lock (_filteredContents)
|
||||
{
|
||||
ListHelpers.InPlaceUpdateList<ExploreListItem>(_filteredContents, filteredResults);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_filteredContents = filteredResults.ToList();
|
||||
}
|
||||
|
||||
RaiseItemsChanged(-1);
|
||||
}
|
||||
|
||||
public override IListItem[] GetItems()
|
||||
{
|
||||
if (_filteredContents != null)
|
||||
{
|
||||
return _filteredContents.ToArray();
|
||||
}
|
||||
|
||||
if (_directoryContents != null)
|
||||
{
|
||||
return _directoryContents.ToArray();
|
||||
}
|
||||
|
||||
IsLoading = true;
|
||||
if (!Path.Exists(_path))
|
||||
{
|
||||
EmptyContent = new CommandItem(title: Resources.Indexer_File_Does_Not_Exist);
|
||||
return [];
|
||||
}
|
||||
|
||||
var attr = File.GetAttributes(_path);
|
||||
|
||||
// detect whether its a directory or file
|
||||
if ((attr & FileAttributes.Directory) != FileAttributes.Directory)
|
||||
{
|
||||
EmptyContent = new CommandItem(title: Resources.Indexer_File_Is_File_Not_Folder);
|
||||
return [];
|
||||
}
|
||||
|
||||
var contents = Directory.EnumerateFileSystemEntries(_path);
|
||||
_directoryContents = contents
|
||||
.Select(s => new IndexerItem() { FullPath = s, FileName = Path.GetFileName(s) })
|
||||
.Select(i => new ExploreListItem(i))
|
||||
.ToList();
|
||||
|
||||
foreach (var i in _directoryContents)
|
||||
{
|
||||
i.PathChangeRequested += HandlePathChangeRequested;
|
||||
}
|
||||
|
||||
_ = Task.Run(() =>
|
||||
{
|
||||
foreach (var item in _directoryContents)
|
||||
{
|
||||
IconInfo? icon = null;
|
||||
try
|
||||
{
|
||||
var stream = ThumbnailHelper.GetThumbnail(item.FilePath).Result;
|
||||
if (stream != null)
|
||||
{
|
||||
var data = new IconData(RandomAccessStreamReference.CreateFromStream(stream));
|
||||
icon = new IconInfo(data, data);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
item.Icon = icon;
|
||||
}
|
||||
});
|
||||
|
||||
IsLoading = false;
|
||||
|
||||
return _directoryContents.ToArray();
|
||||
}
|
||||
|
||||
private void HandlePathChangeRequested(ExploreListItem sender, string path)
|
||||
{
|
||||
_directoryContents = null;
|
||||
_filteredContents = null;
|
||||
_path = path;
|
||||
Title = path;
|
||||
SearchText = string.Empty;
|
||||
RaiseItemsChanged(-1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
// 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 System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.CmdPal.Ext.Indexer.Data;
|
||||
using Microsoft.CmdPal.Ext.Indexer.Properties;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using Windows.Storage.Streams;
|
||||
|
||||
#nullable enable
|
||||
namespace Microsoft.CmdPal.Ext.Indexer;
|
||||
|
||||
public sealed partial class DirectoryPage : ListPage
|
||||
{
|
||||
private readonly string _path;
|
||||
|
||||
private List<IndexerListItem>? _directoryContents;
|
||||
|
||||
public DirectoryPage(string path)
|
||||
{
|
||||
_path = path;
|
||||
Icon = Icons.FileExplorer;
|
||||
Name = Resources.Indexer_Command_Browse;
|
||||
Title = path;
|
||||
}
|
||||
|
||||
public override IListItem[] GetItems()
|
||||
{
|
||||
if (_directoryContents != null)
|
||||
{
|
||||
return _directoryContents.ToArray();
|
||||
}
|
||||
|
||||
if (!Path.Exists(_path))
|
||||
{
|
||||
EmptyContent = new CommandItem(
|
||||
title: Resources.Indexer_File_Does_Not_Exist,
|
||||
subtitle: $"{_path}");
|
||||
return [];
|
||||
}
|
||||
|
||||
var attr = File.GetAttributes(_path);
|
||||
|
||||
// detect whether its a directory or file
|
||||
if ((attr & FileAttributes.Directory) != FileAttributes.Directory)
|
||||
{
|
||||
EmptyContent = new CommandItem(
|
||||
title: Resources.Indexer_File_Is_File_Not_Folder, subtitle: $"{_path}")
|
||||
{
|
||||
Icon = Icons.Document,
|
||||
};
|
||||
return [];
|
||||
}
|
||||
|
||||
var contents = Directory.EnumerateFileSystemEntries(_path);
|
||||
|
||||
if (!contents.Any())
|
||||
{
|
||||
var item = new IndexerItem() { FullPath = _path, FileName = Path.GetFileName(_path) };
|
||||
var listItemForUs = new IndexerListItem(item, IncludeBrowseCommand.Exclude);
|
||||
EmptyContent = new CommandItem(
|
||||
title: Resources.Indexer_Folder_Is_Empty, subtitle: $"{_path}")
|
||||
{
|
||||
Icon = Icons.FolderOpen,
|
||||
Command = listItemForUs.Command,
|
||||
MoreCommands = listItemForUs.MoreCommands,
|
||||
};
|
||||
return [];
|
||||
}
|
||||
|
||||
_directoryContents = contents
|
||||
.Select(s => new IndexerItem() { FullPath = s, FileName = Path.GetFileName(s) })
|
||||
.Select(i => new IndexerListItem(i, IncludeBrowseCommand.AsDefault))
|
||||
.ToList();
|
||||
|
||||
_ = Task.Run(() =>
|
||||
{
|
||||
foreach (var item in _directoryContents)
|
||||
{
|
||||
IconInfo? icon = null;
|
||||
try
|
||||
{
|
||||
var stream = ThumbnailHelper.GetThumbnail(item.FilePath).Result;
|
||||
if (stream != null)
|
||||
{
|
||||
var data = new IconData(RandomAccessStreamReference.CreateFromStream(stream));
|
||||
icon = new IconInfo(data, data);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
item.Icon = icon;
|
||||
}
|
||||
});
|
||||
|
||||
return _directoryContents.ToArray();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// 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 System.Collections.Generic;
|
||||
using Microsoft.CmdPal.Ext.Indexer.Commands;
|
||||
using Microsoft.CmdPal.Ext.Indexer.Data;
|
||||
using Microsoft.CmdPal.Ext.Indexer.Properties;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using Windows.Foundation;
|
||||
|
||||
#nullable enable
|
||||
namespace Microsoft.CmdPal.Ext.Indexer;
|
||||
|
||||
/// <summary>
|
||||
/// This is almost more of just a sample than anything.
|
||||
/// </summary>
|
||||
internal sealed partial class ExploreListItem : ListItem
|
||||
{
|
||||
internal string FilePath { get; private set; }
|
||||
|
||||
internal event TypedEventHandler<ExploreListItem, string>? PathChangeRequested;
|
||||
|
||||
public ExploreListItem(IndexerItem indexerItem)
|
||||
: base(new NoOpCommand())
|
||||
{
|
||||
FilePath = indexerItem.FullPath;
|
||||
|
||||
Title = indexerItem.FileName;
|
||||
Subtitle = indexerItem.FullPath;
|
||||
List<CommandContextItem> context = [];
|
||||
if (indexerItem.IsDirectory())
|
||||
{
|
||||
Command = new AnonymousCommand(
|
||||
() => { PathChangeRequested?.Invoke(this, FilePath); })
|
||||
{
|
||||
Result = CommandResult.KeepOpen(),
|
||||
Name = Resources.Indexer_Command_Browse,
|
||||
};
|
||||
context.Add(new CommandContextItem(new DirectoryPage(indexerItem.FullPath)));
|
||||
}
|
||||
else
|
||||
{
|
||||
Command = new OpenFileCommand(indexerItem);
|
||||
}
|
||||
|
||||
MoreCommands = [
|
||||
..context,
|
||||
new CommandContextItem(new OpenWithCommand(indexerItem)),
|
||||
new CommandContextItem(new ShowFileInFolderCommand(indexerItem.FullPath) { Name = Resources.Indexer_Command_ShowInFolder }),
|
||||
new CommandContextItem(new CopyPathCommand(indexerItem)),
|
||||
new CommandContextItem(new OpenInConsoleCommand(indexerItem)),
|
||||
new CommandContextItem(new OpenPropertiesCommand(indexerItem)),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// 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.CommandPalette.Extensions.Toolkit;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.Indexer;
|
||||
|
||||
internal sealed class Icons
|
||||
{
|
||||
internal static IconInfo FileExplorerSegoe { get; } = new("\uEC50");
|
||||
|
||||
internal static IconInfo FileExplorer { get; } = IconHelpers.FromRelativePath("Assets\\FileExplorer.png");
|
||||
|
||||
internal static IconInfo OpenFile { get; } = new("\uE8E5"); // OpenFile
|
||||
|
||||
internal static IconInfo Document { get; } = new("\uE8A5"); // Document
|
||||
|
||||
internal static IconInfo FolderOpen { get; } = new("\uE838"); // FolderOpen
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
// 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 System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using ManagedCommon;
|
||||
using Microsoft.CmdPal.Ext.Indexer.Data;
|
||||
using Microsoft.CmdPal.Ext.Indexer.Indexer;
|
||||
using Microsoft.CmdPal.Ext.Indexer.Properties;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using Windows.Storage.Streams;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.Indexer;
|
||||
|
||||
internal sealed partial class IndexerPage : DynamicListPage, IDisposable
|
||||
{
|
||||
private readonly List<IListItem> _indexerListItems = [];
|
||||
|
||||
private SearchQuery _searchQuery = new();
|
||||
|
||||
private uint _queryCookie = 10;
|
||||
|
||||
public IndexerPage()
|
||||
{
|
||||
Id = "com.microsoft.indexer.fileSearch";
|
||||
Icon = Icons.FileExplorer;
|
||||
Name = Resources.Indexer_Title;
|
||||
PlaceholderText = Resources.Indexer_PlaceholderText;
|
||||
}
|
||||
|
||||
public override void UpdateSearchText(string oldSearch, string newSearch)
|
||||
{
|
||||
if (oldSearch != newSearch)
|
||||
{
|
||||
_ = Task.Run(() =>
|
||||
{
|
||||
Query(newSearch);
|
||||
LoadMore();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public override IListItem[] GetItems() => [.. _indexerListItems];
|
||||
|
||||
public override void LoadMore()
|
||||
{
|
||||
IsLoading = true;
|
||||
FetchItems(20);
|
||||
IsLoading = false;
|
||||
RaiseItemsChanged(_indexerListItems.Count);
|
||||
}
|
||||
|
||||
private void Query(string query)
|
||||
{
|
||||
++_queryCookie;
|
||||
_indexerListItems.Clear();
|
||||
_searchQuery.SearchResults.Clear();
|
||||
_searchQuery.CancelOutstandingQueries();
|
||||
|
||||
if (query == string.Empty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Stopwatch stopwatch = new();
|
||||
stopwatch.Start();
|
||||
|
||||
_searchQuery.Execute(query, _queryCookie);
|
||||
|
||||
stopwatch.Stop();
|
||||
Logger.LogDebug($"Query time: {stopwatch.ElapsedMilliseconds} ms, query: \"{query}\"");
|
||||
}
|
||||
|
||||
private void FetchItems(int limit)
|
||||
{
|
||||
if (_searchQuery != null)
|
||||
{
|
||||
var cookie = _searchQuery.Cookie;
|
||||
if (cookie == _queryCookie)
|
||||
{
|
||||
var index = 0;
|
||||
SearchResult result;
|
||||
|
||||
var hasMoreItems = _searchQuery.FetchRows(_indexerListItems.Count, limit);
|
||||
|
||||
while (!_searchQuery.SearchResults.IsEmpty && _searchQuery.SearchResults.TryDequeue(out result) && ++index <= limit)
|
||||
{
|
||||
IconInfo icon = null;
|
||||
try
|
||||
{
|
||||
var stream = ThumbnailHelper.GetThumbnail(result.LaunchUri).Result;
|
||||
if (stream != null)
|
||||
{
|
||||
var data = new IconData(RandomAccessStreamReference.CreateFromStream(stream));
|
||||
icon = new IconInfo(data, data);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Failed to get the icon.", ex);
|
||||
}
|
||||
|
||||
_indexerListItems.Add(new IndexerListItem(new IndexerItem
|
||||
{
|
||||
FileName = result.ItemDisplayName,
|
||||
FullPath = result.LaunchUri,
|
||||
})
|
||||
{
|
||||
Icon = icon,
|
||||
});
|
||||
}
|
||||
|
||||
HasMoreItems = hasMoreItems;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_searchQuery = null;
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user