delete_file_util.dart 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. import 'dart:async';
  2. import 'package:flutter/widgets.dart';
  3. import 'package:logging/logging.dart';
  4. import 'package:photo_manager/photo_manager.dart';
  5. import 'package:photos/core/event_bus.dart';
  6. import 'package:photos/db/files_db.dart';
  7. import 'package:photos/events/collection_updated_event.dart';
  8. import 'package:photos/events/files_updated_event.dart';
  9. import 'package:photos/events/local_photos_updated_event.dart';
  10. import 'package:photos/models/file.dart';
  11. import 'package:photos/services/remote_sync_service.dart';
  12. import 'package:photos/services/sync_service.dart';
  13. import 'package:photos/utils/dialog_util.dart';
  14. import 'package:photos/utils/toast_util.dart';
  15. final _logger = Logger("DeleteFileUtil");
  16. Future<void> deleteFilesFromEverywhere(
  17. BuildContext context, List<File> files) async {
  18. final dialog = createProgressDialog(context, "deleting...");
  19. await dialog.show();
  20. _logger.info("Trying to delete files " + files.toString());
  21. final List<String> localIDs = [];
  22. final List<String> alreadyDeletedIDs = []; // to ignore already deleted files
  23. for (final file in files) {
  24. if (file.localID != null) {
  25. final asset = await file.getAsset();
  26. if (asset == null || !(await asset.exists)) {
  27. _logger.warning("Already deleted " + file.toString());
  28. alreadyDeletedIDs.add(file.localID);
  29. } else {
  30. localIDs.add(file.localID);
  31. }
  32. }
  33. }
  34. Set<String> deletedIDs = Set<String>();
  35. try {
  36. deletedIDs = (await PhotoManager.editor.deleteWithIds(localIDs)).toSet();
  37. } catch (e, s) {
  38. _logger.severe("Could not delete file", e, s);
  39. }
  40. final updatedCollectionIDs = Set<int>();
  41. final List<int> uploadedFileIDsToBeDeleted = [];
  42. final List<File> deletedFiles = [];
  43. for (final file in files) {
  44. if (file.localID != null) {
  45. // Remove only those files that have already been removed from disk
  46. if (deletedIDs.contains(file.localID) ||
  47. alreadyDeletedIDs.contains(file.localID)) {
  48. deletedFiles.add(file);
  49. if (file.uploadedFileID != null) {
  50. uploadedFileIDsToBeDeleted.add(file.uploadedFileID);
  51. updatedCollectionIDs.add(file.collectionID);
  52. } else {
  53. await FilesDB.instance.deleteLocalFile(file.localID);
  54. }
  55. }
  56. } else {
  57. updatedCollectionIDs.add(file.collectionID);
  58. deletedFiles.add(file);
  59. uploadedFileIDsToBeDeleted.add(file.uploadedFileID);
  60. }
  61. }
  62. if (uploadedFileIDsToBeDeleted.isNotEmpty) {
  63. try {
  64. await SyncService.instance
  65. .deleteFilesOnServer(uploadedFileIDsToBeDeleted);
  66. await FilesDB.instance
  67. .deleteMultipleUploadedFiles(uploadedFileIDsToBeDeleted);
  68. } catch (e) {
  69. _logger.severe(e);
  70. await dialog.hide();
  71. showGenericErrorDialog(context);
  72. throw e;
  73. }
  74. for (final collectionID in updatedCollectionIDs) {
  75. Bus.instance.fire(CollectionUpdatedEvent(
  76. collectionID,
  77. deletedFiles
  78. .where((file) => file.collectionID == collectionID)
  79. .toList(),
  80. type: EventType.deleted,
  81. ));
  82. }
  83. }
  84. if (deletedFiles.isNotEmpty) {
  85. Bus.instance
  86. .fire(LocalPhotosUpdatedEvent(deletedFiles, type: EventType.deleted));
  87. }
  88. await dialog.hide();
  89. showToast("deleted from everywhere");
  90. if (uploadedFileIDsToBeDeleted.isNotEmpty) {
  91. RemoteSyncService.instance.sync(silently: true);
  92. }
  93. }
  94. Future<void> deleteFilesOnDeviceOnly(
  95. BuildContext context, List<File> files) async {
  96. final dialog = createProgressDialog(context, "deleting...");
  97. await dialog.show();
  98. _logger.info("Trying to delete files " + files.toString());
  99. final List<String> localIDs = [];
  100. final List<String> alreadyDeletedIDs = []; // to ignore already deleted files
  101. for (final file in files) {
  102. if (file.localID != null) {
  103. final asset = await file.getAsset();
  104. if (asset == null || !(await asset.exists)) {
  105. _logger.warning("Already deleted " + file.toString());
  106. alreadyDeletedIDs.add(file.localID);
  107. } else {
  108. localIDs.add(file.localID);
  109. }
  110. }
  111. }
  112. Set<String> deletedIDs = Set<String>();
  113. try {
  114. deletedIDs = (await PhotoManager.editor.deleteWithIds(localIDs)).toSet();
  115. } catch (e, s) {
  116. _logger.severe("Could not delete file", e, s);
  117. }
  118. final List<File> deletedFiles = [];
  119. for (final file in files) {
  120. // Remove only those files that have been removed from disk
  121. if (deletedIDs.contains(file.localID) ||
  122. alreadyDeletedIDs.contains(file.localID)) {
  123. deletedFiles.add(file);
  124. file.localID = null;
  125. FilesDB.instance.update(file);
  126. }
  127. }
  128. if (deletedFiles.isNotEmpty || alreadyDeletedIDs.isNotEmpty) {
  129. Bus.instance
  130. .fire(LocalPhotosUpdatedEvent(deletedFiles, type: EventType.deleted));
  131. }
  132. await dialog.hide();
  133. }
  134. Future<void> deleteLocalFiles(List<String> localIDs) async {
  135. List<String> deletedIDs = [];
  136. try {
  137. deletedIDs = await PhotoManager.editor.deleteWithIds(localIDs);
  138. } catch (e, s) {
  139. _logger.severe("Could not delete files", e, s);
  140. }
  141. if (deletedIDs.isNotEmpty) {
  142. final deletedFiles = await FilesDB.instance.getLocalFiles(deletedIDs);
  143. await FilesDB.instance.deleteLocalFiles(deletedIDs);
  144. _logger.info(deletedFiles.length.toString() + " files deleted locally");
  145. Bus.instance
  146. .fire(LocalPhotosUpdatedEvent(deletedFiles, type: EventType.deleted));
  147. }
  148. }