by extracting the helper methods `_seekTo()` and `_seekBy()`.
This also fixes a potential bug, where in line 1634 it was calculated
`skipDuration - _currentPosition.value.inSeconds` instead of the other way around.
That doesn't make sense. If currentPosition = 120 and skipDuration = 10, this becomes:
`_tempPosition = Duration(seconds: 10 - 120)`; so `= Duration(seconds: -110)`
A negative duration makes no sense as a UI indicator of a seek target.
By extracting:
```
SystemChrome.setEnabledSystemUIMode(
SystemUiMode.manual,
overlays: SystemUiOverlay.values,
);
```
to a file `system_ui.dart` and calling the method `restoreSystemUI()`
Changes:
- Add season-keyword regex (staffel, season, saison, temporada) and
episode-keyword regex (folge, episode, ep.) to reliably extract
the correct number regardless of name format
- parseChapterNumber() now encodes season context into the sort key
(season * 100000 + episode) so multi-season anime sort correctly
across seasons without mixing episode numbers
- Add parseEpisodeNumber() which strips season context and returns
only the episode number within a season; use this for tracker
updates (MAL/AniList/Kitsu) and AniSkip lookups, where the tracker
entry is already season-specific
- Switch updateTrackChapterRead and getAniSkipResults to
parseEpisodeNumber to fix incorrect episode reporting for
multi-season anime
- Compile all RegExp objects as static finals instead of per-call
instantiation
- Refactor duplicated parse logic into a single private _parse()
method with an applySeason flag
- remove the reverse parameter because false is already the model default, so passing it is redundant.
- flip the reverse bool, to keep the chapter sorting of already added manga the same.
Otherwise the user would have to change the sorting orientation for the chapters in the library.
- Add ChapterRecognition for numeric chapter parsing
- Replace old comparators with chapter‑number–aware sorting
- Unify sort modes and simplify list handling
- Rewrite updateMangaDetail with URL‑based dedupe
- Preserve read state across scanlators
- Update existing chapters instead of recreating
- Only create Update entries for new unread chapters
- Recompute smartUpdateDays using combined chapter list
- Remove outdated reversed/index‑based logic
`chapters.length - chapters.reversed.toList().indexOf(chapters.reversed.toList()[finalIndex]) - 1;`
is just the same as
`chapters.length - 1 - finalIndex`
but it creates two lists, which is wasteful.
- Replace synchronous Isar writes with async transactions in `AboutScreen`
- Make `AppLogger.init()` and `dispose()` fully async and guarded with `_busy`
- Remove `StreamController` queue and write directly to the IOSink
- Prevent double‑initialization and race conditions using `_initialized` + `_busy`
- Update log toggle handler to await logger init/dispose for consistency
Fix following Exception when disabling and re-enabling logger:
```
Exception has occurred.
StateError (Bad state: Stream has already been listened to.)
```
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.
Replace per-card Isar tracking streams with a single subscription in
TrackerSectionScreen.
- Build a mediaId -> Track index at the screen level
- Pass resolved Track? into TrackerLibraryImageCard
- Convert TrackerLibraryImageCard to a plain StatelessWidget
- Remove StreamBuilder, ConsumerStatefulWidget, and keep-alive boilerplate
- Keep the same UI while reducing widget-level DB work
This follows the same parent-index pattern used elsewhere and makes
the tracker library view lighter and easier to maintain.