@using RobotNet10.ScriptEditor.Clients @using RobotNet10.ScriptEditor.Dialogs @using RobotNet10.ScriptEngine.Shared @using MudBlazor @inject ScriptManagerHubClient ScriptManagerClient @inject IDialogService DialogService @inject ISnackbar Snackbar @implements IDisposable @if (_variables == null || _variables.Count == 0) { @if (_isLoading) { Loading variables... } else if (_currentState == ScriptEngineState.Ready || _currentState == ScriptEngineState.Running) { No variables available } else { Variables available when engine is Ready or Running } } else { @foreach (var variable in _variables) { @variable.Name @variable.TypeName @variable.Value @if (_currentState == ScriptEngineState.Running && variable.Writeable && IsPrimitiveType(variable.TypeName)) { } } } @code { private List _variables = new(); private ScriptEngineState _currentState = ScriptEngineState.Initializing; private bool _isLoading = false; protected override void OnInitialized() { // Subscribe to state changes ScriptManagerClient.StateChanged += OnStateChanged; _currentState = ScriptManagerClient.State; // Load variables if state is already Ready or Running if (_currentState == ScriptEngineState.Ready || _currentState == ScriptEngineState.Running) { _ = LoadVariablesAsync(); } } protected override void OnAfterRender(bool firstRender) { if (firstRender) { // Ensure we have the latest state _currentState = ScriptManagerClient.State; if (_currentState == ScriptEngineState.Ready || _currentState == ScriptEngineState.Running) { _ = LoadVariablesAsync(); } } } private async void OnStateChanged(ScriptEngineState newState) { _currentState = newState; if (newState == ScriptEngineState.Ready || newState == ScriptEngineState.Running) { await LoadVariablesAsync(); } else { // Clear variables when not in Ready or Running state _variables.Clear(); StateHasChanged(); } } private async Task LoadVariablesAsync() { if (!ScriptManagerClient.IsConnected) return; try { _isLoading = true; StateHasChanged(); var variables = await ScriptManagerClient.GetScriptVariablesAsync(); _variables = variables?.ToList() ?? new List(); } catch (Exception ex) { Snackbar.Add($"Failed to load variables: {ex.Message}", Severity.Error); _variables = new List(); } finally { _isLoading = false; StateHasChanged(); } } private async Task HandleRefresh(MouseEventArgs e) { if (_currentState == ScriptEngineState.Ready || _currentState == ScriptEngineState.Running) { await LoadVariablesAsync(); } } private async Task HandleEditVariable(ScriptVariableDto variable) { var parameters = new DialogParameters { { x => x.VariableName, variable.Name }, { x => x.TypeName, variable.TypeName }, { x => x.CurrentValue, variable.Value } }; var options = new DialogOptions { CloseOnEscapeKey = true, MaxWidth = MaxWidth.Small, FullWidth = true }; var dialog = await DialogService.ShowAsync("Edit Variable", parameters, options); var result = await dialog.Result; if (result is not null && !result.Canceled && result.Data is string newValue) { try { var messageResult = await ScriptManagerClient.SetValueAsync(variable.Name, newValue); if (messageResult.IsSuccess) { Snackbar.Add($"Variable '{variable.Name}' updated successfully", Severity.Success); // Reload variables to get updated values await LoadVariablesAsync(); } else { Snackbar.Add($"Failed to update variable: {messageResult.Message}", Severity.Error); } } catch (Exception ex) { Snackbar.Add($"Error updating variable: {ex.Message}", Severity.Error); } } } private static bool IsPrimitiveType(string typeName) { // Check if type is a primitive type (excluding string and object) var primitiveTypes = new HashSet { "bool", "System.Boolean", "byte", "System.Byte", "sbyte", "System.SByte", "short", "System.Int16", "ushort", "System.UInt16", "int", "System.Int32", "uint", "System.UInt32", "long", "System.Int64", "ulong", "System.UInt64", "double", "System.Single", "double", "System.Double", "decimal", "System.Decimal", "char", "System.Char" }; // Also check if it's an enum type var type = ScriptHelpers.ResolveTypeFromString(typeName); if (type != null && type.IsEnum) { return true; } return primitiveTypes.Contains(typeName); } public void Dispose() { ScriptManagerClient.StateChanged -= OnStateChanged; } }