99 lines
2.7 KiB
Plaintext
99 lines
2.7 KiB
Plaintext
@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
|
|
|
|
<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>
|
|
}
|
|
</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", "./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();
|
|
}
|
|
}
|