Files
Nexus.Reader/src/NexusReader.UI.Shared/Services/ReaderNavigationService.cs
T
mjasin 150cbcdc29 refactor(arch): introduce IEbookRepository, ISyncBroadcaster, fix EpubReader path resolution
Critical fixes (review findings #1, #2, #3):
- Create IEbookRepository abstraction in Application layer
- Remove illegal EF Core dependency from IngestEbookCommandHandler
- Create EbookRepository implementation in Infrastructure/Persistence
- Create ISyncBroadcaster in Application/Abstractions/Messaging
- Create SignalRSyncBroadcaster in Infrastructure/RealTime
- Move UpdateReadingProgressCommandHandler from Infrastructure → Application
- Add EbookId to GetReaderPageQuery and IEpubReader signature
- Rewrite EpubReaderService: DB-resolved file path, remove auto-provisioning
- Split EpubService.cs into EpubReaderService.cs + EpubMetadataExtractor.cs
- Add CurrentEbookId to IReaderNavigationService and ReaderNavigationService
- Update WasmEpubReader and /api/epub endpoint for new signature

High severity fixes (#4, #6, #7, #8, #16):
- Change BookStorageService registration from Singleton → Scoped
- Fix empty catch{} in ReaderCanvas JS interop init — now logs warnings
- Replace all Console.WriteLine with ILogger in KnowledgeService + ReaderCanvas
- Cache JsonSerializerOptions as static field in KnowledgeService
- Wrap SyncService Task.Run body in comprehensive try/catch with ILogger

Medium/Low fixes (#11, #13, #14, #15, #18, #20):
- BookIngestionModal.DisposeAsync now nullifies _epubBytes (50MB array)
- KnowledgeCoordinator.OnGraphUpdated: Action<T> → Func<T, Task>
- BookStorageService: Path.Combine → forward-slash string interpolation
- SignalR CancellationToken passed as named parameter (not payload arg)
2026-05-12 21:21:30 +02: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();
}
}
}
}