Refs #609 (high RAM with stutters).
Manga / anime covers from sources are typically 720x1080 or larger
(~3 MB decoded RGBA per cover). The library grid, library list and
generic browse / search card widgets render those covers at roughly
150x220 logical pixels, but every cover decoded to its full source
resolution and that decoded bitmap landed in Flutter's `imageCache`.
With 30-50 covers in flight during a normal scroll, the default
100 MB cache filled and the engine started evicting + re-decoding
aggressively — exactly the symptom in #609 (stutters + high RAM).
Mangayomi already had `ExtendedResizeImage` available via the
`extended_image_library` package and used it in one place
(`cachedCompressedNetworkImage`, called only from the History
screen). This commit generalises that pattern.
Add a `coverProvider()` helper in `lib/utils/cached_network.dart`
that wraps `CustomExtendedNetworkImageProvider` in
`ExtendedResizeImage` with a 200 KB encoded budget — sharp at
typical thumbnail size on high-DPR screens, ~3.6x smaller decoded
than a full-resolution cover. Pass through the same `cache` /
`cacheMaxAge` knobs the underlying provider exposes so existing
disk-cache behaviour is preserved.
Swap the three high-traffic thumbnail call sites to use it:
* `lib/modules/library/widgets/library_gridview_widget.dart`
* `lib/modules/library/widgets/library_listview_widget.dart`
* `lib/modules/widgets/manga_image_card_widget.dart`
(both `MangaImageCardWidget` and `MangaImageCardListTileWidget`,
used by browse and search results)
Deliberately not changed:
* The manga / anime detail page hero cover — large display, full
resolution is appropriate.
* Reader pages — already memory-managed by `ChapterPreloadManager`
and need full resolution for actual reading.
* `cachedNetworkImage()` and other lower-traffic thumbnail surfaces
(tracker results, calendar, recommendation grid). Easy to extend
in a follow-up if anyone asks; kept narrow here so review is
manageable.
Verified
* `flutter analyze` clean on every touched file
* `flutter build macos --release` succeeds
* Smoke-tested on macOS with the local-all-fixes build: library
grid, library list and browse card all render identical-looking
covers at typical thumbnail sizes; no visible quality regression
at the displayed scale
Replace per-widget Isar StreamBuilder usage with a single shared
library index managed in MangaHomeScreen.
- Subscribe once to manga updates and build a name -> Manga map
- Pass libraryManga down to card widgets instead of querying per item
- Remove StreamBuilder logic from MangaImageCardWidget and list tile
- Use library data for cover, tracker image, and favorite state
- Add favorite overlay indicator based on libraryManga
- Clean up redundant filtering and improve performance
This reduces rebuild overhead and avoids multiple database listeners
per list/grid item.
- new file item_type_filters.dart for the hiddenItemTypes function.
- reduces code duplication in statistics_screen, categories_screen and base_library_tab_screen
- Extract localizedItemType() from `base_library_tab_screen.dart`
- Add localizedSources() and localizedExtensions() for browse_screen.dart
- Reduce if-statements in statistics_screen.dart
- Reduce if-statements in categories_screen.dart
- Reduce if-statements in browse_screen.dart
- Move the cacheDir creation to storage_provider from `others.dart`, `custom_extended_image_provider.dart` and `storage_usage.dart`.
- Use the correct directory, `getApplicationCacheDirectory()` instead of the `getTemporaryDirectory()` (which is being deleted by the OS regularly) for cache files.
- remove the `_cacheDownloadPath` from `storage_usage.dart` as the path is never being created in the first place, so using that path in `clearCache()` and `_getTotalDiskSpace()` is unnecessary.
- allow multiple local folders
- added support for scanning .epub novels
- added metadata,json support
- scanned entries now appear in browse screen instead of the default library category (can be added to library)
Merge `isLongPressedMangaStateProvider` and `isLongPressedStateProvider`
Both providers do the same thing and it is impossible to change the value of the provider in different places in the app at the same time.
So just use one `isLongPressedStateProvider`. Reduces code duplication and there is no confusion about which one to use.
Previously, the same select bar and button styles were defined in both
`library_screen.dart` and `manga_detail_view.dart`, resulting in repeated code.
This commit extracts the select bar and its buttons into reusable widgets
to reduce duplication and improve readability and maintainability.
- Fixed the PathNotFoundException for Windows, which doesn't use "/" in directories, but "\".
(flutter: PathNotFoundException: Creation failed, path = 'C:\Users\User\AppData\Local\Temp\Mangayomi/cacheimagecover' (OS Error: Das System kann den angegebenen Pfad nicht finden.)
Instead of manually concatenating paths using string interpolation, it now uses the join function properly.
- Also fixed that the App was not able to create the directories by including recursive: true in the else statement.