mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-05 18:57:19 +02:00
CmdPal: Plain text viewer and image viewer IContent (#43964)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request This PR introduces new types of IContent: - Plain text content – simple and straightforward, with options to switch between UI and monospace fonts and toggle word wrap. - It's super safe to display any random text content without having to worry about escaping the pesky markdown. - Image viewer content – a more polished way to display images: - When placed in the ContentPage, the component automatically resizes to fit the viewport, ensuring the entire image is visible at once. - Images can be opened in a built-in mini-viewer that lets you view, pan, and zoom without leaving the Command Palette. (Doing this directly on the page proved to be a UX and development headache.) Fully keyboard-controllable, so there’s no need to take your hands off the keys. ## Pictures? Pictures! Plain text content: <img width="960" height="604" alt="image" src="https://github.com/user-attachments/assets/a4ec36f3-2f7f-4a2a-a646-53056c512023" /> Image viewer content: <img width="939" height="605" alt="image" src="https://github.com/user-attachments/assets/c87f5726-8cd0-4015-b2d9-f1457fa1ec96" /> https://github.com/user-attachments/assets/915cd9d2-e4e3-4baf-8df6-6a328a3592ba <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [x] Closes: #41038 <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed
This commit is contained in:
@@ -16,6 +16,8 @@ namespace Microsoft.CmdPal.UI.Helpers;
|
||||
|
||||
internal sealed partial class IconLoaderService : IIconLoaderService
|
||||
{
|
||||
public static readonly Size NoResize = Size.Empty;
|
||||
|
||||
private const DispatcherQueuePriority LoadingPriorityOnDispatcher = DispatcherQueuePriority.Low;
|
||||
private const int DefaultIconSize = 256;
|
||||
private const int MaxWorkerCount = 4;
|
||||
@@ -214,11 +216,6 @@ internal sealed partial class IconLoaderService : IIconLoaderService
|
||||
private static IconSource? GetStringIconSource(string iconString, string? fontFamily, Size size)
|
||||
{
|
||||
var iconSize = (int)Math.Max(size.Width, size.Height);
|
||||
if (iconSize == 0)
|
||||
{
|
||||
iconSize = DefaultIconSize;
|
||||
}
|
||||
|
||||
return IconPathConverter.IconSourceMUX(iconString, fontFamily, iconSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Microsoft.CmdPal.UI.Helpers;
|
||||
/// <summary>
|
||||
/// Common async event handler provides the cache lookup function for the <see cref="IconBox.SourceRequested"/> deferred event.
|
||||
/// </summary>
|
||||
public static partial class IconCacheProvider
|
||||
public static partial class IconProvider
|
||||
{
|
||||
/*
|
||||
Memory Usage Considerations (raw estimates):
|
||||
@@ -29,6 +29,7 @@ public static partial class IconCacheProvider
|
||||
private static IIconSourceProvider _provider32 = null!;
|
||||
private static IIconSourceProvider _provider64 = null!;
|
||||
private static IIconSourceProvider _provider256 = null!;
|
||||
private static IIconSourceProvider _providerUnbound = null!;
|
||||
|
||||
public static void Initialize(IServiceProvider serviceProvider)
|
||||
{
|
||||
@@ -37,6 +38,7 @@ public static partial class IconCacheProvider
|
||||
_provider32 = serviceProvider.GetRequiredKeyedService<IIconSourceProvider>(WellKnownIconSize.Size32);
|
||||
_provider64 = serviceProvider.GetRequiredKeyedService<IIconSourceProvider>(WellKnownIconSize.Size64);
|
||||
_provider256 = serviceProvider.GetRequiredKeyedService<IIconSourceProvider>(WellKnownIconSize.Size256);
|
||||
_providerUnbound = serviceProvider.GetRequiredKeyedService<IIconSourceProvider>(WellKnownIconSize.Unbound);
|
||||
}
|
||||
|
||||
private static async void SourceRequestedCore(IIconSourceProvider service, SourceRequestedEventArgs args)
|
||||
@@ -80,5 +82,8 @@ public static partial class IconCacheProvider
|
||||
|
||||
public static void SourceRequested256(IconBox sender, SourceRequestedEventArgs args)
|
||||
=> SourceRequestedCore(_provider256, args);
|
||||
|
||||
public static void SourceRequestedOriginal(IconBox sender, SourceRequestedEventArgs args)
|
||||
=> SourceRequestedCore(_providerUnbound, args);
|
||||
#pragma warning restore IDE0060 // Remove unused parameter
|
||||
}
|
||||
@@ -36,6 +36,10 @@ internal static class IconServiceRegistration
|
||||
WellKnownIconSize.Size256,
|
||||
(_, _) => new CachedIconSourceProvider(loader, 256, 64));
|
||||
|
||||
services.AddKeyedSingleton<IIconSourceProvider>(
|
||||
WellKnownIconSize.Unbound,
|
||||
(_, _) => new IconSourceProvider(loader, IconLoaderService.NoResize, isPriority: true));
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,15 +12,17 @@ internal sealed class IconSourceProvider : IIconSourceProvider
|
||||
{
|
||||
private readonly IconLoaderService _loader;
|
||||
private readonly Size _iconSize;
|
||||
private readonly bool _isPriority;
|
||||
|
||||
public IconSourceProvider(IconLoaderService loader, Size iconSize)
|
||||
public IconSourceProvider(IconLoaderService loader, Size iconSize, bool isPriority = false)
|
||||
{
|
||||
_loader = loader;
|
||||
_iconSize = iconSize;
|
||||
_isPriority = isPriority;
|
||||
}
|
||||
|
||||
public IconSourceProvider(IconLoaderService loader, int iconSize)
|
||||
: this(loader, new Size(iconSize, iconSize))
|
||||
public IconSourceProvider(IconLoaderService loader, int iconSize, bool isPriority = false)
|
||||
: this(loader, new Size(iconSize, iconSize), isPriority)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -34,7 +36,8 @@ internal sealed class IconSourceProvider : IIconSourceProvider
|
||||
icon.Data?.Unsafe,
|
||||
_iconSize,
|
||||
scale,
|
||||
tcs);
|
||||
tcs,
|
||||
_isPriority ? IconLoadPriority.High : IconLoadPriority.Low);
|
||||
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
@@ -11,4 +11,5 @@ internal enum WellKnownIconSize
|
||||
Size32 = 32,
|
||||
Size64 = 64,
|
||||
Size256 = 256,
|
||||
Unbound = -1,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user