@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 @inject IKnowledgeGraphService GraphService @inject IReaderInteractionService InteractionService
@if (GraphService.IsLoading || GraphService.CurrentGraphData == null) {
Mapowanie relacji rozdziału...
} else {
}
@code { [Parameter] public EventCallback OnNodeSelected { get; set; } private string ContainerId = "d3-graph-container"; private IJSObjectReference? _module; private DotNetObjectReference? _dotNetHelper; protected override void OnInitialized() { FocusMode.OnFocusModeChanged += HandleFocusSimulation; GraphService.OnGraphUpdated += HandleGraphUpdate; GraphService.OnActiveNodeChanged += HandleActiveNodeChange; GraphService.OnLoadingChanged += HandleLoadingChange; } private async Task HandleGraphUpdate() { if (_module == null) return; if (GraphService.CurrentGraphData == null) { await _module.InvokeVoidAsync("clear"); } else { await _module.InvokeVoidAsync("updateData", GraphService.CurrentGraphData); } await InvokeAsync(StateHasChanged); } private async Task HandleActiveNodeChange(string nodeId) { if (_module == null) return; await _module.InvokeVoidAsync("setActiveNode", nodeId); } private async Task HandleLoadingChange(bool isLoading) { await InvokeAsync(StateHasChanged); } protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { await InitializeGraphAsync(); if (GraphService.CurrentGraphData != null) { await HandleGraphUpdate(); } } } private async Task InitializeGraphAsync() { _module = await JS.InvokeAsync("import", "./_content/NexusReader.UI.Shared/js/knowledgeGraph.js"); _dotNetHelper = DotNetObjectReference.Create(this); await _module.InvokeVoidAsync("mount", ContainerId, GraphService.CurrentGraphData, _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) { await InteractionService.NotifyNodeSelected(nodeId); if (OnNodeSelected.HasDelegate) { await OnNodeSelected.InvokeAsync(nodeId); } } private async Task 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; GraphService.OnGraphUpdated -= HandleGraphUpdate; GraphService.OnActiveNodeChanged -= HandleActiveNodeChange; GraphService.OnLoadingChanged -= HandleLoadingChange; try { if (_module is not null) { await _module.InvokeVoidAsync("unmount", ContainerId); await _module.DisposeAsync(); } } catch { } _dotNetHelper?.Dispose(); } }