using System.Diagnostics.CodeAnalysis; using StabilityMatrix.Core.Models.Progress; namespace StabilityMatrix.Core.Models.PackageModification; public class PackageModificationRunner : IPackageModificationRunner { public async Task ExecuteSteps(IReadOnlyList steps) { IProgress progress = new Progress(report => { CurrentProgress = report; if (!string.IsNullOrWhiteSpace(report.Message)) { ConsoleOutput.Add(report.Message); } if (!string.IsNullOrWhiteSpace(report.Title)) { ConsoleOutput.Add(report.Title); } OnProgressChanged(report); }); IsRunning = true; try { foreach (var step in steps) { CurrentStep = step; try { await step.ExecuteAsync(progress).ConfigureAwait(false); } catch (Exception e) { var failedMessage = string.IsNullOrWhiteSpace(ModificationFailedMessage) ? $"Error: {e}" : ModificationFailedMessage + $" ({e})"; progress.Report( new ProgressReport( 1f, title: ModificationFailedTitle, message: failedMessage, isIndeterminate: false ) ); Exception = e; Failed = true; return; } } if (!Failed) { progress.Report( new ProgressReport( 1f, title: ModificationCompleteTitle, message: ModificationCompleteMessage, isIndeterminate: false ) ); } } finally { IsRunning = false; OnCompleted(); } } public bool HideCloseButton { get; init; } public bool ShowDialogOnStart { get; init; } public string? ModificationCompleteTitle { get; init; } = "Install Complete"; public string? ModificationCompleteMessage { get; init; } public string? ModificationFailedTitle { get; init; } = "Install Failed"; public string? ModificationFailedMessage { get; init; } public bool IsRunning { get; private set; } [MemberNotNullWhen(true, nameof(Exception))] public bool Failed { get; private set; } public Exception? Exception { get; set; } public ProgressReport CurrentProgress { get; set; } public IPackageStep? CurrentStep { get; set; } public List ConsoleOutput { get; } = new(); public Guid Id { get; } = Guid.NewGuid(); public event EventHandler? ProgressChanged; public event EventHandler? Completed; protected virtual void OnProgressChanged(ProgressReport e) => ProgressChanged?.Invoke(this, e); protected virtual void OnCompleted() => Completed?.Invoke(this, this); }