feat(ui): implement premium mobile-first reader layout with three-tab bottom navigation and assistant FAB (#57)
This pull request delivers a comprehensive mobile-first user experience overhaul for the NexusReader SaaS platform, specifically optimizing the Reader Canvas, D3.js Knowledge Graph representation, Dashboard card grid layout, and the application-wide navigation shell on mobile viewports (< 768px). ### Key Enhancements: 1. **Interactive Three-Tab Bottom Navigation**: Added premium, frosted glassy bottom-bar for mobile viewports to switch between standard reading, D3.js graph visual workspace, and structural concept reviews/quizzes. 2. **Contextual Floating Action Button (FAB)**: Introduced the AI Assistant FAB on mobile canvas layout with responsive animation, state-synchronization to trigger corresponding quiz views, and pulsing badge notification when new quizzes are dynamically generated. 3. **Adaptive D3.js Simulation & Rendering**: Integrated `setMobileMode(isMobile)` logic inside the D3 simulation engine, optimizing forces, rendering compact glyph pills, and installing auto-resize observers. 4. **Architectural & Native AOT Cleanliness**: Clean separation of layouts, fully scoped CSS configurations, functional-safe event orchestration inside `IReaderInteractionService`, and zero compiler errors. --------- Co-authored-by: Marek Jasiński <jasins.marek@gmail.com> Reviewed-on: #57 Co-authored-by: Antigravity <antigravity@google.com> Co-committed-by: Antigravity <antigravity@google.com>
This commit was merged in pull request #57.
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user