@using MediatR @using NexusReader.Application.Queries.Graph @using Microsoft.JSInterop @using NexusReader.Web.Client.Services @implements IAsyncDisposable @inject IMediator Mediator @inject IJSRuntime JS @inject IFocusModeService FocusMode
@if (GraphData == null) {
Analyzing Chapter Nodes...
}
@code { [Parameter] public EventCallback OnNodeSelected { get; set; } private string ContainerId = "d3-graph-container"; private GraphDataDto? GraphData; private IJSObjectReference? _module; private DotNetObjectReference? _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("import", "./js/knowledgeGraph.js"); _dotNetHelper = DotNetObjectReference.Create(this); await _module.InvokeVoidAsync("mount", ContainerId, GraphData, _dotNetHelper); } [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(); } }