- Wrap `storage.initDB` in try/catch
- Log initialization errors with stack trace
- Show a minimal `_StartupErrorApp` when startup fails
- Skip post‑launch initialization if DB init did not succeed
- Introduce simple error UI with selectable error text
Refs #609 (high RAM with stutters).
Flutter's `imageCache.maximumSizeBytes` defaults to 100 MB. With a large
manga library and full-resolution covers (a typical 720x1080 cover is
about 3 MB decoded), scrolling fills that cap quickly and the engine
starts evicting and re-decoding aggressively — felt as stutters and
elevated heap on memory-constrained devices.
Set the cap explicitly, sized for the platform: 64 MB on mobile, 256 MB
on desktop. Mobile gets a tight ceiling so the OS does not kill the app
on heap pressure; desktop keeps a generous budget so users with very
large libraries still scroll smoothly.
This is a one-line ceiling, not a fix for the underlying decode-at-
source-resolution behaviour — that is being tracked separately and
will further reduce per-image cache pressure.
The encoded-bytes LRU cache in `CustomExtendedNetworkImageProvider`
(`_memoryCache`, 50 MB) is independent of `PaintingBinding.imageCache`
and is unaffected by this change. So is the disk cache from
`extended_image_library`. Only the in-memory cache of decoded
`ui.Image` objects is bounded here.
Verified:
- `flutter analyze` clean
- `flutter build macos --release` succeeds
- Tested on macOS — Activity Monitor shows the desktop budget is
comfortably above what the existing UI normally needs; mobile budget
is consistent with what the system already imposes via OOM kills.
- Replace child mutation with two clearly named variables
- This is a pure refactor:
- base = the result of wrapping with BotToastInit
- withBackHandler = optionally wrapped with _MouseBackButtonHandler
- No logic changes - just clearer variable names and no reassignment.
Improves readability and maintainability.
════════ Exception caught by Flutter framework ═════════════════════════════════
The following assertion was thrown during runApp:
Zone mismatch.
The Flutter bindings were initialized in a different zone than is now being used. This will likely cause confusion and bugs as any zone-specific configuration will inconsistently use the configuration of the original binding initialization zone or this zone based on hard-to-predict factors such as which zone was active when a particular callback was set.
It is important to use the same zone when calling `ensureInitialized` on the binding as when calling `runApp` later.
To make this warning fatal, set BindingBase.debugZoneErrorsAreFatal to true before the bindings are initialized (i.e. as the first statement in `void main() { }`).
When the exception was thrown, this was the stack:
#0 BindingBase.debugCheckZone.<anonymous closure> (package:flutter/src/foundation/binding.dart:519:31)
binding.dart:519
#1 BindingBase.debugCheckZone (package:flutter/src/foundation/binding.dart:525:6)
binding.dart:525
#2 _runWidget (package:flutter/src/widgets/binding.dart:1680:18)
binding.dart:1680
#3 runApp (package:flutter/src/widgets/binding.dart:1616:3)
binding.dart:1616
#4 main.<anonymous closure> (package:mangayomi/main.dart:108:7)
main.dart:108
<asynchronous suspension>
════════════════════════════════════════════════════════════════════════════════
Exception has occurred.
_AssertionError ('package:bot_toast/src/bot_toast_init.dart': Failed assertion: line 9 pos 10: '_key.currentState != null': is not true.)
- Added AppLockScreen for biometric authentication to unlock the app.
- Introduced security settings screen to enable/disable app lock.
- Integrated local_auth package for biometric authentication support.
- Created security state providers to manage app lock state.
- Updated chapter list tile widget to support dismiss actions for bookmarking and marking chapters as read.
- Enhanced CBZ conversion process to include ComicInfo.xml metadata.
- Added conditional UI elements based on platform capabilities.
- Added Completed & Tracked filter in library
[ERROR:flutter/runtime/dart_vm_initializer.cc(40)] Unhandled Exception: Cannot use the Ref of totalChapterCacheSizeStateProvider after it has been disposed. This typically happens if:
- A provider rebuilt, but the previous "build" was still pending and is still performing operations.
You should therefore either use `ref.onDispose` to cancel pending work, or
check `ref.mounted` after async gaps or anything that could invalidate the provider.
- You tried to use Ref inside `onDispose` or other life-cycles.
This is not supported, as the provider is already being disposed.
#0 Ref._throwIfInvalidUsage (package:riverpod/src/core/ref.dart:220:7)
ref.dart:220
#1 AnyNotifier.state= (package:riverpod/src/core/provider/notifier_provider.dart:91:9)
notifier_provider.dart:91
#2 TotalChapterCacheSizeState.build.<anonymous closure> (package:mangayomi/modules/more/data_and_storage/providers/storage_usage.dart:17:42)
storage_usage.dart:17
#3 Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:948:45)
future_impl.dart:948
#4 Future._propagateToListeners (dart:async/future_impl.dart:977:13)
future_impl.dart:977
#5 Future._completeWithValue (dart:async/future_impl.dart:720:5)
future_impl.dart:720
<asynchronous suspension>
The initialization of discordRPC on iOS and Android was leading to a grey screen (UnimplementedError), preventing the app to paint the Flutter UI.
The flutter_discord_rpc is only available on macOS, Linux and Windows.