@using LANCommander.SDK.PowerShell @using LANCommander.Server.Services.PowerShell @using XtermBlazor @using LogLevel = Microsoft.Extensions.Logging.LogLevel @inherits FeedbackComponent @inject ScriptDebugger ScriptDebugger @inject GameService GameService @inject ToolService ToolService @inject RedistributableService RedistributableService @inject ILogger Logger @implements IDisposable
@if (_status == PackagingStatus.Complete) { } else if (_status == PackagingStatus.Failed) { } else if (_status == PackagingStatus.Stopped) { }
@if (_status == PackagingStatus.Running) { @FormatElapsed()
@code { enum PackagingStatus { Running, Complete, Failed, Stopped } Guid _id = Guid.NewGuid(); Terminal? _terminal; CancellationTokenSource? _cts; DateTime? _startTime; TimeSpan _elapsed; System.Threading.Timer? _elapsedTimer; PackagingStatus _status = PackagingStatus.Running; bool _hasErrors; string? _errorMessage; readonly TerminalOptions _terminalOptions = new() { CursorBlink = false, CursorStyle = CursorStyle.Bar, }; protected override async Task OnInitializedAsync() { _status = PackagingStatus.Running; _hasErrors = false; _errorMessage = null; ScriptDebugger.OnStart = Start; ScriptDebugger.OnEnd = End; ScriptDebugger.OnOutput = Output; ScriptDebugger.OnBreak = null; _cts?.Dispose(); _cts = new CancellationTokenSource(); _startTime = DateTime.UtcNow; _elapsedTimer = new System.Threading.Timer( _ => InvokeAsync(StateHasChanged), null, TimeSpan.Zero, TimeSpan.FromSeconds(1)); } async Task OnTerminalReady() { if (_terminal != null) await _terminal.FitAsync(); await RunAsync(); } async Task RunAsync() { try { if (Options.GameId != Guid.Empty) await GameService.PackageAsync(Options.GameId); else if (Options.ToolId != Guid.Empty) await ToolService.PackageAsync(Options.ToolId); else if (Options.RedistributableId != Guid.Empty) await RedistributableService.PackageAsync(Options.RedistributableId); } catch (Exception ex) { _hasErrors = true; _errorMessage = ex.Message; Logger.LogError(ex, "Packaging failed with an exception"); if (_terminal != null) await _terminal.WriteLine(ex.Message, LogLevel.Error); StopTimer(); _elapsed = _startTime.HasValue ? DateTime.UtcNow - _startTime.Value : TimeSpan.Zero; _status = PackagingStatus.Failed; await InvokeAsync(StateHasChanged); } } async Task Start(IScriptDebugContext context) { if (_terminal == null) return; await InvokeAsync(StateHasChanged); } async Task End(IScriptDebugContext context) { StopTimer(); _elapsed = _startTime.HasValue ? DateTime.UtcNow - _startTime.Value : TimeSpan.Zero; if (_terminal != null) await _terminal.WriteLine($"\nCompleted in {FormatTimeSpan(_elapsed)}", LogLevel.Information); _status = _hasErrors ? PackagingStatus.Failed : PackagingStatus.Complete; await InvokeAsync(StateHasChanged); } async Task Output(IScriptDebugContext context, LogLevel level, string message) { if (_terminal == null) return; if (level == LogLevel.Error) { _hasErrors = true; _errorMessage ??= message; } try { await _terminal.WriteLine(message, level); } catch { } } async Task Stop() { _cts?.Cancel(); StopTimer(); _elapsed = _startTime.HasValue ? DateTime.UtcNow - _startTime.Value : TimeSpan.Zero; if (_terminal != null) await _terminal.WriteLine("\nScript stopped by user.", LogLevel.Warning); _status = PackagingStatus.Stopped; await InvokeAsync(StateHasChanged); } void StopTimer() { _elapsedTimer?.Dispose(); _elapsedTimer = null; } string FormatElapsed() { if (!_startTime.HasValue) return ""; var elapsed = DateTime.UtcNow - _startTime.Value; return FormatTimeSpan(elapsed); } static string FormatTimeSpan(TimeSpan ts) { if (ts.TotalHours >= 1) return ts.ToString(@"h\:mm\:ss"); return ts.ToString(@"m\:ss"); } public void Dispose() { _cts?.Cancel(); _cts?.Dispose(); StopTimer(); } }