feature: required wifi when downloading, custom download location

This commit is contained in:
kodjomoustapha 2023-06-04 15:50:13 +01:00
parent e2115f0a0a
commit 05bada5661
10 changed files with 142 additions and 122 deletions

View file

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

View file

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

View file

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

View file

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

View file

@ -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: [

View file

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

View file

@ -40,7 +40,7 @@ final saveAsCBZArchiveStateProvider =
typedef _$SaveAsCBZArchiveState = AutoDisposeNotifier<bool>;
String _$downloadLocationStateHash() =>
r'92db9558ed1275edfb1a6f8dca3d87905e985f95';
r'b883597443ed34622e20d20d51a1db56919f5362';
/// See also [DownloadLocationState].
@ProviderFor(DownloadLocationState)

View file

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

View file

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

View file

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