2021-05-03 21:14:44 +00:00
|
|
|
import 'dart:async';
|
|
|
|
|
|
|
|
import 'package:flutter/widgets.dart';
|
|
|
|
import 'package:logging/logging.dart';
|
|
|
|
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/collection_updated_event.dart';
|
|
|
|
import 'package:photos/events/files_updated_event.dart';
|
|
|
|
import 'package:photos/events/local_photos_updated_event.dart';
|
|
|
|
import 'package:photos/models/file.dart';
|
2021-06-14 16:24:15 +00:00
|
|
|
import 'package:photos/services/remote_sync_service.dart';
|
2021-05-03 21:14:44 +00:00
|
|
|
import 'package:photos/services/sync_service.dart';
|
|
|
|
import 'package:photos/utils/dialog_util.dart';
|
|
|
|
import 'package:photos/utils/toast_util.dart';
|
|
|
|
|
|
|
|
final _logger = Logger("DeleteFileUtil");
|
|
|
|
|
|
|
|
Future<void> deleteFilesFromEverywhere(
|
|
|
|
BuildContext context, List<File> files) async {
|
|
|
|
final dialog = createProgressDialog(context, "deleting...");
|
|
|
|
await dialog.show();
|
2021-06-13 20:09:06 +00:00
|
|
|
_logger.info("Trying to delete files " + files.toString());
|
2021-06-13 19:49:25 +00:00
|
|
|
final List<String> localIDs = [];
|
|
|
|
final List<String> alreadyDeletedIDs = []; // to ignore already deleted files
|
2021-05-03 21:14:44 +00:00
|
|
|
for (final file in files) {
|
|
|
|
if (file.localID != null) {
|
2021-06-13 19:49:25 +00:00
|
|
|
final asset = await file.getAsset();
|
|
|
|
if (asset == null || !(await asset.exists)) {
|
2021-06-13 20:09:06 +00:00
|
|
|
_logger.warning("Already deleted " + file.toString());
|
2021-06-13 19:49:25 +00:00
|
|
|
alreadyDeletedIDs.add(file.localID);
|
|
|
|
} else {
|
|
|
|
localIDs.add(file.localID);
|
|
|
|
}
|
2021-05-03 21:14:44 +00:00
|
|
|
}
|
|
|
|
}
|
2021-06-13 20:38:26 +00:00
|
|
|
Set<String> deletedIDs = Set<String>();
|
2021-05-03 21:14:44 +00:00
|
|
|
try {
|
|
|
|
deletedIDs = (await PhotoManager.editor.deleteWithIds(localIDs)).toSet();
|
|
|
|
} catch (e, s) {
|
|
|
|
_logger.severe("Could not delete file", e, s);
|
|
|
|
}
|
|
|
|
final updatedCollectionIDs = Set<int>();
|
|
|
|
final List<int> uploadedFileIDsToBeDeleted = [];
|
|
|
|
final List<File> deletedFiles = [];
|
|
|
|
for (final file in files) {
|
|
|
|
if (file.localID != null) {
|
2021-06-13 19:49:25 +00:00
|
|
|
// Remove only those files that have already been removed from disk
|
|
|
|
if (deletedIDs.contains(file.localID) ||
|
|
|
|
alreadyDeletedIDs.contains(file.localID)) {
|
2021-05-03 21:14:44 +00:00
|
|
|
deletedFiles.add(file);
|
|
|
|
if (file.uploadedFileID != null) {
|
|
|
|
uploadedFileIDsToBeDeleted.add(file.uploadedFileID);
|
|
|
|
updatedCollectionIDs.add(file.collectionID);
|
|
|
|
} else {
|
|
|
|
await FilesDB.instance.deleteLocalFile(file.localID);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2021-05-03 21:26:23 +00:00
|
|
|
updatedCollectionIDs.add(file.collectionID);
|
|
|
|
deletedFiles.add(file);
|
2021-05-03 21:14:44 +00:00
|
|
|
uploadedFileIDsToBeDeleted.add(file.uploadedFileID);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (uploadedFileIDsToBeDeleted.isNotEmpty) {
|
|
|
|
try {
|
|
|
|
await SyncService.instance
|
|
|
|
.deleteFilesOnServer(uploadedFileIDsToBeDeleted);
|
|
|
|
await FilesDB.instance
|
|
|
|
.deleteMultipleUploadedFiles(uploadedFileIDsToBeDeleted);
|
|
|
|
} catch (e) {
|
|
|
|
_logger.severe(e);
|
|
|
|
await dialog.hide();
|
|
|
|
showGenericErrorDialog(context);
|
|
|
|
throw e;
|
|
|
|
}
|
|
|
|
for (final collectionID in updatedCollectionIDs) {
|
|
|
|
Bus.instance.fire(CollectionUpdatedEvent(
|
2021-05-03 21:26:23 +00:00
|
|
|
collectionID,
|
|
|
|
deletedFiles
|
|
|
|
.where((file) => file.collectionID == collectionID)
|
|
|
|
.toList(),
|
|
|
|
type: EventType.deleted,
|
|
|
|
));
|
2021-05-03 21:14:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (deletedFiles.isNotEmpty) {
|
|
|
|
Bus.instance
|
|
|
|
.fire(LocalPhotosUpdatedEvent(deletedFiles, type: EventType.deleted));
|
|
|
|
}
|
|
|
|
await dialog.hide();
|
|
|
|
showToast("deleted from everywhere");
|
|
|
|
if (uploadedFileIDsToBeDeleted.isNotEmpty) {
|
2021-06-14 16:24:15 +00:00
|
|
|
RemoteSyncService.instance.sync(silently: true);
|
2021-05-03 21:14:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> deleteFilesOnDeviceOnly(
|
|
|
|
BuildContext context, List<File> files) async {
|
|
|
|
final dialog = createProgressDialog(context, "deleting...");
|
|
|
|
await dialog.show();
|
2021-06-13 20:09:06 +00:00
|
|
|
_logger.info("Trying to delete files " + files.toString());
|
2021-06-13 19:49:25 +00:00
|
|
|
final List<String> localIDs = [];
|
|
|
|
final List<String> alreadyDeletedIDs = []; // to ignore already deleted files
|
2021-05-03 21:14:44 +00:00
|
|
|
for (final file in files) {
|
|
|
|
if (file.localID != null) {
|
2021-06-13 19:49:25 +00:00
|
|
|
final asset = await file.getAsset();
|
|
|
|
if (asset == null || !(await asset.exists)) {
|
2021-06-13 20:09:06 +00:00
|
|
|
_logger.warning("Already deleted " + file.toString());
|
2021-06-13 19:49:25 +00:00
|
|
|
alreadyDeletedIDs.add(file.localID);
|
|
|
|
} else {
|
|
|
|
localIDs.add(file.localID);
|
|
|
|
}
|
2021-05-03 21:14:44 +00:00
|
|
|
}
|
|
|
|
}
|
2021-06-13 20:38:26 +00:00
|
|
|
Set<String> deletedIDs = Set<String>();
|
2021-05-25 12:26:31 +00:00
|
|
|
try {
|
|
|
|
deletedIDs = (await PhotoManager.editor.deleteWithIds(localIDs)).toSet();
|
|
|
|
} catch (e, s) {
|
|
|
|
_logger.severe("Could not delete file", e, s);
|
|
|
|
}
|
2021-05-03 21:14:44 +00:00
|
|
|
final List<File> deletedFiles = [];
|
|
|
|
for (final file in files) {
|
|
|
|
// Remove only those files that have been removed from disk
|
2021-06-13 19:49:25 +00:00
|
|
|
if (deletedIDs.contains(file.localID) ||
|
|
|
|
alreadyDeletedIDs.contains(file.localID)) {
|
2021-05-03 21:14:44 +00:00
|
|
|
deletedFiles.add(file);
|
|
|
|
file.localID = null;
|
|
|
|
FilesDB.instance.update(file);
|
|
|
|
}
|
|
|
|
}
|
2021-06-13 19:49:25 +00:00
|
|
|
if (deletedFiles.isNotEmpty || alreadyDeletedIDs.isNotEmpty) {
|
2021-05-03 21:14:44 +00:00
|
|
|
Bus.instance
|
|
|
|
.fire(LocalPhotosUpdatedEvent(deletedFiles, type: EventType.deleted));
|
|
|
|
}
|
|
|
|
await dialog.hide();
|
|
|
|
}
|