mirror of
https://github.com/kodjodevf/mangayomi.git
synced 2026-04-20 23:22:07 +00:00
feature: required wifi when downloading, custom download location
This commit is contained in:
parent
e2115f0a0a
commit
05bada5661
10 changed files with 142 additions and 122 deletions
|
|
@ -332,9 +332,9 @@ class _MangaChapterPageGalleryState
|
|||
),
|
||||
subtitle: SizedBox(
|
||||
width: mediaWidth(context, 0.8),
|
||||
child: Text(
|
||||
child: const Text(
|
||||
"",
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -27,9 +27,10 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
List<String> _pageUrls = [];
|
||||
|
||||
final StorageProvider _storageProvider = StorageProvider();
|
||||
_startDownload() async {
|
||||
final data = await ref
|
||||
.watch(downloadChapterProvider(chapter: widget.chapter).future);
|
||||
_startDownload(bool? useWifi) async {
|
||||
final data = await ref.watch(
|
||||
downloadChapterProvider(chapter: widget.chapter, useWifi: useWifi)
|
||||
.future);
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_pageUrls = data;
|
||||
|
|
@ -84,7 +85,7 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
Theme.of(context).iconTheme.color!.withOpacity(0.7),
|
||||
),
|
||||
onSelected: (value) {
|
||||
if (value.toString() == 'Delete') {
|
||||
if (value == 1) {
|
||||
setState(() {
|
||||
_isStarted = false;
|
||||
});
|
||||
|
|
@ -92,9 +93,8 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
}
|
||||
},
|
||||
itemBuilder: (context) => [
|
||||
const PopupMenuItem(value: 'Send', child: Text("Send")),
|
||||
const PopupMenuItem(
|
||||
value: 'Delete', child: Text('Delete')),
|
||||
const PopupMenuItem(value: 0, child: Text("Send")),
|
||||
const PopupMenuItem(value: 1, child: Text('Delete')),
|
||||
],
|
||||
)
|
||||
: entries.first.isStartDownload! &&
|
||||
|
|
@ -105,13 +105,22 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
child: PopupMenuButton(
|
||||
child: _downloadWidget(context, true),
|
||||
onSelected: (value) {
|
||||
if (value.toString() == 'Cancel') {
|
||||
if (value == 0) {
|
||||
_cancelTasks();
|
||||
}
|
||||
if (value == 0) {
|
||||
_cancelTasks();
|
||||
} else if (value == 1) {
|
||||
_cancelTasks();
|
||||
_startDownload(false);
|
||||
}
|
||||
},
|
||||
itemBuilder: (context) => [
|
||||
const PopupMenuItem(
|
||||
value: 'Cancel', child: Text("Cancel")),
|
||||
value: 1,
|
||||
child: Text("Start downlading now")),
|
||||
const PopupMenuItem(
|
||||
value: 0, child: Text("Cancel")),
|
||||
],
|
||||
))
|
||||
: entries.first.succeeded != 0
|
||||
|
|
@ -164,13 +173,22 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
],
|
||||
),
|
||||
onSelected: (value) {
|
||||
if (value.toString() == 'Cancel') {
|
||||
if (value == 0) {
|
||||
_cancelTasks();
|
||||
}
|
||||
if (value == 0) {
|
||||
_cancelTasks();
|
||||
} else if (value == 1) {
|
||||
_cancelTasks();
|
||||
_startDownload(false);
|
||||
}
|
||||
},
|
||||
itemBuilder: (context) => [
|
||||
const PopupMenuItem(
|
||||
value: 'Cancel', child: Text("Cancel")),
|
||||
value: 1,
|
||||
child: Text("Start downlading now")),
|
||||
const PopupMenuItem(
|
||||
value: 0, child: Text("Cancel")),
|
||||
],
|
||||
))
|
||||
: entries.first.succeeded == 0
|
||||
|
|
@ -199,9 +217,9 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
size: 25,
|
||||
),
|
||||
onSelected: (value) {
|
||||
if (value.toString() == 'Retry') {
|
||||
if (value == 0) {
|
||||
_cancelTasks();
|
||||
_startDownload();
|
||||
_startDownload(null);
|
||||
setState(() {
|
||||
_isStarted = true;
|
||||
});
|
||||
|
|
@ -209,7 +227,7 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
},
|
||||
itemBuilder: (context) => [
|
||||
const PopupMenuItem(
|
||||
value: 'Retry', child: Text("Retry")),
|
||||
value: 0, child: Text("Retry")),
|
||||
],
|
||||
));
|
||||
}
|
||||
|
|
@ -220,20 +238,24 @@ class _ChapterPageDownloadState extends ConsumerState<ChapterPageDownload>
|
|||
child: PopupMenuButton(
|
||||
child: _downloadWidget(context, true),
|
||||
onSelected: (value) {
|
||||
if (value.toString() == 'Cancel') {
|
||||
if (value == 0) {
|
||||
_cancelTasks();
|
||||
} else if (value == 1) {
|
||||
_cancelTasks();
|
||||
_startDownload(false);
|
||||
}
|
||||
},
|
||||
itemBuilder: (context) => [
|
||||
const PopupMenuItem(
|
||||
value: 'Cancel', child: Text("Cancel")),
|
||||
value: 1, child: Text("Start downlading now")),
|
||||
const PopupMenuItem(value: 0, child: Text("Cancel")),
|
||||
],
|
||||
))
|
||||
: IconButton(
|
||||
splashRadius: 5,
|
||||
iconSize: 17,
|
||||
onPressed: () {
|
||||
_startDownload();
|
||||
_startDownload(null);
|
||||
setState(() {
|
||||
_isStarted = true;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -4,10 +4,12 @@ import 'package:isar/isar.dart';
|
|||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/chapter.dart';
|
||||
import 'package:mangayomi/models/download.dart';
|
||||
import 'package:mangayomi/modules/more/settings/downloads/providers/downloads_state_provider.dart';
|
||||
import 'package:mangayomi/providers/storage_provider.dart';
|
||||
import 'package:mangayomi/services/get_chapter_url.dart';
|
||||
import 'package:mangayomi/utils/headers.dart';
|
||||
import 'package:mangayomi/utils/reg_exp_matcher.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
part 'download_provider.g.dart';
|
||||
|
||||
|
|
@ -15,11 +17,14 @@ part 'download_provider.g.dart';
|
|||
Future<List<String>> downloadChapter(
|
||||
DownloadChapterRef ref, {
|
||||
required Chapter chapter,
|
||||
bool? useWifi,
|
||||
}) async {
|
||||
List<String> pageUrls = [];
|
||||
List<DownloadTask> tasks = [];
|
||||
final StorageProvider storageProvider = StorageProvider();
|
||||
await storageProvider.requestPermission();
|
||||
final tempDir = await getTemporaryDirectory();
|
||||
bool onlyOnWifi = useWifi ?? ref.watch(onlyOnWifiStateProvider);
|
||||
Directory? path;
|
||||
bool isOk = false;
|
||||
final manga = chapter.manga.value!;
|
||||
|
|
@ -65,7 +70,6 @@ Future<List<String>> downloadChapter(
|
|||
File("${path1.path}" ".nomedia").create();
|
||||
}
|
||||
}
|
||||
// log(path2.path);
|
||||
if (!(await path2.exists())) {
|
||||
path2.create();
|
||||
}
|
||||
|
|
@ -80,46 +84,34 @@ Future<List<String>> downloadChapter(
|
|||
if (await File("${path.path}" "${padIndex(index + 1)}.jpg").exists()) {
|
||||
} else {
|
||||
tasks.add(DownloadTask(
|
||||
taskId: pageUrls[index],
|
||||
headers: ref.watch(headersProvider(source: manga.source!)),
|
||||
url: pageUrls[index],
|
||||
filename: "${padIndex(index + 1)}.jpg",
|
||||
baseDirectory:
|
||||
Platform.isWindows || Platform.isMacOS || Platform.isLinux
|
||||
? BaseDirectory.applicationDocuments
|
||||
: BaseDirectory.temporary,
|
||||
directory:
|
||||
Platform.isWindows || Platform.isMacOS || Platform.isLinux
|
||||
? 'Mangayomi/$finalPath'
|
||||
: finalPath,
|
||||
updates: Updates.statusAndProgress,
|
||||
allowPause: true,
|
||||
));
|
||||
taskId: pageUrls[index],
|
||||
headers: ref.watch(headersProvider(source: manga.source!)),
|
||||
url: pageUrls[index],
|
||||
filename: "${padIndex(index + 1)}.jpg",
|
||||
baseDirectory: Platform.isAndroid
|
||||
? BaseDirectory.temporary
|
||||
: BaseDirectory.applicationDocuments,
|
||||
directory: 'Mangayomi/$finalPath',
|
||||
updates: Updates.statusAndProgress,
|
||||
allowPause: true,
|
||||
requiresWiFi: onlyOnWifi));
|
||||
}
|
||||
} else {
|
||||
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!)),
|
||||
url: pageUrls[index],
|
||||
filename: "${padIndex(index + 1)}.jpg",
|
||||
baseDirectory: Platform.isWindows ||
|
||||
Platform.isMacOS ||
|
||||
Platform.isLinux ||
|
||||
Platform.isIOS
|
||||
? BaseDirectory.applicationDocuments
|
||||
: BaseDirectory.temporary,
|
||||
directory: Platform.isWindows ||
|
||||
Platform.isMacOS ||
|
||||
Platform.isLinux ||
|
||||
Platform.isIOS
|
||||
? 'Mangayomi/$finalPath'
|
||||
: finalPath,
|
||||
updates: Updates.statusAndProgress,
|
||||
allowPause: true,
|
||||
));
|
||||
taskId: pageUrls[index],
|
||||
headers: ref.watch(headersProvider(source: manga.source!)),
|
||||
url: pageUrls[index],
|
||||
filename: "${padIndex(index + 1)}.jpg",
|
||||
baseDirectory: Platform.isAndroid
|
||||
? BaseDirectory.temporary
|
||||
: BaseDirectory.applicationDocuments,
|
||||
directory: 'Mangayomi/$finalPath',
|
||||
updates: Updates.statusAndProgress,
|
||||
allowPause: true,
|
||||
requiresWiFi: onlyOnWifi));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -173,22 +165,12 @@ Future<List<String>> downloadChapter(
|
|||
},
|
||||
taskProgressCallback: (taskProgress) async {
|
||||
if (taskProgress.progress == 1.0) {
|
||||
final downloadTask = DownloadTask(
|
||||
creationTime: taskProgress.task.creationTime,
|
||||
taskId: taskProgress.task.taskId,
|
||||
headers: taskProgress.task.headers,
|
||||
url: taskProgress.task.url,
|
||||
filename: taskProgress.task.filename,
|
||||
baseDirectory: taskProgress.task.baseDirectory,
|
||||
directory: taskProgress.task.directory,
|
||||
updates: taskProgress.task.updates,
|
||||
allowPause: taskProgress.task.allowPause,
|
||||
);
|
||||
if (Platform.isAndroid) {
|
||||
await FileDownloader().moveToSharedStorage(
|
||||
downloadTask, SharedStorage.external,
|
||||
directory: finalPath);
|
||||
}
|
||||
await File(
|
||||
"${tempDir.path}/${taskProgress.task.directory}/${taskProgress.task.filename}")
|
||||
.copy("${path!.path}/${taskProgress.task.filename}");
|
||||
await File(
|
||||
"${tempDir.path}/${taskProgress.task.directory}/${taskProgress.task.filename}")
|
||||
.delete();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ part of 'download_provider.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$downloadChapterHash() => r'abdb9aa7362e0cc436ec56de57521fea203d3041';
|
||||
String _$downloadChapterHash() => r'07e6c9782618562329005e15ce973061bf70d441';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
|
@ -43,9 +43,11 @@ class DownloadChapterFamily extends Family<AsyncValue<List<String>>> {
|
|||
/// See also [downloadChapter].
|
||||
DownloadChapterProvider call({
|
||||
required Chapter chapter,
|
||||
bool? useWifi,
|
||||
}) {
|
||||
return DownloadChapterProvider(
|
||||
chapter: chapter,
|
||||
useWifi: useWifi,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -55,6 +57,7 @@ class DownloadChapterFamily extends Family<AsyncValue<List<String>>> {
|
|||
) {
|
||||
return call(
|
||||
chapter: provider.chapter,
|
||||
useWifi: provider.useWifi,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -78,10 +81,12 @@ class DownloadChapterProvider extends AutoDisposeFutureProvider<List<String>> {
|
|||
/// See also [downloadChapter].
|
||||
DownloadChapterProvider({
|
||||
required this.chapter,
|
||||
this.useWifi,
|
||||
}) : super.internal(
|
||||
(ref) => downloadChapter(
|
||||
ref,
|
||||
chapter: chapter,
|
||||
useWifi: useWifi,
|
||||
),
|
||||
from: downloadChapterProvider,
|
||||
name: r'downloadChapterProvider',
|
||||
|
|
@ -95,16 +100,20 @@ class DownloadChapterProvider extends AutoDisposeFutureProvider<List<String>> {
|
|||
);
|
||||
|
||||
final Chapter chapter;
|
||||
final bool? useWifi;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is DownloadChapterProvider && other.chapter == chapter;
|
||||
return other is DownloadChapterProvider &&
|
||||
other.chapter == chapter &&
|
||||
other.useWifi == useWifi;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||
hash = _SystemHash.combine(hash, chapter.hashCode);
|
||||
hash = _SystemHash.combine(hash, useWifi.hashCode);
|
||||
|
||||
return _SystemHash.finish(hash);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,47 +42,41 @@ class _DownloadsScreenState extends ConsumerState<DownloadsScreen> {
|
|||
shrinkWrap: true,
|
||||
children: [
|
||||
RadioListTile(
|
||||
dense: true,
|
||||
contentPadding: const EdgeInsets.all(0),
|
||||
value: downloadLocationState.$2.isEmpty
|
||||
? downloadLocationState.$1
|
||||
: downloadLocationState.$2,
|
||||
groupValue: downloadLocationState.$1,
|
||||
onChanged: (value) {
|
||||
ref
|
||||
.read(downloadLocationStateProvider
|
||||
.notifier)
|
||||
.set("");
|
||||
Navigator.pop(context);
|
||||
},
|
||||
title: Row(
|
||||
children: [Text(downloadLocationState.$1)],
|
||||
),
|
||||
),
|
||||
RadioListTile(
|
||||
dense: true,
|
||||
contentPadding: const EdgeInsets.all(0),
|
||||
value: downloadLocationState.$2.isEmpty
|
||||
? downloadLocationState.$1
|
||||
: downloadLocationState.$2,
|
||||
groupValue: downloadLocationState.$2,
|
||||
onChanged: (value) async {
|
||||
String? result = await FilePicker.platform
|
||||
.getDirectoryPath();
|
||||
|
||||
if (result != null) {
|
||||
dense: true,
|
||||
contentPadding: const EdgeInsets.all(0),
|
||||
value: downloadLocationState.$2.isEmpty
|
||||
? downloadLocationState.$1
|
||||
: downloadLocationState.$2,
|
||||
groupValue: downloadLocationState.$1,
|
||||
onChanged: (value) {
|
||||
ref
|
||||
.read(downloadLocationStateProvider
|
||||
.notifier)
|
||||
.set(result);
|
||||
} else {}
|
||||
if (!mounted) return;
|
||||
Navigator.pop(context);
|
||||
},
|
||||
title: const Row(
|
||||
children: [Text("Custom location")],
|
||||
),
|
||||
),
|
||||
.set("");
|
||||
Navigator.pop(context);
|
||||
},
|
||||
title: Text(downloadLocationState.$1)),
|
||||
RadioListTile(
|
||||
dense: true,
|
||||
contentPadding: const EdgeInsets.all(0),
|
||||
value: downloadLocationState.$2.isEmpty
|
||||
? downloadLocationState.$1
|
||||
: downloadLocationState.$2,
|
||||
groupValue: downloadLocationState.$2,
|
||||
onChanged: (value) async {
|
||||
String? result = await FilePicker.platform
|
||||
.getDirectoryPath();
|
||||
|
||||
if (result != null) {
|
||||
ref
|
||||
.read(downloadLocationStateProvider
|
||||
.notifier)
|
||||
.set(result);
|
||||
} else {}
|
||||
if (!mounted) return;
|
||||
Navigator.pop(context);
|
||||
},
|
||||
title: const Text("Custom location")),
|
||||
],
|
||||
)),
|
||||
actions: [
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ class DownloadLocationState extends _$DownloadLocationState {
|
|||
Directory? _storageProvider;
|
||||
|
||||
Future refresh() async {
|
||||
_storageProvider = await StorageProvider().getDirectory();
|
||||
_storageProvider = await StorageProvider().getDefaultDirectory();
|
||||
final settings = isar.settings.getSync(227);
|
||||
state = (
|
||||
"${_storageProvider!.path}downloads",
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ final saveAsCBZArchiveStateProvider =
|
|||
|
||||
typedef _$SaveAsCBZArchiveState = AutoDisposeNotifier<bool>;
|
||||
String _$downloadLocationStateHash() =>
|
||||
r'92db9558ed1275edfb1a6f8dca3d87905e985f95';
|
||||
r'b883597443ed34622e20d20d51a1db56919f5362';
|
||||
|
||||
/// See also [DownloadLocationState].
|
||||
@ProviderFor(DownloadLocationState)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
// ignore_for_file: depend_on_referenced_packages
|
||||
import 'dart:io';
|
||||
import 'package:mangayomi/main.dart';
|
||||
import 'package:mangayomi/models/chapter.dart';
|
||||
import 'package:mangayomi/models/settings.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
|
|
@ -22,7 +24,7 @@ class StorageProvider {
|
|||
return true;
|
||||
}
|
||||
|
||||
Future<Directory?> getDirectory() async {
|
||||
Future<Directory?> getDefaultDirectory() async {
|
||||
Directory? directory;
|
||||
if (Platform.isAndroid) {
|
||||
directory = Directory("/storage/emulated/0/Mangayomi/");
|
||||
|
|
@ -33,6 +35,20 @@ class StorageProvider {
|
|||
return directory;
|
||||
}
|
||||
|
||||
Future<Directory?> getDirectory() async {
|
||||
Directory? directory;
|
||||
String path = isar.settings.getSync(227)!.downloadLocation ?? "";
|
||||
if (Platform.isAndroid) {
|
||||
directory =
|
||||
Directory(path.isEmpty ? "/storage/emulated/0/Mangayomi/" : "$path/");
|
||||
} else {
|
||||
final dir = await getApplicationDocumentsDirectory();
|
||||
final p = path.isEmpty ? dir.path : path;
|
||||
directory = Directory("$p/Mangayomi/");
|
||||
}
|
||||
return directory;
|
||||
}
|
||||
|
||||
Future<Directory?> getMangaChapterDirectory(
|
||||
Chapter chapter,
|
||||
) async {
|
||||
|
|
|
|||
11
pubspec.lock
11
pubspec.lock
|
|
@ -52,12 +52,11 @@ packages:
|
|||
background_downloader:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "."
|
||||
ref: HEAD
|
||||
resolved-ref: "92c20d487d7f63a36105bf944ddaa1be6374706d"
|
||||
url: "https://github.com/kodjodevf/background_downloader.git"
|
||||
source: git
|
||||
version: "7.0.1"
|
||||
name: background_downloader
|
||||
sha256: "4fac00620a0c6740062009a86a1d0918c17a9fab0f2bccd48f35143a1d261928"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.3.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -51,9 +51,7 @@ dependencies:
|
|||
google_fonts: ^4.0.3
|
||||
url_launcher: ^6.1.10
|
||||
package_info_plus: ^4.0.2
|
||||
background_downloader:
|
||||
git:
|
||||
url: https://github.com/kodjodevf/background_downloader.git
|
||||
background_downloader: ^7.3.0
|
||||
permission_handler: ^10.2.0
|
||||
flutter_inappwebview: ^6.0.0-beta.22
|
||||
draggable_menu: ^2.0.2
|
||||
|
|
|
|||
Loading…
Reference in a new issue