CmdPal: Tidy up some winget experiences (#38174)

I'm filing this so that I don't lose it on this machine I use less often. We can probably hold it out of 0.90


Fixes:
* If a package is installed, we always display the version as "Unknown"
  * also deals with a case where getting the package metadata could fail, and we'd hide the list item. That's only possible in the "installed, no updates available" case
* Allow package updates, add an icon for updates
* moves off the preview winget API onto a higher stable version
This commit is contained in:
Mike Griese 2025-04-23 06:45:34 -05:00 committed by GitHub
parent f085ba0cd2
commit b0e7473760
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 76 additions and 18 deletions

View File

@ -45,7 +45,7 @@
<PackageVersion Include="Microsoft.Web.WebView2" Version="1.0.2903.40" />
<!-- Package Microsoft.Win32.SystemEvents added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Drawing.Common but the 8.0.1 version wasn't published to nuget. -->
<PackageVersion Include="Microsoft.Win32.SystemEvents" Version="9.0.4" />
<PackageVersion Include="Microsoft.WindowsPackageManager.ComInterop" Version="1.10.120-preview" />
<PackageVersion Include="Microsoft.WindowsPackageManager.ComInterop" Version="1.10.340" />
<PackageVersion Include="Microsoft.Windows.Compatibility" Version="9.0.4" />
<PackageVersion Include="Microsoft.Windows.CsWin32" Version="0.2.46-beta" />
<!-- CsWinRT version needs to be set to have a WinRT.Runtime.dll at the same version contained inside the NET SDK we're currently building on CI. -->

View File

@ -1473,7 +1473,7 @@ SOFTWARE.
- Microsoft.Windows.CsWinRT 2.2.0
- Microsoft.Windows.SDK.BuildTools 10.0.22621.2428
- Microsoft.WindowsAppSDK 1.6.250205002
- Microsoft.WindowsPackageManager.ComInterop 1.10.120-preview
- Microsoft.WindowsPackageManager.ComInterop 1.10.340
- Microsoft.Xaml.Behaviors.WinUI.Managed 2.0.9
- Microsoft.Xaml.Behaviors.Wpf 1.1.39
- ModernWpfUI 0.9.4

View File

@ -22,10 +22,12 @@ public partial class InstallPackageCommand : InvokableCommand
private IAsyncOperationWithProgress<UninstallResult, UninstallProgress>? _unInstallAction;
private Task? _installTask;
public bool IsInstalled { get; private set; }
public PackageInstallCommandState InstallCommandState { get; private set; }
public static IconInfo CompletedIcon { get; } = new("\uE930"); // Completed
public static IconInfo UpdateIcon { get; } = new("\uE74A"); // Up
public static IconInfo DownloadIcon { get; } = new("\uE896"); // Download
public static IconInfo DeleteIcon { get; } = new("\uE74D"); // Delete
@ -44,23 +46,41 @@ public partial class InstallPackageCommand : InvokableCommand
internal bool SkipDependencies { get; set; }
public InstallPackageCommand(CatalogPackage package, bool isInstalled)
public InstallPackageCommand(CatalogPackage package, PackageInstallCommandState isInstalled)
{
_package = package;
IsInstalled = isInstalled;
InstallCommandState = isInstalled;
UpdateAppearance();
}
internal void FakeChangeStatus()
{
IsInstalled = !IsInstalled;
InstallCommandState = InstallCommandState switch
{
PackageInstallCommandState.Install => PackageInstallCommandState.Uninstall,
PackageInstallCommandState.Update => PackageInstallCommandState.Uninstall,
PackageInstallCommandState.Uninstall => PackageInstallCommandState.Install,
_ => throw new NotImplementedException(),
};
UpdateAppearance();
}
private void UpdateAppearance()
{
Icon = IsInstalled ? CompletedIcon : DownloadIcon;
Name = IsInstalled ? Properties.Resources.winget_uninstall_name : Properties.Resources.winget_install_name;
Icon = InstallCommandState switch
{
PackageInstallCommandState.Install => DownloadIcon,
PackageInstallCommandState.Update => UpdateIcon,
PackageInstallCommandState.Uninstall => CompletedIcon,
_ => throw new NotImplementedException(),
};
Name = InstallCommandState switch
{
PackageInstallCommandState.Install => Properties.Resources.winget_install_name,
PackageInstallCommandState.Update => Properties.Resources.winget_update_name,
PackageInstallCommandState.Uninstall => Properties.Resources.winget_uninstall_name,
_ => throw new NotImplementedException(),
};
}
public override ICommandResult Invoke()
@ -72,7 +92,7 @@ public partial class InstallPackageCommand : InvokableCommand
return CommandResult.KeepOpen();
}
if (IsInstalled)
if (InstallCommandState == PackageInstallCommandState.Uninstall)
{
// Uninstall
_installBanner.State = MessageState.Info;
@ -88,7 +108,8 @@ public partial class InstallPackageCommand : InvokableCommand
_installTask = Task.Run(() => TryDoInstallOperation(_unInstallAction));
}
else
else if (InstallCommandState is PackageInstallCommandState.Install or
PackageInstallCommandState.Update)
{
// Install
_installBanner.State = MessageState.Info;
@ -117,7 +138,8 @@ public partial class InstallPackageCommand : InvokableCommand
try
{
await action.AsTask();
_installBanner.Message = IsInstalled ?
_installBanner.Message = InstallCommandState == PackageInstallCommandState.Uninstall ?
string.Format(CultureInfo.CurrentCulture, UninstallPackageFinished, _package.Name) :
string.Format(CultureInfo.CurrentCulture, InstallPackageFinished, _package.Name);
@ -125,9 +147,10 @@ public partial class InstallPackageCommand : InvokableCommand
_installBanner.State = MessageState.Success;
_installTask = null;
_ = Task.Run(() =>
_ = Task.Run(async () =>
{
Thread.Sleep(2500);
await Task.Delay(2500).ConfigureAwait(false);
if (_installTask == null)
{
WinGetExtensionHost.Instance.HideStatus(_installBanner);
@ -228,3 +251,10 @@ public partial class InstallPackageCommand : InvokableCommand
}
}
}
public enum PackageInstallCommandState
{
Uninstall = 0,
Update = 1,
Install = 2,
}

View File

@ -6,6 +6,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using ManagedCommon;
using Microsoft.CommandPalette.Extensions;
@ -31,7 +32,7 @@ public partial class InstallPackageListItem : ListItem
{
_package = package;
var version = _package.DefaultInstallVersion;
var version = _package.DefaultInstallVersion ?? _package.InstalledVersion;
var versionTagText = "Unknown";
if (version != null)
{
@ -49,7 +50,16 @@ public partial class InstallPackageListItem : ListItem
private Details? BuildDetails(PackageVersionInfo? version)
{
var metadata = version?.GetCatalogPackageMetadata();
CatalogPackageMetadata? metadata = null;
try
{
metadata = version?.GetCatalogPackageMetadata();
}
catch (COMException ex)
{
Logger.LogWarning($"{ex.ErrorCode}");
}
if (metadata != null)
{
if (metadata.Tags.Where(t => t.Equals(WinGetExtensionPage.ExtensionsTag, StringComparison.OrdinalIgnoreCase)).Any())
@ -149,12 +159,17 @@ public partial class InstallPackageListItem : ListItem
var status = await _package.CheckInstalledStatusAsync();
var isInstalled = _package.InstalledVersion != null;
var installedState = isInstalled ?
(_package.IsUpdateAvailable ?
PackageInstallCommandState.Update : PackageInstallCommandState.Uninstall) :
PackageInstallCommandState.Install;
// might be an uninstall command
InstallPackageCommand installCommand = new(_package, isInstalled);
InstallPackageCommand installCommand = new(_package, installedState);
if (isInstalled)
{
this.Icon = InstallPackageCommand.CompletedIcon;
this.Icon = installCommand.Icon;
this.Command = new NoOpCommand();
List<IContextItem> contextMenu = [];
CommandContextItem uninstallContextItem = new(installCommand)
@ -180,7 +195,7 @@ public partial class InstallPackageListItem : ListItem
}
// didn't find the app
_installCommand = new InstallPackageCommand(_package, isInstalled);
_installCommand = new InstallPackageCommand(_package, installedState);
this.Command = _installCommand;
Icon = _installCommand.Icon;

View File

@ -330,6 +330,15 @@ namespace Microsoft.CmdPal.Ext.WinGet.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Update.
/// </summary>
public static string winget_update_name {
get {
return ResourceManager.GetString("winget_update_name", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to View online.
/// </summary>

View File

@ -154,6 +154,10 @@
<value>Install</value>
<comment></comment>
</data>
<data name="winget_update_name" xml:space="preserve">
<value>Update</value>
<comment></comment>
</data>
<data name="winget_uninstalling_package" xml:space="preserve">
<value>Uninstalling {0}...</value>
<comment>{0} will be replaced by the name of an app package</comment>