95 lines
3.0 KiB
Plaintext
95 lines
3.0 KiB
Plaintext
@page "/reader"
|
|
@layout ReaderLayout
|
|
@attribute [Authorize]
|
|
@using NexusReader.UI.Shared.Services
|
|
@implements IAsyncDisposable
|
|
@inject IQuizStateService QuizState
|
|
@inject IFocusModeService FocusMode
|
|
@inject IJSRuntime JS
|
|
@inject NavigationManager NavManager
|
|
@inject IReaderNavigationService NavService
|
|
<PageTitle>Nexus E-Reader</PageTitle>
|
|
|
|
<div class="home-reader-container">
|
|
<ReaderCanvas @ref="readerCanvas" />
|
|
</div>
|
|
|
|
|
|
@code {
|
|
private ReaderCanvas? readerCanvas;
|
|
private string? _activeQuizBlockId;
|
|
|
|
private IJSObjectReference? _interopModule;
|
|
private IJSObjectReference? _keydownHandler;
|
|
private DotNetObjectReference<Home>? _dotNetRef;
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
QuizState.OnQuizRequested += HandleQuizRequestedAsync;
|
|
FocusMode.OnFocusModeChanged += HandleUpdate;
|
|
await FocusMode.InitializeAsync();
|
|
|
|
// Handle deep-linking to a specific chapter
|
|
var uri = NavManager.ToAbsoluteUri(NavManager.Uri);
|
|
if (Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(uri.Query).TryGetValue("chapter", out var chapterValue))
|
|
{
|
|
if (int.TryParse(chapterValue, out var chapterIndex))
|
|
{
|
|
await NavService.GoToChapter(chapterIndex);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
|
{
|
|
if (firstRender)
|
|
{
|
|
try {
|
|
_interopModule = await JS.InvokeAsync<IJSObjectReference>("import", "./_content/NexusReader.UI.Shared/js/focusInterop.js");
|
|
_dotNetRef = DotNetObjectReference.Create(this);
|
|
_keydownHandler = await _interopModule.InvokeAsync<IJSObjectReference>("attachKeyboardListener", _dotNetRef);
|
|
} catch { } /* ignored dynamically */
|
|
}
|
|
}
|
|
|
|
[JSInvokable]
|
|
public async Task OnFocusKeypressed()
|
|
{
|
|
await FocusMode.ToggleAsync();
|
|
StateHasChanged();
|
|
}
|
|
|
|
private async Task HandleNodeSelected(string nodeId)
|
|
{
|
|
if (readerCanvas != null)
|
|
{
|
|
await readerCanvas.ScrollToNodeAsync(nodeId);
|
|
}
|
|
}
|
|
|
|
private async Task HandleQuizRequestedAsync(string blockId)
|
|
{
|
|
_activeQuizBlockId = blockId;
|
|
await InvokeAsync(StateHasChanged);
|
|
}
|
|
|
|
private Task HandleUpdate() => InvokeAsync(StateHasChanged);
|
|
|
|
public async ValueTask DisposeAsync()
|
|
{
|
|
QuizState.OnQuizRequested -= HandleQuizRequestedAsync;
|
|
FocusMode.OnFocusModeChanged -= HandleUpdate;
|
|
|
|
if (_interopModule != null && _keydownHandler != null)
|
|
{
|
|
try {
|
|
await _interopModule.InvokeVoidAsync("detachKeyboardListener", _keydownHandler);
|
|
await _interopModule.DisposeAsync();
|
|
await _keydownHandler.DisposeAsync();
|
|
} catch { } // Circuit disconnected catch explicitly
|
|
}
|
|
|
|
_dotNetRef?.Dispose();
|
|
}
|
|
}
|