Pull out the code to download a file to gallery
This commit is contained in:
parent
a148f1a7af
commit
24fc486721
2 changed files with 102 additions and 91 deletions
|
@ -4,30 +4,23 @@ import 'package:flutter/cupertino.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:media_extension/media_extension.dart';
|
||||
import 'package:path/path.dart' as file_path;
|
||||
import 'package:photo_manager/photo_manager.dart';
|
||||
import 'package:photos/core/event_bus.dart';
|
||||
import 'package:photos/db/files_db.dart';
|
||||
import 'package:photos/events/local_photos_updated_event.dart';
|
||||
import "package:photos/generated/l10n.dart";
|
||||
import "package:photos/l10n/l10n.dart";
|
||||
import "package:photos/models/file/extensions/file_props.dart";
|
||||
import 'package:photos/models/file/file.dart';
|
||||
import 'package:photos/models/file/file_type.dart';
|
||||
import 'package:photos/models/file/trash_file.dart';
|
||||
import 'package:photos/models/ignored_file.dart';
|
||||
import "package:photos/models/metadata/common_keys.dart";
|
||||
import 'package:photos/models/selected_files.dart';
|
||||
import "package:photos/service_locator.dart";
|
||||
import 'package:photos/services/collections_service.dart';
|
||||
import 'package:photos/services/hidden_service.dart';
|
||||
import 'package:photos/services/ignored_files_service.dart';
|
||||
import 'package:photos/services/local_sync_service.dart';
|
||||
import 'package:photos/ui/collections/collection_action_sheet.dart';
|
||||
import 'package:photos/ui/viewer/file/custom_app_bar.dart';
|
||||
import "package:photos/ui/viewer/file_details/favorite_widget.dart";
|
||||
import "package:photos/ui/viewer/file_details/upload_icon_widget.dart";
|
||||
import 'package:photos/utils/dialog_util.dart';
|
||||
import "package:photos/utils/file_download_util.dart";
|
||||
import 'package:photos/utils/file_util.dart';
|
||||
import "package:photos/utils/magic_util.dart";
|
||||
import 'package:photos/utils/toast_util.dart';
|
||||
|
@ -330,98 +323,16 @@ class FileAppBarState extends State<FileAppBar> {
|
|||
);
|
||||
await dialog.show();
|
||||
try {
|
||||
final FileType type = file.fileType;
|
||||
final bool downloadLivePhotoOnDroid =
|
||||
type == FileType.livePhoto && Platform.isAndroid;
|
||||
AssetEntity? savedAsset;
|
||||
final File? fileToSave = await getFile(file);
|
||||
//Disabling notifications for assets changing to insert the file into
|
||||
//files db before triggering a sync.
|
||||
await PhotoManager.stopChangeNotify();
|
||||
if (type == FileType.image) {
|
||||
savedAsset = await PhotoManager.editor
|
||||
.saveImageWithPath(fileToSave!.path, title: file.title!);
|
||||
} else if (type == FileType.video) {
|
||||
savedAsset = await PhotoManager.editor
|
||||
.saveVideo(fileToSave!, title: file.title!);
|
||||
} else if (type == FileType.livePhoto) {
|
||||
final File? liveVideoFile =
|
||||
await getFileFromServer(file, liveVideo: true);
|
||||
if (liveVideoFile == null) {
|
||||
throw AssertionError("Live video can not be null");
|
||||
}
|
||||
if (downloadLivePhotoOnDroid) {
|
||||
await _saveLivePhotoOnDroid(fileToSave!, liveVideoFile, file);
|
||||
} else {
|
||||
savedAsset = await PhotoManager.editor.darwin.saveLivePhoto(
|
||||
imageFile: fileToSave!,
|
||||
videoFile: liveVideoFile,
|
||||
title: file.title!,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (savedAsset != null) {
|
||||
file.localID = savedAsset.id;
|
||||
await FilesDB.instance.insert(file);
|
||||
Bus.instance.fire(
|
||||
LocalPhotosUpdatedEvent(
|
||||
[file],
|
||||
source: "download",
|
||||
),
|
||||
);
|
||||
} else if (!downloadLivePhotoOnDroid && savedAsset == null) {
|
||||
_logger.severe('Failed to save assert of type $type');
|
||||
}
|
||||
await downloadToGallery(file);
|
||||
showToast(context, S.of(context).fileSavedToGallery);
|
||||
await dialog.hide();
|
||||
} catch (e) {
|
||||
_logger.warning("Failed to save file", e);
|
||||
await dialog.hide();
|
||||
await showGenericErrorDialog(context: context, error: e);
|
||||
} finally {
|
||||
await PhotoManager.startChangeNotify();
|
||||
LocalSyncService.instance.checkAndSync().ignore();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _saveLivePhotoOnDroid(
|
||||
File image,
|
||||
File video,
|
||||
EnteFile enteFile,
|
||||
) async {
|
||||
debugPrint("Downloading LivePhoto on Droid");
|
||||
AssetEntity? savedAsset = await (PhotoManager.editor
|
||||
.saveImageWithPath(image.path, title: enteFile.title!));
|
||||
if (savedAsset == null) {
|
||||
throw Exception("Failed to save image of live photo");
|
||||
}
|
||||
IgnoredFile ignoreVideoFile = IgnoredFile(
|
||||
savedAsset.id,
|
||||
savedAsset.title ?? '',
|
||||
savedAsset.relativePath ?? 'remoteDownload',
|
||||
"remoteDownload",
|
||||
);
|
||||
await IgnoredFilesService.instance.cacheAndInsert([ignoreVideoFile]);
|
||||
final videoTitle = file_path.basenameWithoutExtension(enteFile.title!) +
|
||||
file_path.extension(video.path);
|
||||
savedAsset = (await (PhotoManager.editor.saveVideo(
|
||||
video,
|
||||
title: videoTitle,
|
||||
)));
|
||||
if (savedAsset == null) {
|
||||
throw Exception("Failed to save video of live photo");
|
||||
}
|
||||
|
||||
ignoreVideoFile = IgnoredFile(
|
||||
savedAsset.id,
|
||||
savedAsset.title ?? videoTitle,
|
||||
savedAsset.relativePath ?? 'remoteDownload',
|
||||
"remoteDownload",
|
||||
);
|
||||
await IgnoredFilesService.instance.cacheAndInsert([ignoreVideoFile]);
|
||||
}
|
||||
|
||||
Future<void> _setAs(EnteFile file) async {
|
||||
final dialog = createProgressDialog(context, S.of(context).pleaseWait);
|
||||
await dialog.show();
|
||||
|
|
|
@ -4,14 +4,23 @@ import "package:computer/computer.dart";
|
|||
import 'package:dio/dio.dart';
|
||||
import "package:flutter/foundation.dart";
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:path/path.dart' as file_path;
|
||||
import "package:photo_manager/photo_manager.dart";
|
||||
import 'package:photos/core/configuration.dart';
|
||||
import "package:photos/core/event_bus.dart";
|
||||
import 'package:photos/core/network/network.dart';
|
||||
import "package:photos/db/files_db.dart";
|
||||
import "package:photos/events/local_photos_updated_event.dart";
|
||||
import 'package:photos/models/file/file.dart';
|
||||
import "package:photos/models/file/file_type.dart";
|
||||
import "package:photos/models/ignored_file.dart";
|
||||
import 'package:photos/services/collections_service.dart';
|
||||
import "package:photos/services/ignored_files_service.dart";
|
||||
import "package:photos/services/local_sync_service.dart";
|
||||
import 'package:photos/utils/crypto_util.dart';
|
||||
import "package:photos/utils/data_util.dart";
|
||||
import "package:photos/utils/fake_progress.dart";
|
||||
import "package:photos/utils/file_util.dart";
|
||||
|
||||
final _logger = Logger("file_download_util");
|
||||
|
||||
|
@ -115,6 +124,97 @@ Future<Uint8List> getFileKeyUsingBgWorker(EnteFile file) async {
|
|||
);
|
||||
}
|
||||
|
||||
Future<void> downloadToGallery(EnteFile file) async {
|
||||
try {
|
||||
final FileType type = file.fileType;
|
||||
final bool downloadLivePhotoOnDroid =
|
||||
type == FileType.livePhoto && Platform.isAndroid;
|
||||
AssetEntity? savedAsset;
|
||||
final File? fileToSave = await getFile(file);
|
||||
//Disabling notifications for assets changing to insert the file into
|
||||
//files db before triggering a sync.
|
||||
await PhotoManager.stopChangeNotify();
|
||||
if (type == FileType.image) {
|
||||
savedAsset = await PhotoManager.editor
|
||||
.saveImageWithPath(fileToSave!.path, title: file.title!);
|
||||
} else if (type == FileType.video) {
|
||||
savedAsset =
|
||||
await PhotoManager.editor.saveVideo(fileToSave!, title: file.title!);
|
||||
} else if (type == FileType.livePhoto) {
|
||||
final File? liveVideoFile =
|
||||
await getFileFromServer(file, liveVideo: true);
|
||||
if (liveVideoFile == null) {
|
||||
throw AssertionError("Live video can not be null");
|
||||
}
|
||||
if (downloadLivePhotoOnDroid) {
|
||||
await _saveLivePhotoOnDroid(fileToSave!, liveVideoFile, file);
|
||||
} else {
|
||||
savedAsset = await PhotoManager.editor.darwin.saveLivePhoto(
|
||||
imageFile: fileToSave!,
|
||||
videoFile: liveVideoFile,
|
||||
title: file.title!,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (savedAsset != null) {
|
||||
file.localID = savedAsset.id;
|
||||
await FilesDB.instance.insert(file);
|
||||
Bus.instance.fire(
|
||||
LocalPhotosUpdatedEvent(
|
||||
[file],
|
||||
source: "download",
|
||||
),
|
||||
);
|
||||
} else if (!downloadLivePhotoOnDroid && savedAsset == null) {
|
||||
_logger.severe('Failed to save assert of type $type');
|
||||
}
|
||||
} catch (e) {
|
||||
_logger.warning("Failed to save file", e);
|
||||
rethrow;
|
||||
} finally {
|
||||
await PhotoManager.startChangeNotify();
|
||||
LocalSyncService.instance.checkAndSync().ignore();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _saveLivePhotoOnDroid(
|
||||
File image,
|
||||
File video,
|
||||
EnteFile enteFile,
|
||||
) async {
|
||||
debugPrint("Downloading LivePhoto on Droid");
|
||||
AssetEntity? savedAsset = await (PhotoManager.editor
|
||||
.saveImageWithPath(image.path, title: enteFile.title!));
|
||||
if (savedAsset == null) {
|
||||
throw Exception("Failed to save image of live photo");
|
||||
}
|
||||
IgnoredFile ignoreVideoFile = IgnoredFile(
|
||||
savedAsset.id,
|
||||
savedAsset.title ?? '',
|
||||
savedAsset.relativePath ?? 'remoteDownload',
|
||||
"remoteDownload",
|
||||
);
|
||||
await IgnoredFilesService.instance.cacheAndInsert([ignoreVideoFile]);
|
||||
final videoTitle = file_path.basenameWithoutExtension(enteFile.title!) +
|
||||
file_path.extension(video.path);
|
||||
savedAsset = (await (PhotoManager.editor.saveVideo(
|
||||
video,
|
||||
title: videoTitle,
|
||||
)));
|
||||
if (savedAsset == null) {
|
||||
throw Exception("Failed to save video of live photo");
|
||||
}
|
||||
|
||||
ignoreVideoFile = IgnoredFile(
|
||||
savedAsset.id,
|
||||
savedAsset.title ?? videoTitle,
|
||||
savedAsset.relativePath ?? 'remoteDownload',
|
||||
"remoteDownload",
|
||||
);
|
||||
await IgnoredFilesService.instance.cacheAndInsert([ignoreVideoFile]);
|
||||
}
|
||||
|
||||
Uint8List _decryptFileKey(Map<String, dynamic> args) {
|
||||
final encryptedKey = CryptoUtil.base642bin(args["encryptedKey"]);
|
||||
final nonce = CryptoUtil.base642bin(args["keyDecryptionNonce"]);
|
||||
|
|
Loading…
Add table
Reference in a new issue