mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-03 17:56:44 +02:00
_targets #45572_ This change allows our contact menu factory to actually create and add additional context menu commands for pinning commands to the top level. Now for any command provider built with the latest SDK that return subcommands with an ID, we will add additional context menu commands that allows you to pin that command to the top level. <img width="540" height="181" alt="image" src="https://github.com/user-attachments/assets/6c2cfe3c-4143-44d1-9308-bfc71db4c842" /> <img width="729" height="317" alt="image" src="https://github.com/user-attachments/assets/4ff75c9f-1f35-4c1e-a03e-6fab5cbab423" /> related to https://github.com/microsoft/PowerToys/issues/45191 related to https://github.com/microsoft/PowerToys/issues/45201 This PR notably does not remove pinning from the apps extension. I thought that made sense to do as a follow-up PR for the sake of reviewability. --- description from #45676 which was merged into this Removes the code that the apps provider was using to support pinning apps to the top level list of commands. Now the all apps provider just uses the global support for pinning commands to the top level. This does have the side effect of removing the separation of pinned apps from unpinned apps on the All Apps page. However, we all pretty much agree that wasn't a particularly widely used feature, and it's safe to remove. With this, we can finally call this issue done 🎉 closes https://github.com/microsoft/PowerToys/issues/45191
171 lines
4.8 KiB
C#
171 lines
4.8 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 System.Collections.ObjectModel;
|
|
using System.Diagnostics;
|
|
using Microsoft.CmdPal.Common;
|
|
using Microsoft.CommandPalette.Extensions;
|
|
using Microsoft.CommandPalette.Extensions.Toolkit;
|
|
using Windows.Foundation;
|
|
|
|
namespace Microsoft.CmdPal.UI.ViewModels;
|
|
|
|
public abstract partial class AppExtensionHost : IExtensionHost
|
|
{
|
|
private static readonly GlobalLogPageContext _globalLogPageContext = new();
|
|
|
|
private static ulong _hostingHwnd;
|
|
|
|
public static ObservableCollection<LogMessageViewModel> LogMessages { get; } = [];
|
|
|
|
public ulong HostingHwnd => _hostingHwnd;
|
|
|
|
public string LanguageOverride => string.Empty;
|
|
|
|
public ObservableCollection<StatusMessageViewModel> StatusMessages { get; } = [];
|
|
|
|
public static void SetHostHwnd(ulong hostHwnd) => _hostingHwnd = hostHwnd;
|
|
|
|
public void DebugLog(string message)
|
|
{
|
|
#if DEBUG
|
|
this.ProcessLogMessage(new LogMessage(message));
|
|
#endif
|
|
}
|
|
|
|
public IAsyncAction HideStatus(IStatusMessage? message)
|
|
{
|
|
if (message is null)
|
|
{
|
|
return Task.CompletedTask.AsAsyncAction();
|
|
}
|
|
|
|
_ = Task.Run(() =>
|
|
{
|
|
ProcessHideStatusMessage(message);
|
|
});
|
|
return Task.CompletedTask.AsAsyncAction();
|
|
}
|
|
|
|
public void Log(string message)
|
|
{
|
|
this.ProcessLogMessage(new LogMessage(message));
|
|
}
|
|
|
|
public IAsyncAction LogMessage(ILogMessage? message)
|
|
{
|
|
if (message is null)
|
|
{
|
|
return Task.CompletedTask.AsAsyncAction();
|
|
}
|
|
|
|
CoreLogger.LogDebug(message.Message);
|
|
|
|
_ = Task.Run(() =>
|
|
{
|
|
ProcessLogMessage(message);
|
|
});
|
|
|
|
// We can't just make a LogMessageViewModel : ExtensionObjectViewModel
|
|
// because we don't necessarily know the page context. Butts.
|
|
return Task.CompletedTask.AsAsyncAction();
|
|
}
|
|
|
|
public void ProcessHideStatusMessage(IStatusMessage message)
|
|
{
|
|
Task.Factory.StartNew(
|
|
() =>
|
|
{
|
|
try
|
|
{
|
|
var vm = StatusMessages.Where(messageVM => messageVM.Model.Unsafe == message).FirstOrDefault();
|
|
if (vm is not null)
|
|
{
|
|
StatusMessages.Remove(vm);
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
},
|
|
CancellationToken.None,
|
|
TaskCreationOptions.None,
|
|
_globalLogPageContext.Scheduler);
|
|
}
|
|
|
|
public void ProcessLogMessage(ILogMessage message)
|
|
{
|
|
var vm = new LogMessageViewModel(message, _globalLogPageContext);
|
|
vm.SafeInitializePropertiesSynchronous();
|
|
|
|
Task.Factory.StartNew(
|
|
() =>
|
|
{
|
|
LogMessages.Add(vm);
|
|
},
|
|
CancellationToken.None,
|
|
TaskCreationOptions.None,
|
|
_globalLogPageContext.Scheduler);
|
|
}
|
|
|
|
public void ProcessStatusMessage(IStatusMessage message, StatusContext context)
|
|
{
|
|
// If this message is already in the list of messages, just bring it to the top
|
|
var oldVm = StatusMessages.Where(messageVM => messageVM.Model.Unsafe == message).FirstOrDefault();
|
|
if (oldVm is not null)
|
|
{
|
|
Task.Factory.StartNew(
|
|
() =>
|
|
{
|
|
StatusMessages.Remove(oldVm);
|
|
StatusMessages.Add(oldVm);
|
|
},
|
|
CancellationToken.None,
|
|
TaskCreationOptions.None,
|
|
_globalLogPageContext.Scheduler);
|
|
return;
|
|
}
|
|
|
|
var vm = new StatusMessageViewModel(message, new(_globalLogPageContext));
|
|
vm.SafeInitializePropertiesSynchronous();
|
|
|
|
Task.Factory.StartNew(
|
|
() =>
|
|
{
|
|
StatusMessages.Add(vm);
|
|
},
|
|
CancellationToken.None,
|
|
TaskCreationOptions.None,
|
|
_globalLogPageContext.Scheduler);
|
|
}
|
|
|
|
public IAsyncAction ShowStatus(IStatusMessage? message, StatusContext context)
|
|
{
|
|
if (message is null)
|
|
{
|
|
return Task.CompletedTask.AsAsyncAction();
|
|
}
|
|
|
|
Debug.WriteLine(message.Message);
|
|
|
|
_ = Task.Run(() =>
|
|
{
|
|
ProcessStatusMessage(message, context);
|
|
});
|
|
|
|
return Task.CompletedTask.AsAsyncAction();
|
|
}
|
|
|
|
public abstract string? GetExtensionDisplayName();
|
|
}
|
|
|
|
public interface IAppHostService
|
|
{
|
|
AppExtensionHost GetDefaultHost();
|
|
|
|
AppExtensionHost GetHostForCommand(object? context, AppExtensionHost? currentHost);
|
|
|
|
ICommandProviderContext GetProviderContextForCommand(object? command, ICommandProviderContext? currentContext);
|
|
}
|