[mob][photos] Deletion fixes (#5792)

## Description

- Fix issue where user is not able to delete own files in a shared album
- Fix issue where deletion of not yet uploaded files leads to showing
grey boxes in gallery

## Tests

Tested in debug mode on my pixel phone.
This commit is contained in:
Laurens Priem
2025-05-05 11:46:03 +05:30
committed by GitHub
5 changed files with 50 additions and 6 deletions

View File

@@ -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;
}

View File

@@ -388,6 +388,16 @@ class CollectionsService {
.toList();
}
List<int> 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<Collection> outgoing = [];
final List<Collection> incoming = [];

View File

@@ -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<void> trashFilesOnServer(List<TrashRequest> trashRequestItems) async {
final includedFileIDs = <int>{};
final uniqueItems = <TrashRequest>[];
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 = <String, dynamic>{};

View File

@@ -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,
),
);
}

View File

@@ -201,6 +201,7 @@ Future<void> deleteFilesOnDeviceOnly(
final List<String> localAssetIDs = [];
final List<String> localSharedMediaIDs = [];
final List<String> alreadyDeletedIDs = []; // to ignore already deleted files
final List<String?> localOnlyIDs = [];
bool hasLocalOnlyFiles = false;
for (final file in files) {
if (file.localID != null) {
@@ -215,6 +216,7 @@ Future<void> deleteFilesOnDeviceOnly(
}
if (file.uploadedFileID == null) {
hasLocalOnlyFiles = true;
localOnlyIDs.add(file.localID);
}
}
if (hasLocalOnlyFiles && Platform.isAndroid) {
@@ -237,8 +239,12 @@ Future<void> 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) {