Compare commits

...

5 Commits

Author SHA1 Message Date
Mike Griese
e7eb2d0239 Add the TextToSuggest back, just for demo purposes 2025-04-30 20:36:24 -05:00
Mike Griese
aefae2935e heck just use the original shell provider for history 2025-04-30 10:05:16 -05:00
Mike Griese
727367960e Start adding history 2025-04-30 06:01:45 -05:00
Mike Griese
32700658fd Deduplicate a bunch of code 2025-04-30 04:25:59 -05:00
Mike Griese
a7cb535515 What if the run page had the same typeahead that Rundlg had? 2025-04-29 17:01:49 -05:00
6 changed files with 213 additions and 1 deletions

View File

@@ -27,6 +27,7 @@
PreviewKeyDown="FilterBox_PreviewKeyDown"
PreviewKeyUp="FilterBox_PreviewKeyUp"
Style="{StaticResource SearchTextBoxStyle}"
Description="{x:Bind CurrentPageViewModel.TextToSuggest, Mode=OneWay}"
TextChanged="FilterBox_TextChanged" />
<!-- Disabled Description="{x:Bind CurrentPageViewModel.TextToSuggest, Mode=OneWay}" for now, needs more work -->
</UserControl>

View File

@@ -9,4 +9,6 @@ namespace Microsoft.CmdPal.Ext.Shell;
internal sealed class Icons
{
internal static IconInfo RunV2 { get; } = IconHelpers.FromRelativePath("Assets\\Run.svg");
internal static IconInfo Folder { get; } = new("📁");
}

View File

@@ -15,6 +15,10 @@
<ItemGroup>
<ProjectReference Include="..\..\extensionsdk\Microsoft.CommandPalette.Extensions.Toolkit\Microsoft.CommandPalette.Extensions.Toolkit.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.CommandLine" />
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Resources.Designer.cs">
<DependentUpon>Resources.resx</DependentUpon>

View File

@@ -0,0 +1,45 @@
// 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.IO;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
namespace Microsoft.CmdPal.Ext.Shell;
internal sealed partial class PathListItem : ListItem
{
private readonly Lazy<IconInfo> _icon;
private readonly bool _isDirectory;
public override IIconInfo? Icon { get => _icon.Value; set => base.Icon = value; }
public PathListItem(string path)
: base(new OpenUrlCommand(path))
{
var fileName = Path.GetFileName(path);
_isDirectory = Directory.Exists(path);
if (_isDirectory)
{
path = path + "\\";
fileName = fileName + "\\";
}
Title = fileName;
Subtitle = path;
TextToSuggest = path;
MoreCommands = [
new CommandContextItem(new CopyTextCommand(path))
];
_icon = new Lazy<IconInfo>(() =>
{
var iconStream = ThumbnailHelper.GetThumbnail(path).Result;
var icon = iconStream != null ? IconInfo.FromStream(iconStream) :
_isDirectory ? Icons.Folder : Icons.RunV2;
return icon;
});
}
}

View File

@@ -0,0 +1,150 @@
// 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 Microsoft.CmdPal.Ext.Shell.Helpers;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
namespace Microsoft.CmdPal.Ext.Shell;
internal sealed partial class RunMainPage : DynamicListPage
{
private readonly ShellListPageHelpers _helper;
private readonly List<ListItem> _topLevelItems = new();
private List<ListItem> _historyItems = new();
private List<ListItem> _pathItems = new();
public RunMainPage(SettingsManager settingsManager)
{
Name = "Open"; // LOC!
Title = "Run commands"; // LOC!
Icon = Icons.RunV2;
PlaceholderText = "Type the name of a command to run"; // LOC!
_helper = new(settingsManager);
EmptyContent = new CommandItem()
{
Title = "Run commands",
Icon = Icons.RunV2,
};
var allAppsCommandItem = new ListItem(new NoOpCommand()
{
Name = "Open",
Icon = IconHelpers.FromRelativePath("Assets\\AllApps.svg"),
})
{
Title = "All apps",
Subtitle = "Search installed apps",
};
var calculatorCommandItem = new ListItem(new NoOpCommand()
{
Name = "Open",
Icon = IconHelpers.FromRelativePath("Assets\\Calculator.png"),
})
{
Title = "Calculator",
Subtitle = "Press = to type an equation",
};
// var fileSearchCommandItem = new ListItem(new NoOpCommand()
// {
// Name = "Open",
// Icon = IconHelpers.FromRelativePath("Assets\\FileExplorer.png"),
// })
// {
// Title = "Search files",
// Subtitle = "Search files on this device",
// };
_topLevelItems.Add(allAppsCommandItem);
_topLevelItems.Add(calculatorCommandItem);
// _topLevelItems.Add(fileSearchCommandItem);
}
public override void UpdateSearchText(string oldSearch, string newSearch)
{
// If the search text is the start of a path to a file (it might be a
// UNC path), then we want to list all the files that start with that text:
// 1. Check if the search text is a valid path
// 2. If it is, then list all the files that start with that text
var searchText = newSearch.Trim();
_historyItems = _helper.Query(searchText);
_historyItems.ForEach(i =>
{
i.Icon = Icons.RunV2;
i.Subtitle = string.Empty;
});
// TODO we can be smarter about only re-reading the filesystem if the
// new search is just the oldSearch+some chars
if (string.IsNullOrEmpty(searchText) || string.IsNullOrWhiteSpace(searchText))
{
_pathItems.Clear();
RaiseItemsChanged();
return;
}
var directoryPath = string.Empty;
var searchPattern = string.Empty;
// Check if the search text is a valid path
if (Path.IsPathRooted(searchText) && Path.GetDirectoryName(searchText) is string directoryName)
{
directoryPath = directoryName;
searchPattern = $"{Path.GetFileName(searchText)}*";
}
// we should also handle just drive roots, ala c:\ or d:\
else if (searchText.Length == 2 && searchText[1] == ':')
{
directoryPath = searchText + "\\";
searchPattern = $"*";
}
// Check if the search text is a valid UNC path
else if (searchText.StartsWith(@"\\", System.StringComparison.CurrentCultureIgnoreCase) && searchText.Contains(@"\\"))
{
directoryPath = searchText;
searchPattern = $"*";
}
// Check if the directory exists
if (Directory.Exists(directoryPath))
{
// Get all the files in the directory that start with the search text
var files = Directory.GetFileSystemEntries(directoryPath, searchPattern);
// Create a list of commands for each file
var commands = files.Select(PathToListItem).ToList();
// Add the commands to the list
_pathItems = commands;
}
else
{
_pathItems.Clear();
}
RaiseItemsChanged();
}
private ListItem PathToListItem(string path)
{
return new PathListItem(path);
}
public override IListItem[] GetItems()
{
return ListHelpers.FilterList(_topLevelItems, SearchText)
.Concat(_historyItems)
.Concat(_pathItems)
.ToArray();
}
}

View File

@@ -13,6 +13,7 @@ namespace Microsoft.CmdPal.Ext.Shell;
public partial class ShellCommandsProvider : CommandProvider
{
private readonly CommandItem _shellPageItem;
private readonly CommandItem _runMainPageItem;
private readonly SettingsManager _settingsManager = new();
private readonly FallbackCommandItem _fallbackItem;
@@ -34,9 +35,18 @@ public partial class ShellCommandsProvider : CommandProvider
new CommandContextItem(Settings.SettingsPage),
],
};
_runMainPageItem = new CommandItem(new RunMainPage(_settingsManager))
{
Icon = Icons.RunV2,
Title = "Run 2 electric boogaloo", // LOC!
Subtitle = Resources.cmd_plugin_description,
MoreCommands = [
new CommandContextItem(Settings.SettingsPage),
],
};
}
public override ICommandItem[] TopLevelCommands() => [_shellPageItem];
public override ICommandItem[] TopLevelCommands() => [_shellPageItem, _runMainPageItem];
public override IFallbackCommandItem[]? FallbackCommands() => [_fallbackItem];
}