You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
77 lines
3.0 KiB
77 lines
3.0 KiB
1 year ago
|
using System;
|
||
|
using System.Diagnostics.CodeAnalysis;
|
||
|
using CommunityToolkit.Mvvm.Input;
|
||
|
using NLog;
|
||
|
using StabilityMatrix.Avalonia.Services;
|
||
|
using StabilityMatrix.Core.Extensions;
|
||
|
|
||
|
namespace StabilityMatrix.Avalonia.Extensions;
|
||
|
|
||
|
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||
|
public static class RelayCommandExtensions
|
||
|
{
|
||
|
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||
|
|
||
|
/// <summary>
|
||
|
/// Attach an error handler to the command that will invoke the given action when an exception occurs.
|
||
|
/// </summary>
|
||
|
/// <param name="command">The command to attach the error handler to.</param>
|
||
|
/// <param name="onError">The action to invoke when an exception occurs.</param>
|
||
|
/// <exception cref="ArgumentException">Thrown if the command was not created with the FlowExceptionsToTaskScheduler option enabled.</exception>
|
||
|
public static T WithErrorHandler<T>(this T command, Action<Exception> onError) where T : IAsyncRelayCommand
|
||
|
{
|
||
|
if (command is AsyncRelayCommand relayCommand)
|
||
|
{
|
||
|
// Check that the FlowExceptionsToTaskScheduler flag is set
|
||
|
var options = relayCommand.GetPrivateField<AsyncRelayCommandOptions>("options");
|
||
|
|
||
|
if (!options.HasFlag(AsyncRelayCommandOptions.FlowExceptionsToTaskScheduler))
|
||
|
{
|
||
|
throw new ArgumentException(
|
||
|
"The command must be created with the FlowExceptionsToTaskScheduler option enabled"
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
command.PropertyChanged += (sender, e) =>
|
||
|
{
|
||
|
if (sender is not IAsyncRelayCommand senderCommand)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
// On ExecutionTask updates, check if there is an exception
|
||
|
if (
|
||
|
e.PropertyName == nameof(AsyncRelayCommand.ExecutionTask)
|
||
|
&& senderCommand.ExecutionTask is { Exception: { } exception }
|
||
|
)
|
||
|
{
|
||
|
onError(exception);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
return command;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Attach an error handler to the command that will log the error and show a notification.
|
||
|
/// </summary>
|
||
|
/// <param name="command">The command to attach the error handler to.</param>
|
||
|
/// <param name="notificationService">The notification service to use to show the notification.</param>
|
||
|
/// <param name="logLevel">The log level to use when logging the error. Defaults to LogLevel.Error</param>
|
||
|
/// <exception cref="ArgumentException">Thrown if the command was not created with the FlowExceptionsToTaskScheduler option enabled.</exception>
|
||
|
public static T WithNotificationErrorHandler<T>(
|
||
|
this T command,
|
||
|
INotificationService notificationService,
|
||
|
LogLevel? logLevel = default
|
||
|
) where T : IAsyncRelayCommand
|
||
|
{
|
||
|
logLevel ??= LogLevel.Error;
|
||
|
|
||
|
return command.WithErrorHandler(e =>
|
||
|
{
|
||
|
Logger.Log(logLevel, e, "Error executing command");
|
||
|
notificationService.ShowPersistent("Error", $"[{e.GetType().Name}] {e.Message}");
|
||
|
});
|
||
|
}
|
||
|
}
|