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