Merge pull request #332 from NBA2K1/main

File path fixes (Issue #331)
This commit is contained in:
Moustapha Kodjo Amadou 2024-12-11 09:04:00 +01:00 committed by GitHub
commit a15d989656
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 124 additions and 160 deletions

View file

@ -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;

View file

@ -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();
} }

View file

@ -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));
} }

View file

@ -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();
} }
} }
}, },

View file

@ -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());

View file

@ -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)),
), ),

View file

@ -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 ?? ""
); );
} }

View file

@ -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 {