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.
- 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
- 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.
Before fixing the Category Removal Bug (commit 58537281), the "Default" Category would be empty when removing a populated category.
So when there is only one Category left, and the user hides that one Category, `tabCount` would be <= 0, leading to an Exception:
```
_AssertionError ('package:flutter/src/material/tab_controller.dart': Failed assertion: line 116 pos 15: 'initialIndex >= 0 && (length == 0 || initialIndex < length)': is not true.)
```
Now there is a check (`tabCount <= 0`), that IF tabCount is ever <= 0, it would show `_bodyWithoutCategories`.