using Spectre.Console; namespace FCPModUpdater.UI; public static class ProgressReporter { public static async Task WithStatusAsync(string status, Func> action) { return await AnsiConsole.Status() .Spinner(Spinner.Known.Dots) .SpinnerStyle(Style.Parse("blue")) .StartAsync(status, async _ => await action()); } public static async Task WithStatusAsync(string status, Func action) { await AnsiConsole.Status() .Spinner(Spinner.Known.Dots) .SpinnerStyle(Style.Parse("blue")) .StartAsync(status, async _ => await action()); } public static async Task WithProgressAsync( string description, IEnumerable<(string Name, Func Action)> tasks) { await AnsiConsole.Progress() .Columns( new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn(), new SpinnerColumn()) .StartAsync(async ctx => { var taskList = tasks.ToList(); var progressTasks = taskList .Select(t => (Task: ctx.AddTask(t.Name), t.Action)) .ToList(); foreach ((ProgressTask task, var action) in progressTasks) { await action(task); task.Value = 100; } }); } public static async Task> WithBatchProgressAsync( string description, IReadOnlyList items, Func nameSelector, Func, Task<(bool Success, string? Error)>> action) { var results = new List<(string Name, bool Success, string? Error)>(); await AnsiConsole.Progress() .Columns( new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn(), new SpinnerColumn()) .StartAsync(async ctx => { ProgressTask overallTask = ctx.AddTask($"[bold]{description}[/]", maxValue: items.Count); foreach (T item in items) { var name = nameSelector(item); ProgressTask itemTask = ctx.AddTask($" {name}"); var progress = new Progress(p => itemTask.Value = p); try { var (success, error) = await action(item, progress); results.Add((name, success, error)); itemTask.Value = 100; itemTask.Description = success ? $" [green]{name}[/]" : $" [red]{name}[/]"; } catch (Exception ex) { results.Add((name, false, ex.Message)); itemTask.Value = 100; itemTask.Description = $" [red]{name}[/]"; } overallTask.Increment(1); } }); return results; } }