commit
a15d989656
8 changed files with 124 additions and 160 deletions
|
|
@ -4,6 +4,7 @@ import 'package:flutter/foundation.dart';
|
||||||
import 'package:mangayomi/modules/manga/archive_reader/models/models.dart';
|
import 'package:mangayomi/modules/manga/archive_reader/models/models.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:path/path.dart' as p;
|
||||||
part 'archive_reader_providers.g.dart';
|
part 'archive_reader_providers.g.dart';
|
||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
|
|
@ -99,13 +100,8 @@ LocalArchive _extractArchive(String path) {
|
||||||
final localArchive = LocalArchive()
|
final localArchive = LocalArchive()
|
||||||
..path = path
|
..path = path
|
||||||
..extensionType =
|
..extensionType =
|
||||||
setTypeExtension(path.split('/').last.split("\\").last.split(".").last)
|
setTypeExtension(p.extension(path).replaceFirst(".", ""))
|
||||||
..name = path
|
..name = p.basenameWithoutExtension(path);
|
||||||
.split('/')
|
|
||||||
.last
|
|
||||||
.split("\\")
|
|
||||||
.last
|
|
||||||
.replaceAll(RegExp(r'\.(cbz|zip|cbt|tar)'), '');
|
|
||||||
Archive? archive;
|
Archive? archive;
|
||||||
final inputStream = InputFileStream(path);
|
final inputStream = InputFileStream(path);
|
||||||
final extensionType = localArchive.extensionType;
|
final extensionType = localArchive.extensionType;
|
||||||
|
|
@ -120,14 +116,13 @@ LocalArchive _extractArchive(String path) {
|
||||||
final filename = file.name;
|
final filename = file.name;
|
||||||
if (file.isFile) {
|
if (file.isFile) {
|
||||||
if (_isImageFile(filename) && !filename.startsWith('.')) {
|
if (_isImageFile(filename) && !filename.startsWith('.')) {
|
||||||
|
final data = file.content as Uint8List;
|
||||||
if (filename.contains("cover")) {
|
if (filename.contains("cover")) {
|
||||||
final data = file.content as Uint8List;
|
|
||||||
localArchive.coverImage = data;
|
localArchive.coverImage = data;
|
||||||
} else {
|
} else {
|
||||||
final data = file.content as Uint8List;
|
|
||||||
localArchive.images!.add(LocalImage()
|
localArchive.images!.add(LocalImage()
|
||||||
..image = data
|
..image = data
|
||||||
..name = filename.split('/').last.split("\\").last);
|
..name = p.basename(filename));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -140,13 +135,8 @@ LocalArchive _extractArchive(String path) {
|
||||||
(String, LocalExtensionType, Uint8List, String) _extractArchiveOnly(
|
(String, LocalExtensionType, Uint8List, String) _extractArchiveOnly(
|
||||||
String path) {
|
String path) {
|
||||||
final extensionType =
|
final extensionType =
|
||||||
setTypeExtension(path.split('/').last.split("\\").last.split(".").last);
|
setTypeExtension(p.extension(path).replaceFirst('.', ''));
|
||||||
final name = path
|
final name = p.basenameWithoutExtension(path);
|
||||||
.split('/')
|
|
||||||
.last
|
|
||||||
.split("\\")
|
|
||||||
.last
|
|
||||||
.replaceAll(RegExp(r'\.(cbz|zip|cbt|tar)'), '');
|
|
||||||
Uint8List? coverImage;
|
Uint8List? coverImage;
|
||||||
|
|
||||||
Archive? archive;
|
Archive? archive;
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import 'package:mangayomi/services/background_downloader/background_downloader.d
|
||||||
import 'package:mangayomi/utils/extensions/string_extensions.dart';
|
import 'package:mangayomi/utils/extensions/string_extensions.dart';
|
||||||
import 'package:mangayomi/utils/global_style.dart';
|
import 'package:mangayomi/utils/global_style.dart';
|
||||||
import 'package:share_plus/share_plus.dart';
|
import 'package:share_plus/share_plus.dart';
|
||||||
|
import 'package:path/path.dart' as p;
|
||||||
|
|
||||||
class ChapterPageDownload extends ConsumerStatefulWidget {
|
class ChapterPageDownload extends ConsumerStatefulWidget {
|
||||||
final Chapter chapter;
|
final Chapter chapter;
|
||||||
|
|
@ -49,9 +50,9 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
||||||
|
|
||||||
List<XFile> files = [];
|
List<XFile> files = [];
|
||||||
|
|
||||||
final cbzFile = File("${mangaDir!.path}${widget.chapter.name}.cbz");
|
final cbzFile = File(p.join(mangaDir!.path, "${widget.chapter.name}.cbz"));
|
||||||
final mp4File = File(
|
final mp4File = File(
|
||||||
"${mangaDir.path}${widget.chapter.name!.replaceForbiddenCharacters(' ')}.mp4");
|
p.join(mangaDir.path, "${widget.chapter.name!.replaceForbiddenCharacters(' ')}.mp4"));
|
||||||
if (cbzFile.existsSync()) {
|
if (cbzFile.existsSync()) {
|
||||||
files = [XFile(cbzFile.path)];
|
files = [XFile(cbzFile.path)];
|
||||||
} else if (mp4File.existsSync()) {
|
} else if (mp4File.existsSync()) {
|
||||||
|
|
@ -72,14 +73,14 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
||||||
|
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
final cbzFile = File("${mangaDir!.path}${widget.chapter.name}.cbz");
|
final cbzFile = File(p.join(mangaDir!.path, "${widget.chapter.name}.cbz"));
|
||||||
if (cbzFile.existsSync()) {
|
if (cbzFile.existsSync()) {
|
||||||
cbzFile.deleteSync();
|
cbzFile.deleteSync();
|
||||||
}
|
}
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
try {
|
try {
|
||||||
final mp4File = File(
|
final mp4File = File(
|
||||||
"${mangaDir!.path}${widget.chapter.name!.replaceForbiddenCharacters(' ')}.mp4");
|
p.join(mangaDir!.path, "${widget.chapter.name!.replaceForbiddenCharacters(' ')}.mp4"));
|
||||||
if (mp4File.existsSync()) {
|
if (mp4File.existsSync()) {
|
||||||
mp4File.deleteSync();
|
mp4File.deleteSync();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import 'package:archive/archive_io.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:path/path.dart' as path;
|
||||||
part 'convert_to_cbz.g.dart';
|
part 'convert_to_cbz.g.dart';
|
||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
|
|
@ -34,7 +35,7 @@ List<String> _convertToCBZ((String, String, String, List<String>) datas) {
|
||||||
|
|
||||||
if (imagesPaths.isNotEmpty && pageList.length == imagesPaths.length) {
|
if (imagesPaths.isNotEmpty && pageList.length == imagesPaths.length) {
|
||||||
var encoder = ZipFileEncoder();
|
var encoder = ZipFileEncoder();
|
||||||
encoder.create("$mangaDir/$chapterName.cbz");
|
encoder.create(path.join(mangaDir, "$chapterName.cbz"));
|
||||||
for (var path in imagesPaths) {
|
for (var path in imagesPaths) {
|
||||||
encoder.addFile(File(path));
|
encoder.addFile(File(path));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import 'package:mangayomi/utils/extensions/string_extensions.dart';
|
||||||
import 'package:mangayomi/utils/headers.dart';
|
import 'package:mangayomi/utils/headers.dart';
|
||||||
import 'package:mangayomi/utils/reg_exp_matcher.dart';
|
import 'package:mangayomi/utils/reg_exp_matcher.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
import 'package:path/path.dart' as p;
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
part 'download_provider.g.dart';
|
part 'download_provider.g.dart';
|
||||||
|
|
@ -45,10 +46,19 @@ Future<List<PageUrl>> downloadChapter(
|
||||||
: "";
|
: "";
|
||||||
final chapterName = chapter.name!.replaceForbiddenCharacters(' ');
|
final chapterName = chapter.name!.replaceForbiddenCharacters(' ');
|
||||||
|
|
||||||
final isManga = chapter.manga.value!.isManga!;
|
final isManga = manga.isManga!;
|
||||||
final finalPath =
|
final pathSegments = [
|
||||||
"downloads/${isManga ? "Manga" : "Anime"}/${manga.source} (${manga.lang!.toUpperCase()})/${manga.name!.replaceForbiddenCharacters('_')}${isManga ? "/$scanlator${chapter.name!.replaceForbiddenCharacters('_')}" : ""}";
|
"downloads",
|
||||||
path = Directory("${path1!.path}$finalPath/");
|
isManga ? "Manga" : "Anime",
|
||||||
|
"${manga.source} (${manga.lang!.toUpperCase()})",
|
||||||
|
manga.name!.replaceForbiddenCharacters('_'),
|
||||||
|
];
|
||||||
|
if (isManga) {
|
||||||
|
pathSegments.add(scanlator);
|
||||||
|
pathSegments.add(chapter.name!.replaceForbiddenCharacters('_'));
|
||||||
|
}
|
||||||
|
final finalPath = p.joinAll(pathSegments);
|
||||||
|
path = Directory(p.join(path1!.path, finalPath));
|
||||||
Map<String, String> videoHeader = {};
|
Map<String, String> videoHeader = {};
|
||||||
bool hasM3U8File = false;
|
bool hasM3U8File = false;
|
||||||
bool nonM3U8File = false;
|
bool nonM3U8File = false;
|
||||||
|
|
@ -60,7 +70,7 @@ Future<List<PageUrl>> downloadChapter(
|
||||||
Future<void> processConvert() async {
|
Future<void> processConvert() async {
|
||||||
if (hasM3U8File) {
|
if (hasM3U8File) {
|
||||||
await m3u8Downloader?.mergeTsToMp4(
|
await m3u8Downloader?.mergeTsToMp4(
|
||||||
"${path!.path}$chapterName.mp4", "${path.path}$chapterName");
|
p.join(path!.path, "$chapterName.mp4"), p.join(path.path, chapterName));
|
||||||
} else {
|
} else {
|
||||||
if (ref.watch(saveAsCBZArchiveStateProvider)) {
|
if (ref.watch(saveAsCBZArchiveStateProvider)) {
|
||||||
await ref.watch(convertToCBZProvider(path!.path, mangaDir!.path,
|
await ref.watch(convertToCBZProvider(path!.path, mangaDir!.path,
|
||||||
|
|
@ -120,7 +130,7 @@ Future<List<PageUrl>> downloadChapter(
|
||||||
if (hasM3U8File) {
|
if (hasM3U8File) {
|
||||||
m3u8Downloader = M3u8Downloader(
|
m3u8Downloader = M3u8Downloader(
|
||||||
m3u8Url: videosUrls.first.url,
|
m3u8Url: videosUrls.first.url,
|
||||||
downloadDir: "${path!.path}$chapterName",
|
downloadDir: p.join(path!.path, chapterName),
|
||||||
headers: videosUrls.first.headers ?? {});
|
headers: videosUrls.first.headers ?? {});
|
||||||
(tsList, tsKey, tsIv, m3u8MediaSequence) =
|
(tsList, tsKey, tsIv, m3u8MediaSequence) =
|
||||||
await m3u8Downloader!.getTsList();
|
await m3u8Downloader!.getTsList();
|
||||||
|
|
@ -144,39 +154,24 @@ Future<List<PageUrl>> downloadChapter(
|
||||||
|
|
||||||
if (pageUrls.isNotEmpty) {
|
if (pageUrls.isNotEmpty) {
|
||||||
bool cbzFileExist =
|
bool cbzFileExist =
|
||||||
await File("${mangaDir!.path}${chapter.name}.cbz").exists() &&
|
await File(p.join(mangaDir!.path, "${chapter.name}.cbz")).exists() &&
|
||||||
ref.watch(saveAsCBZArchiveStateProvider);
|
ref.watch(saveAsCBZArchiveStateProvider);
|
||||||
bool mp4FileExist = await File("${mangaDir.path}$chapterName.mp4").exists();
|
bool mp4FileExist = await File(p.join(mangaDir.path, "$chapterName.mp4")).exists();
|
||||||
if (!cbzFileExist && isManga || !mp4FileExist && !isManga) {
|
if (!cbzFileExist && isManga || !mp4FileExist && !isManga) {
|
||||||
for (var index = 0; index < pageUrls.length; index++) {
|
for (var index = 0; index < pageUrls.length; index++) {
|
||||||
final path2 = Directory("${path1.path}downloads/");
|
final path2 = Directory(p.join(path1.path,
|
||||||
final path5 =
|
"downloads",
|
||||||
Directory("${path1.path}downloads/${isManga ? "Manga" : "Anime"}/");
|
isManga ? "Manga" : "Anime",
|
||||||
final path4 = Directory(
|
"${manga.source} (${manga.lang!.toUpperCase()})",
|
||||||
"${path5.path}${manga.source} (${manga.lang!.toUpperCase()})/");
|
manga.name!.replaceForbiddenCharacters('_')));
|
||||||
final path3 = Directory(
|
if (!(await path2.exists())) {
|
||||||
"${path4.path}${manga.name!.replaceForbiddenCharacters('_')}/");
|
await path2.create(recursive: true);
|
||||||
|
|
||||||
if (!(await path1.exists())) {
|
|
||||||
await path1.create();
|
|
||||||
}
|
}
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
if (!(await File("${path1.path}" ".nomedia").exists())) {
|
if (!(await File(p.join(path1.path, ".nomedia")).exists())) {
|
||||||
await File("${path1.path}" ".nomedia").create();
|
await File(p.join(path1.path, ".nomedia")).create();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!(await path2.exists())) {
|
|
||||||
await path2.create();
|
|
||||||
}
|
|
||||||
if (!(await path5.exists())) {
|
|
||||||
await path5.create();
|
|
||||||
}
|
|
||||||
if (!(await path4.exists())) {
|
|
||||||
await path4.create();
|
|
||||||
}
|
|
||||||
if (!(await path3.exists())) {
|
|
||||||
await path3.create();
|
|
||||||
}
|
|
||||||
final page = pageUrls[index];
|
final page = pageUrls[index];
|
||||||
final cookie = MClient.getCookiesPref(page.url);
|
final cookie = MClient.getCookiesPref(page.url);
|
||||||
final headers = isManga
|
final headers = isManga
|
||||||
|
|
@ -192,109 +187,70 @@ Future<List<PageUrl>> downloadChapter(
|
||||||
pageHeaders.addAll(page.headers ?? {});
|
pageHeaders.addAll(page.headers ?? {});
|
||||||
|
|
||||||
if (isManga) {
|
if (isManga) {
|
||||||
final file = File(
|
final file = File(p.join(tempDir.path, "Mangayomi", finalPath, "${padIndex(index + 1)}.jpg"));
|
||||||
"${tempDir.path}/Mangayomi/$finalPath/${padIndex(index + 1)}.jpg");
|
|
||||||
if (file.existsSync()) {
|
if (file.existsSync()) {
|
||||||
Directory(path.path).createSync(recursive: true);
|
Directory(path.path).createSync(recursive: true);
|
||||||
await file.copy("${path.path}${padIndex(index + 1)}.jpg");
|
await file.copy(p.join(path.path, "${padIndex(index + 1)}.jpg"));
|
||||||
await file.delete();
|
await file.delete();
|
||||||
} else {
|
} else {
|
||||||
if ((await path.exists())) {
|
if (!(await path.exists())) {
|
||||||
if (await File("${path.path}${padIndex(index + 1)}.jpg")
|
|
||||||
.exists()) {
|
|
||||||
} else {
|
|
||||||
tasks.add(DownloadTask(
|
|
||||||
taskId: page.url,
|
|
||||||
headers: pageHeaders,
|
|
||||||
url: page.url.trim().trimLeft().trimRight(),
|
|
||||||
filename: "${padIndex(index + 1)}.jpg",
|
|
||||||
baseDirectory: BaseDirectory.temporary,
|
|
||||||
directory: 'Mangayomi/$finalPath',
|
|
||||||
updates: Updates.statusAndProgress,
|
|
||||||
retries: 3,
|
|
||||||
allowPause: true,
|
|
||||||
requiresWiFi: onlyOnWifi));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
await path.create();
|
await path.create();
|
||||||
if (await File("${path.path}" "${padIndex(index + 1)}.jpg")
|
}
|
||||||
.exists()) {
|
if (!(await File(p.join(path.path, "${padIndex(index + 1)}.jpg")).exists())) {
|
||||||
} else {
|
tasks.add(DownloadTask(
|
||||||
tasks.add(DownloadTask(
|
taskId: page.url,
|
||||||
taskId: page.url,
|
headers: pageHeaders,
|
||||||
headers: pageHeaders,
|
url: page.url.trim().trimLeft().trimRight(),
|
||||||
url: page.url.trim().trimLeft().trimRight(),
|
filename: "${padIndex(index + 1)}.jpg",
|
||||||
filename: "${padIndex(index + 1)}.jpg",
|
baseDirectory: BaseDirectory.temporary,
|
||||||
baseDirectory: BaseDirectory.temporary,
|
directory: p.join('Mangayomi', finalPath),
|
||||||
directory: 'Mangayomi/$finalPath',
|
updates: Updates.statusAndProgress,
|
||||||
updates: Updates.statusAndProgress,
|
retries: 3,
|
||||||
allowPause: true,
|
allowPause: true,
|
||||||
retries: 3,
|
requiresWiFi: onlyOnWifi));
|
||||||
requiresWiFi: onlyOnWifi));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
final file =
|
final file = File(p.join(tempDir.path, "Mangayomi", finalPath, "$chapterName.mp4"));
|
||||||
File("${tempDir.path}/Mangayomi/$finalPath/$chapterName.mp4");
|
|
||||||
if (file.existsSync()) {
|
if (file.existsSync()) {
|
||||||
await file.copy("${path.path}$chapterName.mp4");
|
await file.copy(p.join(path.path, "$chapterName.mp4"));
|
||||||
await file.delete();
|
await file.delete();
|
||||||
} else if (hasM3U8File) {
|
} else if (hasM3U8File) {
|
||||||
final tempFile = File(
|
final tempFile = File(p.join(tempDir.path, "Mangayomi", finalPath, chapterName, "TS_${index + 1}.ts"));
|
||||||
"${tempDir.path}/Mangayomi/$finalPath/$chapterName/TS_${index + 1}.ts");
|
final file = File(p.join(path.path, chapterName, "TS_${index + 1}.ts"));
|
||||||
final file = File("${path.path}$chapterName/TS_${index + 1}.ts");
|
|
||||||
if (tempFile.existsSync()) {
|
if (tempFile.existsSync()) {
|
||||||
Directory("${path.path}$chapterName").createSync(recursive: true);
|
Directory(p.join(path.path, chapterName)).createSync(recursive: true);
|
||||||
await tempFile
|
await tempFile.copy(p.join(path.path, chapterName, "TS_${index + 1}.ts"));
|
||||||
.copy("${path.path}$chapterName/TS_${index + 1}.ts");
|
|
||||||
await tempFile.delete();
|
await tempFile.delete();
|
||||||
} else if (file.existsSync()) {
|
} else if (!(file.existsSync())) {
|
||||||
} else {
|
|
||||||
tasks.add(DownloadTask(
|
tasks.add(DownloadTask(
|
||||||
taskId: page.url,
|
taskId: page.url,
|
||||||
headers: pageHeaders,
|
headers: pageHeaders,
|
||||||
url: page.url.trim().trimLeft().trimRight(),
|
url: page.url.trim().trimLeft().trimRight(),
|
||||||
filename: "TS_${index + 1}.ts",
|
filename: "TS_${index + 1}.ts",
|
||||||
baseDirectory: BaseDirectory.temporary,
|
baseDirectory: BaseDirectory.temporary,
|
||||||
directory: 'Mangayomi/$finalPath/$chapterName/',
|
directory: p.join('Mangayomi', finalPath, chapterName),
|
||||||
updates: Updates.statusAndProgress,
|
updates: Updates.statusAndProgress,
|
||||||
allowPause: true,
|
allowPause: true,
|
||||||
retries: 3,
|
retries: 3,
|
||||||
requiresWiFi: onlyOnWifi));
|
requiresWiFi: onlyOnWifi));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ((await path.exists())) {
|
if (!(await path.exists())) {
|
||||||
if (await File("${path.path}$chapterName.mp4").exists()) {
|
|
||||||
} else {
|
|
||||||
tasks.add(DownloadTask(
|
|
||||||
taskId: page.url,
|
|
||||||
headers: pageHeaders,
|
|
||||||
url: page.url.trim().trimLeft().trimRight(),
|
|
||||||
filename: "$chapterName.mp4",
|
|
||||||
baseDirectory: BaseDirectory.temporary,
|
|
||||||
directory: 'Mangayomi/$finalPath',
|
|
||||||
updates: Updates.statusAndProgress,
|
|
||||||
allowPause: true,
|
|
||||||
retries: 3,
|
|
||||||
requiresWiFi: onlyOnWifi));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
await path.create();
|
await path.create();
|
||||||
if (await File("${path.path}$chapterName.mp4").exists()) {
|
}
|
||||||
} else {
|
if (!(await File(p.join(path.path, "$chapterName.mp4")).exists())) {
|
||||||
tasks.add(DownloadTask(
|
tasks.add(DownloadTask(
|
||||||
taskId: page.url,
|
taskId: page.url,
|
||||||
headers: pageHeaders,
|
headers: pageHeaders,
|
||||||
url: page.url.trim().trimLeft().trimRight(),
|
url: page.url.trim().trimLeft().trimRight(),
|
||||||
filename: "$chapterName.mp4",
|
filename: "$chapterName.mp4",
|
||||||
baseDirectory: BaseDirectory.temporary,
|
baseDirectory: BaseDirectory.temporary,
|
||||||
directory: 'Mangayomi/$finalPath',
|
directory: p.join("Mangayomi", finalPath),
|
||||||
updates: Updates.statusAndProgress,
|
updates: Updates.statusAndProgress,
|
||||||
allowPause: true,
|
allowPause: true,
|
||||||
retries: 3,
|
retries: 3,
|
||||||
requiresWiFi: onlyOnWifi));
|
requiresWiFi: onlyOnWifi));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -319,7 +275,7 @@ Future<List<PageUrl>> downloadChapter(
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (hasM3U8File) {
|
if (hasM3U8File) {
|
||||||
await Directory("${path.path}$chapterName").create(recursive: true);
|
await Directory(p.join(path.path, chapterName)).create(recursive: true);
|
||||||
}
|
}
|
||||||
savePageUrls();
|
savePageUrls();
|
||||||
await FileDownloader().downloadBatch(
|
await FileDownloader().downloadBatch(
|
||||||
|
|
@ -394,14 +350,14 @@ Future<List<PageUrl>> downloadChapter(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (progress == 1.0) {
|
if (progress == 1.0) {
|
||||||
final file = File(
|
final file = File(p.join(tempDir.path, taskProgress.task.directory, taskProgress.task.filename));
|
||||||
"${tempDir.path}/${taskProgress.task.directory}/${taskProgress.task.filename}");
|
if(hasM3U8File) {
|
||||||
final newFile = await file.copy(
|
final newFile = await file.copy(p.join(path!.path, chapterName, taskProgress.task.filename));
|
||||||
"${path!.path}${hasM3U8File ? "$chapterName/" : ""}${taskProgress.task.filename}");
|
await file.delete();
|
||||||
await file.delete();
|
await m3u8Downloader?.processBytes(newFile, tsKey, tsIv, m3u8MediaSequence);
|
||||||
if (hasM3U8File) {
|
} else {
|
||||||
await m3u8Downloader?.processBytes(
|
await file.copy(p.join(path!.path, taskProgress.task.filename));
|
||||||
newFile, tsKey, tsIv, m3u8MediaSequence);
|
await file.delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import 'package:mangayomi/modules/more/backup_and_restore/providers/backup.dart'
|
||||||
import 'package:mangayomi/providers/storage_provider.dart';
|
import 'package:mangayomi/providers/storage_provider.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:path/path.dart' as p;
|
||||||
part 'auto_backup.g.dart';
|
part 'auto_backup.g.dart';
|
||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
|
|
@ -44,7 +45,7 @@ class AutoBackupLocationState extends _$AutoBackupLocationState {
|
||||||
|
|
||||||
void set(String location) {
|
void set(String location) {
|
||||||
final settings = isar.settings.getSync(227);
|
final settings = isar.settings.getSync(227);
|
||||||
state = ("${_storageProvider!.path}backup", location);
|
state = (p.join(_storageProvider!.path, "backup"), location);
|
||||||
isar.writeTxnSync(
|
isar.writeTxnSync(
|
||||||
() => isar.settings.putSync(settings!..autoBackupLocation = location));
|
() => isar.settings.putSync(settings!..autoBackupLocation = location));
|
||||||
}
|
}
|
||||||
|
|
@ -59,7 +60,7 @@ class AutoBackupLocationState extends _$AutoBackupLocationState {
|
||||||
state = (
|
state = (
|
||||||
Platform.isIOS
|
Platform.isIOS
|
||||||
? _storageProvider!.path
|
? _storageProvider!.path
|
||||||
: "${_storageProvider!.path}backup/",
|
: p.join(_storageProvider!.path, "backup"),
|
||||||
settings!.autoBackupLocation ?? ""
|
settings!.autoBackupLocation ?? ""
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -82,7 +83,7 @@ Future<void> checkAndBackup(Ref ref) async {
|
||||||
final backupLocation = ref.watch(autoBackupLocationStateProvider).$2;
|
final backupLocation = ref.watch(autoBackupLocationStateProvider).$2;
|
||||||
Directory? backupDirectory;
|
Directory? backupDirectory;
|
||||||
backupDirectory = Directory(backupLocation.isEmpty
|
backupDirectory = Directory(backupLocation.isEmpty
|
||||||
? "${defaulteDirectory!.path}backup/"
|
? p.join(defaulteDirectory!.path, "backup")
|
||||||
: backupLocation);
|
: backupLocation);
|
||||||
if (Platform.isIOS) {
|
if (Platform.isIOS) {
|
||||||
backupDirectory = await (storageProvider.getIosBackupDirectory());
|
backupDirectory = await (storageProvider.getIosBackupDirectory());
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ import 'package:mangayomi/providers/l10n_providers.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:share_plus/share_plus.dart';
|
import 'package:share_plus/share_plus.dart';
|
||||||
|
import 'package:path/path.dart' as p;
|
||||||
part 'backup.g.dart';
|
part 'backup.g.dart';
|
||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
|
|
@ -118,12 +119,12 @@ void doBackUp(Ref ref,
|
||||||
final regExp = RegExp(r'[^a-zA-Z0-9 .()\-\s]');
|
final regExp = RegExp(r'[^a-zA-Z0-9 .()\-\s]');
|
||||||
final name =
|
final name =
|
||||||
'mangayomi_${DateTime.now().toString().replaceAll(regExp, '_').replaceAll(' ', '_')}';
|
'mangayomi_${DateTime.now().toString().replaceAll(regExp, '_').replaceAll(' ', '_')}';
|
||||||
final backupFilePath = '$path/$name.backup.db';
|
final backupFilePath = p.join(path, "$name.backup.db");
|
||||||
final file = File(backupFilePath);
|
final file = File(backupFilePath);
|
||||||
|
|
||||||
file.writeAsStringSync(jsonEncode(datas));
|
file.writeAsStringSync(jsonEncode(datas));
|
||||||
var encoder = ZipFileEncoder();
|
var encoder = ZipFileEncoder();
|
||||||
encoder.create('$path/$name.backup');
|
encoder.create(p.join(path, "$name.backup"));
|
||||||
encoder.addFile(File(backupFilePath));
|
encoder.addFile(File(backupFilePath));
|
||||||
encoder.close();
|
encoder.close();
|
||||||
Directory(backupFilePath).deleteSync(recursive: true);
|
Directory(backupFilePath).deleteSync(recursive: true);
|
||||||
|
|
@ -147,8 +148,8 @@ void doBackUp(Ref ref,
|
||||||
alignment: Alignment.topLeft,
|
alignment: Alignment.topLeft,
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Share.shareXFiles([XFile('$path/$name.backup')],
|
Share.shareXFiles([XFile(p.join(path, "$name.backup"))],
|
||||||
text: '$name.backup');
|
text: "$name.backup");
|
||||||
},
|
},
|
||||||
child: Text(context.l10n.share)),
|
child: Text(context.l10n.share)),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import 'package:mangayomi/main.dart';
|
||||||
import 'package:mangayomi/models/settings.dart';
|
import 'package:mangayomi/models/settings.dart';
|
||||||
import 'package:mangayomi/providers/storage_provider.dart';
|
import 'package:mangayomi/providers/storage_provider.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
import 'package:path/path.dart' as path;
|
||||||
part 'downloads_state_provider.g.dart';
|
part 'downloads_state_provider.g.dart';
|
||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
|
|
@ -44,7 +45,7 @@ class DownloadLocationState extends _$DownloadLocationState {
|
||||||
|
|
||||||
void set(String location) {
|
void set(String location) {
|
||||||
final settings = isar.settings.getSync(227);
|
final settings = isar.settings.getSync(227);
|
||||||
state = ("${_storageProvider!.path}downloads", location);
|
state = (path.join(_storageProvider!.path, 'downloads'), location);
|
||||||
isar.writeTxnSync(
|
isar.writeTxnSync(
|
||||||
() => isar.settings.putSync(settings!..downloadLocation = location));
|
() => isar.settings.putSync(settings!..downloadLocation = location));
|
||||||
}
|
}
|
||||||
|
|
@ -55,7 +56,7 @@ class DownloadLocationState extends _$DownloadLocationState {
|
||||||
_storageProvider = await StorageProvider().getDefaultDirectory();
|
_storageProvider = await StorageProvider().getDefaultDirectory();
|
||||||
final settings = isar.settings.getSync(227);
|
final settings = isar.settings.getSync(227);
|
||||||
state = (
|
state = (
|
||||||
"${_storageProvider!.path}downloads",
|
path.join(_storageProvider!.path, 'downloads'),
|
||||||
settings!.downloadLocation ?? ""
|
settings!.downloadLocation ?? ""
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ class StorageProvider {
|
||||||
directory = Directory("/storage/emulated/0/Mangayomi/");
|
directory = Directory("/storage/emulated/0/Mangayomi/");
|
||||||
} else {
|
} else {
|
||||||
final dir = await getApplicationDocumentsDirectory();
|
final dir = await getApplicationDocumentsDirectory();
|
||||||
directory = Directory("${dir.path}/Mangayomi/");
|
directory = Directory(path.join(dir.path, 'Mangayomi'));
|
||||||
}
|
}
|
||||||
return directory;
|
return directory;
|
||||||
}
|
}
|
||||||
|
|
@ -69,14 +69,14 @@ class StorageProvider {
|
||||||
|
|
||||||
Future<Directory?> getDirectory() async {
|
Future<Directory?> getDirectory() async {
|
||||||
Directory? directory;
|
Directory? directory;
|
||||||
String path = isar.settings.getSync(227)!.downloadLocation ?? "";
|
String customPath = isar.settings.getSync(227)!.downloadLocation ?? "";
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
directory =
|
directory =
|
||||||
Directory(path.isEmpty ? "/storage/emulated/0/Mangayomi/" : "$path/");
|
Directory(customPath.isEmpty ? "/storage/emulated/0/Mangayomi/" : "$customPath/");
|
||||||
} else {
|
} else {
|
||||||
final dir = await getApplicationDocumentsDirectory();
|
final dir = await getApplicationDocumentsDirectory();
|
||||||
final p = path.isEmpty ? dir.path : path;
|
final basePath = customPath.isEmpty ? dir.path : customPath;
|
||||||
directory = Directory("$p/Mangayomi/");
|
directory = Directory(path.join(basePath, "Mangayomi"));
|
||||||
}
|
}
|
||||||
return directory;
|
return directory;
|
||||||
}
|
}
|
||||||
|
|
@ -88,18 +88,31 @@ class StorageProvider {
|
||||||
String scanlator = chapter.scanlator?.isNotEmpty ?? false
|
String scanlator = chapter.scanlator?.isNotEmpty ?? false
|
||||||
? "${chapter.scanlator!.replaceForbiddenCharacters('_')}_"
|
? "${chapter.scanlator!.replaceForbiddenCharacters('_')}_"
|
||||||
: "";
|
: "";
|
||||||
final isManga = chapter.manga.value!.isManga!;
|
final isManga = manga.isManga!;
|
||||||
final dir = await getDirectory();
|
final dir = await getDirectory();
|
||||||
return Directory(
|
final directoryPath = path.join(
|
||||||
"${dir!.path}/downloads/${isManga ? "Manga" : "Anime"}/${manga.source} (${manga.lang!.toUpperCase()})/${manga.name!.replaceForbiddenCharacters('_')}/$scanlator${chapter.name!.replaceForbiddenCharacters('_')}/");
|
dir!.path,
|
||||||
|
"downloads",
|
||||||
|
isManga ? "Manga" : "Anime",
|
||||||
|
"${manga.source} (${manga.lang!.toUpperCase()})",
|
||||||
|
manga.name!.replaceForbiddenCharacters('_'),
|
||||||
|
"$scanlator${chapter.name!.replaceForbiddenCharacters('_')}",
|
||||||
|
);
|
||||||
|
return Directory(directoryPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Directory?> getMangaMainDirectory(Chapter chapter) async {
|
Future<Directory?> getMangaMainDirectory(Chapter chapter) async {
|
||||||
final manga = chapter.manga.value!;
|
final manga = chapter.manga.value!;
|
||||||
final isManga = chapter.manga.value!.isManga!;
|
final isManga = manga.isManga!;
|
||||||
final dir = await getDirectory();
|
final dir = await getDirectory();
|
||||||
return Directory(
|
final directoryPath = path.join(
|
||||||
"${dir!.path}/downloads/${isManga ? "Manga" : "Anime"}/${manga.source} (${manga.lang!.toUpperCase()})/${manga.name!.replaceForbiddenCharacters('_')}/");
|
dir!.path,
|
||||||
|
"downloads",
|
||||||
|
isManga ? "Manga" : "Anime",
|
||||||
|
"${manga.source} (${manga.lang!.toUpperCase()})",
|
||||||
|
manga.name!.replaceForbiddenCharacters('_'),
|
||||||
|
);
|
||||||
|
return Directory(directoryPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Directory?> getDatabaseDirectory() async {
|
Future<Directory?> getDatabaseDirectory() async {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue