feat: implement epub service, navigation service, and global error boundary with updated reader UI layouts

This commit is contained in:
2026-04-25 16:16:36 +02:00
parent f3e94c4f42
commit 59074a05a0
23 changed files with 726 additions and 157 deletions
@@ -0,0 +1,9 @@
using FluentResults;
using NexusReader.Application.Queries.Reader;
namespace NexusReader.Application.Abstractions.Services;
public interface IEpubService
{
Task<Result<ReaderPageViewModel>> GetEpubContentAsync(int chapterIndex);
}
@@ -2,4 +2,4 @@ using NexusReader.Application.Abstractions.Messaging;
namespace NexusReader.Application.Queries.Reader;
public record GetReaderPageQuery : IQuery<ReaderPageViewModel>;
public record GetReaderPageQuery(int ChapterIndex = 0) : IQuery<ReaderPageViewModel>;
@@ -1,20 +1,20 @@
using FluentResults;
using NexusReader.Application.Abstractions.Messaging;
using NexusReader.Application.Abstractions.Services;
namespace NexusReader.Application.Queries.Reader;
internal sealed class GetReaderPageQueryHandler : IQueryHandler<GetReaderPageQuery, ReaderPageViewModel>
{
public Task<Result<ReaderPageViewModel>> Handle(GetReaderPageQuery request, CancellationToken cancellationToken)
{
var blocks = new List<ContentBlock>
{
new TextSegmentBlock("renesans-intro", "Renesans, nazywany również odrodzeniem, to epoka w historii kultury europejskiej, która zapoczątkowała odejście od średniowiecznego teocentryzmu na rzecz humanizmu. Narodził się we Włoszech, a dokładnie we Florencji, w XV wieku, skąd promieniował na całą Europę."),
new TextSegmentBlock("medyceusze", "Głównym mecenasem sztuki i nauki we Florencji był potężny ród Medyceuszy. To dzięki ich wsparciu miasto stało się kolebką nowożytnej myśli, gromadząc wokół siebie najwybitniejsze umysły tamtych czasów."),
new AiActionTriggerBlock("da-vinci-ai", "Leonardo da Vinci był jednym z najważniejszych twórców tego okresu. Czy chciałbyś dowiedzieć się więcej o jego najważniejszych wynalazkach, czy wolisz sprawdzić swoją dotychczasową wiedzę?", new List<string> { "Pokaż więcej", "Rozwiąż quiz" }),
new TextSegmentBlock("leonardo-detail", "Człowiek renesansu, uosabiany właśnie przez Leonarda, był wszechstronnie wykształcony. Interesował się sztuką, inżynierią, anatomią i filozofią, stawiając jednostkę w centrum wszechświata.")
};
private readonly IEpubService _epubService;
return Task.FromResult(Result.Ok(new ReaderPageViewModel(blocks)));
public GetReaderPageQueryHandler(IEpubService epubService)
{
_epubService = epubService;
}
public async Task<Result<ReaderPageViewModel>> Handle(GetReaderPageQuery request, CancellationToken cancellationToken)
{
return await _epubService.GetEpubContentAsync(request.ChapterIndex);
}
}
@@ -1,7 +1,11 @@
using System.Text.Json.Serialization;
namespace NexusReader.Application.Queries.Reader;
[JsonDerivedType(typeof(TextSegmentBlock), "text")]
[JsonDerivedType(typeof(AiActionTriggerBlock), "trigger")]
public abstract record ContentBlock(string Id);
public record TextSegmentBlock(string Id, string Content) : ContentBlock(Id);
public record AiActionTriggerBlock(string Id, string Dialogue, List<string> ActionOptions) : ContentBlock(Id);
public record ReaderPageViewModel(List<ContentBlock> Blocks);
public record ReaderPageViewModel(List<ContentBlock> Blocks, int CurrentChapterIndex, int TotalChapters, string ChapterTitle);