SPT-AKI-Installer/Aki.Core/Model/LiveTableTask.cs

161 lines
5.1 KiB
C#
Raw Normal View History

2022-07-09 00:33:55 -04:00
using Spectre.Console;
using SPT_AKI_Installer.Aki.Core.Interfaces;
using System;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace SPT_AKI_Installer.Aki.Core.Model
{
public abstract class LiveTableTask : ILiveTaskTableEntry, IProgressableTask, IDisposable
{
/// <summary>
/// The name that will be displayed in th first column of the table
/// </summary>
public string TaskName { get; set; }
/// <summary>
/// Wheather the task reports progress or not
/// </summary>
public bool IsIndeterminate;
/// <summary>
/// The progress (percent completed) of the task
/// </summary>
public int Progress { get; set; }
/// <summary>
/// The row index in the table of the task
/// </summary>
public int RowIndex { get; set; }
2022-07-09 13:08:41 -04:00
private bool _continueRenderingProgress = false;
private bool _continueRenderingIndeterminateProgress = false;
2022-07-09 00:33:55 -04:00
private int _indeterminateState = 0;
private string _currentStatus = "running";
private Table _table { get; set; }
private LiveDisplayContext _context { get; set; }
public LiveTableTask(string name, bool isIndeterminate = true)
{
TaskName = name;
IsIndeterminate = isIndeterminate;
}
private string GetIndetermminateStatus()
{
string status = $"[blue]{_currentStatus.EscapeMarkup()} ";
if (_indeterminateState > 3) _indeterminateState = 0;
status += new string('.', _indeterminateState);
status += "[/]";
_indeterminateState++;
return status;
}
/// <summary>
/// Start indeterminate progress spinner
/// </summary>
/// <remarks>this doesn't need to be called if you set isIndeterminate in the constructor. You need to set IsIndeterminate to false to stop this background task</remarks>
public void StartDrawingIndeterminateProgress()
{
2022-07-09 13:08:41 -04:00
_continueRenderingProgress = false;
_continueRenderingIndeterminateProgress = true;
new Task(new Action(() => { RenderIndeterminateProgress(ref _continueRenderingIndeterminateProgress); })).Start();
2022-07-09 00:33:55 -04:00
}
public void StartDrawingProgress()
{
2022-07-09 13:08:41 -04:00
Progress = 0;
_continueRenderingIndeterminateProgress = false;
_continueRenderingProgress = true;
new Task(new Action(() => { RenderProgress(ref _continueRenderingProgress); })).Start();
2022-07-09 00:33:55 -04:00
}
private void ReRenderEntry(string message)
{
_table.RemoveRow(RowIndex);
_table.InsertRow(RowIndex, TaskName, message);
_context.Refresh();
}
private void RenderIndeterminateProgress(ref bool continueRendering)
{
while (continueRendering)
{
ReRenderEntry(GetIndetermminateStatus());
Thread.Sleep(300);
}
}
private void RenderProgress(ref bool continueRendering)
{
while (continueRendering)
{
string progressBar = new string(' ', 10);
int progressFill = (int)Math.Floor((double)Progress / 10);
progressBar = progressBar.Remove(0, progressFill).Insert(0, new string('=', progressFill));
progressBar = $"[blue][[{progressBar}]][/] {Progress}% {_currentStatus}";
ReRenderEntry(progressBar);
Thread.Sleep(300);
}
}
/// <summary>
/// Set the context and table for this task
/// </summary>
/// <param name="context"></param>
/// <param name="table"></param>
/// <remarks>This is called by <see cref="LiveTableTaskRunner"/> when it is ran. No need to call it yourself</remarks>
public void SetContext(LiveDisplayContext context, Table table)
{
_context = context;
_table = table;
}
/// <summary>
/// Set the status text for the task
/// </summary>
/// <param name="message">The message to show</param>
/// <param name="stopRendering">Stop rendering progress updates (progress and indeterminate progress tasks)</param>
/// <remarks>If you are running an indeterminate task, set render to false. It will render at the next indeterminate update interval</remarks>
public void SetStatus(string message, bool stopRendering = true)
{
_currentStatus = message;
if (stopRendering)
{
2022-07-09 13:08:41 -04:00
_continueRenderingProgress = false;
_continueRenderingIndeterminateProgress = false;
2022-07-09 00:33:55 -04:00
ReRenderEntry(message);
}
}
/// <summary>
/// Run the task async
/// </summary>
/// <returns>Returns the result of the task</returns>
public abstract Task<GenericResult> RunAsync();
public void Dispose()
{
IsIndeterminate = false;
}
}
}