mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-02-02 06:46:22 +01:00
Download album
This commit is contained in:
parent
e7f510ac4f
commit
4c222a239a
7 changed files with 88 additions and 15 deletions
|
@ -14,7 +14,11 @@ import 'package:nc_photos/use_case/download_file.dart';
|
||||||
import 'package:tuple/tuple.dart';
|
import 'package:tuple/tuple.dart';
|
||||||
|
|
||||||
class DownloadHandler {
|
class DownloadHandler {
|
||||||
Future<void> downloadFiles(Account account, List<File> files) async {
|
Future<void> downloadFiles(
|
||||||
|
Account account,
|
||||||
|
List<File> files, {
|
||||||
|
String? parentDir,
|
||||||
|
}) async {
|
||||||
_log.info("[downloadFiles] Downloading ${files.length} file");
|
_log.info("[downloadFiles] Downloading ${files.length} file");
|
||||||
var controller = SnackBarManager().showSnackBar(SnackBar(
|
var controller = SnackBarManager().showSnackBar(SnackBar(
|
||||||
content: Text(L10n.global().downloadProcessingNotification),
|
content: Text(L10n.global().downloadProcessingNotification),
|
||||||
|
@ -26,7 +30,12 @@ class DownloadHandler {
|
||||||
final successes = <Tuple2<File, dynamic>>[];
|
final successes = <Tuple2<File, dynamic>>[];
|
||||||
for (final f in files) {
|
for (final f in files) {
|
||||||
try {
|
try {
|
||||||
successes.add(Tuple2(f, await DownloadFile()(account, f)));
|
final result = await DownloadFile()(
|
||||||
|
account,
|
||||||
|
f,
|
||||||
|
parentDir: parentDir,
|
||||||
|
);
|
||||||
|
successes.add(Tuple2(f, result));
|
||||||
} on PermissionException catch (_) {
|
} on PermissionException catch (_) {
|
||||||
_log.warning("[downloadFiles] Permission not granted");
|
_log.warning("[downloadFiles] Permission not granted");
|
||||||
controller?.close();
|
controller?.close();
|
||||||
|
|
|
@ -15,6 +15,7 @@ class FileDownloader extends itf.FileDownloader {
|
||||||
Map<String, String>? headers,
|
Map<String, String>? headers,
|
||||||
String? mimeType,
|
String? mimeType,
|
||||||
required String filename,
|
required String filename,
|
||||||
|
String? parentDir,
|
||||||
bool? shouldNotify,
|
bool? shouldNotify,
|
||||||
}) {
|
}) {
|
||||||
if (platform_k.isAndroid) {
|
if (platform_k.isAndroid) {
|
||||||
|
@ -23,6 +24,7 @@ class FileDownloader extends itf.FileDownloader {
|
||||||
headers: headers,
|
headers: headers,
|
||||||
mimeType: mimeType,
|
mimeType: mimeType,
|
||||||
filename: filename,
|
filename: filename,
|
||||||
|
parentDir: parentDir,
|
||||||
shouldNotify: shouldNotify,
|
shouldNotify: shouldNotify,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -35,15 +37,23 @@ class FileDownloader extends itf.FileDownloader {
|
||||||
Map<String, String>? headers,
|
Map<String, String>? headers,
|
||||||
String? mimeType,
|
String? mimeType,
|
||||||
required String filename,
|
required String filename,
|
||||||
|
String? parentDir,
|
||||||
bool? shouldNotify,
|
bool? shouldNotify,
|
||||||
}) async {
|
}) async {
|
||||||
|
final String path;
|
||||||
|
if (parentDir?.isNotEmpty == true) {
|
||||||
|
path = "$parentDir/$filename";
|
||||||
|
} else {
|
||||||
|
path = filename;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
_log.info("[_downloadUrlAndroid] Start downloading '$url'");
|
_log.info("[_downloadUrlAndroid] Start downloading '$url'");
|
||||||
final id = await Download.downloadUrl(
|
final id = await Download.downloadUrl(
|
||||||
url: url,
|
url: url,
|
||||||
headers: headers,
|
headers: headers,
|
||||||
mimeType: mimeType,
|
mimeType: mimeType,
|
||||||
filename: filename,
|
filename: path,
|
||||||
shouldNotify: shouldNotify,
|
shouldNotify: shouldNotify,
|
||||||
);
|
);
|
||||||
late final String uri;
|
late final String uri;
|
||||||
|
|
|
@ -5,6 +5,9 @@ abstract class FileDownloader {
|
||||||
/// - web: null
|
/// - web: null
|
||||||
/// - android: Uri to the downloaded file
|
/// - android: Uri to the downloaded file
|
||||||
///
|
///
|
||||||
|
/// [parentDir] is a hint that set the parent directory where the files are
|
||||||
|
/// saved. Whether this is supported or not is implementation specific
|
||||||
|
///
|
||||||
/// [shouldNotify] is a hint that suggest whether to notify user about the
|
/// [shouldNotify] is a hint that suggest whether to notify user about the
|
||||||
/// progress. The actual decision is made by the underlying platform code and
|
/// progress. The actual decision is made by the underlying platform code and
|
||||||
/// is not guaranteed to respect this flag
|
/// is not guaranteed to respect this flag
|
||||||
|
@ -13,6 +16,7 @@ abstract class FileDownloader {
|
||||||
Map<String, String>? headers,
|
Map<String, String>? headers,
|
||||||
String? mimeType,
|
String? mimeType,
|
||||||
required String filename,
|
required String filename,
|
||||||
|
String? parentDir,
|
||||||
bool? shouldNotify,
|
bool? shouldNotify,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,14 +6,13 @@ import 'package:nc_photos/mobile/platform.dart'
|
||||||
import 'package:path/path.dart' as path;
|
import 'package:path/path.dart' as path;
|
||||||
|
|
||||||
class DownloadFile {
|
class DownloadFile {
|
||||||
DownloadFile();
|
|
||||||
|
|
||||||
/// Download [file]
|
/// Download [file]
|
||||||
///
|
///
|
||||||
/// See [FileDownloader.downloadUrl]
|
/// See [FileDownloader.downloadUrl]
|
||||||
Future<dynamic> call(
|
Future<dynamic> call(
|
||||||
Account account,
|
Account account,
|
||||||
File file, {
|
File file, {
|
||||||
|
String? parentDir,
|
||||||
bool? shouldNotify,
|
bool? shouldNotify,
|
||||||
}) {
|
}) {
|
||||||
final downloader = platform.FileDownloader();
|
final downloader = platform.FileDownloader();
|
||||||
|
@ -25,6 +24,7 @@ class DownloadFile {
|
||||||
},
|
},
|
||||||
mimeType: file.contentType,
|
mimeType: file.contentType,
|
||||||
filename: path.basename(file.path),
|
filename: path.basename(file.path),
|
||||||
|
parentDir: parentDir,
|
||||||
shouldNotify: shouldNotify,
|
shouldNotify: shouldNotify,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ class FileDownloader extends itf.FileDownloader {
|
||||||
Map<String, String>? headers,
|
Map<String, String>? headers,
|
||||||
String? mimeType,
|
String? mimeType,
|
||||||
required String filename,
|
required String filename,
|
||||||
|
String? parentDir,
|
||||||
bool? shouldNotify,
|
bool? shouldNotify,
|
||||||
}) async {
|
}) async {
|
||||||
final uri = Uri.parse(url);
|
final uri = Uri.parse(url);
|
||||||
|
|
|
@ -232,7 +232,18 @@ class _AlbumBrowserState extends State<AlbumBrowser>
|
||||||
} else if (isSelectionMode) {
|
} else if (isSelectionMode) {
|
||||||
return _buildSelectionAppBar(context);
|
return _buildSelectionAppBar(context);
|
||||||
} else {
|
} else {
|
||||||
return buildNormalAppBar(context, widget.account, _album!);
|
return buildNormalAppBar(
|
||||||
|
context,
|
||||||
|
widget.account,
|
||||||
|
_album!,
|
||||||
|
menuItemBuilder: (_) => [
|
||||||
|
PopupMenuItem(
|
||||||
|
value: _menuValueDownload,
|
||||||
|
child: Text(L10n.global().downloadTooltip),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
onSelectedMenuItem: (option) => _onMenuSelected(context, option),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,6 +305,25 @@ class _AlbumBrowserState extends State<AlbumBrowser>
|
||||||
album: _album));
|
album: _album));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _onMenuSelected(BuildContext context, int option) {
|
||||||
|
switch (option) {
|
||||||
|
case _menuValueDownload:
|
||||||
|
_onDownloadPressed();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_log.shout("[_onMenuSelected] Unknown option: $option");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onDownloadPressed() {
|
||||||
|
DownloadHandler().downloadFiles(
|
||||||
|
widget.account,
|
||||||
|
_sortedItems.whereType<AlbumFileItem>().map((e) => e.file).toList(),
|
||||||
|
parentDir: _album!.name,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void _onSelectionAppBarSharePressed(BuildContext context) {
|
void _onSelectionAppBarSharePressed(BuildContext context) {
|
||||||
assert(platform_k.isAndroid);
|
assert(platform_k.isAndroid);
|
||||||
final selected = selectedListItems
|
final selected = selectedListItems
|
||||||
|
@ -666,6 +696,8 @@ class _AlbumBrowserState extends State<AlbumBrowser>
|
||||||
late AppEventListener<AlbumUpdatedEvent> _albumUpdatedListener;
|
late AppEventListener<AlbumUpdatedEvent> _albumUpdatedListener;
|
||||||
|
|
||||||
static final _log = Logger("widget.album_browser._AlbumBrowserState");
|
static final _log = Logger("widget.album_browser._AlbumBrowserState");
|
||||||
|
|
||||||
|
static const _menuValueDownload = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum _SelectionMenuOption {
|
enum _SelectionMenuOption {
|
||||||
|
|
|
@ -223,24 +223,32 @@ class _DynamicAlbumBrowserState extends State<DynamicAlbumBrowser>
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildNormalAppBar(BuildContext context) {
|
Widget _buildNormalAppBar(BuildContext context) {
|
||||||
|
final menuItems = <PopupMenuEntry<int>>[
|
||||||
|
PopupMenuItem(
|
||||||
|
value: _menuValueDownload,
|
||||||
|
child: Text(L10n.global().downloadTooltip),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
if (canEdit) {
|
||||||
|
menuItems.add(PopupMenuItem(
|
||||||
|
value: _menuValueConvertBasic,
|
||||||
|
child: Text(L10n.global().convertBasicAlbumMenuLabel),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
return buildNormalAppBar(
|
return buildNormalAppBar(
|
||||||
context,
|
context,
|
||||||
widget.account,
|
widget.account,
|
||||||
_album!,
|
_album!,
|
||||||
menuItemBuilder: canEdit
|
menuItemBuilder: (_) => menuItems,
|
||||||
? (context) => [
|
|
||||||
PopupMenuItem(
|
|
||||||
value: _menuValueConvertBasic,
|
|
||||||
child: Text(L10n.global().convertBasicAlbumMenuLabel),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
: null,
|
|
||||||
onSelectedMenuItem: (option) {
|
onSelectedMenuItem: (option) {
|
||||||
switch (option) {
|
switch (option) {
|
||||||
case _menuValueConvertBasic:
|
case _menuValueConvertBasic:
|
||||||
_onAppBarConvertBasicPressed(context);
|
_onAppBarConvertBasicPressed(context);
|
||||||
break;
|
break;
|
||||||
|
case _menuValueDownload:
|
||||||
|
_onDownloadPressed();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
_log.shout("[_buildNormalAppBar] Unknown value: $option");
|
_log.shout("[_buildNormalAppBar] Unknown value: $option");
|
||||||
break;
|
break;
|
||||||
|
@ -358,6 +366,14 @@ class _DynamicAlbumBrowserState extends State<DynamicAlbumBrowser>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _onDownloadPressed() {
|
||||||
|
DownloadHandler().downloadFiles(
|
||||||
|
widget.account,
|
||||||
|
_sortedItems.whereType<AlbumFileItem>().map((e) => e.file).toList(),
|
||||||
|
parentDir: _album!.name,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void _onSelectionAppBarSharePressed(BuildContext context) {
|
void _onSelectionAppBarSharePressed(BuildContext context) {
|
||||||
assert(platform_k.isAndroid);
|
assert(platform_k.isAndroid);
|
||||||
final selected = selectedListItems
|
final selected = selectedListItems
|
||||||
|
@ -576,6 +592,7 @@ class _DynamicAlbumBrowserState extends State<DynamicAlbumBrowser>
|
||||||
static final _log =
|
static final _log =
|
||||||
Logger("widget.dynamic_album_browser._DynamicAlbumBrowserState");
|
Logger("widget.dynamic_album_browser._DynamicAlbumBrowserState");
|
||||||
static const _menuValueConvertBasic = 0;
|
static const _menuValueConvertBasic = 0;
|
||||||
|
static const _menuValueDownload = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum _SelectionMenuOption {
|
enum _SelectionMenuOption {
|
||||||
|
|
Loading…
Reference in a new issue