- fix: #25 can't download any anime

- code refactor
This commit is contained in:
kodjomoustapha 2023-09-19 20:17:40 +01:00
parent a7d801e210
commit 31b3f96729
20 changed files with 379 additions and 403 deletions

View file

@ -724,10 +724,10 @@ class MBridge {
.videosFromUrl(url, newHeaders, prefix: prefix, suffix: suffix);
}
static Future<List<Video>> streamTapeExtractor(String url) async {
return await StreamTapeExtractor().videosFromUrl(
url,
);
static Future<List<Video>> streamTapeExtractor(
String url, String? quality) async {
return await StreamTapeExtractor()
.videosFromUrl(url, quality: quality ?? "StreamTape");
}
//Utility to use substring
@ -1750,6 +1750,12 @@ class $MBridge extends MBridge with $Bridge {
BridgeTypeAnnotation(
BridgeTypeRef.type(RuntimeTypes.stringType)),
false),
BridgeParameter(
'quality',
BridgeTypeAnnotation(
BridgeTypeRef.type(RuntimeTypes.stringType),
nullable: true),
true),
],
namedParams: []),
isStatic: true),
@ -2134,8 +2140,9 @@ class $MBridge extends MBridge with $Bridge {
static $Future $streamTapeExtractor(
Runtime runtime, $Value? target, List<$Value?> args) =>
$Future.wrap(MBridge.streamTapeExtractor(args[0]!.$value).then(
(value) => $List.wrap(value.map((e) => _toVideoModel(e)).toList())));
$Future.wrap(MBridge.streamTapeExtractor(args[0]!.$value, args[1]!.$value)
.then((value) =>
$List.wrap(value.map((e) => _toVideoModel(e)).toList())));
static $Future $mp4UploadExtractor(
Runtime runtime, $Value? target, List<$Value?> args) =>

View file

@ -673,7 +673,7 @@ class _AnimeStreamPageState extends riv.ConsumerState<AnimeStreamPage> {
Video(
subtitleViewConfiguration: const SubtitleViewConfiguration(
style: TextStyle(
height: 1.4,
height: 2,
fontSize: 40,
fontWeight: FontWeight.bold,
color: Colors.white,

View file

@ -13,10 +13,6 @@ class AnimeStreamController {
return episode.manga.value!;
}
Chapter geAnime() {
return episode;
}
final incognitoMode = isar.settings.getSync(227)!.incognitoMode!;
Settings getIsarSetting() {
@ -82,9 +78,9 @@ class AnimeStreamController {
void setAnimeHistoryUpdate() {
if (!incognitoMode) {
isar.writeTxnSync(() {
Manga? manga = episode.manga.value;
manga!.lastRead = DateTime.now().millisecondsSinceEpoch;
isar.mangas.putSync(manga);
Manga? anime = episode.manga.value;
anime!.lastRead = DateTime.now().millisecondsSinceEpoch;
isar.mangas.putSync(anime);
});
History? history;
@ -112,24 +108,14 @@ class AnimeStreamController {
}
void setCurrentPosition(int duration) {
if (!incognitoMode) {
final chap = episode;
isar.writeTxnSync(() {
chap.lastPageRead = (duration).toString();
isar.chapters.putSync(chap);
});
if (!episode.isRead!) {
if (!incognitoMode) {
final ep = episode;
isar.writeTxnSync(() {
ep.lastPageRead = (duration).toString();
isar.chapters.putSync(ep);
});
}
}
}
String getAnimeName() {
return getAnime().name!;
}
String getSourceName() {
return getAnime().source!;
}
String getChapterTitle() {
return episode.name!;
}
}

View file

@ -87,7 +87,7 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
final isLongPressed = ref.watch(isLongPressedStateProvider);
final chapterNameList = ref.watch(chaptersListStateProvider);
final scanlators = ref.watch(scanlatorsFilterStateProvider(widget.manga!));
bool reverse = ref
bool reverse = !ref
.watch(sortChapterStateProvider(mangaId: widget.manga!.id!))
.reverse!;
final filterUnread =
@ -194,7 +194,7 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
(a, b) {
return (a.dateUpload == null || b.dateUpload == null)
? 0
: a.dateUpload!.compareTo(b.dateUpload!);
: int.parse(a.dateUpload!).compareTo(int.parse(b.dateUpload!));
},
);
}
@ -764,7 +764,6 @@ class _MangaDetailViewState extends ConsumerState<MangaDetailView>
chapter.id!);
}
});
ref
.read(
isLongPressedStateProvider

View file

@ -92,37 +92,42 @@ Future<dynamic> updateMangaDetail(UpdateMangaDetailRef ref,
return;
}
isar.writeTxnSync(() {
final chaptersNames = manga.chapters.map((e) => e.name).toList();
isar.mangas.putSync(manga);
if (getManga.names!.isNotEmpty &&
getManga.names!.length > manga.chapters.length) {
int newChapsIndex = getManga.names!.length - manga.chapters.length;
manga.lastUpdate = DateTime.now().millisecondsSinceEpoch;
for (var i = 0; i < newChapsIndex; i++) {
String title = "";
String scanlator = "";
if (getManga.chaptersChaps != null &&
getManga.chaptersVolumes != null) {
title = beautifyChapterName(getManga.chaptersVolumes![i],
getManga.chaptersChaps![i], getManga.names![i], getManga.lang!);
} else {
title = getManga.names![i].trim().trimLeft().trimRight();
}
if (getManga.chaptersScanlators != null) {
scanlator = getManga.chaptersScanlators![i]
.toString()
.replaceAll(']', "")
.replaceAll("[", "");
}
final chapter = Chapter(
name: title,
url: getManga.urls![i].trim().trimLeft().trimRight(),
dateUpload: getManga.chaptersDateUploads!.isEmpty
? null
: getManga.chaptersDateUploads![i],
scanlator: scanlator,
)..manga.value = manga;
isar.chapters.putSync(chapter);
chapter.manga.saveSync();
manga.lastUpdate = DateTime.now().millisecondsSinceEpoch;
List<Chapter> chapters = [];
for (var i = 0; i < getManga.names!.length; i++) {
String title = "";
String scanlator = "";
if (getManga.chaptersChaps != null && getManga.chaptersVolumes != null) {
title = beautifyChapterName(getManga.chaptersVolumes![i],
getManga.chaptersChaps![i], getManga.names![i], getManga.lang!);
} else {
title = getManga.names![i].trim().trimLeft().trimRight();
}
if (getManga.chaptersScanlators != null) {
scanlator = getManga.chaptersScanlators![i]
.toString()
.replaceAll(']', "")
.replaceAll("[", "");
}
final chapter = Chapter(
name: title,
url: getManga.urls![i].trim().trimLeft().trimRight(),
dateUpload: getManga.chaptersDateUploads!.isEmpty
? DateTime.now().millisecondsSinceEpoch.toString()
: getManga.chaptersDateUploads![i],
scanlator: scanlator,
)..manga.value = manga;
chapters.add(chapter);
chapters.add(chapter);
}
for (var chap in chapters.reversed.toList()) {
if (!chaptersNames.contains(chap.name)) {
isar.chapters.putSync(chap);
chap.manga.saveSync();
}
}
});

View file

@ -6,7 +6,7 @@ part of 'update_manga_detail_providers.dart';
// RiverpodGenerator
// **************************************************************************
String _$updateMangaDetailHash() => r'0d87713f3a9ea3c6d792086eab56596f533beef7';
String _$updateMangaDetailHash() => r'0c54e4073f2b5ea61c2075afe68ffe67eac77faf';
/// Copied from Dart SDK
class _SystemHash {

View file

@ -77,12 +77,10 @@ class ChapterListTileWidget extends ConsumerWidget {
children: [
if ((chapter.manga.value!.isLocalArchive ?? false) == false)
Text(
dateFormat(
!chapter.manga.value!.isManga!
? DateTime.now().millisecondsSinceEpoch.toString()
: chapter.dateUpload!,
ref: ref,
context: context),
chapter.dateUpload == null || chapter.dateUpload!.isEmpty
? ""
: dateFormat(chapter.dateUpload!,
ref: ref, context: context),
style: const TextStyle(fontSize: 11),
),
if (!chapter.isRead!)

View file

@ -30,15 +30,13 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
final StorageProvider _storageProvider = StorageProvider();
_startDownload(bool? useWifi) async {
if (widget.chapter.manga.value!.isManga!) {
final data = await ref.watch(
downloadChapterProvider(chapter: widget.chapter, useWifi: useWifi)
.future);
if (mounted) {
setState(() {
_pageUrls = data;
});
}
final data = await ref.watch(
downloadChapterProvider(chapter: widget.chapter, useWifi: useWifi)
.future);
if (mounted) {
setState(() {
_pageUrls = data;
});
}
}
@ -54,6 +52,9 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
if (await File("${mangaDir!.path}${widget.chapter.name}.cbz").exists()) {
File("${mangaDir.path}${widget.chapter.name}.cbz").deleteSync();
}
if (await File("${mangaDir.path}${widget.chapter.name}.mp4").exists()) {
File("${mangaDir.path}${widget.chapter.name}.mp4").deleteSync();
}
path!.deleteSync(recursive: true);
} catch (_) {}
isar.writeTxnSync(() {

View file

@ -36,9 +36,10 @@ Future<List<String>> downloadChapter(
String scanlator = chapter.scanlator!.isNotEmpty
? "${chapter.scanlator!.replaceAll(regExp, '_')}_"
: "";
final isManga = chapter.manga.value!.isManga!;
final finalPath =
"downloads/${isManga ? "Manga" : "Anime"}/${manga.source} (${manga.lang!.toUpperCase()})/${manga.name!.replaceAll(regExp, '_')}/$scanlator${chapter.name!.replaceAll(regExp, '_')}";
"downloads/${isManga ? "Manga" : "Anime"}/${manga.source} (${manga.lang!.toUpperCase()})/${manga.name!.replaceAll(regExp, '_')}${isManga ? "/$scanlator${chapter.name!.replaceAll(regExp, '_')}" : ""}";
path = Directory("${path1!.path}$finalPath/");
Map<String, String> videoHeader = {};
if (isManga) {
@ -58,11 +59,12 @@ Future<List<String>> downloadChapter(
episode: chapter,
).future)
.then((value) {
final videosUrls =
value.$1.where((element) => !element.url.contains(".mp4")).toList();
final videosUrls = value.$1
.where((element) => element.originalUrl.endsWith(".mp4"))
.toList();
if (videosUrls.isNotEmpty) {
pageUrls = [videosUrls.first.url];
videoHeader.addAll(videosUrls.first.headers!);
videoHeader.addAll(videosUrls.first.headers ?? {});
isOk = true;
}
});
@ -80,7 +82,10 @@ Future<List<String>> downloadChapter(
bool cbzFileExist =
await File("${mangaDir!.path}${chapter.name}.cbz").exists() &&
ref.watch(saveAsCBZArchiveStateProvider);
if (!cbzFileExist) {
bool mp4FileExist =
await File("${mangaDir.path}${chapter.name}.mp4").exists() &&
ref.watch(saveAsCBZArchiveStateProvider);
if (!cbzFileExist || !mp4FileExist) {
for (var index = 0; index < pageUrls.length; index++) {
final path2 = Directory("${path1.path}downloads/");
final path5 =
@ -110,43 +115,75 @@ Future<List<String>> downloadChapter(
if (!(await path3.exists())) {
path3.create();
}
if ((await path.exists())) {
if (await File("${path.path}" "${padIndex(index + 1)}.jpg")
.exists()) {
if (isManga) {
if ((await path.exists())) {
if (await File("${path.path}" "${padIndex(index + 1)}.jpg")
.exists()) {
} else {
tasks.add(DownloadTask(
taskId: pageUrls[index],
headers: ref.watch(headersProvider(
source: manga.source!, lang: manga.lang!)),
url: pageUrls[index].trim().trimLeft().trimRight(),
filename: "${padIndex(index + 1)}.jpg",
baseDirectory: BaseDirectory.temporary,
directory: 'Mangayomi/$finalPath',
updates: Updates.statusAndProgress,
retries: 3,
allowPause: true,
requiresWiFi: onlyOnWifi));
}
} else {
tasks.add(DownloadTask(
taskId: pageUrls[index],
headers: isManga
? videoHeader
: ref.watch(headersProvider(
source: manga.source!, lang: manga.lang!)),
url: pageUrls[index].trim().trimLeft().trimRight(),
filename: "${padIndex(index + 1)}.jpg",
baseDirectory: BaseDirectory.temporary,
directory: 'Mangayomi/$finalPath',
updates: Updates.statusAndProgress,
allowPause: true,
requiresWiFi: onlyOnWifi));
path.create();
if (await File("${path.path}" "${padIndex(index + 1)}.jpg")
.exists()) {
} else {
tasks.add(DownloadTask(
taskId: pageUrls[index],
headers: ref.watch(headersProvider(
source: manga.source!, lang: manga.lang!)),
url: pageUrls[index].trim().trimLeft().trimRight(),
filename: "${padIndex(index + 1)}.jpg",
baseDirectory: BaseDirectory.temporary,
directory: 'Mangayomi/$finalPath',
updates: Updates.statusAndProgress,
allowPause: true,
retries: 3,
requiresWiFi: onlyOnWifi));
}
}
} else {
path.create();
if (await File("${path.path}" "${padIndex(index + 1)}.jpg")
.exists()) {
if ((await path.exists())) {
if (await File("${path.path}${chapter.name}.mp4").exists()) {
} else {
tasks.add(DownloadTask(
taskId: pageUrls[index],
headers: videoHeader,
url: pageUrls[index].trim().trimLeft().trimRight(),
filename: "${chapter.name}.mp4",
baseDirectory: BaseDirectory.temporary,
directory: 'Mangayomi/$finalPath',
updates: Updates.statusAndProgress,
allowPause: true,
retries: 3,
requiresWiFi: onlyOnWifi));
}
} else {
tasks.add(DownloadTask(
taskId: pageUrls[index],
headers: isManga
? videoHeader
: ref.watch(headersProvider(
source: manga.source!, lang: manga.lang!)),
url: pageUrls[index].trim().trimLeft().trimRight(),
filename: "${padIndex(index + 1)}.jpg",
baseDirectory: BaseDirectory.temporary,
directory: 'Mangayomi/$finalPath',
updates: Updates.statusAndProgress,
allowPause: true,
requiresWiFi: onlyOnWifi));
path.create();
if (await File("${path.path}${chapter.name}.mp4").exists()) {
} else {
tasks.add(DownloadTask(
taskId: pageUrls[index],
headers: videoHeader,
url: pageUrls[index].trim().trimLeft().trimRight(),
filename: "${chapter.name}.mp4",
baseDirectory: BaseDirectory.temporary,
directory: 'Mangayomi/$finalPath',
updates: Updates.statusAndProgress,
allowPause: true,
retries: 3,
requiresWiFi: onlyOnWifi));
}
}
}
}
@ -171,10 +208,12 @@ Future<List<String>> downloadChapter(
tasks,
batchProgressCallback: (succeeded, failed) async {
if (succeeded == tasks.length) {
if (ref.watch(saveAsCBZArchiveStateProvider)) {
await ref.watch(convertToCBZProvider(
path!.path, mangaDir.path, chapter.name!, pageUrls)
.future);
if (isManga) {
if (ref.watch(saveAsCBZArchiveStateProvider)) {
await ref.watch(convertToCBZProvider(
path!.path, mangaDir.path, chapter.name!, pageUrls)
.future);
}
}
}
bool isEmpty = isar.downloads
@ -186,7 +225,7 @@ Future<List<String>> downloadChapter(
succeeded: succeeded,
failed: failed,
total: tasks.length,
isDownload: (succeeded == tasks.length) ? true : false,
isDownload: (succeeded == tasks.length),
taskIds: pageUrls,
isStartDownload: true,
chapterId: chapter.id,
@ -203,7 +242,7 @@ Future<List<String>> downloadChapter(
isar.downloads.putSync(model
..succeeded = succeeded
..failed = failed
..isDownload = (succeeded == tasks.length) ? true : false);
..isDownload = (succeeded == tasks.length));
});
}
},
@ -231,7 +270,7 @@ Future<List<String>> downloadChapter(
succeeded: (progress * 100).toInt(),
failed: 0,
total: 100,
isDownload: (progress == 1.0) ? true : false,
isDownload: (progress == 1.0),
taskIds: pageUrls,
isStartDownload: true,
chapterId: chapter.id,
@ -248,7 +287,7 @@ Future<List<String>> downloadChapter(
isar.downloads.putSync(model
..succeeded = (progress * 100).toInt()
..failed = 0
..isDownload = (progress == 1.0) ? true : false);
..isDownload = (progress == 1.0));
});
}
},

View file

@ -6,7 +6,7 @@ part of 'download_provider.dart';
// RiverpodGenerator
// **************************************************************************
String _$downloadChapterHash() => r'58c91ea79c1d0b9d8df621de2a8007a366683a52';
String _$downloadChapterHash() => r'66f65a8ecf86c8633ae77f528589d941bc52420e';
/// Copied from Dart SDK
class _SystemHash {

View file

@ -3,59 +3,44 @@ import 'dart:typed_data';
import 'package:extended_image/extended_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:mangayomi/modules/manga/reader/providers/auto_crop_image_provider.dart';
// import 'package:mangayomi/modules/manga/reader/providers/auto_crop_image_provider.dart';
import 'package:mangayomi/modules/manga/reader/providers/reader_controller_provider.dart';
import 'package:mangayomi/modules/manga/reader/reader_view.dart';
import 'package:mangayomi/modules/more/settings/reader/providers/reader_state_provider.dart';
import 'package:mangayomi/utils/headers.dart';
import 'package:mangayomi/utils/reg_exp_matcher.dart';
class ImageViewCenter extends ConsumerWidget {
final String lang;
final String url;
final int index;
final String source;
final Directory path;
final bool isLocale;
final Uint8List? archiveImage;
final WidgetRef parentRef;
final UChapDataPreload datas;
final Widget? Function(ExtendedImageState state) loadStateChanged;
final Function(ExtendedImageGestureState state) onDoubleTap;
final GestureConfig Function(ExtendedImageState state)
initGestureConfigHandler;
const ImageViewCenter({
super.key,
required this.url,
required this.index,
required this.path,
required this.source,
required this.datas,
required this.loadStateChanged,
required this.onDoubleTap,
required this.initGestureConfigHandler,
required this.isLocale,
required this.lang,
required this.parentRef,
this.archiveImage,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
final cropBorders = ref.watch(cropBordersStateProvider);
final cropBorderData = parentRef.watch(autoCropImageBorderProvider(
autoCrop: cropBorders,
url: url,
archiveImages: archiveImage,
isLocaleList: isLocale,
path: path,
index: index));
return cropBorderData.when(
data: (data) {
return data != null
? _imageView(true, data, ref)
: _imageView(isLocale, archiveImage, ref);
},
error: (error, stackTrace) => Center(child: Text(error.toString())),
loading: () => _imageView(isLocale, archiveImage, ref),
);
// final cropBorder = ref.watch(cropBordersStateProvider);
return _imageView(datas.isLocale!, datas.archiveImage, ref);
// StreamBuilder<Uint8List?>(
// stream: ref
// .watch(autoCropImageBorderProvider(
// datas: datas, cropBorder: cropBorder)
// .future)
// .asStream(),
// builder: (context, snapshot) {
// final hasData = snapshot.hasData && snapshot.data != null;
// if (hasData) {
// return _imageView(hasData, snapshot.data, ref);
// }
// return _imageView(datas.isLocale!, datas.archiveImage, ref);
// });
}
Widget _imageView(bool isLocale, Uint8List? archiveImage, WidgetRef ref) {
@ -73,7 +58,7 @@ class ImageViewCenter extends ConsumerWidget {
loadStateChanged: loadStateChanged,
)
: ExtendedImage.file(
File("${path.path}" "${padIndex(index + 1)}.jpg"),
File("${datas.path!.path}" "${padIndex(datas.index! + 1)}.jpg"),
fit: getBoxFit(scaleType),
clearMemoryCacheWhenDispose: true,
enableMemoryCache: false,
@ -83,9 +68,11 @@ class ImageViewCenter extends ConsumerWidget {
loadStateChanged: loadStateChanged,
)
: ExtendedImage.network(
url.trim().trimLeft().trimRight(),
datas.url!.trim().trimLeft().trimRight(),
fit: getBoxFit(scaleType),
headers: ref.watch(headersProvider(source: source, lang: lang)),
headers: ref.watch(headersProvider(
source: datas.chapter!.manga.value!.source!,
lang: datas.chapter!.manga.value!.lang!)),
enableMemoryCache: true,
mode: ExtendedImageMode.gesture,
cacheMaxAge: const Duration(days: 7),

View file

@ -3,8 +3,9 @@ import 'dart:typed_data';
import 'package:extended_image/extended_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:mangayomi/modules/manga/reader/providers/auto_crop_image_provider.dart';
// import 'package:mangayomi/modules/manga/reader/providers/auto_crop_image_provider.dart';
import 'package:mangayomi/modules/manga/reader/providers/reader_controller_provider.dart';
import 'package:mangayomi/modules/manga/reader/reader_view.dart';
import 'package:mangayomi/modules/more/settings/reader/providers/reader_state_provider.dart';
import 'package:mangayomi/providers/l10n_providers.dart';
import 'package:mangayomi/utils/colors.dart';
@ -14,50 +15,35 @@ import 'package:mangayomi/utils/reg_exp_matcher.dart';
import 'package:mangayomi/modules/manga/reader/widgets/circular_progress_indicator_animate_rotate.dart';
class ImageViewVertical extends ConsumerWidget {
final bool isLocale;
final String url;
final int index;
final String source;
final Directory path;
final String lang;
final Uint8List? archiveImage;
final WidgetRef parentRef;
final UChapDataPreload datas;
final Function(bool) failedToLoadImage;
const ImageViewVertical(
{super.key,
required this.url,
required this.index,
required this.path,
required this.source,
required this.isLocale,
required this.lang,
this.archiveImage,
required this.parentRef,
required this.failedToLoadImage});
{super.key, required this.datas, required this.failedToLoadImage});
@override
Widget build(BuildContext context, WidgetRef ref) {
final cropBorders = ref.watch(cropBordersStateProvider);
final cropBorderData = parentRef.watch(autoCropImageBorderProvider(
autoCrop: cropBorders,
url: url,
archiveImages: archiveImage,
isLocaleList: isLocale,
path: path,
index: index));
// final cropBorder = ref.watch(cropBordersStateProvider);
return Container(
color: Colors.black,
child: cropBorderData.when(
data: (data) {
return data != null
? _imageView(true, data, context, ref)
: _imageView(isLocale, archiveImage, context, ref);
},
error: (error, stackTrace) => Center(child: Text(error.toString())),
loading: () => _imageView(isLocale, archiveImage, context, ref),
));
color: Colors.black,
child: _imageView(datas.isLocale!, datas.archiveImage, context, ref),
// StreamBuilder<Uint8List?>(
// stream: ref
// .watch(autoCropImageBorderProvider(
// datas: datas, cropBorder: cropBorder)
// .future)
// .asStream(),
// builder: (context, snapshot) {
// final hasData = snapshot.hasData && snapshot.data != null;
// if (hasData) {
// return _imageView(hasData, snapshot.data, context, ref);
// }
// return _imageView(
// datas.isLocale!, datas.archiveImage, context, ref);
// }),
);
}
Widget _imageView(bool isLocale, Uint8List? archiveImage,
@ -67,7 +53,7 @@ class ImageViewVertical extends ConsumerWidget {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (index == 0)
if (datas.index == 0)
SizedBox(
height: MediaQuery.of(context).padding.top,
),
@ -88,7 +74,8 @@ class ImageViewVertical extends ConsumerWidget {
: ExtendedImage.file(
fit: getBoxFit(scaleType),
enableMemoryCache: false,
File('${path.path}${padIndex(index + 1)}.jpg'),
File(
'${datas.path!.path}${padIndex(datas.index! + 1)}.jpg'),
enableLoadState: true, loadStateChanged: (state) {
if (state.extendedImageLoadState == LoadState.loading) {
return Container(
@ -98,8 +85,10 @@ class ImageViewVertical extends ConsumerWidget {
}
return null;
})
: ExtendedImage.network(url.trim().trimLeft().trimRight(),
headers: ref.watch(headersProvider(source: source, lang: lang)),
: ExtendedImage.network(datas.url!.trim().trimLeft().trimRight(),
headers: ref.watch(headersProvider(
source: datas.chapter!.manga.value!.source!,
lang: datas.chapter!.manga.value!.lang!)),
handleLoadingProgress: true,
cacheMaxAge: const Duration(days: 7),
fit: getBoxFit(scaleType),

View file

@ -1,68 +1,70 @@
import 'dart:io';
import 'package:extended_image/extended_image.dart';
import 'dart:isolate';
import 'package:flutter/foundation.dart';
import 'package:image/image.dart';
import 'package:mangayomi/modules/manga/reader/reader_view.dart';
import 'package:mangayomi/utils/reg_exp_matcher.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'auto_crop_image_provider.g.dart';
@Riverpod(keepAlive: true)
Future<Uint8List?> autoCropImageBorder(AutoCropImageBorderRef ref,
{required bool autoCrop,
required String? url,
required Uint8List? archiveImages,
required bool isLocaleList,
required Directory path,
required int index}) async {
if (autoCrop) {
if (archiveImages != null) {
return await compute(_cropImageFuture, (archiveImages, null));
} else if (isLocaleList) {
return await compute(_cropImageFuture, (
File('${path.path}${padIndex(index + 1)}.jpg').readAsBytesSync(),
null
));
{required UChapDataPreload datas, required bool cropBorder}) async {
final ReceivePort receivePort = ReceivePort();
(Uint8List?, SendPort)? data;
try {
if (cropBorder) {
if (datas.archiveImage != null) {
data = (datas.archiveImage, receivePort.sendPort);
} else if (datas.isLocale!) {
data = (
File('${datas.path!.path}${padIndex(datas.index! + 1)}.jpg')
.readAsBytesSync(),
receivePort.sendPort
);
} else {
// String path = "";
// File? cachedImage;
// if (datas.url != null) {
// cachedImage = await getCachedImageFile(datas.url!);
// }
// if (cachedImage != null) {
// path = cachedImage.path;
// }
// if (path.isNotEmpty) {
// data = (File(path).readAsBytesSync(), receivePort.sendPort);
// } else {
// data = (null, receivePort.sendPort);
// }
}
await Isolate.spawn(_autocropImageIsolate, data);
return await receivePort.first as Uint8List?;
}
return await compute(_cropImageFuture, (null, url));
return null;
} on Object {
receivePort.close();
return null;
}
return null;
}
Future<Uint8List?> _cropImageFuture((Uint8List?, String?) datas) async {
Uint8List? oldImage;
String path = "";
Uint8List? image = datas.$1;
File? cachedImage;
String? url = datas.$2;
if (url != null) {
cachedImage = await getCachedImageFile(url);
Future<Uint8List?> _autocropImageIsolate((Uint8List?, SendPort?)? datas) async {
SendPort? resultPort = datas!.$2;
Uint8List? img = datas.$1;
if (img == null) {
Isolate.exit(resultPort, null);
}
if (cachedImage != null) {
path = cachedImage.path;
}
if (path.isNotEmpty) {
oldImage = File(path).readAsBytesSync();
} else if (image != null) {
oldImage = image;
}
if (oldImage != null) {
return await compute(_autocropImageIsolate, oldImage);
}
return null;
}
FutureOr<Uint8List?> _autocropImageIsolate(Uint8List? cropData) async {
Image? croppedImage;
Image? image = decodeImage(cropData!);
image =
copyCrop(image!, x: 0, y: 0, width: image.width, height: image.height);
Image? image = decodeImage(img);
int left = 0;
int top = 0;
int right = image.width;
int right = image!.width;
int bottom = image.height;
// Find left coordinate
for (int x = 0; x < image.width; x++) {
bool stop = false;
@ -132,5 +134,6 @@ FutureOr<Uint8List?> _autocropImageIsolate(Uint8List? cropData) async {
height: bottom - top,
);
return encodeJpg(croppedImage);
Uint8List? encodeImage = encodeJpg(croppedImage);
Isolate.exit(resultPort, encodeImage);
}

View file

@ -7,7 +7,7 @@ part of 'auto_crop_image_provider.dart';
// **************************************************************************
String _$autoCropImageBorderHash() =>
r'059cbf2ee6f6ef931841e19851f201047a16bad6';
r'f156727d84d4721617872f4c51c81cef2c1466e9';
/// Copied from Dart SDK
class _SystemHash {
@ -41,20 +41,12 @@ class AutoCropImageBorderFamily extends Family<AsyncValue<Uint8List?>> {
/// See also [autoCropImageBorder].
AutoCropImageBorderProvider call({
required bool autoCrop,
required String? url,
required Uint8List? archiveImages,
required bool isLocaleList,
required Directory path,
required int index,
required UChapDataPreload datas,
required bool cropBorder,
}) {
return AutoCropImageBorderProvider(
autoCrop: autoCrop,
url: url,
archiveImages: archiveImages,
isLocaleList: isLocaleList,
path: path,
index: index,
datas: datas,
cropBorder: cropBorder,
);
}
@ -63,12 +55,8 @@ class AutoCropImageBorderFamily extends Family<AsyncValue<Uint8List?>> {
covariant AutoCropImageBorderProvider provider,
) {
return call(
autoCrop: provider.autoCrop,
url: provider.url,
archiveImages: provider.archiveImages,
isLocaleList: provider.isLocaleList,
path: provider.path,
index: provider.index,
datas: provider.datas,
cropBorder: provider.cropBorder,
);
}
@ -91,21 +79,13 @@ class AutoCropImageBorderFamily extends Family<AsyncValue<Uint8List?>> {
class AutoCropImageBorderProvider extends FutureProvider<Uint8List?> {
/// See also [autoCropImageBorder].
AutoCropImageBorderProvider({
required bool autoCrop,
required String? url,
required Uint8List? archiveImages,
required bool isLocaleList,
required Directory path,
required int index,
required UChapDataPreload datas,
required bool cropBorder,
}) : this._internal(
(ref) => autoCropImageBorder(
ref as AutoCropImageBorderRef,
autoCrop: autoCrop,
url: url,
archiveImages: archiveImages,
isLocaleList: isLocaleList,
path: path,
index: index,
datas: datas,
cropBorder: cropBorder,
),
from: autoCropImageBorderProvider,
name: r'autoCropImageBorderProvider',
@ -116,12 +96,8 @@ class AutoCropImageBorderProvider extends FutureProvider<Uint8List?> {
dependencies: AutoCropImageBorderFamily._dependencies,
allTransitiveDependencies:
AutoCropImageBorderFamily._allTransitiveDependencies,
autoCrop: autoCrop,
url: url,
archiveImages: archiveImages,
isLocaleList: isLocaleList,
path: path,
index: index,
datas: datas,
cropBorder: cropBorder,
);
AutoCropImageBorderProvider._internal(
@ -131,20 +107,12 @@ class AutoCropImageBorderProvider extends FutureProvider<Uint8List?> {
required super.allTransitiveDependencies,
required super.debugGetCreateSourceHash,
required super.from,
required this.autoCrop,
required this.url,
required this.archiveImages,
required this.isLocaleList,
required this.path,
required this.index,
required this.datas,
required this.cropBorder,
}) : super.internal();
final bool autoCrop;
final String? url;
final Uint8List? archiveImages;
final bool isLocaleList;
final Directory path;
final int index;
final UChapDataPreload datas;
final bool cropBorder;
@override
Override overrideWith(
@ -159,12 +127,8 @@ class AutoCropImageBorderProvider extends FutureProvider<Uint8List?> {
dependencies: null,
allTransitiveDependencies: null,
debugGetCreateSourceHash: null,
autoCrop: autoCrop,
url: url,
archiveImages: archiveImages,
isLocaleList: isLocaleList,
path: path,
index: index,
datas: datas,
cropBorder: cropBorder,
),
);
}
@ -177,46 +141,26 @@ class AutoCropImageBorderProvider extends FutureProvider<Uint8List?> {
@override
bool operator ==(Object other) {
return other is AutoCropImageBorderProvider &&
other.autoCrop == autoCrop &&
other.url == url &&
other.archiveImages == archiveImages &&
other.isLocaleList == isLocaleList &&
other.path == path &&
other.index == index;
other.datas == datas &&
other.cropBorder == cropBorder;
}
@override
int get hashCode {
var hash = _SystemHash.combine(0, runtimeType.hashCode);
hash = _SystemHash.combine(hash, autoCrop.hashCode);
hash = _SystemHash.combine(hash, url.hashCode);
hash = _SystemHash.combine(hash, archiveImages.hashCode);
hash = _SystemHash.combine(hash, isLocaleList.hashCode);
hash = _SystemHash.combine(hash, path.hashCode);
hash = _SystemHash.combine(hash, index.hashCode);
hash = _SystemHash.combine(hash, datas.hashCode);
hash = _SystemHash.combine(hash, cropBorder.hashCode);
return _SystemHash.finish(hash);
}
}
mixin AutoCropImageBorderRef on FutureProviderRef<Uint8List?> {
/// The parameter `autoCrop` of this provider.
bool get autoCrop;
/// The parameter `datas` of this provider.
UChapDataPreload get datas;
/// The parameter `url` of this provider.
String? get url;
/// The parameter `archiveImages` of this provider.
Uint8List? get archiveImages;
/// The parameter `isLocaleList` of this provider.
bool get isLocaleList;
/// The parameter `path` of this provider.
Directory get path;
/// The parameter `index` of this provider.
int get index;
/// The parameter `cropBorder` of this provider.
bool get cropBorder;
}
class _AutoCropImageBorderProviderElement
@ -224,18 +168,9 @@ class _AutoCropImageBorderProviderElement
_AutoCropImageBorderProviderElement(super.provider);
@override
bool get autoCrop => (origin as AutoCropImageBorderProvider).autoCrop;
UChapDataPreload get datas => (origin as AutoCropImageBorderProvider).datas;
@override
String? get url => (origin as AutoCropImageBorderProvider).url;
@override
Uint8List? get archiveImages =>
(origin as AutoCropImageBorderProvider).archiveImages;
@override
bool get isLocaleList => (origin as AutoCropImageBorderProvider).isLocaleList;
@override
Directory get path => (origin as AutoCropImageBorderProvider).path;
@override
int get index => (origin as AutoCropImageBorderProvider).index;
bool get cropBorder => (origin as AutoCropImageBorderProvider).cropBorder;
}
// ignore_for_file: type=lint
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member

View file

@ -11,6 +11,7 @@ import 'package:go_router/go_router.dart';
import 'package:mangayomi/main.dart';
import 'package:mangayomi/models/chapter.dart';
import 'package:mangayomi/models/settings.dart';
// import 'package:mangayomi/modules/manga/reader/providers/auto_crop_image_provider.dart';
import 'package:mangayomi/modules/more/settings/reader/providers/reader_state_provider.dart';
import 'package:mangayomi/providers/l10n_providers.dart';
import 'package:mangayomi/sources/utils/utils.dart';
@ -182,6 +183,16 @@ class _MangaChapterPageGalleryState
"${_uChapDataPreload[index].path!.path}${padIndex(_uChapDataPreload[index].index! + 1)}.jpg")),
context);
}
// final cropBorders = ref.watch(cropBordersStateProvider);
// ref
// .watch(autoCropImageBorderProvider(
// cropBorder: cropBorders, datas: _uChapDataPreload[index])
// .future)
// .then((value) {
// if (value != null) {
// precacheImage(ExtendedMemoryImageProvider(value), context);
// }
// });
} else {
precacheImage(
ExtendedNetworkImageProvider(
@ -331,6 +342,7 @@ class _MangaChapterPageGalleryState
_preloadImage(_currentIndex! - i);
}
}
// _initCropBorders();
}
void _onPageChanged(int index) {
@ -733,13 +745,11 @@ class _MangaChapterPageGalleryState
onChangeEnd: (newValue) {
try {
final index = _uChapDataPreload
.where((element) =>
.firstWhere((element) =>
element.chapter ==
chapter &&
element.index ==
newValue.toInt())
.toList()
.first
.pageIndex;
_onBtnTapped(
@ -882,7 +892,7 @@ class _MangaChapterPageGalleryState
const Icon(
Icons.crop_rounded,
),
if (cropBorders)
if (!cropBorders)
Positioned(
right: 8,
child: Transform.scale(
@ -922,6 +932,36 @@ class _MangaChapterPageGalleryState
);
}
// _initCropBorders() async {
// final uChapDataPreloadF = _uChapDataPreload
// .where((element) => element.chapter == chapter)
// .toList();
// for (var element in uChapDataPreloadF) {
// if (mounted) {
// // Uint8List? res;
// // res =
// await ref.watch(
// autoCropImageBorderProvider(cropBorder: true, datas: element)
// .future);
// // bool isOk = false;
// // while (res == null && isOk == false) {
// // try {
// // await Future.delayed(const Duration(seconds: 1));
// // res = await ref.refresh(
// // autoCropImageBorderProvider(cropBorder: true, datas: element)
// // .future);
// // if (res != null) {
// // isOk = true;
// // }
// // } catch (_) {
// // isOk = true;
// // }
// // }
// }
// }
// }
Widget _showPage() {
return Consumer(builder: (context, ref, child) {
final currentIndex = ref.watch(currentIndexProvider(chapter));
@ -1172,6 +1212,7 @@ class _MangaChapterPageGalleryState
.setPageIndex(_uChapDataPreload[_currentIndex!].index!);
_isBookmarked = _readerController.getChapterBookmarked();
}
return true;
},
child: ValueListenableBuilder(
@ -1190,7 +1231,6 @@ class _MangaChapterPageGalleryState
basePosition: _scalePosition,
onScaleEnd: _onScaleEnd,
child: ScrollablePositionedList.separated(
// physics: const ClampingScrollPhysics(),
minCacheExtent: 15 * mediaHeight(context, 1),
initialScrollIndex: _currentIndex!,
itemCount: _uChapDataPreload.length,
@ -1204,20 +1244,7 @@ class _MangaChapterPageGalleryState
},
onDoubleTap: () {},
child: ImageViewVertical(
archiveImage:
_uChapDataPreload[index].archiveImage,
source: _readerController.getSourceName(),
index: _uChapDataPreload[index].index!,
url: _uChapDataPreload[index].url!,
path: _uChapDataPreload[index].path!,
isLocale:
_uChapDataPreload[index].isLocale!,
lang: _uChapDataPreload[index]
.chapter!
.manga
.value!
.lang!,
parentRef: ref,
datas: _uChapDataPreload[index],
failedToLoadImage: (value) {
// _failedToLoadImage.value = value;
},
@ -1249,13 +1276,7 @@ class _MangaChapterPageGalleryState
},
itemBuilder: (BuildContext context, int index) {
return ImageViewCenter(
parentRef: ref,
archiveImage:
_uChapDataPreload[index].archiveImage,
source: _readerController.getSourceName(),
index: _uChapDataPreload[index].index!,
url: _uChapDataPreload[index].url!,
path: _uChapDataPreload[index].path!,
datas: _uChapDataPreload[index],
loadStateChanged:
(ExtendedImageState state) {
if (state.extendedImageLoadState ==
@ -1414,13 +1435,6 @@ class _MangaChapterPageGalleryState
_doubleClickAnimationController.forward();
},
isLocale:
_uChapDataPreload[index].isLocale!,
lang: _uChapDataPreload[index]
.chapter!
.manga
.value!
.lang!,
);
},
itemCount: _uChapDataPreload.length,

View file

@ -256,16 +256,20 @@ Future<String> getWebViewPath() async {
}
Future<String?> decodeHtml(Webview webview, {String? sourceId}) async {
final html = await webview
.evaluateJavaScript("window.document.documentElement.outerHTML;");
final cookie = await webview.evaluateJavaScript("window.document.cookie;");
if (cookie != null && sourceId != null) {
setCookieBA(cookie, sourceId);
try {
final html = await webview
.evaluateJavaScript("window.document.documentElement.outerHTML;");
final cookie = await webview.evaluateJavaScript("window.document.cookie;");
if (cookie != null && sourceId != null) {
setCookieBA(cookie, sourceId);
}
final res = jsonDecode(html!) as String;
return res == "<html><head></head><body></body></html>" || res.isEmpty
? null
: res;
} catch (_) {
return null;
}
final res = jsonDecode(html!) as String;
return res == "<html><head></head><body></body></html>" || res.isEmpty
? null
: res;
}

View file

@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:io';
import 'package:dart_eval/stdlib/core.dart';
import 'package:mangayomi/eval/bridge_class/manga_model.dart';
import 'package:mangayomi/eval/bridge_class/model.dart';
@ -6,6 +7,7 @@ import 'package:mangayomi/eval/compiler/compiler.dart';
import 'package:mangayomi/models/chapter.dart';
import 'package:mangayomi/models/video.dart';
import 'package:mangayomi/eval/runtime/runtime.dart';
import 'package:mangayomi/providers/storage_provider.dart';
import 'package:mangayomi/sources/utils/utils.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'get_anime_servers.g.dart';
@ -15,15 +17,17 @@ Future<(List<Video>, bool)> getAnimeServers(
GetAnimeServersRef ref, {
required Chapter episode,
}) async {
final storageProvider = StorageProvider();
final mangaDirectory = await storageProvider.getMangaMainDirectory(episode);
final isLocalArchive = episode.manga.value!.isLocalArchive!;
List<Video> video = [];
if (episode.manga.value!.isLocalArchive!) {
return (
[
Video(episode.archivePath!, episode.name!, episode.archivePath!,
subtitles: [])
],
true
);
if (await File("${mangaDirectory!.path}${episode.name}.mp4").exists() ||
isLocalArchive) {
final path = isLocalArchive
? episode.archivePath
: "${mangaDirectory.path}${episode.name}.mp4";
return ([Video(path!, episode.name!, path, subtitles: [])], true);
}
final source =
getSource(episode.manga.value!.lang!, episode.manga.value!.source!);
@ -51,8 +55,13 @@ Future<(List<Video>, bool)> getAnimeServers(
if (subs is $List) {
subtitles = subs.map((e) => Track(e.file, e.label)).toList();
}
List<Track>? audios = [];
var auds = e.audios;
if (auds is $List) {
audios = auds.map((e) => Track(e.file, e.label)).toList();
}
return Video(e.url, e.quality, e.originalUrl,
headers: e.headers, subtitles: subtitles);
headers: e.headers, subtitles: subtitles, audios: audios);
},
).toList();
}

View file

@ -6,7 +6,7 @@ part of 'get_anime_servers.dart';
// RiverpodGenerator
// **************************************************************************
String _$getAnimeServersHash() => r'd42c9b20b5f1c27c8adaab3d1f1873461883b840';
String _$getAnimeServersHash() => r'39f02b0c0b51a78a7c1a67747686909beedc5d0e';
/// Copied from Dart SDK
class _SystemHash {

View file

@ -6,7 +6,7 @@ part of 'cookie.dart';
// RiverpodGenerator
// **************************************************************************
String _$setCookieHash() => r'55073d2aceae6ce9bf03d61d390dfb84150d272e';
String _$setCookieHash() => r'd10ac9b2e839e2a5c369900c65c557723c8f2d37';
/// Copied from Dart SDK
class _SystemHash {

View file

@ -1,5 +1,5 @@
name: mangayomi
description: Free and open source manga reader multi plateform app inspired by Tachiyomi.
description: Free and open source manga reader and anime streaming cross-plateform app inspired by Tachiyomi.
version: 0.0.44+17