diff --git a/mobile/lib/ui/viewer/file_details/file_info_face_widget.dart b/mobile/lib/ui/viewer/file_details/file_info_face_widget.dart index cf433103d1..eee2b42ccb 100644 --- a/mobile/lib/ui/viewer/file_details/file_info_face_widget.dart +++ b/mobile/lib/ui/viewer/file_details/file_info_face_widget.dart @@ -1,8 +1,6 @@ import "dart:async"; -import "dart:developer" show log; import "dart:typed_data"; -import "package:flutter/cupertino.dart"; import "package:flutter/foundation.dart" show kDebugMode; import "package:flutter/material.dart"; import "package:logging/logging.dart"; @@ -14,7 +12,6 @@ import "package:photos/models/ml/face/face.dart"; import "package:photos/models/ml/face/person.dart"; import "package:photos/services/machine_learning/face_ml/face_detection/detection.dart"; import "package:photos/services/machine_learning/face_ml/face_filtering/face_filtering_constants.dart"; -import "package:photos/services/machine_learning/face_ml/feedback/cluster_feedback.dart"; import "package:photos/services/machine_learning/ml_service.dart"; import "package:photos/services/search_service.dart"; import "package:photos/theme/ente_theme.dart"; @@ -31,7 +28,6 @@ class FileInfoFaceWidget extends StatefulWidget { final PersonEntity? person; final String? clusterID; final bool highlight; - final bool editMode; const FileInfoFaceWidget( this.file, @@ -40,7 +36,6 @@ class FileInfoFaceWidget extends StatefulWidget { this.person, this.clusterID, this.highlight = false, - this.editMode = false, super.key, }); @@ -56,11 +51,6 @@ class _FileInfoFaceWidgetState extends State { @override Widget build(BuildContext context) { final bool givenFaces = widget.faceCrops != null; - return _buildFaceImageGenerated(givenFaces); - } - - Widget _buildFaceImageGenerated(bool givenFaces) { - late final mlDataDB = MLDataDB.instance; return FutureBuilder?>( future: givenFaces ? widget.faceCrops @@ -71,97 +61,7 @@ class _FileInfoFaceWidgetState extends State { MemoryImage(snapshot.data![widget.face.faceID]!); return GestureDetector( - onTap: () async { - if (widget.editMode) return; - - log( - "FaceWidget is tapped, with person ${widget.person?.data.name} and clusterID ${widget.clusterID}", - name: "FaceWidget", - ); - if (widget.person == null && widget.clusterID == null) { - // Double check that it doesn't belong to an existing clusterID. - final existingClusterID = - await mlDataDB.getClusterIDForFaceID(widget.face.faceID); - if (existingClusterID != null) { - final fileIdsToClusterIds = - await mlDataDB.getFileIdToClusterIds(); - final files = - await SearchService.instance.getAllFilesForSearch(); - final clusterFiles = files - .where( - (file) => - fileIdsToClusterIds[file.uploadedFileID] - ?.contains(existingClusterID) ?? - false, - ) - .toList(); - await Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => ClusterPage( - clusterFiles, - clusterID: existingClusterID, - ), - ), - ); - return; - } - if (widget.face.score <= kMinimumQualityFaceScore) { - // The face score is too low for automatic clustering, - // assigning a manual new clusterID so that the user can cluster it manually - final String clusterID = newClusterID(); - await mlDataDB.updateFaceIdToClusterId( - {widget.face.faceID: clusterID}, - ); - await Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => ClusterPage( - [widget.file], - clusterID: clusterID, - ), - ), - ); - return; - } - - showShortToast( - context, - S.of(context).faceNotClusteredYet, - ); - unawaited(MLService.instance.clusterAllImages(force: true)); - return; - } - if (widget.person != null) { - await Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => PeoplePage( - person: widget.person!, - searchResult: null, - ), - ), - ); - } else if (widget.clusterID != null) { - final fileIdsToClusterIds = - await mlDataDB.getFileIdToClusterIds(); - final files = - await SearchService.instance.getAllFilesForSearch(); - final clusterFiles = files - .where( - (file) => - fileIdsToClusterIds[file.uploadedFileID] - ?.contains(widget.clusterID) ?? - false, - ) - .toList(); - await Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => ClusterPage( - clusterFiles, - clusterID: widget.clusterID!, - ), - ), - ); - } - }, + onTap: _onTap, child: Column( children: [ Stack( @@ -195,66 +95,10 @@ class _FileInfoFaceWidgetState extends State { ), ), ), - // TODO: the edges of the green line are still not properly rounded around ClipRRect - if (widget.editMode) - Positioned( - right: 0, - top: 0, - child: GestureDetector( - onTap: _cornerIconPressed, - child: isJustRemoved - ? const Icon( - CupertinoIcons.add_circled_solid, - color: Colors.green, - ) - : const Icon( - Icons.cancel, - color: Colors.red, - ), - ), - ), ], ), const SizedBox(height: 8), - if (widget.person != null) - Text( - widget.person!.data.isIgnored - ? '(' + S.of(context).ignored + ')' - : widget.person!.data.name.trim(), - style: Theme.of(context).textTheme.bodySmall, - overflow: TextOverflow.ellipsis, - maxLines: 1, - ), - if (kDebugMode) - Text( - 'S: ${widget.face.score.toStringAsFixed(3)} (I)', - style: Theme.of(context).textTheme.bodySmall, - maxLines: 1, - ), - if (kDebugMode) - Text( - 'B: ${widget.face.blur.toStringAsFixed(0)} (I)', - style: Theme.of(context).textTheme.bodySmall, - maxLines: 1, - ), - if (kDebugMode) - Text( - 'D: ${widget.face.detection.getFaceDirection().toDirectionString()} (I)', - style: Theme.of(context).textTheme.bodySmall, - maxLines: 1, - ), - if (kDebugMode) - Text( - 'Sideways: ${widget.face.detection.faceIsSideways().toString()} (I)', - style: Theme.of(context).textTheme.bodySmall, - maxLines: 1, - ), - if (kDebugMode && widget.face.score < kMinimumFaceShowScore) - Text( - 'Not visible to user (I)', - style: Theme.of(context).textTheme.bodySmall, - maxLines: 1, - ), + ..._buildFaceInfo(), ], ), ); @@ -287,24 +131,120 @@ class _FileInfoFaceWidgetState extends State { ); } - void _cornerIconPressed() async { - log('face widget (file info) corner icon is pressed'); - try { - if (isJustRemoved) { - await ClusterFeedbackService.instance - .addFacesToCluster([widget.face.faceID], widget.clusterID!); - } else { - await ClusterFeedbackService.instance - .removeFilesFromCluster([widget.file], widget.clusterID!); - } - - setState(() { - isJustRemoved = !isJustRemoved; - }); - } catch (e, s) { - _logger.severe( - "removing face/file from cluster from file info widget failed: $e, \n $s", + List _buildFaceInfo() { + final List faceInfo = []; + if (widget.person != null) { + faceInfo.add( + Text( + widget.person!.data.isIgnored + ? '(' + S.of(context).ignored + ')' + : widget.person!.data.name.trim(), + style: Theme.of(context).textTheme.bodySmall, + overflow: TextOverflow.ellipsis, + maxLines: 1, + ), ); } + if (kDebugMode) { + faceInfo.add( + Text( + 'S: ${widget.face.score.toStringAsFixed(3)} (I)', + style: Theme.of(context).textTheme.bodySmall, + maxLines: 1, + ), + ); + faceInfo.add( + Text( + 'B: ${widget.face.blur.toStringAsFixed(0)} (I)', + style: Theme.of(context).textTheme.bodySmall, + maxLines: 1, + ), + ); + faceInfo.add( + Text( + 'D: ${widget.face.detection.getFaceDirection().toDirectionString()} (I)', + style: Theme.of(context).textTheme.bodySmall, + maxLines: 1, + ), + ); + faceInfo.add( + Text( + 'Sideways: ${widget.face.detection.faceIsSideways().toString()} (I)', + style: Theme.of(context).textTheme.bodySmall, + maxLines: 1, + ), + ); + if (widget.face.score < kMinimumFaceShowScore) { + faceInfo.add( + Text( + 'Not visible to user (I)', + style: Theme.of(context).textTheme.bodySmall, + maxLines: 1, + ), + ); + } + } + return faceInfo; + } + + Future _onTap() async { + final mlDataDB = MLDataDB.instance; + if (widget.person != null) { + await Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => PeoplePage( + person: widget.person!, + searchResult: null, + ), + ), + ); + return; + } + final String? clusterID = widget.clusterID ?? + await mlDataDB.getClusterIDForFaceID(widget.face.faceID); + if (clusterID != null) { + final fileIdsToClusterIds = await mlDataDB.getFileIdToClusterIds(); + final files = await SearchService.instance.getAllFilesForSearch(); + final clusterFiles = files + .where( + (file) => + fileIdsToClusterIds[file.uploadedFileID]?.contains(clusterID) ?? + false, + ) + .toList(); + await Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => ClusterPage( + clusterFiles, + clusterID: clusterID, + ), + ), + ); + return; + } + if (widget.face.score <= kMinimumQualityFaceScore) { + // The face score is too low for automatic clustering, + // assigning a manual new clusterID so that the user can cluster it manually + final String clusterID = newClusterID(); + await mlDataDB.updateFaceIdToClusterId( + {widget.face.faceID: clusterID}, + ); + await Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => ClusterPage( + [widget.file], + clusterID: clusterID, + ), + ), + ); + return; + } + + showShortToast( + context, + S.of(context).faceNotClusteredYet, + ); + unawaited(MLService.instance.clusterAllImages(force: true)); + return; } } diff --git a/mobile/lib/ui/viewer/file_details/file_info_faces_item_widget.dart b/mobile/lib/ui/viewer/file_details/file_info_faces_item_widget.dart index a693620d12..bdbcc49656 100644 --- a/mobile/lib/ui/viewer/file_details/file_info_faces_item_widget.dart +++ b/mobile/lib/ui/viewer/file_details/file_info_faces_item_widget.dart @@ -25,8 +25,6 @@ class FacesItemWidget extends StatefulWidget { } class _FacesItemWidgetState extends State { - bool editMode = false; - @override void initState() { super.initState(); @@ -38,18 +36,14 @@ class _FacesItemWidgetState extends State { return InfoItemWidget( key: const ValueKey("Faces"), leadingIcon: Icons.face_retouching_natural_outlined, - subtitleSection: _faceWidgets(context, widget.file, editMode), + subtitleSection: _faceWidgets(context, widget.file), hasChipButtons: true, biggerSpinner: true, ); } - Future> _faceWidgets( - BuildContext context, - EnteFile file, - bool editMode, - ) async { - late final mlDataDB = MLDataDB.instance; + Future> _faceWidgets(BuildContext context, EnteFile file) async { + final mlDataDB = MLDataDB.instance; try { if (file.uploadedFileID == null) { return [const NoFaceChipButtonWidget(NoFacesReason.fileNotUploaded)]; @@ -151,7 +145,6 @@ class _FacesItemWidgetState extends State { clusterID: clusterID, person: person, highlight: highlight, - editMode: highlight ? editMode : false, ), ); }