@using LANCommander.SDK.PowerShell @using LANCommander.SDK.Services @using LANCommander.Server.Services.PowerShell @using XtermBlazor @using LogLevel = Microsoft.Extensions.Logging.LogLevel @inject ScriptDebugger ScriptDebugger @inject ScriptClient ScriptClient @inject GameService GameService @inject ToolService ToolService @inject RedistributableService RedistributableService
@if (Active) {
@FormatElapsed()
}
@code { [Parameter] public Guid Id { get; set; } [Parameter] public bool Active { get; set; } [Parameter] public EventCallback ActiveChanged { get; set; } private Terminal? _terminal; private CancellationTokenSource? _cts; private DateTime? _startTime; private System.Threading.Timer? _elapsedTimer; private readonly TerminalOptions _options = new() { CursorBlink = true, CursorStyle = CursorStyle.Bar, }; async Task SetActive(bool active) { Active = active; if (ActiveChanged.HasDelegate) await ActiveChanged.InvokeAsync(Active); } private void InitializeDebugger() { ScriptDebugger.OnBreak = Break; ScriptDebugger.OnStart = Start; ScriptDebugger.OnEnd = End; ScriptDebugger.OnOutput = Output; ScriptClient.Debug = true; _cts?.Dispose(); _cts = new CancellationTokenSource(); _startTime = DateTime.UtcNow; _elapsedTimer = new System.Threading.Timer( _ => InvokeAsync(StateHasChanged), null, TimeSpan.Zero, TimeSpan.FromSeconds(1)); } public async Task DebugPackagingScript(Guid gameId) { InitializeDebugger(); await GameService.PackageAsync(gameId); } public async Task DebugToolPackagingScript(Guid toolId) { InitializeDebugger(); await ToolService.PackageAsync(toolId); } public async Task DebugRedistributablePackagingScript(Guid redistributableId) { InitializeDebugger(); await RedistributableService.PackageAsync(redistributableId); } public async Task Start(IScriptDebugContext context) { if (_terminal is null) return; await _terminal.Clear(); await SetActive(true); await InvokeAsync(StateHasChanged); await _terminal.Focus(); await _terminal.FitAsync(); } public async Task End(IScriptDebugContext context) { StopTimer(); if (_terminal != null && _startTime.HasValue) { var elapsed = DateTime.UtcNow - _startTime.Value; await _terminal.WriteLine($"\nCompleted in {FormatTimeSpan(elapsed)}", LogLevel.Information); } await SetActive(false); await InvokeAsync(StateHasChanged); } public async Task Break(IScriptDebugContext context) { if (_terminal is null) return; while (true) { var input = await _terminal.ReadLineAsync(); if (input.Trim().Equals("exit", StringComparison.OrdinalIgnoreCase)) break; if (input.StartsWith('$')) input = "Write-Host " + input; await context.ExecuteAsync(input); } } public async Task Output(IScriptDebugContext context, LogLevel level, string message) { if (_terminal is null) return; try { await _terminal.WriteLine(message, level); } catch (Exception ex) { } } async Task Stop() { _cts?.Cancel(); StopTimer(); if (_terminal != null) await _terminal.WriteLine("\nScript stopped by user.", LogLevel.Warning); await SetActive(false); 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"); } }