Skip to content

Commit

Permalink
The top-level reloads on install, but doesn't work on manual reload
Browse files Browse the repository at this point in the history
  • Loading branch information
zadjii committed Jan 27, 2025
1 parent 899c233 commit bbc23b4
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Windows.Foundation;

namespace Microsoft.CmdPal.Common.Services;

Expand All @@ -21,6 +22,8 @@ public interface IExtensionService

public event EventHandler OnExtensionsChanged;

public event TypedEventHandler<IExtensionService, IEnumerable<IExtensionWrapper>>? OnExtensionAdded;

public void EnableExtension(string extensionUniqueId);

public void DisableExtension(string extensionUniqueId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Microsoft.CmdPal.Extensions;
using Windows.ApplicationModel;
using Windows.ApplicationModel.AppExtensions;
using Windows.Foundation;
using Windows.Foundation.Collections;

namespace Microsoft.CmdPal.UI.ViewModels.Models;
Expand All @@ -14,6 +15,8 @@ public class ExtensionService : IExtensionService, IDisposable
{
public event EventHandler OnExtensionsChanged = (_, _) => { };

public event TypedEventHandler<IExtensionService, IEnumerable<IExtensionWrapper>>? OnExtensionAdded;

private static readonly PackageCatalog _catalog = PackageCatalog.OpenForCurrentUser();
private static readonly Lock _lock = new();
private readonly SemaphoreSlim _getInstalledExtensionsLock = new(1, 1);
Expand Down Expand Up @@ -47,15 +50,38 @@ private void Catalog_PackageInstalling(PackageCatalog sender, PackageInstallingE
{
lock (_lock)
{
var isCmdPalExtension = Task.Run(() =>
var isCmdPalExtensionResult = Task.Run(() =>
{
return IsValidCmdPalExtension(args.Package);
}).Result;

if (isCmdPalExtension)
var isExtension = isCmdPalExtensionResult.IsExtension;
var extension = isCmdPalExtensionResult.Extension;
if (isExtension && extension != null)
{
Task.Run(async () =>
{
await _getInstalledExtensionsLock.WaitAsync();
try
{
var wrappers = await CreateWrappersForExtension(extension);

UpdateExtensionsListsFromWrappers(wrappers);

OnExtensionAdded?.Invoke(this, wrappers);
}
finally
{
_getInstalledExtensionsLock.Release();
}
});

OnPackageChange(args.Package);
}

// if (isCmdPalExtension)
// {
// OnPackageChange(args.Package);
// }
}
}
}
Expand Down Expand Up @@ -84,12 +110,13 @@ private void Catalog_PackageUpdating(PackageCatalog sender, PackageUpdatingEvent
{
lock (_lock)
{
var isCmdPalExtension = Task.Run(() =>
var isCmdPalExtensionResult = Task.Run(() =>
{
return IsValidCmdPalExtension(args.TargetPackage);
}).Result;

if (isCmdPalExtension)
var isExtension = isCmdPalExtensionResult.IsExtension;
if (isExtension)
{
OnPackageChange(args.TargetPackage);
}
Expand All @@ -104,7 +131,7 @@ private void OnPackageChange(Package package)
OnExtensionsChanged.Invoke(this, EventArgs.Empty);
}

private static async Task<bool> IsValidCmdPalExtension(Package package)
private static async Task<IsExtensionResult> IsValidCmdPalExtension(Package package)
{
var extensions = await AppExtensionCatalog.Open("com.microsoft.windows.commandpalette").FindAllAsync();
foreach (var extension in extensions)
Expand All @@ -113,11 +140,11 @@ private static async Task<bool> IsValidCmdPalExtension(Package package)
{
var (cmdPalProvider, classId) = await GetCmdPalExtensionPropertiesAsync(extension);

return cmdPalProvider != null && classId.Count != 0;
return new(cmdPalProvider != null && classId.Count != 0, extension);
}
}

return false;
return new(false, null);
}

private static async Task<(IPropertySet? CmdPalProvider, List<string> ClassIds)> GetCmdPalExtensionPropertiesAsync(AppExtension extension)
Expand Down Expand Up @@ -160,59 +187,82 @@ public async Task<IEnumerable<IExtensionWrapper>> GetInstalledExtensionsAsync(bo
var extensions = await GetInstalledAppExtensionsAsync();
foreach (var extension in extensions)
{
var (cmdPalProvider, classIds) = await GetCmdPalExtensionPropertiesAsync(extension);
var wrappers = await CreateWrappersForExtension(extension);
UpdateExtensionsListsFromWrappers(wrappers);
}
}

if (cmdPalProvider == null || classIds.Count == 0)
{
continue;
}
return includeDisabledExtensions ? _installedExtensions : _enabledExtensions;
}
finally
{
_getInstalledExtensionsLock.Release();
}
}

foreach (var classId in classIds)
{
var extensionWrapper = new ExtensionWrapper(extension, classId);
private static void UpdateExtensionsListsFromWrappers(List<ExtensionWrapper> wrappers)
{
foreach (var extensionWrapper in wrappers)
{
// var localSettingsService = Application.Current.GetService<ILocalSettingsService>();
var extensionUniqueId = extensionWrapper.ExtensionUniqueId;
var isExtensionDisabled = false; // await localSettingsService.ReadSettingAsync<bool>(extensionUniqueId + "-ExtensionDisabled");

var supportedInterfaces = GetSubPropertySet(cmdPalProvider, "SupportedInterfaces");
if (supportedInterfaces is not null)
{
foreach (var supportedInterface in supportedInterfaces)
{
ProviderType pt;
if (Enum.TryParse(supportedInterface.Key, out pt))
{
extensionWrapper.AddProviderType(pt);
}
else
{
// TODO: throw warning or fire notification that extension declared unsupported extension interface
// https://github.com/microsoft/DevHome/issues/617
}
}
}
_installedExtensions.Add(extensionWrapper);
if (!isExtensionDisabled)
{
_enabledExtensions.Add(extensionWrapper);
}

// var localSettingsService = Application.Current.GetService<ILocalSettingsService>();
var extensionUniqueId = extension.AppInfo.AppUserModelId + "!" + extension.Id;
var isExtensionDisabled = false; // await localSettingsService.ReadSettingAsync<bool>(extensionUniqueId + "-ExtensionDisabled");
// TelemetryFactory.Get<ITelemetry>().Log(
// "Extension_ReportInstalled",
// LogLevel.Critical,
// new ReportInstalledExtensionEvent(extensionUniqueId, isEnabled: !isExtensionDisabled));
}
}

_installedExtensions.Add(extensionWrapper);
if (!isExtensionDisabled)
{
_enabledExtensions.Add(extensionWrapper);
}
private static async Task<List<ExtensionWrapper>> CreateWrappersForExtension(AppExtension extension)
{
var (cmdPalProvider, classIds) = await GetCmdPalExtensionPropertiesAsync(extension);

// TelemetryFactory.Get<ITelemetry>().Log(
// "Extension_ReportInstalled",
// LogLevel.Critical,
// new ReportInstalledExtensionEvent(extensionUniqueId, isEnabled: !isExtensionDisabled));
}
}
}
if (cmdPalProvider == null || classIds.Count == 0)
{
return [];
}

return includeDisabledExtensions ? _installedExtensions : _enabledExtensions;
List<ExtensionWrapper> wrappers = [];
foreach (var classId in classIds)
{
var extensionWrapper = CreateExtensionWrapper(extension, cmdPalProvider, classId);
wrappers.Add(extensionWrapper);
}
finally

return wrappers;
}

private static ExtensionWrapper CreateExtensionWrapper(AppExtension extension, IPropertySet cmdPalProvider, string classId)
{
var extensionWrapper = new ExtensionWrapper(extension, classId);

var supportedInterfaces = GetSubPropertySet(cmdPalProvider, "SupportedInterfaces");
if (supportedInterfaces is not null)
{
_getInstalledExtensionsLock.Release();
foreach (var supportedInterface in supportedInterfaces)
{
ProviderType pt;
if (Enum.TryParse(supportedInterface.Key, out pt))
{
extensionWrapper.AddProviderType(pt);
}
else
{
// TODO: throw warning or fire notification that extension declared unsupported extension interface
// https://github.com/microsoft/DevHome/issues/617
}
}
}

return extensionWrapper;
}

public IExtensionWrapper? GetInstalledExtension(string extensionUniqueId)
Expand Down Expand Up @@ -348,3 +398,7 @@ public void DisableExtension(string extensionUniqueId)
// return true;
//} */
}

internal record struct IsExtensionResult(bool IsExtension, AppExtension? Extension)
{
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ public class ExtensionWrapper : IExtensionWrapper
{
private const int HResultRpcServerNotRunning = -2147023174;

private readonly string _appUserModelId;
private readonly string _extensionId;

private readonly Lock _lock = new();
private readonly List<ProviderType> _providerTypes = [];

Expand All @@ -37,7 +40,8 @@ public ExtensionWrapper(AppExtension appExtension, string classId)
Publisher = appExtension.Package.PublisherDisplayName;
InstalledDate = appExtension.Package.InstalledDate;
Version = appExtension.Package.Id.Version;
ExtensionUniqueId = appExtension.AppInfo.AppUserModelId + "!" + appExtension.Id;
_appUserModelId = appExtension.AppInfo.AppUserModelId;
_extensionId = appExtension.Id;
}

public string PackageDisplayName { get; }
Expand Down Expand Up @@ -65,7 +69,7 @@ public ExtensionWrapper(AppExtension appExtension, string classId)
/// <item>The Extension Id. This is the unique identifier of the extension within the application.</item>
/// </list>
/// </summary>
public string ExtensionUniqueId { get; }
public string ExtensionUniqueId => _appUserModelId + "!" + _extensionId;

public bool IsRunning()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,11 +207,34 @@ public async Task<bool> LoadExtensionsAsync()
}
}

extensionService.OnExtensionAdded += ExtensionService_OnExtensionAddedAsync;

IsLoading = false;

return true;
}

private void ExtensionService_OnExtensionAddedAsync(IExtensionService sender, IEnumerable<IExtensionWrapper> extensions)
{
_ = Task.Run(async () =>
{
foreach (var extension in extensions)
{
try
{
await extension.StartExtensionAsync();
CommandProviderWrapper wrapper = new(extension);
_extensionCommandProviders.Add(wrapper);
await LoadTopLevelCommandsFromProvider(wrapper);
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
}
});
}

public TopLevelCommandItemWrapper? LookupCommand(string id)
{
foreach (var command in TopLevelCommands)
Expand Down

0 comments on commit bbc23b4

Please sign in to comment.