Files
FCP-Mod-Updater/UI/ProgressReporter.cs

103 lines
3.5 KiB
C#

using Spectre.Console;
namespace FCPModUpdater.UI;
public static class ProgressReporter
{
public static async Task<T> WithStatusAsync<T>(string status, Func<Task<T>> 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<Task> 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<ProgressTask, Task> 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<IReadOnlyList<(string Name, bool Success, string? Error)>> WithBatchProgressAsync<T>(
string description,
IReadOnlyList<T> items,
Func<T, string> nameSelector,
Func<T, IProgress<double>, Task<(bool Success, string? Error)>> action)
{
var itemTasks = new List<ProgressTask>();
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}");
itemTasks.Add(itemTask);
var progress = new Progress<double>(p => itemTask.Value = p);
try
{
var (success, error) = await action(item, progress);
itemTask.Tag(new BatchResult(name, success, error));
itemTask.Value = 100;
itemTask.Description = success
? $" [green]{name}[/]"
: $" [red]{name}[/]";
}
catch (Exception ex)
{
itemTask.Tag(new BatchResult(name, false, ex.Message));
itemTask.Value = 100;
itemTask.Description = $" [red]{name}[/]";
}
overallTask.Increment(1);
}
});
return itemTasks
.Select(t => (BatchResult)t.Tag!)
.Select(r => (r.Name, r.Success, r.Error))
.ToList();
}
private record BatchResult(string Name, bool Success, string? Error);
}