150cbcdc29
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)
77 lines
2.1 KiB
C#
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();
|
|
}
|
|
}
|
|
}
|
|
}
|