Files
PowerToys/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/CommandProvider.cs
Mike Griese 0f87b61dad CmdPal: Load pinned command items from anywhere (#45566)
This doesn't actually have a UX to expose this yet - we need to stack a
couple of PRs up to get to that.

But this adds plumbing such that we can now stash away a command ID, and
retrieve it later as a top-level command. Kinda like pinning for apps,
but for _anything_.

It works off of a new command provider interface `ICommandProvider4`,
which lets us look up Command**Item**s by ID. If we see a command ID
stored in that command provider's settings, we will try to look it up,
and then load it from the command provider.

e.g.

```json
    "com.microsoft.cmdpal.builtin.system": {
      "IsEnabled": true,
      "FallbackCommands": {
        "com.microsoft.cmdpal.builtin.system.fallback": {
          "IsEnabled": true,
          "IncludeInGlobalResults": true
        }
      },
      "PinnedCommandIds": [
        "com.microsoft.cmdpal.builtin.system.lock",
        "com.microsoft.cmdpal.builtin.system.restart_shell"
      ]
    },
```
will get us
<img width="840" height="197" alt="image"
src="https://github.com/user-attachments/assets/9ed19003-8361-4318-8dc9-055414456a51"
/>

Then it's just a matter of plumbing the command provider ID through the
layers, so that the command item knows who it is from. We'll need that
later for actually wiring this to the command's context menu.

related to #45191 
related to #45201
2026-02-19 16:20:05 -06:00

94 lines
3.2 KiB
C#

// 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 Windows.Foundation;
namespace Microsoft.CommandPalette.Extensions.Toolkit;
public abstract partial class CommandProvider :
ICommandProvider,
ICommandProvider2,
ICommandProvider3,
ICommandProvider4
{
public virtual string Id { get; protected set; } = string.Empty;
public virtual string DisplayName { get; protected set; } = string.Empty;
public virtual IconInfo Icon { get; protected set; } = new IconInfo();
public event TypedEventHandler<object, IItemsChangedEventArgs>? ItemsChanged;
public abstract ICommandItem[] TopLevelCommands();
public virtual IFallbackCommandItem[]? FallbackCommands() => null;
public virtual ICommand? GetCommand(string id) => null;
public virtual ICommandItem? GetCommandItem(string id) => null;
public virtual ICommandSettings? Settings { get; protected set; }
public virtual bool Frozen { get; protected set; } = true;
IIconInfo ICommandProvider.Icon => Icon;
public virtual void InitializeWithHost(IExtensionHost host) => ExtensionHost.Initialize(host);
#pragma warning disable CA1816 // Dispose methods should call SuppressFinalize
public virtual void Dispose()
{
}
#pragma warning restore CA1816 // Dispose methods should call SuppressFinalize
protected void RaiseItemsChanged(int totalItems = -1)
{
try
{
// TODO #181 - This is the same thing that BaseObservable has to deal with.
ItemsChanged?.Invoke(this, new ItemsChangedEventArgs(totalItems));
}
catch
{
}
}
/// <summary>
/// Get the dock bands provided by this command provider. Dock bands are
/// strips of items that appear on various UI surfaces in CmdPal, such as a
/// toolbar. Each ICommandItem returned from this method will be treated as
/// one atomic band by cmdpal.
///
/// If the command on an item here is a
/// IListPage, then cmdpal will render all of the items on that page as one
/// band. You can use this to create complex bands with multiple buttons.
/// </summary>
public virtual ICommandItem[]? GetDockBands()
{
return null;
}
/// <summary>
/// This is used to manually populate the WinRT type cache in CmdPal with
/// any interfaces that might not follow a straight linear path of requires.
///
/// You don't need to call this as an extension author.
/// </summary>
/// <returns>an array of objects that implement all the leaf interfaces we support</returns>
public object[] GetApiExtensionStubs()
{
return [new SupportCommandsWithProperties()];
}
/// <summary>
/// A stub class which implements IExtendedAttributesProvider. Just marshalling this
/// across the ABI will be enough for CmdPal to store IExtendedAttributesProvider in
/// its type cache.
/// </summary>
private sealed partial class SupportCommandsWithProperties : IExtendedAttributesProvider
{
public IDictionary<string, object>? GetProperties() => null;
}
}