Files
Nexus.Reader/src/NexusReader.UI.Shared/Services/ReaderNavigationService.cs
T
Antigravity 5a2223a4c8 feat: Ingestion Pipeline Stabilization and WASM Service Proxies (#42)
This PR stabilizes the Nexus Ingestion Engine by implementing functional service proxies for the Blazor WASM client and refining the backend infrastructure for real-time progress tracking and database compatibility.

### Key Changes
- **Infrastructure Stabilization**:
  - Implemented production-grade `EbookRepository` with PostgreSQL `EF.Functions.ILike` support.
  - Enforced `IsReadyForReading = false` state for newly added ebooks (resolves #35).
  - Updated `SignalRSyncBroadcaster` to support targeted user messaging and ingestion-specific progress updates (resolves #37).
- **WASM Client Functional Proxies**:
  - Replaced "Throwing" dummy services with `WasmEbookRepository`, `WasmSyncBroadcaster`, `WasmBookStorageService`, and `WasmEmbeddingGenerator`.
  - These services proxy requests to the backend via a new set of Minimal API endpoints in `NexusReader.Web`.
- **Domain Refinement**:
  - Added `IsReadyForReading` flag to the `Ebook` entity to manage background AI processing states.

### Related Issues
- Fixes #35
- Fixes #36
- Fixes #37

---------

Co-authored-by: Marek Jasiński <jasins.marek@gmail.com>
Reviewed-on: #42
Co-authored-by: Antigravity <antigravity@google.com>
Co-committed-by: Antigravity <antigravity@google.com>
2026-05-13 18:24:24 +00:00

77 lines
2.1 KiB
C#

using Microsoft.AspNetCore.Components;
namespace NexusReader.UI.Shared.Services;
public class ReaderNavigationService : IReaderNavigationService
{
private readonly NavigationManager _navigationManager;
public ReaderNavigationService(NavigationManager navigationManager)
{
_navigationManager = navigationManager;
}
public Guid CurrentEbookId { get; private set; } = Guid.Empty;
public int CurrentChapterIndex { get; private set; } = 0;
public int TotalChapters { get; private set; } = 1;
public string ChapterTitle { get; private set; } = "Loading...";
public event Func<Task>? OnNavigationChanged;
public async Task GoToChapter(int index)
{
if (index < 0 || index >= TotalChapters) return;
CurrentChapterIndex = index;
await NotifyNavigationChangedAsync();
}
public async Task GoToNextChapter()
{
if (CurrentChapterIndex < TotalChapters - 1)
{
await GoToChapter(CurrentChapterIndex + 1);
}
}
public async Task GoToPreviousChapter()
{
if (CurrentChapterIndex > 0)
{
await GoToChapter(CurrentChapterIndex - 1);
}
}
public async Task UpdateMetadataAsync(int currentIndex, int totalChapters, string title)
{
bool changed = false;
if (CurrentChapterIndex != currentIndex) { CurrentChapterIndex = currentIndex; changed = true; }
if (TotalChapters != totalChapters) { TotalChapters = totalChapters; changed = true; }
if (ChapterTitle != title) { ChapterTitle = title; changed = true; }
if (changed)
{
await NotifyNavigationChangedAsync();
}
}
public void NavigateToBook(Guid bookId)
{
CurrentEbookId = bookId;
CurrentChapterIndex = 0;
_navigationManager.NavigateTo($"/reader/{bookId}");
}
private async Task NotifyNavigationChangedAsync()
{
var handlers = OnNavigationChanged?.GetInvocationList();
if (handlers != null)
{
foreach (var handler in handlers.Cast<Func<Task>>())
{
await handler();
}
}
}
}