`wrapWithKeyboardListener` creates a `FocusNode()` internally on every call.
If no `focusNode` is passed, a new one is allocated every rebuild, which can cause focus flicker.
Without this fix, keyboard focus can be intermittently lost after widget rebuilds,
which would silently swallow keyboard shortcuts.
By extracting:
```
SystemChrome.setEnabledSystemUIMode(
SystemUiMode.manual,
overlays: SystemUiOverlay.values,
);
```
to a file `system_ui.dart` and calling the method `restoreSystemUI()`
When this setting is turned on, the app will automatically mark chapters as read if they have the same chapter number as a chapter you've already read.
This is useful for sources where:
- multiple scanlators upload the same chapter number
- duplicate entries appear due to different naming formats
- a series has repeated or alternative releases of the same chapter
With the setting enabled, you won’t have to manually mark each duplicate as read.
The horizontal layout (_buildHorizontalLayout) used FittedBox as a
shared scaffold for both vertical and horizontal reading modes.
FittedBox passes unbounded width constraints to its child, which caused
RenderFlex to throw "children have non-zero flex but incoming width
constraints are unbounded" when Row + Expanded children were used.
This cascaded into a chain of "RenderBox was not laid out" assertions
all the way up through IntrinsicHeight, ConstrainedBox, FittedBox,
LayoutBuilder, and into the ScrollablePositionedList in
image_view_webtoon.dart.
Fix: split the two layout paths before they reach a scaffold widget.
The vertical path keeps FittedBox (safe, maxWidth is capped at 480px).
The horizontal path uses SizedBox(width: MediaQuery screenWidth) so
Row/Expanded always receive a finite width constraint.
Fix an Exception:
```
════════ Exception caught by rendering library ═════════════════════════════════
A RenderFlex overflowed by 274 pixels on the bottom.
The relevant error-causing widget was:
Column Column:file:///lib/modules/manga/reader/widgets/chapter_transition_page.dart:28:18
════════════════════════════════════════════════════════════════════════════════
```
Improved: The UI adapts to the reading mode now
MangasListState previously stored selected manga IDs as List<int>.
Every visible library card called .contains() on that list once per
rebuild to determine its highlight state, making each check O(n) in
the number of selected items. The provider's own update/selectAll/
selectSome methods also used .contains() and .remove() on a List.
Change the state type to Set<int> throughout, making all membership
checks O(1). Updated all consumers: library_gridview_widget,
library_listview_widget, library_app_bar, library_dialogs, and
MangasSetIsReadState.
call `_processCropBorders()` once, from _initCurrentIndex and after new pages arrive.
Also make _processCropBorders idempotent by the existing _cropBorderCheckList guard
fix for the "jump back" bug that occurred when scrolling up in vertical continuous and webtoon reader modes.
- `ChapterPreloadManager` was maintaining its own `_currentIndex`.
- When prepending previous chapter pages, the index was being incremented
twice (once in the manager + once in `_handlePrevChapterPrepended`).
- This caused `itemScrollController.jumpTo()` to overshoot, resulting in
a visible jump forward (perceived as "jump back" while trying to scroll up).
- Removed all index management (`_currentIndex`, getter, setter, startIndex)
from `ChapterPreloadManager` and `ReaderMemoryManagement`.
- `ChapterPreloadManager` is now a pure data container (only manages `_pages`).
- `_handlePrevChapterPrepended` now captures the **current visible top index**
*before* prepending and adjusts the scroll position only once.
- `_readProgressListener` is now the single source of truth for `_currentIndex`.
- Removed stale `initialScrollIndex` logic from preload initialization.