mirror of
https://github.com/microsoft/PowerToys
synced 2025-09-01 15:05:12 +00:00
CmdPal: Fix SUI crash ; Allow extensions to be disabled (#38040)
Both `TopLevelCommandItemWrapper` and `TopLevelViewModel` were really the same thing. The latter was from an earlier prototype, and the former is a more correct, safer abstraction. We really should have only ever used the former, but alas, we only used it for the SUI, and it piggy-backed off the latter, and that meant the latter's bugs became the former's. tldr: I made the icon access safe in the SUI. And while I was doing this, because we now have a cleaner VM abstraction here in the host, we can actually cleanly disable extensions, because the `CommandProviderWrapper` knows which `ViewModel`s it made. Closes https://github.com/zadjii-msft/PowerToys/issues/426 Closes https://github.com/zadjii-msft/PowerToys/issues/478 Closes https://github.com/zadjii-msft/PowerToys/issues/577
This commit is contained in:
@@ -6,6 +6,8 @@ using ManagedCommon;
|
||||
using Microsoft.CmdPal.Common.Services;
|
||||
using Microsoft.CmdPal.UI.ViewModels.Models;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
using Windows.Foundation;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.ViewModels;
|
||||
@@ -20,9 +22,9 @@ public sealed class CommandProviderWrapper
|
||||
|
||||
private readonly TaskScheduler _taskScheduler;
|
||||
|
||||
public ICommandItem[] TopLevelItems { get; private set; } = [];
|
||||
public TopLevelViewModel[] TopLevelItems { get; private set; } = [];
|
||||
|
||||
public IFallbackCommandItem[] FallbackItems { get; private set; } = [];
|
||||
public TopLevelViewModel[] FallbackItems { get; private set; } = [];
|
||||
|
||||
public string DisplayName { get; private set; } = string.Empty;
|
||||
|
||||
@@ -38,7 +40,13 @@ public sealed class CommandProviderWrapper
|
||||
|
||||
public CommandSettingsViewModel? Settings { get; private set; }
|
||||
|
||||
public string ProviderId => $"{Extension?.PackageFamilyName ?? string.Empty}/{Id}";
|
||||
public string ProviderId
|
||||
{
|
||||
get
|
||||
{
|
||||
return string.IsNullOrEmpty(Extension?.ExtensionUniqueId) ? Id : Extension.ExtensionUniqueId;
|
||||
}
|
||||
}
|
||||
|
||||
public CommandProviderWrapper(ICommandProvider provider, TaskScheduler mainThread)
|
||||
{
|
||||
@@ -105,13 +113,25 @@ public sealed class CommandProviderWrapper
|
||||
isValid = true;
|
||||
}
|
||||
|
||||
public async Task LoadTopLevelCommands()
|
||||
private ProviderSettings GetProviderSettings(SettingsModel settings)
|
||||
{
|
||||
return settings.GetProviderSettings(this);
|
||||
}
|
||||
|
||||
public async Task LoadTopLevelCommands(IServiceProvider serviceProvider, WeakReference<IPageContext> pageContext)
|
||||
{
|
||||
if (!isValid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var settings = serviceProvider.GetService<SettingsModel>()!;
|
||||
|
||||
if (!GetProviderSettings(settings).IsEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ICommandItem[]? commands = null;
|
||||
IFallbackCommandItem[]? fallbacks = null;
|
||||
|
||||
@@ -119,7 +139,7 @@ public sealed class CommandProviderWrapper
|
||||
{
|
||||
var model = _commandProvider.Unsafe!;
|
||||
|
||||
var t = new Task<ICommandItem[]>(model.TopLevelCommands);
|
||||
Task<ICommandItem[]> t = new(model.TopLevelCommands);
|
||||
t.Start();
|
||||
commands = await t.ConfigureAwait(false);
|
||||
|
||||
@@ -134,6 +154,8 @@ public sealed class CommandProviderWrapper
|
||||
Settings = new(model.Settings, this, _taskScheduler);
|
||||
Settings.InitializeProperties();
|
||||
|
||||
InitializeCommands(commands, fallbacks, serviceProvider, pageContext);
|
||||
|
||||
Logger.LogDebug($"Loaded commands from {DisplayName} ({ProviderId})");
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -142,15 +164,33 @@ public sealed class CommandProviderWrapper
|
||||
Logger.LogError($"Extension was {Extension!.PackageFamilyName}");
|
||||
Logger.LogError(e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeCommands(ICommandItem[] commands, IFallbackCommandItem[] fallbacks, IServiceProvider serviceProvider, WeakReference<IPageContext> pageContext)
|
||||
{
|
||||
var settings = serviceProvider.GetService<SettingsModel>()!;
|
||||
|
||||
Func<ICommandItem?, bool, TopLevelViewModel> makeAndAdd = (ICommandItem? i, bool fallback) =>
|
||||
{
|
||||
CommandItemViewModel commandItemViewModel = new(new(i), pageContext);
|
||||
TopLevelViewModel topLevelViewModel = new(commandItemViewModel, fallback, ExtensionHost, ProviderId, settings, serviceProvider);
|
||||
|
||||
topLevelViewModel.ItemViewModel.SlowInitializeProperties();
|
||||
|
||||
return topLevelViewModel;
|
||||
};
|
||||
if (commands != null)
|
||||
{
|
||||
TopLevelItems = commands;
|
||||
TopLevelItems = commands
|
||||
.Select(c => makeAndAdd(c, false))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
if (fallbacks != null)
|
||||
{
|
||||
FallbackItems = fallbacks;
|
||||
FallbackItems = fallbacks
|
||||
.Select(c => makeAndAdd(c, true))
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user