Pilfer TypedEventHandlerExtensions from WCT (#404)

I think this pilfers the `InvokeAsync` as mentioned in #333

WE can't use the actual version for the same reason we can't use that one TryEnqueue extension - the WCT MD Text block we're on uses a different version of the WCT than the latest version, so the two get confused. 

We can remove this pilfered copy after either #245 or #219

Closes #333
This commit is contained in:
Mike Griese
2025-02-06 05:39:38 -06:00
committed by GitHub
parent da40c449bd
commit 96404f02b2
3 changed files with 78 additions and 3 deletions

View File

@@ -1709,6 +1709,7 @@ TOPDOWNDIB
TOUCHEVENTF
TOUCHINPUT
TRACEHANDLE
TResult
tracelogging
tracerpt
trackbar
@@ -1720,6 +1721,7 @@ triaging
trl
trx
tsa
TSender
TServer
tstoi
TStr

View File

@@ -2,6 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.CmdPal.UI.Deferred;
using Microsoft.CmdPal.UI.ViewModels;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml;
@@ -90,14 +91,14 @@ public partial class IconBox : ContentControl
{
// TODO GH #239 switch back when using the new MD text block
// _ = @this._queue.EnqueueAsync(() =>
@this._queue.TryEnqueue(new(() =>
@this._queue.TryEnqueue(new(async () =>
{
var requestedTheme = @this.ActualTheme;
var eventArgs = new SourceRequestedEventArgs(e.NewValue, requestedTheme);
if (@this.SourceRequested != null)
{
@this.SourceRequested.Invoke(@this, eventArgs);
await @this.SourceRequested.InvokeAsync(@this, eventArgs);
@this.Source = eventArgs.Value;
@@ -131,7 +132,7 @@ public partial class IconBox : ContentControl
// The range of MDL2 Icons isn't explicitly defined, but
// we're using this based off the table on:
// https://docs.microsoft.com/en-us/windows/uwp/design/style/segoe-ui-symbol-font
var isMDL2Icon = ch >= '\uE700' && ch <= '\uF8FF';
var isMDL2Icon = ch is >= '\uE700' and <= '\uF8FF';
if (!isMDL2Icon)
{
@this.Padding = new Thickness(-4);

View File

@@ -0,0 +1,72 @@
// 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 CommunityToolkit.Common.Deferred;
using Windows.Foundation;
// Pilfered from CommunityToolkit.WinUI.Deferred
namespace Microsoft.CmdPal.UI.Deferred;
/// <summary>
/// Extensions to <see cref="TypedEventHandler{TSender, TResult}"/> for Deferred Events.
/// </summary>
public static class TypedEventHandlerExtensions
{
/// <summary>
/// Use to invoke an async <see cref="TypedEventHandler{TSender, TResult}"/> using <see cref="DeferredEventArgs"/>.
/// </summary>
/// <typeparam name="S">Type of sender.</typeparam>
/// <typeparam name="R"><see cref="EventArgs"/> type.</typeparam>
/// <param name="eventHandler"><see cref="TypedEventHandler{TSender, TResult}"/> to be invoked.</param>
/// <param name="sender">Sender of the event.</param>
/// <param name="eventArgs"><see cref="EventArgs"/> instance.</param>
/// <returns><see cref="Task"/> to wait on deferred event handler.</returns>
#pragma warning disable CA1715 // Identifiers should have correct prefix
#pragma warning disable SA1314 // Type parameter names should begin with T
public static Task InvokeAsync<S, R>(this TypedEventHandler<S, R> eventHandler, S sender, R eventArgs)
#pragma warning restore SA1314 // Type parameter names should begin with T
#pragma warning restore CA1715 // Identifiers should have correct prefix
where R : DeferredEventArgs => InvokeAsync(eventHandler, sender, eventArgs, CancellationToken.None);
/// <summary>
/// Use to invoke an async <see cref="TypedEventHandler{TSender, TResult}"/> using <see cref="DeferredEventArgs"/> with a <see cref="CancellationToken"/>.
/// </summary>
/// <typeparam name="S">Type of sender.</typeparam>
/// <typeparam name="R"><see cref="EventArgs"/> type.</typeparam>
/// <param name="eventHandler"><see cref="TypedEventHandler{TSender, TResult}"/> to be invoked.</param>
/// <param name="sender">Sender of the event.</param>
/// <param name="eventArgs"><see cref="EventArgs"/> instance.</param>
/// <param name="cancellationToken"><see cref="CancellationToken"/> option.</param>
/// <returns><see cref="Task"/> to wait on deferred event handler.</returns>
#pragma warning disable CA1715 // Identifiers should have correct prefix
#pragma warning disable SA1314 // Type parameter names should begin with T
public static Task InvokeAsync<S, R>(this TypedEventHandler<S, R> eventHandler, S sender, R eventArgs, CancellationToken cancellationToken)
#pragma warning restore SA1314 // Type parameter names should begin with T
#pragma warning restore CA1715 // Identifiers should have correct prefix
where R : DeferredEventArgs
{
if (eventHandler == null)
{
return Task.CompletedTask;
}
var tasks = eventHandler.GetInvocationList()
.OfType<TypedEventHandler<S, R>>()
.Select(invocationDelegate =>
{
cancellationToken.ThrowIfCancellationRequested();
invocationDelegate(sender, eventArgs);
#pragma warning disable CS0618 // Type or member is obsolete
var deferral = eventArgs.GetCurrentDeferralAndReset();
return deferral?.WaitForCompletion(cancellationToken) ?? Task.CompletedTask;
#pragma warning restore CS0618 // Type or member is obsolete
})
.ToArray();
return Task.WhenAll(tasks);
}
}