mirror of
https://github.com/kodjodevf/mangayomi.git
synced 2026-03-11 17:25:32 +00:00
refactor
This commit is contained in:
parent
606c59d70b
commit
e2c7398903
5 changed files with 65 additions and 41 deletions
|
|
@ -37,16 +37,14 @@ Future<List<PageUrl>> downloadChapter(
|
|||
bool isOk = false;
|
||||
final manga = chapter.manga.value!;
|
||||
final path1 = await storageProvider.getDirectory();
|
||||
final forbiddenCharacters =
|
||||
RegExp(r'[\\/:*?"<>|\0]|(^CON$|^PRN$|^AUX$|^NUL$|^COM[1-9]$|^LPT[1-9]$)');
|
||||
String scanlator = chapter.scanlator!.isNotEmpty
|
||||
? "${chapter.scanlator!.replaceAll(forbiddenCharacters, '_')}_"
|
||||
? "${chapter.scanlator!.replaceForbiddenCharacters('_')}_"
|
||||
: "";
|
||||
final chapterName = chapter.name!.replaceAll(forbiddenCharacters, ' ');
|
||||
final chapterName = chapter.name!.replaceForbiddenCharacters(' ');
|
||||
|
||||
final isManga = chapter.manga.value!.isManga!;
|
||||
final finalPath =
|
||||
"downloads/${isManga ? "Manga" : "Anime"}/${manga.source} (${manga.lang!.toUpperCase()})/${manga.name!.replaceAll(forbiddenCharacters, '_')}${isManga ? "/$scanlator${chapter.name!.replaceAll(forbiddenCharacters, '_')}" : ""}";
|
||||
"downloads/${isManga ? "Manga" : "Anime"}/${manga.source} (${manga.lang!.toUpperCase()})/${manga.name!.replaceForbiddenCharacters('_')}${isManga ? "/$scanlator${chapter.name!.replaceForbiddenCharacters('_')}" : ""}";
|
||||
path = Directory("${path1!.path}$finalPath/");
|
||||
Map<String, String> videoHeader = {};
|
||||
|
||||
|
|
@ -120,7 +118,7 @@ Future<List<PageUrl>> downloadChapter(
|
|||
final path4 = Directory(
|
||||
"${path5.path}${manga.source} (${manga.lang!.toUpperCase()})/");
|
||||
final path3 = Directory(
|
||||
"${path4.path}${manga.name!.replaceAll(forbiddenCharacters, '_')}/");
|
||||
"${path4.path}${manga.name!.replaceForbiddenCharacters('_')}/");
|
||||
|
||||
if (!(await path1.exists())) {
|
||||
await path1.create();
|
||||
|
|
|
|||
|
|
@ -12,14 +12,12 @@ import 'package:mangayomi/models/settings.dart';
|
|||
import 'package:mangayomi/models/source.dart';
|
||||
import 'package:mangayomi/models/track.dart';
|
||||
import 'package:mangayomi/models/track_preference.dart';
|
||||
import 'package:mangayomi/utils/extensions/string_extensions.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
class StorageProvider {
|
||||
final _forbiddenCharacters =
|
||||
RegExp(r'[\\/:*?"<>|\0]|(^CON$|^PRN$|^AUX$|^NUL$|^COM[1-9]$|^LPT[1-9]$)');
|
||||
|
||||
Future<bool> requestPermission() async {
|
||||
Permission permission = Permission.manageExternalStorage;
|
||||
if (Platform.isAndroid) {
|
||||
|
|
@ -80,12 +78,12 @@ class StorageProvider {
|
|||
) async {
|
||||
final manga = chapter.manga.value!;
|
||||
String scanlator = chapter.scanlator?.isNotEmpty ?? false
|
||||
? "${chapter.scanlator!.replaceAll(_forbiddenCharacters, '_')}_"
|
||||
? "${chapter.scanlator!.replaceForbiddenCharacters('_')}_"
|
||||
: "";
|
||||
final isManga = chapter.manga.value!.isManga!;
|
||||
final dir = await getDirectory();
|
||||
return Directory(
|
||||
"${dir!.path}/downloads/${isManga ? "Manga" : "Anime"}/${manga.source} (${manga.lang!.toUpperCase()})/${manga.name!.replaceAll(_forbiddenCharacters, '_')}/$scanlator${chapter.name!.replaceAll(_forbiddenCharacters, '_')}/");
|
||||
"${dir!.path}/downloads/${isManga ? "Manga" : "Anime"}/${manga.source} (${manga.lang!.toUpperCase()})/${manga.name!.replaceForbiddenCharacters('_')}/$scanlator${chapter.name!.replaceForbiddenCharacters('_')}/");
|
||||
}
|
||||
|
||||
Future<Directory?> getMangaMainDirectory(Chapter chapter) async {
|
||||
|
|
@ -93,7 +91,7 @@ class StorageProvider {
|
|||
final isManga = chapter.manga.value!.isManga!;
|
||||
final dir = await getDirectory();
|
||||
return Directory(
|
||||
"${dir!.path}/downloads/${isManga ? "Manga" : "Anime"}/${manga.source} (${manga.lang!.toUpperCase()})/${manga.name!.replaceAll(_forbiddenCharacters, '_')}/");
|
||||
"${dir!.path}/downloads/${isManga ? "Manga" : "Anime"}/${manga.source} (${manga.lang!.toUpperCase()})/${manga.name!.replaceForbiddenCharacters('_')}/");
|
||||
}
|
||||
|
||||
Future<Directory?> getDatabaseDirectory() async {
|
||||
|
|
|
|||
|
|
@ -35,9 +35,12 @@ base class Request {
|
|||
/// Set [post] to make the request using POST instead of GET.
|
||||
/// In the constructor, [post] must be one of the following:
|
||||
/// - a String: POST request with [post] as the body, encoded in utf8
|
||||
/// - a List of bytes: POST request with [post] as the body
|
||||
/// - a Map: will be jsonEncoded to a String and set as the POST body
|
||||
/// - a List of bytes: will be converted to a String using String.fromCharCodes
|
||||
/// and set as the POST body
|
||||
/// - a List: map will be jsonEncoded to a String and set as the POST body
|
||||
///
|
||||
/// The field [post] will be a UInt8List representing the bytes, or the String
|
||||
/// The field [post] will be a String
|
||||
final String? post;
|
||||
|
||||
/// Maximum number of retries the downloader should attempt
|
||||
|
|
@ -59,7 +62,10 @@ base class Request {
|
|||
/// [post] if set, uses POST instead of GET. Post must be one of the
|
||||
/// following:
|
||||
/// - a String: POST request with [post] as the body, encoded in utf8
|
||||
/// - a List of bytes: POST request with [post] as the body
|
||||
/// - a Map: will be jsonEncoded to a String and set as the POST body
|
||||
/// - a List of bytes: will be converted to a String using String.fromCharCodes
|
||||
/// and set as the POST body
|
||||
/// - a List: map will be jsonEncoded to a String and set as the POST body
|
||||
///
|
||||
/// [retries] if >0 will retry a failed download this many times
|
||||
Request(
|
||||
|
|
@ -74,7 +80,11 @@ base class Request {
|
|||
headers = headers ?? {},
|
||||
httpRequestMethod =
|
||||
httpRequestMethod?.toUpperCase() ?? (post == null ? 'GET' : 'POST'),
|
||||
post = post is Uint8List ? String.fromCharCodes(post) : post,
|
||||
post = post is Uint8List
|
||||
? String.fromCharCodes(post)
|
||||
: post is Map || post is List
|
||||
? jsonEncode(post)
|
||||
: post,
|
||||
retriesRemaining = retries,
|
||||
creationTime = creationTime ?? DateTime.now() {
|
||||
if (retries < 0 || retries > 10) {
|
||||
|
|
@ -255,7 +265,10 @@ sealed class Task extends Request implements Comparable {
|
|||
/// [post] if set, uses POST instead of GET. Post must be one of the
|
||||
/// following:
|
||||
/// - a String: POST request with [post] as the body, encoded in utf8
|
||||
/// - a List of bytes: POST request with [post] as the body
|
||||
/// - a Map: will be jsonEncoded to a String and set as the POST body
|
||||
/// - a List of bytes: will be converted to a String using String.fromCharCodes
|
||||
/// and set as the POST body
|
||||
/// - a List: map will be jsonEncoded to a String and set as the POST body
|
||||
/// [directory] optional directory name, precedes [filename]
|
||||
/// [baseDirectory] one of the base directories, precedes [directory]
|
||||
/// [group] if set allows different callbacks or processing for different
|
||||
|
|
@ -346,6 +359,10 @@ sealed class Task extends Request implements Comparable {
|
|||
}
|
||||
|
||||
/// Returns the path to the directory represented by [baseDirectory]
|
||||
///
|
||||
/// On Windows, if [baseDirectory] is .root, returns the empty string
|
||||
/// because the drive letter is required to be included in the directory
|
||||
/// path
|
||||
static Future<String> baseDirectoryPath(BaseDirectory baseDirectory) async {
|
||||
Directory? externalStorageDirectory;
|
||||
Directory? externalCacheDirectory;
|
||||
|
|
@ -377,7 +394,9 @@ sealed class Task extends Request implements Comparable {
|
|||
(BaseDirectory.applicationLibrary, true) =>
|
||||
Directory(p.join(externalStorageDirectory!.path, 'Library'))
|
||||
};
|
||||
return baseDir.absolute.path;
|
||||
return (Platform.isWindows && baseDirectory == BaseDirectory.root)
|
||||
? ''
|
||||
: baseDir.absolute.path;
|
||||
}
|
||||
|
||||
/// Extract the baseDirectory, directory and filename from
|
||||
|
|
@ -398,19 +417,20 @@ sealed class Task extends Request implements Comparable {
|
|||
// try to match the start of the absoluteDirectory to one of the
|
||||
// directories represented by the BaseDirectory enum.
|
||||
// Order matters, as some may be subdirs of others
|
||||
final testSequence = Platform.isAndroid || Platform.isLinux
|
||||
? [
|
||||
BaseDirectory.temporary,
|
||||
BaseDirectory.applicationLibrary,
|
||||
BaseDirectory.applicationSupport,
|
||||
BaseDirectory.applicationDocuments
|
||||
]
|
||||
: [
|
||||
BaseDirectory.temporary,
|
||||
BaseDirectory.applicationSupport,
|
||||
BaseDirectory.applicationLibrary,
|
||||
BaseDirectory.applicationDocuments
|
||||
];
|
||||
final testSequence =
|
||||
Platform.isAndroid || Platform.isLinux || Platform.isWindows
|
||||
? [
|
||||
BaseDirectory.temporary,
|
||||
BaseDirectory.applicationLibrary,
|
||||
BaseDirectory.applicationSupport,
|
||||
BaseDirectory.applicationDocuments
|
||||
]
|
||||
: [
|
||||
BaseDirectory.temporary,
|
||||
BaseDirectory.applicationSupport,
|
||||
BaseDirectory.applicationLibrary,
|
||||
BaseDirectory.applicationDocuments
|
||||
];
|
||||
for (final baseDirectoryEnum in testSequence) {
|
||||
final baseDirPath = await baseDirectoryPath(baseDirectoryEnum);
|
||||
final (match, directory) = _contains(baseDirPath, absoluteDirectoryPath);
|
||||
|
|
@ -437,7 +457,9 @@ sealed class Task extends Request implements Comparable {
|
|||
/// [dirPath] should not contain a filename - if it does, it is returned
|
||||
/// as part of the subdir.
|
||||
static (bool, String) _contains(String baseDirPath, String dirPath) {
|
||||
final match = RegExp('^$baseDirPath/?(.*)').firstMatch(dirPath);
|
||||
final escapedBaseDirPath =
|
||||
'$baseDirPath${Platform.pathSeparator}?'.replaceAll(r'\', r'\\');
|
||||
final match = RegExp('^$escapedBaseDirPath(.*)').firstMatch(dirPath);
|
||||
return (match != null, match?.group(1) ?? '');
|
||||
}
|
||||
|
||||
|
|
@ -561,12 +583,11 @@ final class DownloadTask extends Task {
|
|||
/// [httpRequestMethod] the HTTP request method used (e.g. GET, POST)
|
||||
/// [post] if set, uses POST instead of GET. Post must be one of the
|
||||
/// following:
|
||||
/// - true: POST request without a body
|
||||
/// - a String: POST request with [post] as the body, encoded in utf8 and
|
||||
/// content-type 'text/plain'
|
||||
/// - a List of bytes: POST request with [post] as the body
|
||||
/// - a Map: POST request with [post] as form fields, encoded in utf8 and
|
||||
/// content-type 'application/x-www-form-urlencoded'
|
||||
/// - a String: POST request with [post] as the body, encoded in utf8
|
||||
/// - a Map: will be jsonEncoded to a String and set as the POST body
|
||||
/// - a List of bytes: will be converted to a String using String.fromCharCodes
|
||||
/// and set as the POST body
|
||||
/// - a List: map will be jsonEncoded to a String and set as the POST body
|
||||
///
|
||||
/// [directory] optional directory name, precedes [filename]
|
||||
/// [baseDirectory] one of the base directories, precedes [directory]
|
||||
|
|
@ -667,6 +688,7 @@ final class DownloadTask extends Task {
|
|||
///
|
||||
/// The suggested filename is obtained by making a HEAD request to the url
|
||||
/// represented by the [DownloadTask], including urlQueryParameters and headers
|
||||
|
||||
|
||||
/// Constant used with `filename` field to indicate server suggestion requested
|
||||
static const suggestedFilename = '?';
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import 'package:mangayomi/models/video.dart';
|
|||
import 'package:mangayomi/providers/storage_provider.dart';
|
||||
import 'package:mangayomi/services/torrent_server.dart';
|
||||
import 'package:mangayomi/sources/utils/utils.dart';
|
||||
import 'package:mangayomi/utils/extensions/string_extensions.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
part 'get_video_list.g.dart';
|
||||
|
||||
|
|
@ -20,10 +21,8 @@ Future<(List<Video>, bool, String?)> getVideoList(
|
|||
final mangaDirectory = await storageProvider.getMangaMainDirectory(episode);
|
||||
final isLocalArchive = episode.manga.value!.isLocalArchive! &&
|
||||
episode.manga.value!.source != "torrent";
|
||||
final forbiddenCharacters =
|
||||
RegExp(r'[\\/:*?"<>|\0]|(^CON$|^PRN$|^AUX$|^NUL$|^COM[1-9]$|^LPT[1-9]$)');
|
||||
final mp4animePath =
|
||||
"${mangaDirectory!.path}${episode.name!.replaceAll(forbiddenCharacters, ' ')}.mp4";
|
||||
"${mangaDirectory!.path}${episode.name!.replaceForbiddenCharacters(' ')}.mp4";
|
||||
|
||||
if (await File(mp4animePath).exists() || isLocalArchive) {
|
||||
final path = isLocalArchive ? episode.archivePath : mp4animePath;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,13 @@ extension StringExtensions on String {
|
|||
return substring(leftIndex, rightIndex);
|
||||
}
|
||||
|
||||
String replaceForbiddenCharacters(String source) {
|
||||
return replaceAll(
|
||||
RegExp(
|
||||
r'[\\/:*?"<>|\0]|(^CON$|^PRN$|^AUX$|^NUL$|^COM[1-9]$|^LPT[1-9]$)'),
|
||||
source);
|
||||
}
|
||||
|
||||
bool isMediaVideo() {
|
||||
return [
|
||||
"3gp",
|
||||
|
|
|
|||
Loading…
Reference in a new issue