mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-03 01:36:31 +02:00
CmdPal: Fallback ranking and global results (#43549)
> [!IMPORTANT] > For extension developers, this release includes a new required `string Id` property for `FallbackCommandItem`. While your existing extensions will continue to work, without this `Id` being set, your fallbacks will not display and will not be rankable. > Before this is released, you will want to prepare your extension fallbacks. > > As an example, we are naming our built-in extensions as: > - Calculator extension provider Id: `com.microsoft.cmdpal.builtin.calculator` > - Calculator extension fallback: `com.microsoft.cmdpal.builtin.calculator.fallback` > > While the content of the Id isn't important, what is important is that it is unique to your extension and fallback to avoid conflicting with other extensions. Now the good stuff: ## What the heck does it do!? ### The backstory In PowerToys 0.95, we released performance improvements to Command Palette. One of the many ways we improved its speed is by no longer ranking fallback commands with other "top level" commands. Instead, all fallbacks would surface at the bottom of the results and be listed in the order they were registered with Command Palette. But this was only a temporary solution until the work included in this pull request was ready. In reality, not all fallbacks were treated equally. We marked the calculator and run fallbacks as "special." Special fallbacks **were** ranked like top-level commands and allowed to surface to the top of the results. ### The new "hotness" This PR brings the power of fallback management back to the people. In the Command Palette settings, you, dear user, can specify what order you want fallbacks to display in at the bottom of the results. This keeps those fallbacks unranked by Command Palette but displays them in an order that makes sense for you. But keep in mind, these will still live at the bottom of search results. But alas, we have also heard your cries that you'd like _some_ fallbacks to be ranked by Command Palette and surface to the top of the results. So, this PR allows you to mark any fallback as "special" by choosing to include them in the global results. Special (Global) fallbacks are treated like "top level" commands and appear in the search result based on their title & description. ### Screenshots/video <img width="1005" height="611" alt="image" src="https://github.com/user-attachments/assets/8ba5d861-f887-47ed-8552-ba78937322d2" /> <img width="1501" height="973" alt="image" src="https://github.com/user-attachments/assets/9edb7675-8084-4f14-8bdc-72d7d06d500e" /> <img width="706" height="744" alt="image" src="https://github.com/user-attachments/assets/81ae0252-b87d-4172-a5ea-4d3102134baf" /> <img width="666" height="786" alt="image" src="https://github.com/user-attachments/assets/acb76acf-531d-4e60-bb44-d1edeec77dce" /> ### GitHub issue maintenance details Closes #38312 Closes #38288 Closes #42524 Closes #41024 Closes #40351 Closes #41696 Closes #40193 --------- Co-authored-by: Niels Laute <niels.laute@live.nl> Co-authored-by: Jiří Polášek <me@jiripolasek.com>
This commit is contained in:
@@ -10,11 +10,12 @@ namespace Microsoft.CmdPal.Ext.Calc.Pages;
|
||||
|
||||
public sealed partial class FallbackCalculatorItem : FallbackCommandItem
|
||||
{
|
||||
private const string _id = "com.microsoft.cmdpal.builtin.calculator.fallback";
|
||||
private readonly CopyTextCommand _copyCommand = new(string.Empty);
|
||||
private readonly ISettingsInterface _settings;
|
||||
|
||||
public FallbackCalculatorItem(ISettingsInterface settings)
|
||||
: base(new NoOpCommand(), Resources.calculator_title)
|
||||
: base(new NoOpCommand(), Resources.calculator_title, _id)
|
||||
{
|
||||
Command = _copyCommand;
|
||||
_copyCommand.Name = string.Empty;
|
||||
|
||||
@@ -16,7 +16,8 @@ namespace Microsoft.CmdPal.Ext.Indexer;
|
||||
|
||||
internal sealed partial class FallbackOpenFileItem : FallbackCommandItem, System.IDisposable
|
||||
{
|
||||
private static readonly NoOpCommand _baseCommandWithId = new() { Id = "com.microsoft.indexer.fallback" };
|
||||
private const string _id = "com.microsoft.cmdpal.builtin.indexer.fallback";
|
||||
private static readonly NoOpCommand _baseCommandWithId = new() { Id = _id };
|
||||
|
||||
private readonly CompositeFormat fallbackItemSearchPageTitleCompositeFormat = CompositeFormat.Parse(Resources.Indexer_fallback_searchPage_title);
|
||||
|
||||
@@ -27,7 +28,7 @@ internal sealed partial class FallbackOpenFileItem : FallbackCommandItem, System
|
||||
private Func<string, bool> _suppressCallback;
|
||||
|
||||
public FallbackOpenFileItem()
|
||||
: base(_baseCommandWithId, Resources.Indexer_Find_Path_fallback_display_title)
|
||||
: base(_baseCommandWithId, Resources.Indexer_Find_Path_fallback_display_title, _id)
|
||||
{
|
||||
Title = string.Empty;
|
||||
Subtitle = string.Empty;
|
||||
|
||||
@@ -28,7 +28,7 @@ internal sealed partial class FallbackRemoteDesktopItem : FallbackCommandItem
|
||||
private readonly NoOpCommand _emptyCommand = new NoOpCommand();
|
||||
|
||||
public FallbackRemoteDesktopItem(IRdpConnectionsManager rdpConnectionsManager)
|
||||
: base(Resources.remotedesktop_title)
|
||||
: base(Resources.remotedesktop_title, _id)
|
||||
{
|
||||
_rdpConnectionsManager = rdpConnectionsManager;
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace Microsoft.CmdPal.Ext.Shell;
|
||||
|
||||
internal sealed partial class FallbackExecuteItem : FallbackCommandItem, IDisposable
|
||||
{
|
||||
private const string _id = "com.microsoft.cmdpal.builtin.shell.fallback";
|
||||
private static readonly char[] _systemDirectoryRoots = ['\\', '/'];
|
||||
|
||||
private readonly Action<string>? _addToHistory;
|
||||
@@ -19,8 +20,9 @@ internal sealed partial class FallbackExecuteItem : FallbackCommandItem, IDispos
|
||||
|
||||
public FallbackExecuteItem(SettingsManager settings, Action<string>? addToHistory, ITelemetryService telemetryService)
|
||||
: base(
|
||||
new NoOpCommand() { Id = "com.microsoft.run.fallback" },
|
||||
ResourceLoaderInstance.GetString("shell_command_display_title"))
|
||||
new NoOpCommand() { Id = _id },
|
||||
ResourceLoaderInstance.GetString("shell_command_display_title"),
|
||||
_id)
|
||||
{
|
||||
Title = string.Empty;
|
||||
Subtitle = ResourceLoaderInstance.GetString("generic_run_command");
|
||||
|
||||
@@ -12,8 +12,10 @@ namespace Microsoft.CmdPal.Ext.System;
|
||||
|
||||
internal sealed partial class FallbackSystemCommandItem : FallbackCommandItem
|
||||
{
|
||||
private const string _id = "com.microsoft.cmdpal.builtin.system.fallback";
|
||||
|
||||
public FallbackSystemCommandItem(ISettingsInterface settings)
|
||||
: base(new NoOpCommand(), Resources.Microsoft_plugin_ext_fallback_display_title)
|
||||
: base(new NoOpCommand(), Resources.Microsoft_plugin_ext_fallback_display_title, _id)
|
||||
{
|
||||
Title = string.Empty;
|
||||
Subtitle = string.Empty;
|
||||
|
||||
@@ -13,12 +13,13 @@ namespace Microsoft.CmdPal.Ext.TimeDate;
|
||||
|
||||
internal sealed partial class FallbackTimeDateItem : FallbackCommandItem
|
||||
{
|
||||
private const string _id = "com.microsoft.cmdpal.builtin.timedate.fallback";
|
||||
private readonly HashSet<string> _validOptions;
|
||||
private ISettingsInterface _settingsManager;
|
||||
private DateTime? _timestamp;
|
||||
|
||||
public FallbackTimeDateItem(ISettingsInterface settings, DateTime? timestamp = null)
|
||||
: base(new NoOpCommand(), Resources.Microsoft_plugin_timedate_fallback_display_title)
|
||||
: base(new NoOpCommand(), Resources.Microsoft_plugin_timedate_fallback_display_title, _id)
|
||||
{
|
||||
Title = string.Empty;
|
||||
Subtitle = string.Empty;
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Microsoft.CmdPal.Ext.WebSearch.Commands;
|
||||
|
||||
internal sealed partial class FallbackExecuteSearchItem : FallbackCommandItem
|
||||
{
|
||||
private const string _id = "com.microsoft.cmdpal.builtin.websearch.execute.fallback";
|
||||
private readonly SearchWebCommand _executeItem;
|
||||
private static readonly CompositeFormat PluginOpen = System.Text.CompositeFormat.Parse(Properties.Resources.plugin_open);
|
||||
private static readonly CompositeFormat SubtitleText = System.Text.CompositeFormat.Parse(Properties.Resources.web_search_fallback_subtitle);
|
||||
@@ -20,7 +21,7 @@ internal sealed partial class FallbackExecuteSearchItem : FallbackCommandItem
|
||||
private readonly IBrowserInfoService _browserInfoService;
|
||||
|
||||
public FallbackExecuteSearchItem(ISettingsInterface settings, IBrowserInfoService browserInfoService)
|
||||
: base(new SearchWebCommand(string.Empty, settings, browserInfoService) { Id = "com.microsoft.websearch.fallback" }, Resources.command_item_title)
|
||||
: base(new SearchWebCommand(string.Empty, settings, browserInfoService) { Id = _id }, Resources.command_item_title, _id)
|
||||
{
|
||||
_executeItem = (SearchWebCommand)Command!;
|
||||
_browserInfoService = browserInfoService;
|
||||
|
||||
@@ -15,13 +15,14 @@ namespace Microsoft.CmdPal.Ext.WebSearch;
|
||||
|
||||
internal sealed partial class FallbackOpenURLItem : FallbackCommandItem
|
||||
{
|
||||
private const string _id = "com.microsoft.cmdpal.builtin.websearch.openurl.fallback";
|
||||
private readonly IBrowserInfoService _browserInfoService;
|
||||
private readonly OpenURLCommand _executeItem;
|
||||
private static readonly CompositeFormat PluginOpenURL = System.Text.CompositeFormat.Parse(Properties.Resources.plugin_open_url);
|
||||
private static readonly CompositeFormat PluginOpenUrlInBrowser = System.Text.CompositeFormat.Parse(Properties.Resources.plugin_open_url_in_browser);
|
||||
|
||||
public FallbackOpenURLItem(ISettingsInterface settings, IBrowserInfoService browserInfoService)
|
||||
: base(new OpenURLCommand(string.Empty, browserInfoService), Resources.open_url_fallback_title)
|
||||
: base(new OpenURLCommand(string.Empty, browserInfoService), Resources.open_url_fallback_title, _id)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(browserInfoService);
|
||||
|
||||
|
||||
@@ -2,11 +2,8 @@
|
||||
// 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.Globalization;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.CmdPal.Ext.WindowsSettings.Classes;
|
||||
using Microsoft.CmdPal.Ext.WindowsSettings.Commands;
|
||||
using Microsoft.CmdPal.Ext.WindowsSettings.Helpers;
|
||||
using Microsoft.CmdPal.Ext.WindowsSettings.Properties;
|
||||
@@ -16,13 +13,15 @@ namespace Microsoft.CmdPal.Ext.WindowsSettings.Pages;
|
||||
|
||||
internal sealed partial class FallbackWindowsSettingsItem : FallbackCommandItem
|
||||
{
|
||||
private const string _id = "com.microsoft.cmdpal.builtin.windows.settings.fallback";
|
||||
|
||||
private readonly Classes.WindowsSettings _windowsSettings;
|
||||
|
||||
private readonly string _title = Resources.settings_fallback_title;
|
||||
private readonly string _subtitle = Resources.settings_fallback_subtitle;
|
||||
|
||||
public FallbackWindowsSettingsItem(Classes.WindowsSettings windowsSettings)
|
||||
: base(new NoOpCommand(), Resources.settings_title)
|
||||
: base(new NoOpCommand(), Resources.settings_title, _id)
|
||||
{
|
||||
Icon = Icons.WindowsSettingsIcon;
|
||||
_windowsSettings = windowsSettings;
|
||||
|
||||
Reference in New Issue
Block a user