diff --git a/mobile/apps/photos/lib/ui/tools/similar_images_page.dart b/mobile/apps/photos/lib/ui/tools/similar_images_page.dart index f5a6896c96..89d50f6a2d 100644 --- a/mobile/apps/photos/lib/ui/tools/similar_images_page.dart +++ b/mobile/apps/photos/lib/ui/tools/similar_images_page.dart @@ -9,6 +9,7 @@ import "package:photos/models/file/file.dart"; import "package:photos/models/selected_files.dart"; import "package:photos/models/similar_files.dart"; import "package:photos/service_locator.dart"; +import "package:photos/services/collections_service.dart"; import "package:photos/services/machine_learning/similar_images_service.dart"; import 'package:photos/theme/ente_theme.dart'; import "package:photos/ui/common/loading_widget.dart"; @@ -707,7 +708,7 @@ class _SimilarImagesPageState extends State { isCritical: true, firstButtonOnTap: () async { try { - await _deleteFilesLogic(filesToDelete); + await _deleteFilesLogic(filesToDelete, true); } catch (e, s) { _logger.severe("Failed to delete files", e, s); if (flagService.internalUser) { @@ -717,29 +718,70 @@ class _SimilarImagesPageState extends State { }, ); } else { - await _deleteFilesLogic(filesToDelete); + await _deleteFilesLogic(filesToDelete, true); } } - Future _deleteFilesLogic(Set filesToDelete) async { - _selectedFiles.unSelectAll(filesToDelete); + Future _deleteFilesLogic( + Set filesToDelete, + bool createSymlink, + ) async { + if (filesToDelete.isEmpty) { + return; + } + final Map> collectionToFilesToAddMap = {}; + final allDeleteFiles = {}; final groupsToRemove = {}; - for (final file in filesToDelete) { - for (final similarGroup in _similarFilesList) { + for (final similarGroup in _similarFilesList) { + final groupDeleteFiles = {}; + for (final file in filesToDelete) { if (similarGroup.containsFile(file)) { similarGroup.removeFile(file); + groupDeleteFiles.add(file); + allDeleteFiles.add(file); if (similarGroup.isEmpty) { - groupsToRemove.add(similarGroup); + break; } } } + if (similarGroup.files.length <= 1) { + groupsToRemove.add(similarGroup); + } + if (groupDeleteFiles.isNotEmpty) { + filesToDelete.removeAll(groupDeleteFiles); + } + if (!similarGroup.isEmpty && createSymlink) { + final filesToKeep = similarGroup.files; + final collectionIDs = + filesToKeep.map((file) => file.collectionID).toSet(); + for (final deletedFile in groupDeleteFiles) { + final collectionID = deletedFile.collectionID; + if (collectionIDs.contains(collectionID) || collectionID == null) { + continue; + } + if (!collectionToFilesToAddMap.containsKey(collectionID)) { + collectionToFilesToAddMap[collectionID] = []; + } + collectionToFilesToAddMap[collectionID]!.addAll(filesToKeep); + } + } } for (final group in groupsToRemove) { _similarFilesList.remove(group); } + if (createSymlink) { + for (final collectionID in collectionToFilesToAddMap.keys) { + await CollectionsService.instance.addSilentlyToCollection( + collectionID, + collectionToFilesToAddMap[collectionID]!, + ); + } + } + + _selectedFiles.unSelectAll(allDeleteFiles); setState(() {}); - await deleteFilesFromRemoteOnly(context, filesToDelete.toList()); + await deleteFilesFromRemoteOnly(context, allDeleteFiles.toList()); } Widget _getSmallSelectButton(bool unselectAll, void Function() onTap) {