feat(ui): implement premium mobile-first reader layout with three-tab bottom navigation and assistant FAB

This commit is contained in:
2026-05-27 09:36:02 +02:00
parent a9a670d776
commit e42546d82f
9 changed files with 947 additions and 111 deletions
@@ -13,6 +13,8 @@
@inject IReaderInteractionService InteractionService
@inject ISyncService SyncService
@inject AuthenticationStateProvider AuthStateProvider
@inject IQuizStateService QuizService
@inject IPlatformService PlatformService
@inject ILogger<ReaderCanvas> Logger
<div class="reader-canvas @(ThemeService.IsLightMode ? "theme-light" : "theme-dark")">
@@ -53,6 +55,17 @@
BlockId="@_selectedBlockId"
Coordinates="@_selectionCoords"
FullPageContent="@GetFullPageContent()" />
@if (_isMobile)
{
<button class="nexus-mobile-assistant-fab @(QuizService.HasNewQuiz ? "has-new-quiz" : "")" @onclick="HandleAssistantFabClick" aria-label="Asystent AI">
<NexusIcon Name="robot" Size="24" Class="neon-glow" />
@if (QuizService.HasNewQuiz)
{
<span class="fab-badge"></span>
}
</button>
}
</div>
@code {
@@ -68,17 +81,29 @@
private ElementReference _containerRef;
private bool _isInteractive;
private string? _currentActiveBlockId;
private bool _isMobile = false;
protected override async Task OnInitializedAsync()
{
await Coordinator.ClearAsync();
ThemeService.OnThemeChanged += HandleUpdate;
NavigationService.OnNavigationChanged += OnNavigationChanged;
QuizService.OnQuizUpdated += HandleUpdate;
InteractionService.OnScrollToBlockRequested += HandleScrollRequested;
InteractionService.OnHighlightBlockRequested += HandleHighlightRequested;
InteractionService.OnTextSelected += HandleTextSelected;
SyncService.OnProgressReceived += HandleSyncProgressReceived;
var context = PlatformService.GetDeviceContext();
if (context.IsSuccess)
{
_isMobile = context.Value.DeviceType switch
{
DeviceType.Phone or DeviceType.Tablet => true,
_ => false
};
}
}
protected override async Task OnParametersSetAsync()
@@ -286,10 +311,16 @@
private Task HandleUpdate() => InvokeAsync(StateHasChanged);
private async Task HandleAssistantFabClick()
{
await InteractionService.RequestAssistant();
}
public void Dispose()
{
ThemeService.OnThemeChanged -= HandleUpdate;
NavigationService.OnNavigationChanged -= OnNavigationChanged;
QuizService.OnQuizUpdated -= HandleUpdate;
InteractionService.OnScrollToBlockRequested -= HandleScrollRequested;
InteractionService.OnHighlightBlockRequested -= HandleHighlightRequested;