Initial commit
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
@implements IAsyncDisposable
|
||||
|
||||
@using RobotNet10.ScriptEditor.Clients
|
||||
@using RobotNet10.ScriptEditor.Models
|
||||
@using RobotNet10.ScriptEditor.Dialogs
|
||||
@using Microsoft.JSInterop
|
||||
@using Microsoft.JSInterop.Implementation
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using RobotNet10.ScriptEditor.Services
|
||||
@using RobotNet10.ScriptEngine.Shared
|
||||
|
||||
@inject IJSRuntime JSRuntime
|
||||
@inject IScriptEngineResource ScriptResource
|
||||
@inject FileManagerHubClient FileManagerClient
|
||||
@inject ScriptManagerHubClient ScriptManagerClient
|
||||
@inject ScriptResourceResolver ResourceResolver
|
||||
@inject ScriptWorkspace Workspace
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IDialogService DialogService
|
||||
@using MudBlazor
|
||||
|
||||
<div class="script-editor-container">
|
||||
<!-- Phần 1: Sidebar (có thể resize ngang) -->
|
||||
<div class="sidebar-container" style="width: @(_sidebarWidth)px;">
|
||||
<div class="sidebar-content">
|
||||
<FileExplorer />
|
||||
<VariableManager />
|
||||
<TaskManager />
|
||||
<MissionManager />
|
||||
</div>
|
||||
<div class="sidebar-resizer"></div>
|
||||
</div>
|
||||
|
||||
<!-- Phần 2 và 3: Editor Area và Console Panel (sắp xếp dọc) -->
|
||||
<div class="editor-console-container">
|
||||
<!-- Phần 2: Editor Area -->
|
||||
<div class="editor-area" id="editor-area">
|
||||
<div class="editor-area-content">
|
||||
<Editor />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Resizer giữa Editor và Console -->
|
||||
<div class="vertical-resizer"></div>
|
||||
|
||||
<!-- Phần 3: Console Panel (có thể resize dọc) -->
|
||||
<div class="console-panel" id="console-panel">
|
||||
<Console />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<MudOverlay Visible="@(!Workspace.IsInitialized)" DarkBackground Modal Absolute AutoClose="false">
|
||||
<MudProgressCircular Color="Color.Primary" Indeterminate="true" />
|
||||
</MudOverlay>
|
||||
|
||||
@code {
|
||||
private int _sidebarWidth = 250; // Chiều rộng mặc định của sidebar (px)
|
||||
private IJSObjectReference? _jsModule;
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
// Subscribe to edit permission revoked event
|
||||
FileManagerClient.EditPermissionRevoked += OnEditPermissionRevoked;
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
try
|
||||
{
|
||||
_jsModule = await JSRuntime.InvokeAsync<IJSObjectReference>(
|
||||
"import", "./_content/RobotNet10.ScriptEditor/scriptEditorResize.js");
|
||||
|
||||
if (_jsModule != null)
|
||||
{
|
||||
await _jsModule.InvokeVoidAsync("initializeLayout");
|
||||
}
|
||||
|
||||
await FileManagerClient.StartAsync();
|
||||
await ScriptManagerClient.StartAsync();
|
||||
|
||||
// Request edit permission before initializing workspace
|
||||
// This will always succeed and force out any previous connection
|
||||
try
|
||||
{
|
||||
await FileManagerClient.RequestEditPermissionAsync();
|
||||
|
||||
// Check if we actually have edit permission (depends on state)
|
||||
var hasPermission = await FileManagerClient.HasEditPermissionAsync();
|
||||
Workspace.IsReadOnly = !hasPermission;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// If request fails, set to read-only
|
||||
Workspace.IsReadOnly = true;
|
||||
}
|
||||
|
||||
var references = await ResourceResolver.GetMetadataReferences(ScriptResource.Modules.ToArray(), ScriptResource.DocModules.ToArray());
|
||||
var rootFolder = await FileManagerClient.GetRootFolderAsync();
|
||||
|
||||
Workspace.Initialize(references, ScriptResource.UsingNamespaces.ToArray(), ScriptResource.AppGlobalType, rootFolder);
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (JSException)
|
||||
{
|
||||
// JavaScript module chưa được load, sẽ được xử lý sau
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Ignore other exceptions but don't crash the component
|
||||
// Mono runtime assertions (e.g., debugger-agent) are non-fatal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnEditPermissionRevoked(string? userId)
|
||||
{
|
||||
// Lock the workspace when permission is revoked
|
||||
Workspace.IsReadOnly = true;
|
||||
StateHasChanged();
|
||||
|
||||
// Show dialog to inform user
|
||||
// User can only close by clicking reload button, not by clicking outside or pressing Escape
|
||||
var options = new DialogOptions
|
||||
{
|
||||
CloseButton = false,
|
||||
CloseOnEscapeKey = false,
|
||||
BackdropClick = false,
|
||||
MaxWidth = MaxWidth.Small,
|
||||
FullWidth = true
|
||||
};
|
||||
|
||||
var parameters = new DialogParameters<PermissionRevokedDialog>
|
||||
{
|
||||
{ x => x.OnReload, new Action(() => NavigationManager.NavigateTo(NavigationManager.Uri, forceLoad: true)) }
|
||||
};
|
||||
|
||||
await DialogService.ShowAsync<PermissionRevokedDialog>("Edit Permission Revoked", parameters, options);
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
// Unsubscribe from events
|
||||
FileManagerClient.EditPermissionRevoked -= OnEditPermissionRevoked;
|
||||
|
||||
if (_jsModule != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _jsModule.InvokeVoidAsync("cleanupLayout");
|
||||
await _jsModule.DisposeAsync();
|
||||
|
||||
// Revoke edit permission before stopping connection
|
||||
if (FileManagerClient.IsConnected)
|
||||
{
|
||||
try
|
||||
{
|
||||
await FileManagerClient.RevokeEditPermissionAsync();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Ignore errors when revoking permission during dispose
|
||||
}
|
||||
}
|
||||
|
||||
await FileManagerClient.StopAsync();
|
||||
await ScriptManagerClient.StopAsync();
|
||||
}
|
||||
catch (JSDisconnectedException)
|
||||
{
|
||||
// Ignore khi JS context đã bị disconnect
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user