Files
egwcorelib/EgwCoreLib.Razor/ProgressDisplay.razor.cs
2023-07-31 09:31:53 +02:00

233 lines
6.3 KiB
C#

using Microsoft.AspNetCore.Components;
namespace EgwCoreLib.Razor
{
public partial class ProgressDisplay : IDisposable
{
#region Public Enums
public enum ModalSize
{
Small,
Medium,
Large
}
#endregion Public Enums
#region Public Properties
/// <summary>
/// Valore corrente
/// </summary>
[Parameter]
public double CurrVal
{
get => actVal;
set
{
actVal = value;
startVal = value;
isLoading = actVal < MaxVal;
}
}
/// <summary>
/// Dimensioni attese modale
/// default: ModalSize.Medium
/// </summary>
[Parameter]
public ModalSize DisplaySize { get; set; } = ModalSize.Medium;
/// <summary>
/// Tempo atteso per prossimo step
/// default: 10000
/// </summary>
[Parameter]
public int ExpTimeMSec { get; set; } = 10000;
/// <summary>
/// Valore massimo ammesso
/// default: 100
/// </summary>
[Parameter]
public double MaxVal { get; set; } = 100;
/// <summary>
/// Style modale
/// default: card
/// alternative: card alert-primary
/// </summary>
[Parameter]
public string ModalCss { get; set; } = "card";
/// <summary>
/// Prossimo valore ammesso (fino al max)
/// default: 100
/// </summary>
[Parameter]
public double NextVal { get; set; } = 100;
/// <summary>
/// Style progressbar
/// default: progress-bar progress-bar-striped progress-bar-animated
/// </summary>
[Parameter]
public string ProgressCss { get; set; } = "progress-bar progress-bar-striped progress-bar-animated";
/// <summary>
/// Intervallo interno per refresh percentuale avanzamento
/// default: 100ms
/// </summary>
[Parameter]
public int RefreshInterval { get; set; } = 100;
/// <summary>
/// Indica se mostrare la percentuale vanzamento
/// default: true
/// </summary>
[Parameter]
public bool ShowPercent { get; set; } = true;
/// <summary>
/// Limite per anticipo slowdown (% della durata di ExpTimeMSec)
/// </summary>
[Parameter]
public double SlowLimit { get; set; } = 0.5;
/// <summary>
/// Numero di secondi prima (rispetto valore ExpTimeMsec) da cui iniziare rallentamento
/// </summary>
private int slowWindowMSec
{
get => (int)(ExpTimeMSec * SlowLimit);
}
/// <summary>
/// Titolo da mostrare (se "" NON lo mostra)
/// </summary>
[Parameter]
public string Title { get; set; } = "Progress";
#endregion Public Properties
#region Public Methods
public void Dispose()
{
uiTimer?.Dispose();
}
#endregion Public Methods
#region Protected Properties
protected string modalDialogCss
{
get
{
string answ = "modal-dialog";
switch (DisplaySize)
{
case ModalSize.Small:
answ = "modal-dialog modal-sm";
break;
case ModalSize.Large:
answ = "modal-dialog modal-xl";
break;
case ModalSize.Medium:
default:
break;
}
return answ;
}
}
#endregion Protected Properties
#region Protected Methods
protected override async Task OnParametersSetAsync()
{
// salvo valori aggiornamento...
if (ExpTimeMSec > 0)
{
lastUpdate = DateTime.Now;
nextUpdate = lastUpdate.AddMilliseconds(ExpTimeMSec);
await RefreshDisplay();
}
if (isLoading)
{
uiTimer?.Dispose();
uiTimer = new PeriodicTimer(TimeSpan.FromMilliseconds(RefreshInterval));
RunTimer();
}
else
{
uiTimer = null;
}
}
#endregion Protected Methods
#region Private Fields
private PeriodicTimer? uiTimer = null;
#endregion Private Fields
#region Private Properties
private double actVal { get; set; } = 100;
private string currWidth { get; set; } = "";
private string displayMsg { get; set; } = "Loading...";
private bool isLoading { get; set; } = false;
private DateTime lastUpdate { get; set; } = DateTime.Now.AddMinutes(-1);
private DateTime nextUpdate { get; set; } = DateTime.Now;
private double startVal { get; set; } = 100;
#endregion Private Properties
#region Private Methods
private async Task RefreshDisplay()
{
currWidth = $"{(double)actVal / MaxVal:P0}";
if (ShowPercent)
{
displayMsg = $"{actVal / MaxVal:P2}";
}
await InvokeAsync(StateHasChanged);
}
private async void RunTimer()
{
while (uiTimer != null && await uiTimer.WaitForNextTickAsync())
{
if (isLoading)
{
DateTime adesso = DateTime.Now;
if (nextUpdate <= adesso.AddMilliseconds(slowWindowMSec))
{
nextUpdate = adesso.AddMilliseconds(RefreshInterval*2);
}
// calcolo delta ms...
var numMs = adesso.Subtract(lastUpdate).TotalMilliseconds;
var denMs = nextUpdate.Subtract(lastUpdate).TotalMilliseconds;
denMs = denMs > 0 ? denMs : 1;
// aggiorno display...
actVal = startVal + (NextVal - startVal) * (numMs / denMs);
await RefreshDisplay();
}
}
}
#endregion Private Methods
}
}