diff --git a/mobile/lib/face/db.dart b/mobile/lib/face/db.dart index 601c15679..6477cb833 100644 --- a/mobile/lib/face/db.dart +++ b/mobile/lib/face/db.dart @@ -695,7 +695,7 @@ class FaceMLDataDB { await db.execute(createNotPersonFeedbackTable); } - Future removePersonFromFiles(List files, Person p) async { + Future removeFilesFromPerson(List files, Person p) async { final db = await instance.database; final result = await db.rawQuery( 'SELECT $faceIDColumn FROM $facesTable LEFT JOIN $clustersTable ' @@ -715,4 +715,24 @@ class FaceMLDataDB { } await forceUpdateClusterIds(faceIDToClusterID); } + + Future removeFilesFromCluster( + List files, + int clusterID, + ) async { + final db = await instance.database; + final result = await db.rawQuery( + 'SELECT $faceIDColumn FROM $facesTable ' + 'WHERE $facesTable.$faceClusterId = ? AND $facesTable.$fileIDColumn IN (${files.map((e) => e.uploadedFileID).join(",")})', + [clusterID], + ); + final Map faceIDToClusterID = {}; + int maxClusterID = DateTime.now().millisecondsSinceEpoch; + for (final faceRow in result) { + maxClusterID += 1; + final faceID = faceRow[faceIDColumn] as String; + faceIDToClusterID[faceID] = maxClusterID; + } + await forceUpdateClusterIds(faceIDToClusterID); + } } diff --git a/mobile/lib/services/machine_learning/face_ml/feedback/cluster_feedback.dart b/mobile/lib/services/machine_learning/face_ml/feedback/cluster_feedback.dart index e762058da..7d445d1a1 100644 --- a/mobile/lib/services/machine_learning/face_ml/feedback/cluster_feedback.dart +++ b/mobile/lib/services/machine_learning/face_ml/feedback/cluster_feedback.dart @@ -305,8 +305,12 @@ class ClusterFeedbackService { } } - Future removePersonFromFiles(List files, Person p) { - return FaceMLDataDB.instance.removePersonFromFiles(files, p); + Future removeFilesFromPerson(List files, Person p) { + return FaceMLDataDB.instance.removeFilesFromPerson(files, p); + } + + Future removeFilesFromCluster(List files, int clusterID) { + return FaceMLDataDB.instance.removeFilesFromCluster(files, clusterID); } Future checkAndDoAutomaticMerges(Person p) async { 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 a87cca795..869c8c317 100644 --- a/mobile/lib/ui/viewer/actions/file_selection_actions_widget.dart +++ b/mobile/lib/ui/viewer/actions/file_selection_actions_widget.dart @@ -401,12 +401,13 @@ class _FileSelectionActionsWidgetState ), ); + // if (widget.type == GalleryType.cluster && widget.clusterID != null) { if (widget.type == GalleryType.cluster) { items.add( SelectionActionButton( labelText: 'Remove', icon: CupertinoIcons.minus, - onTap: () => showToast(context, 'yet to implement'), + onTap: anyUploadedFiles ? _onRemoveFromClusterClicked : null, ), ); } @@ -690,7 +691,7 @@ class _FileSelectionActionsWidgetState ); if (actionResult?.action != null) { if (actionResult!.action == ButtonAction.first) { - await ClusterFeedbackService.instance.removePersonFromFiles( + await ClusterFeedbackService.instance.removeFilesFromPerson( widget.selectedFiles.files.toList(), widget.person!, ); @@ -703,6 +704,49 @@ class _FileSelectionActionsWidgetState } } + Future _onRemoveFromClusterClicked() async { + if (widget.clusterID == null) { + showShortToast(context, 'Cluster ID is null. Cannot remove files.'); + return; + } + final actionResult = await showActionSheet( + context: context, + buttons: [ + ButtonWidget( + labelText: S.of(context).yesRemove, + buttonType: ButtonType.neutral, + buttonSize: ButtonSize.large, + shouldStickToDarkTheme: true, + buttonAction: ButtonAction.first, + isInAlert: true, + ), + ButtonWidget( + labelText: S.of(context).cancel, + buttonType: ButtonType.secondary, + buttonSize: ButtonSize.large, + buttonAction: ButtonAction.second, + shouldStickToDarkTheme: true, + isInAlert: true, + ), + ], + title: "Remove these photos?", + actionSheetType: ActionSheetType.defaultActionSheet, + ); + if (actionResult?.action != null) { + if (actionResult!.action == ButtonAction.first) { + await ClusterFeedbackService.instance.removeFilesFromCluster( + widget.selectedFiles.files.toList(), + widget.clusterID!, + ); + } + Bus.instance.fire(PeopleChangedEvent()); + } + widget.selectedFiles.clearAll(); + if (mounted) { + setState(() => {}); + } + } + Future _copyLink() async { if (_cachedCollectionForSharedLink != null) { final String collectionKey = Base58Encode(