mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-01-23 17:26:18 +01:00
131 lines
3.4 KiB
Dart
131 lines
3.4 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:flutter/services.dart';
|
|
import 'package:logging/logging.dart';
|
|
import 'package:nc_photos/exception.dart';
|
|
import 'package:nc_photos/mobile/android/download.dart' as android;
|
|
import 'package:nc_photos/mobile/android/media_store.dart';
|
|
import 'package:nc_photos/platform/download.dart' as itf;
|
|
import 'package:nc_photos/platform/k.dart' as platform_k;
|
|
|
|
class DownloadBuilder extends itf.DownloadBuilder {
|
|
@override
|
|
build({
|
|
required String url,
|
|
Map<String, String>? headers,
|
|
String? mimeType,
|
|
required String filename,
|
|
String? parentDir,
|
|
bool? shouldNotify,
|
|
}) {
|
|
if (platform_k.isAndroid) {
|
|
return _AndroidDownload(
|
|
url: url,
|
|
headers: headers,
|
|
mimeType: mimeType,
|
|
filename: filename,
|
|
parentDir: parentDir,
|
|
shouldNotify: shouldNotify,
|
|
);
|
|
} else {
|
|
throw UnimplementedError();
|
|
}
|
|
}
|
|
}
|
|
|
|
class _AndroidDownload extends itf.Download {
|
|
_AndroidDownload({
|
|
required this.url,
|
|
this.headers,
|
|
this.mimeType,
|
|
required this.filename,
|
|
this.parentDir,
|
|
this.shouldNotify,
|
|
});
|
|
|
|
@override
|
|
call() async {
|
|
final String path;
|
|
if (parentDir?.isNotEmpty == true) {
|
|
path = "$parentDir/$filename";
|
|
} else {
|
|
path = filename;
|
|
}
|
|
|
|
try {
|
|
_log.info("[call] Start downloading '$url'");
|
|
_downloadId = await android.Download.downloadUrl(
|
|
url: url,
|
|
headers: headers,
|
|
mimeType: mimeType,
|
|
filename: path,
|
|
shouldNotify: shouldNotify,
|
|
);
|
|
_log.info("[call] #$_downloadId -> '$url'");
|
|
late final String uri;
|
|
final completer = Completer();
|
|
onDownloadComplete(android.DownloadCompleteEvent ev) {
|
|
if (ev.downloadId == _downloadId) {
|
|
_log.info("[call] Finished downloading '$url' to '${ev.uri}'");
|
|
uri = ev.uri;
|
|
completer.complete();
|
|
}
|
|
}
|
|
|
|
StreamSubscription<android.DownloadCompleteEvent>? subscription;
|
|
try {
|
|
subscription = android.DownloadEvent.listenDownloadComplete()
|
|
..onData(onDownloadComplete)
|
|
..onError((e, stackTrace) {
|
|
if (e is android.AndroidDownloadError) {
|
|
if (e.downloadId != _downloadId) {
|
|
// not us, ignore
|
|
return;
|
|
}
|
|
completer.completeError(e.error, e.stackTrace);
|
|
} else {
|
|
completer.completeError(e, stackTrace);
|
|
}
|
|
});
|
|
await completer.future;
|
|
} finally {
|
|
subscription?.cancel();
|
|
}
|
|
return uri;
|
|
} on PlatformException catch (e) {
|
|
switch (e.code) {
|
|
case MediaStore.exceptionCodePermissionError:
|
|
throw PermissionException();
|
|
|
|
case android.Download.exceptionCodeDownloadError:
|
|
throw DownloadException(e.message);
|
|
|
|
case android.DownloadEvent.exceptionCodeUserCanceled:
|
|
throw JobCanceledException(e.message);
|
|
|
|
default:
|
|
rethrow;
|
|
}
|
|
}
|
|
}
|
|
|
|
@override
|
|
cancel() async {
|
|
if (_downloadId != null) {
|
|
_log.info("[cancel] Cancel #$_downloadId");
|
|
return await android.Download.cancel(id: _downloadId!);
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
final String url;
|
|
final Map<String, String>? headers;
|
|
final String? mimeType;
|
|
final String filename;
|
|
final String? parentDir;
|
|
final bool? shouldNotify;
|
|
int? _downloadId;
|
|
|
|
static final _log = Logger("mobile.download._AndroidDownload");
|
|
}
|