fix: chapter download scanlator duplicate name
This commit is contained in:
parent
9961d59c17
commit
62bb3dfac4
13 changed files with 142 additions and 371 deletions
|
|
@ -36,25 +36,6 @@ class ChapterPageComick {
|
|||
chapTitle = json['chapTitle'];
|
||||
checkVol2Chap1 = json['checkVol2Chap1'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
if (chapter != null) {
|
||||
data['chapter'] = chapter!.toJson();
|
||||
}
|
||||
|
||||
data['matureContent'] = matureContent;
|
||||
if (chapters != null) {
|
||||
data['chapters'] = chapters!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
|
||||
data['canonical'] = canonical;
|
||||
data['seoTitle'] = seoTitle;
|
||||
data['seoDescription'] = seoDescription;
|
||||
data['chapTitle'] = chapTitle;
|
||||
data['checkVol2Chap1'] = checkVol2Chap1;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Chapter {
|
||||
|
|
@ -115,31 +96,6 @@ class Chapter {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['id'] = id;
|
||||
data['chap'] = chap;
|
||||
|
||||
data['title'] = title;
|
||||
data['server'] = server;
|
||||
data['hid'] = hid;
|
||||
data['hash'] = hash;
|
||||
data['group_name'] = groupName;
|
||||
|
||||
data['created_at'] = createdAt;
|
||||
data['mdid'] = mdid;
|
||||
data['comment_count'] = commentCount;
|
||||
data['up_count'] = upCount;
|
||||
data['down_count'] = downCount;
|
||||
data['status'] = status;
|
||||
data['lang'] = lang;
|
||||
|
||||
if (images != null) {
|
||||
data['images'] = images!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Images {
|
||||
|
|
@ -182,15 +138,4 @@ class Chapters {
|
|||
id = json['id'];
|
||||
title = json['title'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['chap'] = chap;
|
||||
data['vol'] = vol;
|
||||
data['hid'] = hid;
|
||||
data['lang'] = lang;
|
||||
data['id'] = id;
|
||||
data['title'] = title;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,15 +13,6 @@ class MangaChapterModelComick {
|
|||
}
|
||||
total = json['total'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
if (chapters != null) {
|
||||
data['chapters'] = chapters!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
data['total'] = total;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Chapters {
|
||||
|
|
@ -74,26 +65,6 @@ class Chapters {
|
|||
// });
|
||||
// }
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['id'] = id;
|
||||
data['chap'] = chap;
|
||||
data['title'] = title;
|
||||
data['vol'] = vol;
|
||||
data['slug'] = slug;
|
||||
data['lang'] = lang;
|
||||
data['created_at'] = createdAt;
|
||||
data['updated_at'] = updatedAt;
|
||||
data['up_count'] = upCount;
|
||||
data['down_count'] = downCount;
|
||||
data['group_name'] = groupName;
|
||||
data['hid'] = hid;
|
||||
if (mdGroups != null) {
|
||||
data['md_groups'] = mdGroups!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class MdGroups {
|
||||
|
|
@ -106,11 +77,4 @@ class MdGroups {
|
|||
slug = json['slug'];
|
||||
title = json['title'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['slug'] = slug;
|
||||
data['title'] = title;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ class MangaDetailModelComick {
|
|||
if (json['authors'] != null) {
|
||||
authors = json['authors'];
|
||||
}
|
||||
|
||||
|
||||
if (json['genres'] != null) {
|
||||
genres = json['genres'];
|
||||
|
|
@ -38,30 +37,6 @@ class MangaDetailModelComick {
|
|||
matureContent = json['matureContent'];
|
||||
checkVol2Chap1 = json['checkVol2Chap1'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
// if (firstChap != null) {
|
||||
// data['firstChap'] = firstChap!.toJson();
|
||||
// }
|
||||
if (comic != null) {
|
||||
data['comic'] = comic!.toJson();
|
||||
}
|
||||
if (artists != null) {
|
||||
data['artists'] = artists!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
if (authors != null) {
|
||||
data['authors'] = authors!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
// data['langList'] = langList;
|
||||
|
||||
if (genres != null) {
|
||||
data['genres'] = genres!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
data['matureContent'] = matureContent;
|
||||
data['checkVol2Chap1'] = checkVol2Chap1;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class FirstChap {
|
||||
|
|
@ -81,17 +56,6 @@ class FirstChap {
|
|||
chap = json['chap'];
|
||||
hid = json['hid'];
|
||||
lang = json['lang'];
|
||||
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['chap'] = chap;
|
||||
data['hid'] = hid;
|
||||
data['lang'] = lang;
|
||||
data['group_name'] = groupName;
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -184,41 +148,6 @@ class Comic {
|
|||
// langNative = json['lang_native'];
|
||||
coverUrl = json['cover_url'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['id'] = id;
|
||||
data['hid'] = hid;
|
||||
data['title'] = title;
|
||||
data['country'] = country;
|
||||
data['status'] = status;
|
||||
|
||||
data['last_chapter'] = lastChapter;
|
||||
data['chapter_count'] = chapterCount;
|
||||
data['demographic'] = demographic;
|
||||
data['hentai'] = hentai;
|
||||
data['user_follow_count'] = userFollowCount;
|
||||
data['follow_rank'] = followRank;
|
||||
data['comment_count'] = commentCount;
|
||||
data['follow_count'] = followCount;
|
||||
data['desc'] = desc;
|
||||
data['parsed'] = parsed;
|
||||
data['slug'] = slug;
|
||||
|
||||
data['year'] = year;
|
||||
data['bayesian_rating'] = bayesianRating;
|
||||
data['rating_count'] = ratingCount;
|
||||
data['content_rating'] = contentRating;
|
||||
data['translation_completed'] = translationCompleted;
|
||||
data['chapter_numbers_reset_on_new_volume_manual'] =
|
||||
chapterNumbersResetOnNewVolumeManual;
|
||||
|
||||
data['iso639_1'] = iso6391;
|
||||
data['lang_name'] = langName;
|
||||
data['lang_native'] = langNative;
|
||||
data['cover_url'] = coverUrl;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class Artists {
|
||||
|
|
@ -231,11 +160,4 @@ class Artists {
|
|||
name = json['name'];
|
||||
slug = json['slug'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['name'] = name;
|
||||
data['slug'] = slug;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,38 +78,6 @@ class PopularMangaModelComick {
|
|||
json['mu_comics'] != null ? MuComics.fromJson(json['mu_comics']) : null;
|
||||
coverUrl = json['cover_url'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['id'] = id;
|
||||
data['hid'] = hid;
|
||||
data['slug'] = slug;
|
||||
data['title'] = title;
|
||||
data['rating'] = rating;
|
||||
data['bayesian_rating'] = bayesianRating;
|
||||
data['rating_count'] = ratingCount;
|
||||
data['follow_count'] = followCount;
|
||||
data['desc'] = desc;
|
||||
data['last_chapter'] = lastChapter as int;
|
||||
data['translation_completed'] = translationCompleted;
|
||||
data['view_count'] = viewCount;
|
||||
data['content_rating'] = contentRating;
|
||||
data['demographic'] = demographic;
|
||||
data['genres'] = genres;
|
||||
data['user_follow_count'] = userFollowCount;
|
||||
data['year'] = year;
|
||||
if (mdTitles != null) {
|
||||
data['md_titles'] = mdTitles!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
if (mdCovers != null) {
|
||||
data['md_covers'] = mdCovers!.map((v) => v.toJson()).toList();
|
||||
}
|
||||
if (muComics != null) {
|
||||
data['mu_comics'] = muComics!.toJson();
|
||||
}
|
||||
data['cover_url'] = coverUrl;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
class MdTitles {
|
||||
|
|
@ -158,10 +126,4 @@ class MuComics {
|
|||
MuComics.fromJson(Map<String, dynamic> json) {
|
||||
year = json['year'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['year'] = year;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,13 +51,4 @@ class MdCovers {
|
|||
h = json['h'];
|
||||
b2key = json['b2key'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['vol'] = vol;
|
||||
data['w'] = w;
|
||||
data['h'] = h;
|
||||
data['b2key'] = b2key;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,9 +36,12 @@ class StorageProvider {
|
|||
|
||||
Future<Directory?> getMangaChapterDirectory(
|
||||
ModelManga modelManga, index) async {
|
||||
String scanlator = modelManga.chapters![index].scanlator!.isNotEmpty
|
||||
? "${modelManga.chapters![index].scanlator!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}_"
|
||||
: "";
|
||||
final dir = await getDirectory();
|
||||
return Directory(
|
||||
"${dir!.path}/downloads/${modelManga.source} (${modelManga.lang!.toUpperCase()})/${modelManga.name!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}/${modelManga.chapters![index].name!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}/");
|
||||
"${dir!.path}/downloads/${modelManga.source} (${modelManga.lang!.toUpperCase()})/${modelManga.name!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}/$scanlator${modelManga.chapters![index].name!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}/");
|
||||
}
|
||||
|
||||
Future<Directory?> getMangaMainDirectory(ModelManga modelManga, index) async {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:grouped_list/grouped_list.dart';
|
||||
|
|
@ -40,6 +42,10 @@ class ExtensionScreen extends ConsumerWidget {
|
|||
),
|
||||
),
|
||||
itemBuilder: (context, SourceModel element) {
|
||||
if (element.isCloudflare && !Platform.isWindows ||
|
||||
element.isCloudflare && !Platform.isLinux) {
|
||||
return Container();
|
||||
}
|
||||
final source =
|
||||
value.get("${element.sourceName}${element.lang}")!;
|
||||
return ExtensionListTileWidget(
|
||||
|
|
|
|||
|
|
@ -62,22 +62,6 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_chapters = ref
|
||||
.watch(chapterFilterResultStateProvider(modelManga: widget.modelManga!))
|
||||
.chapters;
|
||||
_modelManga = ref.watch(
|
||||
chapterFilterResultStateProvider(modelManga: widget.modelManga!));
|
||||
|
||||
_pageLength = ref
|
||||
.watch(chapterFilterResultStateProvider(
|
||||
modelManga: widget.modelManga!))
|
||||
.chapters!
|
||||
.length +
|
||||
1;
|
||||
|
||||
bool reverse = ref.watch(
|
||||
reverseChapterStateProvider(modelManga: widget.modelManga!))["reverse"];
|
||||
|
||||
return NotificationListener<UserScrollNotification>(
|
||||
onNotification: (notification) {
|
||||
if (notification.direction == ScrollDirection.forward) {
|
||||
|
|
@ -133,8 +117,8 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
|
|||
ref
|
||||
.read(chapterNameListStateProvider
|
||||
.notifier)
|
||||
.selectAll(widget.modelManga!
|
||||
.chapters![i].name!);
|
||||
.selectAll(
|
||||
"${widget.modelManga!.chapters![i].name!}$i");
|
||||
}
|
||||
},
|
||||
icon: const Icon(Icons.select_all)),
|
||||
|
|
@ -150,8 +134,8 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
|
|||
ref
|
||||
.read(chapterNameListStateProvider
|
||||
.notifier)
|
||||
.selectSome(widget.modelManga!
|
||||
.chapters![i].name!);
|
||||
.selectSome(
|
||||
"${widget.modelManga!.chapters![i].name}$i");
|
||||
}
|
||||
ref
|
||||
.read(isLongPressedStateProvider
|
||||
|
|
@ -166,8 +150,8 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
|
|||
ref
|
||||
.read(chapterNameListStateProvider
|
||||
.notifier)
|
||||
.selectSome(widget.modelManga!
|
||||
.chapters![i].name!);
|
||||
.selectSome(
|
||||
"${widget.modelManga!.chapters![i].name}$i");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -247,53 +231,67 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
|
|||
)
|
||||
],
|
||||
)),
|
||||
SafeArea(
|
||||
child: DraggableScrollbar(
|
||||
heightScrollThumb: 48.0,
|
||||
backgroundColor: primaryColor(context),
|
||||
scrollThumbBuilder: (backgroundColor, thumbAnimation,
|
||||
labelAnimation, height,
|
||||
{labelConstraints, labelText}) {
|
||||
return FadeTransition(
|
||||
opacity: thumbAnimation,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: backgroundColor,
|
||||
borderRadius: BorderRadius.circular(20)),
|
||||
height: height,
|
||||
width: 8.0,
|
||||
),
|
||||
);
|
||||
},
|
||||
scrollbarTimeToFade: const Duration(seconds: 2),
|
||||
controller: _scrollController,
|
||||
child: ListView.builder(
|
||||
controller: _scrollController,
|
||||
padding: const EdgeInsets.only(top: 0, bottom: 60),
|
||||
itemCount: _pageLength,
|
||||
itemBuilder: (context, index) {
|
||||
int finalIndex = index - 1;
|
||||
if (index == 0) {
|
||||
return _bodyContainer();
|
||||
}
|
||||
int reverseIndex = _chapters!.length -
|
||||
_chapters!.reversed.toList().indexOf(
|
||||
_chapters!.reversed
|
||||
.toList()[finalIndex]) -
|
||||
1;
|
||||
SafeArea(child: Consumer(builder: (context, ref, child) {
|
||||
_pageLength = ref
|
||||
.watch(chapterFilterResultStateProvider(
|
||||
modelManga: widget.modelManga!))
|
||||
.chapters!
|
||||
.length +
|
||||
1;
|
||||
_chapters = ref
|
||||
.watch(chapterFilterResultStateProvider(
|
||||
modelManga: widget.modelManga!))
|
||||
.chapters;
|
||||
_modelManga = ref.watch(chapterFilterResultStateProvider(
|
||||
modelManga: widget.modelManga!));
|
||||
bool reverse = ref.watch(reverseChapterStateProvider(
|
||||
modelManga: widget.modelManga!))["reverse"];
|
||||
return DraggableScrollbar(
|
||||
heightScrollThumb: 48.0,
|
||||
backgroundColor: primaryColor(context),
|
||||
scrollThumbBuilder: (backgroundColor, thumbAnimation,
|
||||
labelAnimation, height,
|
||||
{labelConstraints, labelText}) {
|
||||
return FadeTransition(
|
||||
opacity: thumbAnimation,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: backgroundColor,
|
||||
borderRadius: BorderRadius.circular(20)),
|
||||
height: height,
|
||||
width: 8.0,
|
||||
),
|
||||
);
|
||||
},
|
||||
scrollbarTimeToFade: const Duration(seconds: 2),
|
||||
controller: _scrollController,
|
||||
child: ListView.builder(
|
||||
controller: _scrollController,
|
||||
padding: const EdgeInsets.only(top: 0, bottom: 60),
|
||||
itemCount: _pageLength,
|
||||
itemBuilder: (context, index) {
|
||||
int finalIndex = index - 1;
|
||||
if (index == 0) {
|
||||
return _bodyContainer();
|
||||
}
|
||||
int reverseIndex = _chapters!.length -
|
||||
_chapters!.reversed.toList().indexOf(
|
||||
_chapters!.reversed.toList()[finalIndex]) -
|
||||
1;
|
||||
|
||||
List<ModelChapters> chapters = reverse
|
||||
? _chapters!.reversed.toList()
|
||||
: _chapters!;
|
||||
List<ModelChapters> chapters = reverse
|
||||
? _chapters!.reversed.toList()
|
||||
: _chapters!;
|
||||
|
||||
return ChapterListTileWidget(
|
||||
chapters: chapters,
|
||||
modelManga: _modelManga!,
|
||||
reverse: reverse,
|
||||
reverseIndex: reverseIndex,
|
||||
finalIndex: finalIndex,
|
||||
);
|
||||
}))),
|
||||
return ChapterListTileWidget(
|
||||
chapters: chapters,
|
||||
modelManga: _modelManga!,
|
||||
reverse: reverse,
|
||||
reverseIndex: reverseIndex,
|
||||
finalIndex: finalIndex,
|
||||
);
|
||||
}));
|
||||
})),
|
||||
],
|
||||
),
|
||||
bottomNavigationBar: Consumer(
|
||||
|
|
|
|||
|
|
@ -445,7 +445,7 @@ class ChapterSetIsBookmarkState extends _$ChapterSetIsBookmarkState {
|
|||
for (var name in ref.watch(chapterNameListStateProvider)) {
|
||||
for (var i = 0; i < modelManga.chapters!.length; i++) {
|
||||
modelManga.chapters![i].isBookmarked =
|
||||
name == modelManga.chapters![i].name
|
||||
name == "${modelManga.chapters![i].name}$i"
|
||||
? !modelManga.chapters![i].isBookmarked
|
||||
: modelManga.chapters![i].isBookmarked;
|
||||
}
|
||||
|
|
@ -463,9 +463,10 @@ class ChapterSetIsReadState extends _$ChapterSetIsReadState {
|
|||
ref.read(isLongPressedStateProvider.notifier).update(false);
|
||||
for (var name in ref.watch(chapterNameListStateProvider)) {
|
||||
for (var i = 0; i < modelManga.chapters!.length; i++) {
|
||||
modelManga.chapters![i].isRead = name == modelManga.chapters![i].name
|
||||
? !modelManga.chapters![i].isRead
|
||||
: modelManga.chapters![i].isRead;
|
||||
modelManga.chapters![i].isRead =
|
||||
name == "${modelManga.chapters![i].name}$i"
|
||||
? !modelManga.chapters![i].isRead
|
||||
: modelManga.chapters![i].isRead;
|
||||
}
|
||||
modelManga.save();
|
||||
}
|
||||
|
|
@ -482,7 +483,7 @@ class ChapterSetDownloadState extends _$ChapterSetDownloadState {
|
|||
List<int> indexList = [];
|
||||
for (var name in ref.watch(chapterNameListStateProvider)) {
|
||||
for (var i = 0; i < modelManga.chapters!.length; i++) {
|
||||
if (modelManga.chapters![i].name == name) {
|
||||
if ("${modelManga.chapters![i].name}$i" == name) {
|
||||
indexList.add(i);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,9 +30,10 @@ class ChapterListTileWidget extends ConsumerWidget {
|
|||
final isLongPressed = ref.watch(isLongPressedStateProvider);
|
||||
final idx = reverse ? reverseIndex : finalIndex;
|
||||
final chapterNameList = ref.watch(chapterNameListStateProvider);
|
||||
log(chapterNameList.toString());
|
||||
final chapterName = modelManga.chapters![idx].name;
|
||||
return Container(
|
||||
color: chapterNameList.contains(chapterName)
|
||||
color: chapterNameList.contains("$chapterName$idx")
|
||||
? primaryColor(context).withOpacity(0.4)
|
||||
: null,
|
||||
child: ListTile(
|
||||
|
|
@ -48,7 +49,7 @@ class ChapterListTileWidget extends ConsumerWidget {
|
|||
if (!isLongPressed) {
|
||||
ref
|
||||
.read(chapterNameListStateProvider.notifier)
|
||||
.update(chapterName!);
|
||||
.update("$chapterName$idx");
|
||||
ref
|
||||
.read(chapterModelStateProvider.notifier)
|
||||
.update(chapters[finalIndex]);
|
||||
|
|
@ -58,7 +59,7 @@ class ChapterListTileWidget extends ConsumerWidget {
|
|||
} else {
|
||||
ref
|
||||
.read(chapterNameListStateProvider.notifier)
|
||||
.update(chapterName!);
|
||||
.update("$chapterName$idx");
|
||||
ref
|
||||
.read(chapterModelStateProvider.notifier)
|
||||
.update(chapters[finalIndex]);
|
||||
|
|
@ -68,7 +69,7 @@ class ChapterListTileWidget extends ConsumerWidget {
|
|||
if (isLongPressed) {
|
||||
ref
|
||||
.read(chapterNameListStateProvider.notifier)
|
||||
.update(chapterName!);
|
||||
.update("$chapterName$idx");
|
||||
ref
|
||||
.read(chapterModelStateProvider.notifier)
|
||||
.update(chapters[finalIndex]);
|
||||
|
|
|
|||
|
|
@ -77,12 +77,13 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 3),
|
||||
child: ValueListenableBuilder<Box<DownloadModel>>(
|
||||
valueListenable: ref.watch(hiveBoxMangaDownloadsProvider).listenable(),
|
||||
valueListenable:
|
||||
ref.watch(hiveBoxMangaDownloadsProvider).listenable(),
|
||||
builder: (context, val, child) {
|
||||
final entries = val.values
|
||||
.where((element) =>
|
||||
element.modelManga.chapters![element.index].name ==
|
||||
widget.modelManga.chapters![widget.index].name)
|
||||
"${element.modelManga.chapters![element.index].name}${element.index}" ==
|
||||
"${widget.modelManga.chapters![widget.index].name}${widget.index}")
|
||||
.toList();
|
||||
|
||||
if (entries.isNotEmpty) {
|
||||
|
|
@ -117,23 +118,7 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
child: _downloadWidget(context, true),
|
||||
onSelected: (value) {
|
||||
if (value.toString() == 'Cancel') {
|
||||
setState(() {
|
||||
_isStarted = false;
|
||||
});
|
||||
List<String> taskIds = [];
|
||||
for (var id in entries.first.taskIds) {
|
||||
taskIds.add(id);
|
||||
}
|
||||
FileDownloader()
|
||||
.cancelTasksWithIds(taskIds)
|
||||
.then((value) async {
|
||||
await Future.delayed(
|
||||
const Duration(seconds: 1));
|
||||
ref.watch(hiveBoxMangaDownloadsProvider).delete(
|
||||
widget.modelManga
|
||||
.chapters![widget.index].name,
|
||||
);
|
||||
});
|
||||
_cancelTasks();
|
||||
}
|
||||
},
|
||||
itemBuilder: (context) => [
|
||||
|
|
@ -148,15 +133,6 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
child: PopupMenuButton(
|
||||
child: Stack(
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Icon(
|
||||
Icons.arrow_downward_sharp,
|
||||
color: Theme.of(context)
|
||||
.iconTheme
|
||||
.color!
|
||||
.withOpacity(0.7),
|
||||
)),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: TweenAnimationBuilder<double>(
|
||||
|
|
@ -187,30 +163,21 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
alignment: Alignment.center,
|
||||
child: Icon(
|
||||
Icons.arrow_downward_sharp,
|
||||
color: Theme.of(context)
|
||||
.scaffoldBackgroundColor,
|
||||
color: (entries.first.succeeded /
|
||||
entries.first.total) >
|
||||
0.5
|
||||
? Theme.of(context)
|
||||
.scaffoldBackgroundColor
|
||||
: Theme.of(context)
|
||||
.iconTheme
|
||||
.color!
|
||||
.withOpacity(0.7),
|
||||
)),
|
||||
],
|
||||
),
|
||||
onSelected: (value) {
|
||||
if (value.toString() == 'Cancel') {
|
||||
setState(() {
|
||||
_isStarted = false;
|
||||
});
|
||||
List<String> taskIds = [];
|
||||
for (var id in entries.first.taskIds) {
|
||||
taskIds.add(id);
|
||||
}
|
||||
FileDownloader()
|
||||
.cancelTasksWithIds(taskIds)
|
||||
.then((value) async {
|
||||
await Future.delayed(
|
||||
const Duration(seconds: 1));
|
||||
ref.watch(hiveBoxMangaDownloadsProvider).delete(
|
||||
widget.modelManga
|
||||
.chapters![widget.index].name,
|
||||
);
|
||||
});
|
||||
_cancelTasks();
|
||||
}
|
||||
},
|
||||
itemBuilder: (context) => [
|
||||
|
|
@ -245,9 +212,11 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
),
|
||||
onSelected: (value) {
|
||||
if (value.toString() == 'Retry') {
|
||||
ref.watch(hiveBoxMangaDownloadsProvider).delete(
|
||||
widget.modelManga
|
||||
.chapters![widget.index].name,
|
||||
ref
|
||||
.watch(
|
||||
hiveBoxMangaDownloadsProvider)
|
||||
.delete(
|
||||
"${widget.modelManga.chapters![widget.index].name}${widget.index}",
|
||||
);
|
||||
_startDownload();
|
||||
setState(() {
|
||||
|
|
@ -269,22 +238,7 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
child: _downloadWidget(context, true),
|
||||
onSelected: (value) {
|
||||
if (value.toString() == 'Cancel') {
|
||||
setState(() {
|
||||
_isStarted = false;
|
||||
});
|
||||
List<String> taskIds = [];
|
||||
for (var id in _urll) {
|
||||
taskIds.add(id);
|
||||
}
|
||||
FileDownloader()
|
||||
.cancelTasksWithIds(taskIds)
|
||||
.then((value) async {
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
ref.watch(hiveBoxMangaDownloadsProvider).delete(
|
||||
widget
|
||||
.modelManga.chapters![widget.index].name!,
|
||||
);
|
||||
});
|
||||
_cancelTasks();
|
||||
}
|
||||
},
|
||||
itemBuilder: (context) => [
|
||||
|
|
@ -309,6 +263,22 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
);
|
||||
}
|
||||
|
||||
_cancelTasks() {
|
||||
setState(() {
|
||||
_isStarted = false;
|
||||
});
|
||||
List<String> taskIds = [];
|
||||
for (var id in _urll) {
|
||||
taskIds.add(id);
|
||||
}
|
||||
FileDownloader().cancelTasksWithIds(taskIds).then((value) async {
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
ref.watch(hiveBoxMangaDownloadsProvider).delete(
|
||||
"${widget.modelManga.chapters![widget.index].name}${widget.index}",
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
bool get wantKeepAlive => true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,11 +23,12 @@ Future<List<dynamic>> downloadChapter(DownloadChapterRef ref,
|
|||
Directory? path;
|
||||
bool isOk = false;
|
||||
final path1 = await storageProvider.getDirectory();
|
||||
|
||||
String scanlator = modelManga.chapters![index].scanlator!.isNotEmpty
|
||||
? "${modelManga.chapters![index].scanlator!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}_"
|
||||
: "";
|
||||
final finalPath =
|
||||
"downloads/${modelManga.source} (${modelManga.lang!.toUpperCase()})/${modelManga.name!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}/${modelManga.chapters![index].name!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}";
|
||||
path = Directory(
|
||||
"${path1!.path}downloads/${modelManga.source} (${modelManga.lang!.toUpperCase()})/${modelManga.name!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}/${modelManga.chapters![index].name!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}/");
|
||||
"downloads/${modelManga.source} (${modelManga.lang!.toUpperCase()})/${modelManga.name!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}/$scanlator${modelManga.chapters![index].name!.replaceAll(RegExp(r'[^a-zA-Z0-9 .()\-\s]'), '_')}";
|
||||
path = Directory("${path1!.path}$finalPath/");
|
||||
ref
|
||||
.read(getMangaChapterUrlProvider(
|
||||
modelManga: modelManga,
|
||||
|
|
@ -134,7 +135,7 @@ Future<List<dynamic>> downloadChapter(DownloadChapterRef ref,
|
|||
|
||||
ref
|
||||
.watch(hiveBoxMangaDownloadsProvider)
|
||||
.put(modelManga.chapters![index].name!, model);
|
||||
.put("${modelManga.chapters![index].name!}$index", model);
|
||||
} else {
|
||||
await FileDownloader().downloadBatch(
|
||||
tasks,
|
||||
|
|
@ -150,7 +151,7 @@ Future<List<dynamic>> downloadChapter(DownloadChapterRef ref,
|
|||
isStartDownload: true);
|
||||
|
||||
Hive.box<DownloadModel>(HiveConstant.hiveBoxDownloads)
|
||||
.put(modelManga.chapters![index].name!, model);
|
||||
.put("${modelManga.chapters![index].name!}$index", model);
|
||||
},
|
||||
taskProgressCallback: (task, progress) async {
|
||||
if (progress == 1.0) {
|
||||
|
|
|
|||
|
|
@ -96,9 +96,17 @@ class DownloadQueueScreen extends ConsumerWidget {
|
|||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
LinearProgressIndicator(
|
||||
value: element.succeeded / element.total,
|
||||
)
|
||||
TweenAnimationBuilder<double>(
|
||||
duration: const Duration(milliseconds: 250),
|
||||
curve: Curves.easeInOut,
|
||||
tween: Tween<double>(
|
||||
begin: 0,
|
||||
end: element.succeeded / element.total,
|
||||
),
|
||||
builder: (context, value, _) =>
|
||||
LinearProgressIndicator(
|
||||
value: value,
|
||||
)),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
@ -118,8 +126,7 @@ class DownloadQueueScreen extends ConsumerWidget {
|
|||
await Future.delayed(
|
||||
const Duration(seconds: 1));
|
||||
ref.watch(hiveBoxMangaDownloadsProvider).delete(
|
||||
element.modelManga
|
||||
.chapters![element.index].name,
|
||||
"${element.modelManga.chapters![element.index].name}${element.index}",
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue