style(ui): refactor reader layout grid, fix focus mode layout collapse, fix SVG rendering dots, reorganize intelligence toolbar #69
Reference in New Issue
Block a user
Delete Branch "feature/reader-visual-refactor"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Reorganized the reader toolbar and layout grid to improve visual consistency and layout robustness in Focus Mode. Fixed outline SVG rendering bugs that caused icons to show as solid dots.
Closes #70
I have conducted a thorough review of PR #69 following the NexusReader code review standards.
While the PR introduces excellent features like Focus Mode visual refactoring, light/dark theme variables support, and background selection summaries, there are a few issues (including memory leaks via globally registered event listeners, layout bugs due to class name mismatches, and CSS isolation violations) that need to be addressed.
I have left detailed inline comments on the respective files with actionable code suggestions.
@@ -69,3 +62,3 @@private Task HandleUpdate() => InvokeAsync(StateHasChanged);private async Task HandleThemeChangedAsync() => await InvokeAsync(StateHasChanged);🟢 Minor/Suggestion: The method
HandleThemeChangedAsyncdoes not need to be marked asasync Tasksince it only awaits a single task and does not contain other logic.You can simplify it to avoid state machine generation overhead:
@@ -428,5 +428,5 @@{await InteractionService.RequestAssistant();}public async ValueTask DisposeAsync()🔴 Blocking: Missing teardown for the text selection listener.
In
DisposeAsync, you should invoke a teardown function on theselectionHandler.jsmodule to unregister the document event listeners and clean up memory.Actionable suggestion:
@@ -208,0 +229,4 @@try{var result = await RequestSummaryAndQuizAsync(text, tenantId);if (result.IsSuccess)🟡 Design/Architecture: If
RequestSummaryAndQuizAsyncfails, the background task completes, but the loading state is cleared and no error feedback is provided to the UI or logged.Consider exposing an error state or logging the failure to improve user feedback.
Actionable suggestion:
@@ -89,2 +178,4 @@}/* Scoped Component overrides for Light Mode (Bypassing Blazor CSS isolation) */.theme-light .intelligence-toolbar {🟡 Design/Architecture: Global CSS overrides for light-mode component colors (like
.theme-light .intelligence-toolbar) violate the architectural separation of concerns.Component-specific styling should live inside their respective scoped stylesheets (e.g.,
IntelligenceToolbar.razor.css) rather than the globalapp.css. Using!importanthere also creates styling conflicts (e.g., the scoped stylesheet has a background of#ffffff, but this global rule overrides it with#f5f5f4).Please move these overrides into
IntelligenceToolbar.razor.css.🟡 Design/Architecture: The class selector
.nexus-buttonhere (and.platform-desktop .nexus-buttonat line 360) is targeting a class that does not exist in any component.The reusable component
NexusButton.razoruses the class.nexus-btn. This class name mismatch prevents platform-specific touch target sizes (such as safe-area-insets, mobile touch targetsmin-height: var(--touch-target-size)) from being applied to the button element.Actionable suggestion:
@@ -39,3 +108,8 @@ export function initSelectionListener(dotNetHelper, container) {document.addEventListener('selectionchange', handleSelection);🔴 Blocking: Registering event listeners on
documentglobally insideinitSelectionListenerwithout a corresponding teardown mechanism causes a memory leak.Every time
ReaderCanvasis loaded or the chapter changes, a newselectionchangelistener is added todocument. These listeners will accumulate over time, leading to degraded performance and multiple handler invocations.Actionable suggestion:
Track the handler function and export a teardown function:
@@ -205,3 +205,3 @@}await dbContext.Database.MigrateAsync();🟢 Minor/Suggestion: The removal of automatic database migration (
MigrateAsync()) at startup is a great architectural choice. It ensures Native AOT compatibility and avoids database locking contention in multi-instance production environments.Please make sure this is documented in the developer onboarding/setup instructions so manual CLI migrations (
dotnet ef database update) are run during local environment setup.I have resolved all 7 feedback items under
#issuecomment-429(comments 422 to 428):.intelligence-toolbarfromapp.cssto scopedIntelligenceToolbar.razor.cssand removed!important..nexus-buttonwith.nexus-btninapp.cssto correctly target theNexusButton.razorcomponent's style classes for mobile/desktop.destroySelectionListener()function inselectionHandler.js, and updatedReaderCanvas.razorto hold reference to_selectionModuleand invoke cleanup onDisposeAsync.KnowledgeCoordinator.cswhenRequestSummaryAndQuizAsyncfails during the selection summary.README.mdfile.HandleThemeChangedAsyncinIntelligenceToolbar.razorto returnTaskdirectly instead of beingasync Task.Verified via local compilation check (
dotnet buildpassed with 0 errors) and successful test runs (all 20 tests passed).