using System.Windows.Input; namespace AcDream.Launcher.ViewModels; public sealed class RelayCommand : ICommand { private readonly Action _execute; private readonly Func? _canExecute; public RelayCommand(Action execute, Func? canExecute = null) : this( _ => execute(), canExecute is null ? null : _ => canExecute()) { ArgumentNullException.ThrowIfNull(execute); } public RelayCommand( Action execute, Func? canExecute = null) { _execute = execute ?? throw new ArgumentNullException(nameof(execute)); _canExecute = canExecute; } public event EventHandler? CanExecuteChanged; public bool CanExecute(object? parameter) => _canExecute?.Invoke(parameter) ?? true; public void Execute(object? parameter) { if (CanExecute(parameter)) { _execute(parameter); } } public void NotifyCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty); } public sealed class AsyncRelayCommand : ICommand { private readonly Func _execute; private readonly Func? _canExecute; private bool _isExecuting; public AsyncRelayCommand(Func execute, Func? canExecute = null) : this( _ => execute(), canExecute is null ? null : _ => canExecute()) { ArgumentNullException.ThrowIfNull(execute); } public AsyncRelayCommand( Func execute, Func? canExecute = null) { _execute = execute ?? throw new ArgumentNullException(nameof(execute)); _canExecute = canExecute; } public event EventHandler? CanExecuteChanged; public bool CanExecute(object? parameter) => !_isExecuting && (_canExecute?.Invoke(parameter) ?? true); public async void Execute(object? parameter) => await ExecuteAsync(parameter).ConfigureAwait(true); public async Task ExecuteAsync(object? parameter = null) { if (!CanExecute(parameter)) { return; } _isExecuting = true; NotifyCanExecuteChanged(); try { await _execute(parameter).ConfigureAwait(true); } finally { _isExecuting = false; NotifyCanExecuteChanged(); } } public void NotifyCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty); }