Initial commit: NexusArchitect Professional Workstation Overhaul
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
@using MediatR
|
||||
@using NexusReader.Application.Queries.Graph
|
||||
@using Microsoft.JSInterop
|
||||
@using NexusReader.UI.Shared.Services
|
||||
@implements IAsyncDisposable
|
||||
@inject IMediator Mediator
|
||||
@inject IJSRuntime JS
|
||||
@inject IFocusModeService FocusMode
|
||||
|
||||
<div class="knowledge-graph-container" id="@ContainerId">
|
||||
@if (GraphData == null)
|
||||
{
|
||||
<div class="loading-state">
|
||||
<NexusIcon Name="robot" Size="48" Class="neon-glow" />
|
||||
<NexusTypography>Analyzing Chapter Nodes...</NexusTypography>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="graph-controls">
|
||||
<button class="zoom-btn" @onclick="ZoomIn" title="Zoom In">+</button>
|
||||
<button class="zoom-btn" @onclick="ZoomOut" title="Zoom Out">−</button>
|
||||
<button class="zoom-btn reset" @onclick="ZoomReset" title="Reset">⟲</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
|
||||
@code {
|
||||
[Parameter] public EventCallback<string> OnNodeSelected { get; set; }
|
||||
|
||||
private string ContainerId = "d3-graph-container";
|
||||
private GraphDataDto? GraphData;
|
||||
private IJSObjectReference? _module;
|
||||
private DotNetObjectReference<KnowledgeGraph>? _dotNetHelper;
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
FocusMode.OnFocusModeChanged += HandleFocusSimulation;
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
var result = await Mediator.Send(new GetKnowledgeGraphQuery());
|
||||
if (result.IsSuccess)
|
||||
{
|
||||
GraphData = result.Value;
|
||||
StateHasChanged();
|
||||
await InitializeGraphAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task InitializeGraphAsync()
|
||||
{
|
||||
_module = await JS.InvokeAsync<IJSObjectReference>("import", "./_content/NexusReader.UI.Shared/js/knowledgeGraph.js");
|
||||
_dotNetHelper = DotNetObjectReference.Create(this);
|
||||
await _module.InvokeVoidAsync("mount", ContainerId, GraphData, _dotNetHelper);
|
||||
}
|
||||
|
||||
private async Task ZoomIn() => await (_module?.InvokeVoidAsync("zoomIn") ?? ValueTask.CompletedTask);
|
||||
private async Task ZoomOut() => await (_module?.InvokeVoidAsync("zoomOut") ?? ValueTask.CompletedTask);
|
||||
private async Task ZoomReset() => await (_module?.InvokeVoidAsync("zoomReset") ?? ValueTask.CompletedTask);
|
||||
|
||||
[JSInvokable]
|
||||
public async Task OnNodeClicked(string nodeId)
|
||||
{
|
||||
if (OnNodeSelected.HasDelegate)
|
||||
{
|
||||
await OnNodeSelected.InvokeAsync(nodeId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private async void HandleFocusSimulation()
|
||||
{
|
||||
if (_module == null) return;
|
||||
try
|
||||
{
|
||||
if (FocusMode.IsFocusModeActive)
|
||||
await _module.InvokeVoidAsync("pause");
|
||||
else
|
||||
await _module.InvokeVoidAsync("resume");
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
FocusMode.OnFocusModeChanged -= HandleFocusSimulation;
|
||||
try
|
||||
{
|
||||
if (_module is not null)
|
||||
{
|
||||
await _module.InvokeVoidAsync("unmount", ContainerId);
|
||||
await _module.DisposeAsync();
|
||||
}
|
||||
}
|
||||
catch (JSDisconnectedException)
|
||||
{
|
||||
// Ignored, the circuit is already closed
|
||||
}
|
||||
catch (TaskCanceledException)
|
||||
{
|
||||
// Ignored, the circuit is already closed
|
||||
}
|
||||
|
||||
_dotNetHelper?.Dispose();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user