parent
a7d801e210
commit
31b3f96729
20 changed files with 379 additions and 403 deletions
|
|
@ -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) =>
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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!;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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!)
|
||||
|
|
|
|||
|
|
@ -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(() {
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
});
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ part of 'download_provider.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$downloadChapterHash() => r'58c91ea79c1d0b9d8df621de2a8007a366683a52';
|
||||
String _$downloadChapterHash() => r'66f65a8ecf86c8633ae77f528589d941bc52420e';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ part of 'cookie.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$setCookieHash() => r'55073d2aceae6ce9bf03d61d390dfb84150d272e';
|
||||
String _$setCookieHash() => r'd10ac9b2e839e2a5c369900c65c557723c8f2d37';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue