diff --git a/mobile/lib/models/gallery_type.dart b/mobile/lib/models/gallery_type.dart index 82e5650b09..a128757afe 100644 --- a/mobile/lib/models/gallery_type.dart +++ b/mobile/lib/models/gallery_type.dart @@ -104,6 +104,7 @@ extension GalleyTypeExtension on GalleryType { bool showDeleteOption() { switch (this) { case GalleryType.ownedCollection: + case GalleryType.sharedCollection: case GalleryType.searchResults: case GalleryType.homepage: case GalleryType.favorite: @@ -119,7 +120,6 @@ extension GalleyTypeExtension on GalleryType { case GalleryType.magic: return true; case GalleryType.trash: - case GalleryType.sharedCollection: case GalleryType.sharedPublicCollection: return false; } diff --git a/mobile/lib/services/collections_service.dart b/mobile/lib/services/collections_service.dart index 3f00218e32..301655490a 100644 --- a/mobile/lib/services/collections_service.dart +++ b/mobile/lib/services/collections_service.dart @@ -388,6 +388,16 @@ class CollectionsService { .toList(); } + List getAllOwnedCollectionIDs() { + final int userID = _config.getUserID()!; + return _collectionIDToCollections.values + .where( + (c) => !c.isDeleted && c.isOwner(userID), + ) + .map((e) => e.id) + .toList(); + } + SharedCollections getSharedCollections() { final List outgoing = []; final List incoming = []; diff --git a/mobile/lib/services/sync/trash_sync_service.dart b/mobile/lib/services/sync/trash_sync_service.dart index 53c94f16c7..b3cf1db6a9 100644 --- a/mobile/lib/services/sync/trash_sync_service.dart +++ b/mobile/lib/services/sync/trash_sync_service.dart @@ -7,6 +7,7 @@ import "package:ente_crypto/ente_crypto.dart"; import 'package:logging/logging.dart'; import 'package:photos/core/constants.dart'; import 'package:photos/core/event_bus.dart'; +import "package:photos/db/files_db.dart"; import 'package:photos/db/trash_db.dart'; import 'package:photos/events/collection_updated_event.dart'; import 'package:photos/events/force_reload_trash_page_event.dart'; @@ -17,6 +18,7 @@ import 'package:photos/models/file/file.dart'; import 'package:photos/models/file/trash_file.dart'; import 'package:photos/models/ignored_file.dart'; import "package:photos/models/metadata/file_magic.dart"; +import "package:photos/services/collections_service.dart"; import 'package:photos/services/ignored_files_service.dart'; import "package:photos/utils/file_key.dart"; import 'package:shared_preferences/shared_preferences.dart'; @@ -108,10 +110,34 @@ class TrashSyncService { Future trashFilesOnServer(List trashRequestItems) async { final includedFileIDs = {}; final uniqueItems = []; + final ownedCollectionIDs = + CollectionsService.instance.getAllOwnedCollectionIDs(); for (final item in trashRequestItems) { if (!includedFileIDs.contains(item.fileID)) { - uniqueItems.add(item); - includedFileIDs.add(item.fileID); + // Check if the collectionID in the request is owned by the user + if (ownedCollectionIDs.contains(item.collectionID)) { + uniqueItems.add(item); + includedFileIDs.add(item.fileID); + } else { + // If not owned, use a different owned collectionID + final fileCollectionIDs = + await FilesDB.instance.getAllCollectionIDsOfFile(item.fileID); + bool foundAnotherOwnedCollection = false; + for (final collectionID in fileCollectionIDs) { + if (ownedCollectionIDs.contains(collectionID)) { + final newItem = TrashRequest(item.fileID, collectionID); + uniqueItems.add(newItem); + includedFileIDs.add(item.fileID); + foundAnotherOwnedCollection = true; + break; + } + } + if (!foundAnotherOwnedCollection) { + _logger.severe( + "File ${item.fileID} is not owned by the user and has no other owned collection", + ); + } + } } } final requestData = {}; diff --git a/mobile/lib/ui/viewer/actions/file_selection_actions_widget.dart b/mobile/lib/ui/viewer/actions/file_selection_actions_widget.dart index 02ca790c66..5f59aa73cd 100644 --- a/mobile/lib/ui/viewer/actions/file_selection_actions_widget.dart +++ b/mobile/lib/ui/viewer/actions/file_selection_actions_widget.dart @@ -134,6 +134,8 @@ class _FileSelectionActionsWidgetState final bool anyOwnedFiles = split.pendingUploads.isNotEmpty || split.ownedByCurrentUser.isNotEmpty; + final bool allOwnedFiles = + ownedAndPendingUploadFilesCount > 0 && split.ownedByOtherUsers.isEmpty; final bool anyUploadedFiles = split.ownedByCurrentUser.isNotEmpty; final showCollageOption = CollageCreatorPage.isValidCount( @@ -259,7 +261,7 @@ class _FileSelectionActionsWidgetState icon: Icons.delete_outline, labelText: S.of(context).delete, onTap: anyOwnedFiles ? _onDeleteClick : null, - shouldShow: ownedAndPendingUploadFilesCount > 0, + shouldShow: allOwnedFiles, ), ); } diff --git a/mobile/lib/utils/delete_file_util.dart b/mobile/lib/utils/delete_file_util.dart index ed1eb28d6c..11a425afa0 100644 --- a/mobile/lib/utils/delete_file_util.dart +++ b/mobile/lib/utils/delete_file_util.dart @@ -201,6 +201,7 @@ Future deleteFilesOnDeviceOnly( final List localAssetIDs = []; final List localSharedMediaIDs = []; final List alreadyDeletedIDs = []; // to ignore already deleted files + final List localOnlyIDs = []; bool hasLocalOnlyFiles = false; for (final file in files) { if (file.localID != null) { @@ -215,6 +216,7 @@ Future deleteFilesOnDeviceOnly( } if (file.uploadedFileID == null) { hasLocalOnlyFiles = true; + localOnlyIDs.add(file.localID); } } if (hasLocalOnlyFiles && Platform.isAndroid) { @@ -237,8 +239,12 @@ Future deleteFilesOnDeviceOnly( if (deletedIDs.contains(file.localID) || alreadyDeletedIDs.contains(file.localID)) { deletedFiles.add(file); - file.localID = null; - await FilesDB.instance.update(file); + if (hasLocalOnlyFiles && localOnlyIDs.contains(file.localID)) { + await FilesDB.instance.deleteLocalFile(file); + } else { + file.localID = null; + await FilesDB.instance.update(file); + } } } if (deletedFiles.isNotEmpty || alreadyDeletedIDs.isNotEmpty) {