mirror of
https://github.com/kodjodevf/mangayomi.git
synced 2026-05-08 01:10:35 +00:00
Merge pull request #536 from NBA2K1/main
Refactor select bar widget and unify manga read state logic
This commit is contained in:
commit
a15afd4334
13 changed files with 429 additions and 711 deletions
|
|
@ -18,11 +18,13 @@ import 'package:mangayomi/models/settings.dart';
|
|||
import 'package:mangayomi/models/update.dart';
|
||||
import 'package:mangayomi/modules/library/providers/add_torrent.dart';
|
||||
import 'package:mangayomi/modules/library/providers/local_archive.dart';
|
||||
import 'package:mangayomi/modules/manga/detail/providers/state_providers.dart';
|
||||
import 'package:mangayomi/modules/manga/detail/providers/update_manga_detail_providers.dart';
|
||||
import 'package:mangayomi/modules/more/categories/providers/isar_providers.dart';
|
||||
import 'package:mangayomi/modules/more/providers/downloaded_only_state_provider.dart';
|
||||
import 'package:mangayomi/modules/more/settings/appearance/providers/theme_mode_state_provider.dart';
|
||||
import 'package:mangayomi/modules/more/settings/sync/providers/sync_providers.dart';
|
||||
import 'package:mangayomi/modules/widgets/bottom_select_bar.dart';
|
||||
import 'package:mangayomi/modules/widgets/category_selection_dialog.dart';
|
||||
import 'package:mangayomi/modules/widgets/custom_draggable_tabbar.dart';
|
||||
import 'package:mangayomi/modules/widgets/manga_image_card_widget.dart';
|
||||
|
|
@ -570,159 +572,85 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
|||
return const ProgressCenter();
|
||||
},
|
||||
),
|
||||
bottomNavigationBar: Consumer(
|
||||
builder: (context, ref, child) {
|
||||
final isLongPressed = ref.watch(isLongPressedMangaStateProvider);
|
||||
final color = Theme.of(context).textTheme.bodyLarge!.color!;
|
||||
bottomNavigationBar: Builder(
|
||||
builder: (context) {
|
||||
final mangaIds = ref.watch(mangasListStateProvider);
|
||||
return AnimatedContainer(
|
||||
curve: Curves.easeIn,
|
||||
decoration: BoxDecoration(
|
||||
color: context.primaryColor.withValues(alpha: 0.2),
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(20),
|
||||
topRight: Radius.circular(20),
|
||||
final color = Theme.of(context).textTheme.bodyLarge!.color!;
|
||||
return BottomSelectBar(
|
||||
isVisible: ref.watch(isLongPressedStateProvider),
|
||||
actions: [
|
||||
BottomSelectButton(
|
||||
icon: Icon(Icons.label_outline_rounded, color: color),
|
||||
onPressed: () {
|
||||
final mangaIdsList = ref.watch(mangasListStateProvider);
|
||||
final List<Manga> bulkMangas = mangaIdsList
|
||||
.map((id) => isar.mangas.getSync(id)!)
|
||||
.toList();
|
||||
showCategorySelectionDialog(
|
||||
context: context,
|
||||
ref: ref,
|
||||
itemType: widget.itemType,
|
||||
bulkMangas: bulkMangas,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
duration: const Duration(milliseconds: 100),
|
||||
height: isLongPressed ? 70 : 0,
|
||||
width: context.width(1),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
height: 70,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
shadowColor: Colors.transparent,
|
||||
elevation: 0,
|
||||
backgroundColor: Colors.transparent,
|
||||
),
|
||||
onPressed: () {
|
||||
final mangaIdsList = ref.watch(
|
||||
mangasListStateProvider,
|
||||
);
|
||||
final List<Manga> bulkMangas = mangaIdsList
|
||||
.map((id) => isar.mangas.getSync(id)!)
|
||||
.toList();
|
||||
showCategorySelectionDialog(
|
||||
context: context,
|
||||
ref: ref,
|
||||
itemType: widget.itemType,
|
||||
bulkMangas: bulkMangas,
|
||||
);
|
||||
},
|
||||
child: Icon(
|
||||
Icons.label_outline_rounded,
|
||||
color: color,
|
||||
),
|
||||
BottomSelectButton(
|
||||
icon: Icon(Icons.done_all_sharp, color: color),
|
||||
onPressed: () {
|
||||
ref
|
||||
.read(
|
||||
mangasSetIsReadStateProvider(
|
||||
mangaIds: mangaIds,
|
||||
markAsRead: true,
|
||||
).notifier,
|
||||
)
|
||||
.set();
|
||||
ref.invalidate(
|
||||
getAllMangaWithoutCategoriesStreamProvider(
|
||||
itemType: widget.itemType,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
height: 70,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: 0,
|
||||
backgroundColor: Colors.transparent,
|
||||
shadowColor: Colors.transparent,
|
||||
),
|
||||
onPressed: () {
|
||||
ref
|
||||
.read(
|
||||
mangasSetIsReadStateProvider(
|
||||
mangaIds: mangaIds,
|
||||
).notifier,
|
||||
)
|
||||
.set();
|
||||
ref.invalidate(
|
||||
getAllMangaWithoutCategoriesStreamProvider(
|
||||
itemType: widget.itemType,
|
||||
),
|
||||
);
|
||||
ref.invalidate(
|
||||
getAllMangaStreamProvider(
|
||||
categoryId: null,
|
||||
itemType: widget.itemType,
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Icon(Icons.done_all_sharp, color: color),
|
||||
);
|
||||
ref.invalidate(
|
||||
getAllMangaStreamProvider(
|
||||
categoryId: null,
|
||||
itemType: widget.itemType,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
height: 70,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: 0,
|
||||
backgroundColor: Colors.transparent,
|
||||
shadowColor: Colors.transparent,
|
||||
),
|
||||
onPressed: () {
|
||||
ref
|
||||
.read(
|
||||
mangasSetUnReadStateProvider(
|
||||
mangaIds: mangaIds,
|
||||
).notifier,
|
||||
)
|
||||
.set();
|
||||
ref.invalidate(
|
||||
getAllMangaWithoutCategoriesStreamProvider(
|
||||
itemType: widget.itemType,
|
||||
),
|
||||
);
|
||||
ref.invalidate(
|
||||
getAllMangaStreamProvider(
|
||||
categoryId: null,
|
||||
itemType: widget.itemType,
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Icon(Icons.remove_done_sharp, color: color),
|
||||
);
|
||||
},
|
||||
),
|
||||
BottomSelectButton(
|
||||
icon: Icon(Icons.remove_done_sharp, color: color),
|
||||
onPressed: () {
|
||||
ref
|
||||
.read(
|
||||
mangasSetIsReadStateProvider(
|
||||
mangaIds: mangaIds,
|
||||
markAsRead: false,
|
||||
).notifier,
|
||||
)
|
||||
.set();
|
||||
ref.invalidate(
|
||||
getAllMangaWithoutCategoriesStreamProvider(
|
||||
itemType: widget.itemType,
|
||||
),
|
||||
),
|
||||
),
|
||||
// Expanded(
|
||||
// child: SizedBox(
|
||||
// height: 70,
|
||||
// child: ElevatedButton(
|
||||
// style: ElevatedButton.styleFrom(
|
||||
// elevation: 0,
|
||||
// backgroundColor: Colors.transparent,
|
||||
// shadowColor: Colors.transparent,
|
||||
// ),
|
||||
// onPressed: () {},
|
||||
// child: Icon(
|
||||
// Icons.download_outlined,
|
||||
// color: color,
|
||||
// )),
|
||||
// ),
|
||||
// ),
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
height: 70,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: 0,
|
||||
backgroundColor: Colors.transparent,
|
||||
shadowColor: Colors.transparent,
|
||||
),
|
||||
onPressed: () {
|
||||
_deleteManga();
|
||||
},
|
||||
child: Icon(
|
||||
Icons.delete_outline_outlined,
|
||||
color: color,
|
||||
),
|
||||
);
|
||||
ref.invalidate(
|
||||
getAllMangaStreamProvider(
|
||||
categoryId: null,
|
||||
itemType: widget.itemType,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
// BottomBarAction(
|
||||
// icon: Icon(Icons.download_outlined, color: color),
|
||||
// onPressed: () {}
|
||||
// ),
|
||||
BottomSelectButton(
|
||||
icon: Icon(Icons.delete_outline_outlined, color: color),
|
||||
onPressed: () => _deleteManga(),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
|
|
@ -1229,7 +1157,7 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
|||
|
||||
ref.read(mangasListStateProvider.notifier).clear();
|
||||
ref
|
||||
.read(isLongPressedMangaStateProvider.notifier)
|
||||
.read(isLongPressedStateProvider.notifier)
|
||||
.update(false);
|
||||
if (mounted) {
|
||||
Navigator.pop(context);
|
||||
|
|
@ -1882,7 +1810,7 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
|||
int? categoryId,
|
||||
Settings settings,
|
||||
) {
|
||||
final isLongPressed = ref.watch(isLongPressedMangaStateProvider);
|
||||
final isLongPressed = ref.watch(isLongPressedStateProvider);
|
||||
final mangaIdsList = ref.watch(mangasListStateProvider);
|
||||
final manga = categoryId == null
|
||||
? ref.watch(
|
||||
|
|
@ -1911,7 +1839,7 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
|||
ref.read(mangasListStateProvider.notifier).clear();
|
||||
|
||||
ref
|
||||
.read(isLongPressedMangaStateProvider.notifier)
|
||||
.read(isLongPressedStateProvider.notifier)
|
||||
.update(!isLongPressed);
|
||||
},
|
||||
icon: const Icon(Icons.clear),
|
||||
|
|
@ -1936,7 +1864,7 @@ class _LibraryScreenState extends ConsumerState<LibraryScreen>
|
|||
.selectSome(manga);
|
||||
}
|
||||
ref
|
||||
.read(isLongPressedMangaStateProvider.notifier)
|
||||
.read(isLongPressedStateProvider.notifier)
|
||||
.update(false);
|
||||
} else {
|
||||
for (var manga in data) {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import 'package:mangayomi/main.dart';
|
|||
import 'package:mangayomi/models/chapter.dart';
|
||||
import 'package:mangayomi/models/manga.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:mangayomi/modules/manga/detail/providers/state_providers.dart';
|
||||
import 'package:mangayomi/modules/manga/reader/providers/reader_controller_provider.dart';
|
||||
import 'package:mangayomi/providers/l10n_providers.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
|
|
@ -785,7 +786,7 @@ class MangasListState extends _$MangasListState {
|
|||
newList.add(value.id!);
|
||||
}
|
||||
if (newList.isEmpty) {
|
||||
ref.read(isLongPressedMangaStateProvider.notifier).update(false);
|
||||
ref.read(isLongPressedStateProvider.notifier).update(false);
|
||||
}
|
||||
state = newList;
|
||||
}
|
||||
|
|
@ -814,65 +815,24 @@ class MangasListState extends _$MangasListState {
|
|||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class IsLongPressedMangaState extends _$IsLongPressedMangaState {
|
||||
@override
|
||||
bool build() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void update(bool value) {
|
||||
state = value;
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class MangasSetIsReadState extends _$MangasSetIsReadState {
|
||||
@override
|
||||
void build({required List<int> mangaIds}) {}
|
||||
void build({required List<int> mangaIds, required bool markAsRead}) {}
|
||||
|
||||
void set() {
|
||||
final allChapters = <Chapter>[];
|
||||
final allMangas = <Manga>[];
|
||||
final now = DateTime.now().millisecondsSinceEpoch;
|
||||
for (var mangaid in mangaIds) {
|
||||
final manga = isar.mangas.getSync(mangaid)!;
|
||||
final chapters = manga.chapters;
|
||||
if (chapters.isNotEmpty) {
|
||||
chapters.last.updateTrackChapterRead(ref);
|
||||
for (var chapter in chapters) {
|
||||
chapter.isRead = true;
|
||||
chapter.lastPageRead = "1";
|
||||
chapter.updatedAt = DateTime.now().millisecondsSinceEpoch;
|
||||
chapter.manga.value = manga;
|
||||
allChapters.add(chapter);
|
||||
}
|
||||
allMangas.add(manga);
|
||||
}
|
||||
}
|
||||
|
||||
isar.writeTxnSync(() {
|
||||
isar.chapters.putAllSync(allChapters);
|
||||
isar.mangas.putAllSync(allMangas);
|
||||
});
|
||||
|
||||
ref.read(isLongPressedMangaStateProvider.notifier).update(false);
|
||||
ref.read(mangasListStateProvider.notifier).clear();
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class MangasSetUnReadState extends _$MangasSetUnReadState {
|
||||
@override
|
||||
void build({required List<int> mangaIds}) {}
|
||||
|
||||
void set() {
|
||||
final allChapters = <Chapter>[];
|
||||
final allMangas = <Manga>[];
|
||||
for (var mangaid in mangaIds) {
|
||||
final manga = isar.mangas.getSync(mangaid)!;
|
||||
for (var chapter in manga.chapters) {
|
||||
chapter.isRead = false;
|
||||
chapter.updatedAt = DateTime.now().millisecondsSinceEpoch;
|
||||
if (chapters.isEmpty) continue;
|
||||
if (markAsRead) chapters.last.updateTrackChapterRead(ref);
|
||||
for (var chapter in chapters) {
|
||||
chapter.isRead = markAsRead;
|
||||
if (markAsRead) chapter.lastPageRead = "1";
|
||||
chapter.updatedAt = now;
|
||||
chapter.manga.value = manga;
|
||||
allChapters.add(chapter);
|
||||
}
|
||||
|
|
@ -884,7 +844,7 @@ class MangasSetUnReadState extends _$MangasSetUnReadState {
|
|||
isar.mangas.putAllSync(allMangas);
|
||||
});
|
||||
|
||||
ref.read(isLongPressedMangaStateProvider.notifier).update(false);
|
||||
ref.read(isLongPressedStateProvider.notifier).update(false);
|
||||
ref.read(mangasListStateProvider.notifier).clear();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2517,7 +2517,7 @@ class _SortLibraryMangaStateProviderElement
|
|||
Settings get settings => (origin as SortLibraryMangaStateProvider).settings;
|
||||
}
|
||||
|
||||
String _$mangasListStateHash() => r'ad1cc419dfd3793bfc8c90f3ce8b7726561dd9ad';
|
||||
String _$mangasListStateHash() => r'bbd2e3600ec22a774b1774ae3c221815e52bfef6';
|
||||
|
||||
/// See also [MangasListState].
|
||||
@ProviderFor(MangasListState)
|
||||
|
|
@ -2533,32 +2533,17 @@ final mangasListStateProvider =
|
|||
);
|
||||
|
||||
typedef _$MangasListState = AutoDisposeNotifier<List<int>>;
|
||||
String _$isLongPressedMangaStateHash() =>
|
||||
r'f77076b0335e92df26a75ea0c338d4214a330184';
|
||||
|
||||
/// See also [IsLongPressedMangaState].
|
||||
@ProviderFor(IsLongPressedMangaState)
|
||||
final isLongPressedMangaStateProvider =
|
||||
AutoDisposeNotifierProvider<IsLongPressedMangaState, bool>.internal(
|
||||
IsLongPressedMangaState.new,
|
||||
name: r'isLongPressedMangaStateProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$isLongPressedMangaStateHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$IsLongPressedMangaState = AutoDisposeNotifier<bool>;
|
||||
String _$mangasSetIsReadStateHash() =>
|
||||
r'8f4f7f22ea8e82cf2370fb997033e1a4ec03168f';
|
||||
r'2a1b1005e2ed5068d36188a3fb969d21b64bfef6';
|
||||
|
||||
abstract class _$MangasSetIsReadState
|
||||
extends BuildlessAutoDisposeNotifier<void> {
|
||||
late final List<int> mangaIds;
|
||||
late final bool markAsRead;
|
||||
|
||||
void build({
|
||||
required List<int> mangaIds,
|
||||
required bool markAsRead,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -2574,9 +2559,11 @@ class MangasSetIsReadStateFamily extends Family<void> {
|
|||
/// See also [MangasSetIsReadState].
|
||||
MangasSetIsReadStateProvider call({
|
||||
required List<int> mangaIds,
|
||||
required bool markAsRead,
|
||||
}) {
|
||||
return MangasSetIsReadStateProvider(
|
||||
mangaIds: mangaIds,
|
||||
markAsRead: markAsRead,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -2586,6 +2573,7 @@ class MangasSetIsReadStateFamily extends Family<void> {
|
|||
) {
|
||||
return call(
|
||||
mangaIds: provider.mangaIds,
|
||||
markAsRead: provider.markAsRead,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -2610,8 +2598,11 @@ class MangasSetIsReadStateProvider
|
|||
/// See also [MangasSetIsReadState].
|
||||
MangasSetIsReadStateProvider({
|
||||
required List<int> mangaIds,
|
||||
required bool markAsRead,
|
||||
}) : this._internal(
|
||||
() => MangasSetIsReadState()..mangaIds = mangaIds,
|
||||
() => MangasSetIsReadState()
|
||||
..mangaIds = mangaIds
|
||||
..markAsRead = markAsRead,
|
||||
from: mangasSetIsReadStateProvider,
|
||||
name: r'mangasSetIsReadStateProvider',
|
||||
debugGetCreateSourceHash:
|
||||
|
|
@ -2622,6 +2613,7 @@ class MangasSetIsReadStateProvider
|
|||
allTransitiveDependencies:
|
||||
MangasSetIsReadStateFamily._allTransitiveDependencies,
|
||||
mangaIds: mangaIds,
|
||||
markAsRead: markAsRead,
|
||||
);
|
||||
|
||||
MangasSetIsReadStateProvider._internal(
|
||||
|
|
@ -2632,9 +2624,11 @@ class MangasSetIsReadStateProvider
|
|||
required super.debugGetCreateSourceHash,
|
||||
required super.from,
|
||||
required this.mangaIds,
|
||||
required this.markAsRead,
|
||||
}) : super.internal();
|
||||
|
||||
final List<int> mangaIds;
|
||||
final bool markAsRead;
|
||||
|
||||
@override
|
||||
void runNotifierBuild(
|
||||
|
|
@ -2642,6 +2636,7 @@ class MangasSetIsReadStateProvider
|
|||
) {
|
||||
return notifier.build(
|
||||
mangaIds: mangaIds,
|
||||
markAsRead: markAsRead,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -2650,13 +2645,16 @@ class MangasSetIsReadStateProvider
|
|||
return ProviderOverride(
|
||||
origin: this,
|
||||
override: MangasSetIsReadStateProvider._internal(
|
||||
() => create()..mangaIds = mangaIds,
|
||||
() => create()
|
||||
..mangaIds = mangaIds
|
||||
..markAsRead = markAsRead,
|
||||
from: from,
|
||||
name: null,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
debugGetCreateSourceHash: null,
|
||||
mangaIds: mangaIds,
|
||||
markAsRead: markAsRead,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
@ -2669,13 +2667,16 @@ class MangasSetIsReadStateProvider
|
|||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is MangasSetIsReadStateProvider && other.mangaIds == mangaIds;
|
||||
return other is MangasSetIsReadStateProvider &&
|
||||
other.mangaIds == mangaIds &&
|
||||
other.markAsRead == markAsRead;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||
hash = _SystemHash.combine(hash, mangaIds.hashCode);
|
||||
hash = _SystemHash.combine(hash, markAsRead.hashCode);
|
||||
|
||||
return _SystemHash.finish(hash);
|
||||
}
|
||||
|
|
@ -2686,6 +2687,9 @@ class MangasSetIsReadStateProvider
|
|||
mixin MangasSetIsReadStateRef on AutoDisposeNotifierProviderRef<void> {
|
||||
/// The parameter `mangaIds` of this provider.
|
||||
List<int> get mangaIds;
|
||||
|
||||
/// The parameter `markAsRead` of this provider.
|
||||
bool get markAsRead;
|
||||
}
|
||||
|
||||
class _MangasSetIsReadStateProviderElement
|
||||
|
|
@ -2695,153 +2699,8 @@ class _MangasSetIsReadStateProviderElement
|
|||
|
||||
@override
|
||||
List<int> get mangaIds => (origin as MangasSetIsReadStateProvider).mangaIds;
|
||||
}
|
||||
|
||||
String _$mangasSetUnReadStateHash() =>
|
||||
r'09ddd287b110fd76494f9f56bd5cf76f58936f1f';
|
||||
|
||||
abstract class _$MangasSetUnReadState
|
||||
extends BuildlessAutoDisposeNotifier<void> {
|
||||
late final List<int> mangaIds;
|
||||
|
||||
void build({
|
||||
required List<int> mangaIds,
|
||||
});
|
||||
}
|
||||
|
||||
/// See also [MangasSetUnReadState].
|
||||
@ProviderFor(MangasSetUnReadState)
|
||||
const mangasSetUnReadStateProvider = MangasSetUnReadStateFamily();
|
||||
|
||||
/// See also [MangasSetUnReadState].
|
||||
class MangasSetUnReadStateFamily extends Family<void> {
|
||||
/// See also [MangasSetUnReadState].
|
||||
const MangasSetUnReadStateFamily();
|
||||
|
||||
/// See also [MangasSetUnReadState].
|
||||
MangasSetUnReadStateProvider call({
|
||||
required List<int> mangaIds,
|
||||
}) {
|
||||
return MangasSetUnReadStateProvider(
|
||||
mangaIds: mangaIds,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
MangasSetUnReadStateProvider getProviderOverride(
|
||||
covariant MangasSetUnReadStateProvider provider,
|
||||
) {
|
||||
return call(
|
||||
mangaIds: provider.mangaIds,
|
||||
);
|
||||
}
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||
_allTransitiveDependencies;
|
||||
|
||||
@override
|
||||
String? get name => r'mangasSetUnReadStateProvider';
|
||||
}
|
||||
|
||||
/// See also [MangasSetUnReadState].
|
||||
class MangasSetUnReadStateProvider
|
||||
extends AutoDisposeNotifierProviderImpl<MangasSetUnReadState, void> {
|
||||
/// See also [MangasSetUnReadState].
|
||||
MangasSetUnReadStateProvider({
|
||||
required List<int> mangaIds,
|
||||
}) : this._internal(
|
||||
() => MangasSetUnReadState()..mangaIds = mangaIds,
|
||||
from: mangasSetUnReadStateProvider,
|
||||
name: r'mangasSetUnReadStateProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$mangasSetUnReadStateHash,
|
||||
dependencies: MangasSetUnReadStateFamily._dependencies,
|
||||
allTransitiveDependencies:
|
||||
MangasSetUnReadStateFamily._allTransitiveDependencies,
|
||||
mangaIds: mangaIds,
|
||||
);
|
||||
|
||||
MangasSetUnReadStateProvider._internal(
|
||||
super._createNotifier, {
|
||||
required super.name,
|
||||
required super.dependencies,
|
||||
required super.allTransitiveDependencies,
|
||||
required super.debugGetCreateSourceHash,
|
||||
required super.from,
|
||||
required this.mangaIds,
|
||||
}) : super.internal();
|
||||
|
||||
final List<int> mangaIds;
|
||||
|
||||
@override
|
||||
void runNotifierBuild(
|
||||
covariant MangasSetUnReadState notifier,
|
||||
) {
|
||||
return notifier.build(
|
||||
mangaIds: mangaIds,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Override overrideWith(MangasSetUnReadState Function() create) {
|
||||
return ProviderOverride(
|
||||
origin: this,
|
||||
override: MangasSetUnReadStateProvider._internal(
|
||||
() => create()..mangaIds = mangaIds,
|
||||
from: from,
|
||||
name: null,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
debugGetCreateSourceHash: null,
|
||||
mangaIds: mangaIds,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
AutoDisposeNotifierProviderElement<MangasSetUnReadState, void>
|
||||
createElement() {
|
||||
return _MangasSetUnReadStateProviderElement(this);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is MangasSetUnReadStateProvider && other.mangaIds == mangaIds;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||
hash = _SystemHash.combine(hash, mangaIds.hashCode);
|
||||
|
||||
return _SystemHash.finish(hash);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||
// ignore: unused_element
|
||||
mixin MangasSetUnReadStateRef on AutoDisposeNotifierProviderRef<void> {
|
||||
/// The parameter `mangaIds` of this provider.
|
||||
List<int> get mangaIds;
|
||||
}
|
||||
|
||||
class _MangasSetUnReadStateProviderElement
|
||||
extends AutoDisposeNotifierProviderElement<MangasSetUnReadState, void>
|
||||
with MangasSetUnReadStateRef {
|
||||
_MangasSetUnReadStateProviderElement(super.provider);
|
||||
|
||||
@override
|
||||
List<int> get mangaIds => (origin as MangasSetUnReadStateProvider).mangaIds;
|
||||
bool get markAsRead => (origin as MangasSetIsReadStateProvider).markAsRead;
|
||||
}
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import 'package:mangayomi/models/history.dart';
|
|||
import 'package:mangayomi/modules/library/providers/isar_providers.dart';
|
||||
import 'package:mangayomi/modules/library/providers/library_state_provider.dart';
|
||||
import 'package:mangayomi/models/manga.dart';
|
||||
import 'package:mangayomi/modules/manga/detail/providers/state_providers.dart';
|
||||
import 'package:mangayomi/modules/widgets/custom_extended_image_provider.dart';
|
||||
import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
|
||||
import 'package:mangayomi/utils/constant.dart';
|
||||
|
|
@ -52,7 +53,7 @@ class _LibraryGridViewWidgetState extends State<LibraryGridViewWidget> {
|
|||
Widget build(BuildContext context) {
|
||||
return Consumer(
|
||||
builder: (context, ref, child) {
|
||||
final isLongPressed = ref.watch(isLongPressedMangaStateProvider);
|
||||
final isLongPressed = ref.watch(isLongPressedStateProvider);
|
||||
final itemType = widget.itemType;
|
||||
|
||||
final gridSize = ref.watch(
|
||||
|
|
@ -430,7 +431,7 @@ class _LibraryGridViewWidgetState extends State<LibraryGridViewWidget> {
|
|||
) {
|
||||
if (!isLongPressed) {
|
||||
ref.read(mangasListStateProvider.notifier).update(entry);
|
||||
ref.read(isLongPressedMangaStateProvider.notifier).update(!isLongPressed);
|
||||
ref.read(isLongPressedStateProvider.notifier).update(!isLongPressed);
|
||||
} else {
|
||||
ref.read(mangasListStateProvider.notifier).update(entry);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import 'package:mangayomi/models/history.dart';
|
|||
import 'package:mangayomi/modules/library/providers/isar_providers.dart';
|
||||
import 'package:mangayomi/modules/library/providers/library_state_provider.dart';
|
||||
import 'package:mangayomi/models/manga.dart';
|
||||
import 'package:mangayomi/modules/manga/detail/providers/state_providers.dart';
|
||||
import 'package:mangayomi/modules/widgets/custom_extended_image_provider.dart';
|
||||
import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
|
||||
import 'package:mangayomi/utils/constant.dart';
|
||||
|
|
@ -44,7 +45,7 @@ class LibraryListViewWidget extends StatelessWidget {
|
|||
bool isLocalArchive = entry.isLocalArchive ?? false;
|
||||
return Consumer(
|
||||
builder: (context, ref, child) {
|
||||
final isLongPressed = ref.watch(isLongPressedMangaStateProvider);
|
||||
final isLongPressed = ref.watch(isLongPressedStateProvider);
|
||||
return Material(
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
color: Colors.transparent,
|
||||
|
|
@ -80,7 +81,7 @@ class LibraryListViewWidget extends StatelessWidget {
|
|||
ref.read(mangasListStateProvider.notifier).update(entry);
|
||||
|
||||
ref
|
||||
.read(isLongPressedMangaStateProvider.notifier)
|
||||
.read(isLongPressedStateProvider.notifier)
|
||||
.update(!isLongPressed);
|
||||
} else {
|
||||
ref.read(mangasListStateProvider.notifier).update(entry);
|
||||
|
|
@ -91,7 +92,7 @@ class LibraryListViewWidget extends StatelessWidget {
|
|||
ref.read(mangasListStateProvider.notifier).update(entry);
|
||||
|
||||
ref
|
||||
.read(isLongPressedMangaStateProvider.notifier)
|
||||
.read(isLongPressedStateProvider.notifier)
|
||||
.update(!isLongPressed);
|
||||
} else {
|
||||
ref.read(mangasListStateProvider.notifier).update(entry);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import 'package:mangayomi/router/router.dart';
|
|||
import 'package:mangayomi/services/fetch_sources_list.dart';
|
||||
import 'package:mangayomi/services/sync_server.dart';
|
||||
import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
|
||||
import 'package:mangayomi/modules/library/providers/library_state_provider.dart';
|
||||
import 'package:mangayomi/modules/manga/detail/providers/state_providers.dart';
|
||||
import 'package:mangayomi/modules/more/providers/incognito_mode_state_provider.dart';
|
||||
|
||||
final libLocationRegex = RegExp(r"^/(Manga|Anime|Novel)Library$");
|
||||
|
|
@ -241,7 +241,7 @@ class _MainScreenState extends ConsumerState<MainScreen> {
|
|||
|
||||
final incognitoMode = ref.watch(incognitoModeStateProvider);
|
||||
final downloadedOnly = ref.watch(downloadedOnlyStateProvider);
|
||||
final isLongPressed = ref.watch(isLongPressedMangaStateProvider);
|
||||
final isLongPressed = ref.watch(isLongPressedStateProvider);
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import 'package:mangayomi/modules/manga/reader/providers/reader_controller_provi
|
|||
import 'package:mangayomi/modules/more/providers/algorithm_weights_state_provider.dart';
|
||||
import 'package:mangayomi/modules/more/settings/appearance/providers/pure_black_dark_mode_state_provider.dart';
|
||||
import 'package:mangayomi/modules/more/settings/track/widgets/track_listile.dart';
|
||||
import 'package:mangayomi/modules/widgets/bottom_select_bar.dart';
|
||||
import 'package:mangayomi/modules/widgets/category_selection_dialog.dart';
|
||||
import 'package:mangayomi/modules/widgets/custom_draggable_tabbar.dart';
|
||||
import 'package:mangayomi/modules/widgets/custom_extended_image_provider.dart';
|
||||
|
|
@ -827,8 +828,8 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
|
|||
],
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: Consumer(
|
||||
builder: (context, ref, child) {
|
||||
bottomNavigationBar: Builder(
|
||||
builder: (context) {
|
||||
final chap = ref.watch(chaptersListStateProvider);
|
||||
bool getLength1 = chap.length == 1;
|
||||
bool checkFirstBookmarked =
|
||||
|
|
@ -837,340 +838,241 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
|
|||
chap.isNotEmpty && chap.first.isRead! && getLength1;
|
||||
final l10n = l10nLocalizations(context)!;
|
||||
final color = Theme.of(context).textTheme.bodyLarge!.color!;
|
||||
return AnimatedContainer(
|
||||
curve: Curves.easeIn,
|
||||
decoration: BoxDecoration(
|
||||
color: context.primaryColor.withValues(alpha: 0.2),
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(20),
|
||||
topRight: Radius.circular(20),
|
||||
return BottomSelectBar(
|
||||
isVisible: isLongPressed,
|
||||
actions: [
|
||||
BottomSelectButton(
|
||||
icon: Icon(
|
||||
checkFirstBookmarked
|
||||
? Icons.bookmark_remove_outlined
|
||||
: Icons.bookmark_add_outlined,
|
||||
color: color,
|
||||
),
|
||||
onPressed: () {
|
||||
final chapters = ref.watch(chaptersListStateProvider);
|
||||
final List<Chapter> updatedChapters = [];
|
||||
final now = DateTime.now().millisecondsSinceEpoch;
|
||||
for (var chapter in chapters) {
|
||||
chapter.isBookmarked = !chapter.isBookmarked!;
|
||||
chapter.updatedAt = now;
|
||||
chapter.manga.value = widget.manga;
|
||||
updatedChapters.add(chapter);
|
||||
}
|
||||
isar.writeTxnSync(() {
|
||||
isar.chapters.putAllSync(updatedChapters);
|
||||
});
|
||||
ref
|
||||
.read(isLongPressedStateProvider.notifier)
|
||||
.update(false);
|
||||
ref.read(chaptersListStateProvider.notifier).clear();
|
||||
},
|
||||
),
|
||||
),
|
||||
duration: const Duration(milliseconds: 100),
|
||||
height: isLongPressed ? 70 : 0,
|
||||
width: context.width(1),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
height: 70,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: 0,
|
||||
backgroundColor: Colors.transparent,
|
||||
shadowColor: Colors.transparent,
|
||||
),
|
||||
onPressed: () {
|
||||
final chapters = ref.watch(
|
||||
chaptersListStateProvider,
|
||||
);
|
||||
final List<Chapter> updatedChapters = [];
|
||||
final now = DateTime.now().millisecondsSinceEpoch;
|
||||
for (var chapter in chapters) {
|
||||
chapter.isBookmarked = !chapter.isBookmarked!;
|
||||
chapter.updatedAt = now;
|
||||
chapter.manga.value = widget.manga;
|
||||
updatedChapters.add(chapter);
|
||||
}
|
||||
isar.writeTxnSync(() {
|
||||
isar.chapters.putAllSync(updatedChapters);
|
||||
});
|
||||
ref
|
||||
.read(isLongPressedStateProvider.notifier)
|
||||
.update(false);
|
||||
ref
|
||||
.read(chaptersListStateProvider.notifier)
|
||||
.clear();
|
||||
},
|
||||
child: Icon(
|
||||
checkFirstBookmarked
|
||||
? Icons.bookmark_remove_outlined
|
||||
: Icons.bookmark_add_outlined,
|
||||
color: color,
|
||||
),
|
||||
),
|
||||
),
|
||||
BottomSelectButton(
|
||||
icon: Icon(
|
||||
checkReadBookmarked
|
||||
? Icons.remove_done_sharp
|
||||
: Icons.done_all_sharp,
|
||||
color: color,
|
||||
),
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
height: 70,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: 0,
|
||||
backgroundColor: Colors.transparent,
|
||||
shadowColor: Colors.transparent,
|
||||
),
|
||||
onPressed: () {
|
||||
final chapters = ref.watch(
|
||||
chaptersListStateProvider,
|
||||
);
|
||||
final List<Chapter> updatedChapters = [];
|
||||
final now = DateTime.now().millisecondsSinceEpoch;
|
||||
for (var chapter in chapters) {
|
||||
chapter.isRead = !chapter.isRead!;
|
||||
if (!chapter.isRead!) {
|
||||
chapter.lastPageRead = "1";
|
||||
}
|
||||
chapter.updatedAt = now;
|
||||
chapter.manga.value = widget.manga;
|
||||
updatedChapters.add(chapter);
|
||||
if (chapter.isRead!) {
|
||||
chapter.updateTrackChapterRead(ref);
|
||||
}
|
||||
}
|
||||
isar.writeTxnSync(() {
|
||||
isar.chapters.putAllSync(updatedChapters);
|
||||
isar.mangas.putSync(widget.manga!);
|
||||
});
|
||||
ref
|
||||
.read(isLongPressedStateProvider.notifier)
|
||||
.update(false);
|
||||
ref
|
||||
.read(chaptersListStateProvider.notifier)
|
||||
.clear();
|
||||
},
|
||||
child: Icon(
|
||||
checkReadBookmarked
|
||||
? Icons.remove_done_sharp
|
||||
: Icons.done_all_sharp,
|
||||
color: color,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (getLength1)
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
height: 70,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: 0,
|
||||
backgroundColor: Colors.transparent,
|
||||
shadowColor: Colors.transparent,
|
||||
),
|
||||
onPressed: () {
|
||||
int index = chapters.indexOf(chap.first);
|
||||
final List<Chapter> updatedChapters = [];
|
||||
final now = DateTime.now().millisecondsSinceEpoch;
|
||||
chapters[index + 1].updateTrackChapterRead(ref);
|
||||
for (
|
||||
var i = index + 1;
|
||||
i < chapters.length;
|
||||
i++
|
||||
) {
|
||||
final chapter = chapters[i];
|
||||
if (!chapter.isRead!) {
|
||||
chapter.isRead = true;
|
||||
chapter.lastPageRead = "1";
|
||||
chapter.updatedAt = now;
|
||||
chapter.manga.value = widget.manga;
|
||||
updatedChapters.add(chapter);
|
||||
}
|
||||
}
|
||||
isar.writeTxnSync(() {
|
||||
isar.chapters.putAllSync(updatedChapters);
|
||||
isar.mangas.putSync(widget.manga!);
|
||||
});
|
||||
ref
|
||||
.read(isLongPressedStateProvider.notifier)
|
||||
.update(false);
|
||||
ref
|
||||
.read(chaptersListStateProvider.notifier)
|
||||
.clear();
|
||||
},
|
||||
child: Stack(
|
||||
children: [
|
||||
Icon(Icons.done_outlined, color: color),
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
child: Icon(
|
||||
Icons.arrow_downward_outlined,
|
||||
size: 11,
|
||||
color: color,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (!isLocalArchive)
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
height: 70,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: 0,
|
||||
backgroundColor: Colors.transparent,
|
||||
shadowColor: Colors.transparent,
|
||||
),
|
||||
onPressed: () {
|
||||
for (var chapter in ref.watch(
|
||||
chaptersListStateProvider,
|
||||
)) {
|
||||
final entries = isar.downloads
|
||||
.filter()
|
||||
.idEqualTo(chapter.id)
|
||||
.findAllSync();
|
||||
if (entries.isEmpty ||
|
||||
!entries.first.isDownload!) {
|
||||
ref.read(
|
||||
addDownloadToQueueProvider(
|
||||
chapter: chapter,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
ref.watch(processDownloadsProvider());
|
||||
|
||||
ref
|
||||
.read(isLongPressedStateProvider.notifier)
|
||||
.update(false);
|
||||
ref
|
||||
.read(chaptersListStateProvider.notifier)
|
||||
.clear();
|
||||
},
|
||||
child: Icon(Icons.download_outlined, color: color),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (isLocalArchive)
|
||||
Expanded(
|
||||
child: SizedBox(
|
||||
height: 70,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: 0,
|
||||
backgroundColor: Colors.transparent,
|
||||
shadowColor: Colors.transparent,
|
||||
),
|
||||
onPressed: () {
|
||||
final selectedChapters = ref.watch(
|
||||
chaptersListStateProvider,
|
||||
);
|
||||
final totalChapters =
|
||||
widget.manga!.chapters.length;
|
||||
final isLastChapters =
|
||||
selectedChapters.length == totalChapters;
|
||||
final isAnime = widget.itemType == ItemType.anime;
|
||||
final entryType = isAnime
|
||||
? l10n.episode
|
||||
: l10n.chapter;
|
||||
final pluralEntryType = isAnime
|
||||
? l10n.episodes
|
||||
: l10n.chapters;
|
||||
final mediaType = isAnime
|
||||
? l10n.anime
|
||||
: l10n.manga;
|
||||
final warningMessage = l10n
|
||||
.last_entry_delete_warning(
|
||||
totalChapters,
|
||||
entryType,
|
||||
pluralEntryType,
|
||||
mediaType,
|
||||
);
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: Text(l10n.delete_chapters),
|
||||
content: isLastChapters
|
||||
? Row(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.warning_amber_rounded,
|
||||
color: Colors.orange,
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Text(
|
||||
warningMessage,
|
||||
style: TextStyle(
|
||||
color: Colors.red,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
: null,
|
||||
actions: [
|
||||
Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text(l10n.cancel),
|
||||
),
|
||||
const SizedBox(width: 15),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
final navigator = Navigator.of(
|
||||
context,
|
||||
);
|
||||
await isar.writeTxn(() async {
|
||||
final idsToDelete =
|
||||
selectedChapters
|
||||
.map((c) => c.id!)
|
||||
.toList();
|
||||
await isar.chapters.deleteAll(
|
||||
idsToDelete,
|
||||
);
|
||||
});
|
||||
if (!mounted) return;
|
||||
ref
|
||||
.read(
|
||||
isLongPressedStateProvider
|
||||
.notifier,
|
||||
)
|
||||
.update(false);
|
||||
ref
|
||||
.read(
|
||||
chaptersListStateProvider
|
||||
.notifier,
|
||||
)
|
||||
.clear();
|
||||
navigator.pop();
|
||||
if (isLastChapters) {
|
||||
navigator.pop();
|
||||
Future.delayed(
|
||||
const Duration(
|
||||
milliseconds: 350,
|
||||
),
|
||||
() {
|
||||
isar.writeTxn(
|
||||
() => isar.mangas.delete(
|
||||
widget.manga!.id!,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
child: Text(l10n.delete),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
onPressed: () {
|
||||
final chapters = ref.watch(chaptersListStateProvider);
|
||||
final List<Chapter> updatedChapters = [];
|
||||
final now = DateTime.now().millisecondsSinceEpoch;
|
||||
for (var chapter in chapters) {
|
||||
chapter.isRead = !chapter.isRead!;
|
||||
if (!chapter.isRead!) {
|
||||
chapter.lastPageRead = "1";
|
||||
}
|
||||
chapter.updatedAt = now;
|
||||
chapter.manga.value = widget.manga;
|
||||
updatedChapters.add(chapter);
|
||||
if (chapter.isRead!) {
|
||||
chapter.updateTrackChapterRead(ref);
|
||||
}
|
||||
}
|
||||
isar.writeTxnSync(() {
|
||||
isar.chapters.putAllSync(updatedChapters);
|
||||
isar.mangas.putSync(widget.manga!);
|
||||
});
|
||||
ref
|
||||
.read(isLongPressedStateProvider.notifier)
|
||||
.update(false);
|
||||
ref.read(chaptersListStateProvider.notifier).clear();
|
||||
},
|
||||
),
|
||||
if (getLength1)
|
||||
BottomSelectButton(
|
||||
icon: Stack(
|
||||
children: [
|
||||
Icon(Icons.done_outlined, color: color),
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
child: Icon(
|
||||
Icons.delete_outline_outlined,
|
||||
Icons.arrow_downward_outlined,
|
||||
size: 11,
|
||||
color: color,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
onPressed: () {
|
||||
int index = chapters.indexOf(chap.first);
|
||||
final List<Chapter> updatedChapters = [];
|
||||
final now = DateTime.now().millisecondsSinceEpoch;
|
||||
chapters[index + 1].updateTrackChapterRead(ref);
|
||||
for (var i = index + 1; i < chapters.length; i++) {
|
||||
final chapter = chapters[i];
|
||||
if (!chapter.isRead!) {
|
||||
chapter.isRead = true;
|
||||
chapter.lastPageRead = "1";
|
||||
chapter.updatedAt = now;
|
||||
chapter.manga.value = widget.manga;
|
||||
updatedChapters.add(chapter);
|
||||
}
|
||||
}
|
||||
isar.writeTxnSync(() {
|
||||
isar.chapters.putAllSync(updatedChapters);
|
||||
isar.mangas.putSync(widget.manga!);
|
||||
});
|
||||
ref
|
||||
.read(isLongPressedStateProvider.notifier)
|
||||
.update(false);
|
||||
ref.read(chaptersListStateProvider.notifier).clear();
|
||||
},
|
||||
),
|
||||
if (!isLocalArchive)
|
||||
BottomSelectButton(
|
||||
icon: Icon(Icons.download_outlined, color: color),
|
||||
onPressed: () {
|
||||
for (var chapter in ref.watch(
|
||||
chaptersListStateProvider,
|
||||
)) {
|
||||
final entries = isar.downloads
|
||||
.filter()
|
||||
.idEqualTo(chapter.id)
|
||||
.findAllSync();
|
||||
if (entries.isEmpty || !entries.first.isDownload!) {
|
||||
ref.read(
|
||||
addDownloadToQueueProvider(chapter: chapter),
|
||||
);
|
||||
}
|
||||
}
|
||||
ref.watch(processDownloadsProvider());
|
||||
|
||||
ref
|
||||
.read(isLongPressedStateProvider.notifier)
|
||||
.update(false);
|
||||
ref.read(chaptersListStateProvider.notifier).clear();
|
||||
},
|
||||
),
|
||||
if (isLocalArchive)
|
||||
BottomSelectButton(
|
||||
icon: Icon(Icons.delete_outline_outlined, color: color),
|
||||
onPressed: () {
|
||||
final selectedChapters = ref.watch(
|
||||
chaptersListStateProvider,
|
||||
);
|
||||
final totalChapters = widget.manga!.chapters.length;
|
||||
final isLastChapters =
|
||||
selectedChapters.length == totalChapters;
|
||||
final isAnime = widget.itemType == ItemType.anime;
|
||||
final entryType = isAnime ? l10n.episode : l10n.chapter;
|
||||
final pluralEntryType = isAnime
|
||||
? l10n.episodes
|
||||
: l10n.chapters;
|
||||
final mediaType = isAnime ? l10n.anime : l10n.manga;
|
||||
final warningMessage = l10n.last_entry_delete_warning(
|
||||
totalChapters,
|
||||
entryType,
|
||||
pluralEntryType,
|
||||
mediaType,
|
||||
);
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: Text(l10n.delete_chapters),
|
||||
content: isLastChapters
|
||||
? Row(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.warning_amber_rounded,
|
||||
color: Colors.orange,
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Text(
|
||||
warningMessage,
|
||||
style: TextStyle(color: Colors.red),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
: null,
|
||||
actions: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text(l10n.cancel),
|
||||
),
|
||||
const SizedBox(width: 15),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
final navigator = Navigator.of(context);
|
||||
await isar.writeTxn(() async {
|
||||
final idsToDelete = selectedChapters
|
||||
.map((c) => c.id!)
|
||||
.toList();
|
||||
await isar.chapters.deleteAll(
|
||||
idsToDelete,
|
||||
);
|
||||
});
|
||||
if (!mounted) return;
|
||||
ref
|
||||
.read(
|
||||
isLongPressedStateProvider
|
||||
.notifier,
|
||||
)
|
||||
.update(false);
|
||||
ref
|
||||
.read(
|
||||
chaptersListStateProvider
|
||||
.notifier,
|
||||
)
|
||||
.clear();
|
||||
navigator.pop();
|
||||
if (isLastChapters) {
|
||||
navigator.pop();
|
||||
Future.delayed(
|
||||
const Duration(milliseconds: 350),
|
||||
() {
|
||||
isar.writeTxn(
|
||||
() => isar.mangas.delete(
|
||||
widget.manga!.id!,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
child: Text(l10n.delete),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
|
|
|
|||
66
lib/modules/widgets/bottom_select_bar.dart
Normal file
66
lib/modules/widgets/bottom_select_bar.dart
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
|
||||
|
||||
/// Bar, that appears at the bottom of the screen when long-pressing (selecting)
|
||||
/// a Manga/Anime/Novel or Chapter/Episode
|
||||
class BottomSelectBar extends StatelessWidget {
|
||||
final bool isVisible;
|
||||
final List<BottomSelectButton> actions;
|
||||
|
||||
const BottomSelectBar({
|
||||
super.key,
|
||||
required this.isVisible,
|
||||
required this.actions,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AnimatedContainer(
|
||||
curve: Curves.easeIn,
|
||||
decoration: BoxDecoration(
|
||||
color: context.primaryColor.withValues(alpha: 0.2),
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(20),
|
||||
topRight: Radius.circular(20),
|
||||
),
|
||||
),
|
||||
duration: const Duration(milliseconds: 100),
|
||||
height: isVisible ? 70 : 0,
|
||||
width: context.width(1),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: actions,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Button for the BottomSelectBar
|
||||
class BottomSelectButton extends StatelessWidget {
|
||||
final Widget icon;
|
||||
final VoidCallback onPressed;
|
||||
|
||||
const BottomSelectButton({
|
||||
super.key,
|
||||
required this.icon,
|
||||
required this.onPressed,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Expanded(
|
||||
child: SizedBox(
|
||||
height: 70,
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
elevation: 0,
|
||||
backgroundColor: Colors.transparent,
|
||||
shadowColor: Colors.transparent,
|
||||
),
|
||||
onPressed: onPressed,
|
||||
child: icon,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ import 'package:mangayomi/models/category.dart';
|
|||
import 'package:mangayomi/models/manga.dart';
|
||||
import 'package:mangayomi/modules/library/providers/library_state_provider.dart';
|
||||
import 'package:mangayomi/modules/library/widgets/list_tile_manga_category.dart';
|
||||
import 'package:mangayomi/modules/manga/detail/providers/state_providers.dart';
|
||||
import 'package:mangayomi/modules/manga/detail/widgets/chapter_filter_list_tile_widget.dart';
|
||||
import 'package:mangayomi/providers/l10n_providers.dart';
|
||||
import 'package:mangayomi/utils/extensions/build_context_extensions.dart';
|
||||
|
|
@ -151,7 +152,7 @@ void showCategorySelectionDialog({
|
|||
if (isBulk) {
|
||||
ref.read(mangasListStateProvider.notifier).clear();
|
||||
ref
|
||||
.read(isLongPressedMangaStateProvider.notifier)
|
||||
.read(isLongPressedStateProvider.notifier)
|
||||
.update(false);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ part of 'aniskip.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$aniSkipHash() => r'2e5d19b025a2207ff64da7bf7908450ea9e5ff8c';
|
||||
String _$aniSkipHash() => r'887869b54e2e151633efd46da83bde845e14f421';
|
||||
|
||||
/// See also [AniSkip].
|
||||
@ProviderFor(AniSkip)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ part of 'sync_server.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$syncServerHash() => r'97a778696e0cc8b8e4c706de50d60464bb7b2f03';
|
||||
String _$syncServerHash() => r'141ba3be28182e05480e06fbf3f1de68f868cb8e';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ part of 'anilist.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$anilistHash() => r'fafb964252b3a5741e981cb8c2f0f2090b3b86ae';
|
||||
String _$anilistHash() => r'c786a526fdacc875e4a7e00886b2bda546eafeae';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ part of 'myanimelist.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$myAnimeListHash() => r'a612e9ce814268ac79dc86d810ca6bd3671812e6';
|
||||
String _$myAnimeListHash() => r'4391ad9446d14b1fb1ffdfbc5323ef04db5140f7';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
|
|
|||
Loading…
Reference in a new issue