From d7e7aaa26f08320fe4f559a870b8af90eec2ecc5 Mon Sep 17 00:00:00 2001 From: laurenspriem Date: Fri, 17 May 2024 10:32:37 +0530 Subject: [PATCH] [mob][photos] Small refactor --- .../ui/viewer/file_details/face_widget.dart | 457 +++++++++--------- 1 file changed, 226 insertions(+), 231 deletions(-) diff --git a/mobile/lib/ui/viewer/file_details/face_widget.dart b/mobile/lib/ui/viewer/file_details/face_widget.dart index bde4548b8a..2fcc39de96 100644 --- a/mobile/lib/ui/viewer/file_details/face_widget.dart +++ b/mobile/lib/ui/viewer/file_details/face_widget.dart @@ -54,233 +54,24 @@ class _FaceWidgetState extends State { Widget build(BuildContext context) { final bool givenFaces = widget.faceCrops != null; if (useGeneratedFaceCrops) { - return FutureBuilder?>( - future: givenFaces ? widget.faceCrops : getFaceCrop(), - builder: (context, snapshot) { - if (snapshot.hasData) { - final ImageProvider imageProvider = - MemoryImage(snapshot.data![widget.face.faceID]!); - - return GestureDetector( - onTap: () async { - if (widget.editMode) return; - - log( - "FaceWidget is tapped, with person ${widget.person} and clusterID ${widget.clusterID}", - name: "FaceWidget", - ); - if (widget.person == null && widget.clusterID == null) { - // Get faceID and double check that it doesn't belong to an existing clusterID. If it does, push that cluster page - final w = (kDebugMode ? EnteWatch('FaceWidget') : null) - ?..start(); - final existingClusterID = await FaceMLDataDB.instance - .getClusterIDForFaceID(widget.face.faceID); - w?.log('getting existing clusterID for faceID'); - if (existingClusterID != null) { - final fileIdsToClusterIds = - await FaceMLDataDB.instance.getFileIdToClusterIds(); - final files = await SearchService.instance.getAllFiles(); - final clusterFiles = files - .where( - (file) => - fileIdsToClusterIds[file.uploadedFileID] - ?.contains(existingClusterID) ?? - false, - ) - .toList(); - await Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => ClusterPage( - clusterFiles, - clusterID: existingClusterID, - ), - ), - ); - } - - // Create new clusterID for the faceID and update DB to assign the faceID to the new clusterID - final int newClusterID = - DateTime.now().microsecondsSinceEpoch; - await FaceMLDataDB.instance.updateFaceIdToClusterId( - {widget.face.faceID: newClusterID}, - ); - - // Push page for the new cluster - await Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => ClusterPage( - [widget.file], - clusterID: newClusterID, - ), - ), - ); - } - if (widget.person != null) { - await Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => PeoplePage( - person: widget.person!, - ), - ), - ); - } else if (widget.clusterID != null) { - final fileIdsToClusterIds = - await FaceMLDataDB.instance.getFileIdToClusterIds(); - final files = await SearchService.instance.getAllFiles(); - 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!, - ), - ), - ); - } - }, - child: Column( - children: [ - Stack( - children: [ - Container( - height: 60, - width: 60, - decoration: ShapeDecoration( - shape: RoundedRectangleBorder( - borderRadius: const BorderRadius.all( - Radius.elliptical(16, 12), - ), - side: widget.highlight - ? BorderSide( - color: - getEnteColorScheme(context).primary700, - width: 1.0, - ) - : BorderSide.none, - ), - ), - child: ClipRRect( - borderRadius: - const BorderRadius.all(Radius.elliptical(16, 12)), - child: SizedBox( - width: 60, - height: 60, - child: Image( - image: imageProvider, - fit: BoxFit.cover, - ), - ), - ), - ), - // 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 - ? '(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)}', - style: Theme.of(context).textTheme.bodySmall, - maxLines: 1, - ), - if (kDebugMode) - Text( - 'B: ${widget.face.blur.toStringAsFixed(0)}', - style: Theme.of(context).textTheme.bodySmall, - maxLines: 1, - ), - if (kDebugMode) - Text( - 'D: ${widget.face.detection.getFaceDirection().toDirectionString()}', - style: Theme.of(context).textTheme.bodySmall, - maxLines: 1, - ), - if (kDebugMode) - Text( - 'Sideways: ${widget.face.detection.faceIsSideways().toString()}', - style: Theme.of(context).textTheme.bodySmall, - maxLines: 1, - ), - if (kDebugMode && widget.face.score < 0.75) - Text( - '[Debug only]', - style: Theme.of(context).textTheme.bodySmall, - maxLines: 1, - ), - // if (kDebugMode) - // if (highlight) - // const Text( - // "Highlighted", - // style: TextStyle( - // color: Colors.red, - // fontSize: 12, - // ), - // ), - ], - ), - ); - } else { - if (snapshot.connectionState == ConnectionState.waiting) { - return const ClipRRect( - borderRadius: BorderRadius.all(Radius.elliptical(16, 12)), - child: SizedBox( - width: 60, // Ensure consistent sizing - height: 60, - child: CircularProgressIndicator(), - ), - ); - } - if (snapshot.hasError) { - log('Error getting face: ${snapshot.error}'); - } - return const ClipRRect( - borderRadius: BorderRadius.all(Radius.elliptical(16, 12)), - child: SizedBox( - width: 60, // Ensure consistent sizing - height: 60, - child: NoThumbnailWidget(), - ), - ); - } - }, - ); + return _buildFaceImageGenerated(givenFaces); } else { - return Builder( - builder: (context) { + return _buildFaceImageFlutterZoom(); + } + } + + Widget _buildFaceImageGenerated(bool givenFaces) { + return FutureBuilder?>( + future: givenFaces ? widget.faceCrops : getFaceCrop(), + builder: (context, snapshot) { + if (snapshot.hasData) { + final ImageProvider imageProvider = + MemoryImage(snapshot.data![widget.face.faceID]!); + return GestureDetector( onTap: () async { + if (widget.editMode) return; + log( "FaceWidget is tapped, with person ${widget.person} and clusterID ${widget.clusterID}", name: "FaceWidget", @@ -386,9 +177,9 @@ class _FaceWidgetState extends State { child: SizedBox( width: 60, height: 60, - child: CroppedFaceImageView( - enteFile: widget.file, - face: widget.face, + child: Image( + image: imageProvider, + fit: BoxFit.cover, ), ), ), @@ -416,7 +207,9 @@ class _FaceWidgetState extends State { const SizedBox(height: 8), if (widget.person != null) Text( - widget.person!.data.name.trim(), + widget.person!.data.isIgnored + ? '(ignored)' + : widget.person!.data.name.trim(), style: Theme.of(context).textTheme.bodySmall, overflow: TextOverflow.ellipsis, maxLines: 1, @@ -445,12 +238,40 @@ class _FaceWidgetState extends State { style: Theme.of(context).textTheme.bodySmall, maxLines: 1, ), + if (kDebugMode && widget.face.score < 0.75) + Text( + '[Debug only]', + style: Theme.of(context).textTheme.bodySmall, + maxLines: 1, + ), ], ), ); - }, - ); - } + } else { + if (snapshot.connectionState == ConnectionState.waiting) { + return const ClipRRect( + borderRadius: BorderRadius.all(Radius.elliptical(16, 12)), + child: SizedBox( + width: 60, + height: 60, + child: CircularProgressIndicator(), + ), + ); + } + if (snapshot.hasError) { + log('Error getting face: ${snapshot.error}'); + } + return const ClipRRect( + borderRadius: BorderRadius.all(Radius.elliptical(16, 12)), + child: SizedBox( + width: 60, + height: 60, + child: NoThumbnailWidget(), + ), + ); + } + }, + ); } void _cornerIconPressed() async { @@ -508,4 +329,178 @@ class _FaceWidgetState extends State { return null; } } + + Widget _buildFaceImageFlutterZoom() { + return Builder( + builder: (context) { + return GestureDetector( + onTap: () async { + log( + "FaceWidget is tapped, with person ${widget.person} and clusterID ${widget.clusterID}", + name: "FaceWidget", + ); + if (widget.person == null && widget.clusterID == null) { + // Get faceID and double check that it doesn't belong to an existing clusterID. If it does, push that cluster page + final w = (kDebugMode ? EnteWatch('FaceWidget') : null)?..start(); + final existingClusterID = await FaceMLDataDB.instance + .getClusterIDForFaceID(widget.face.faceID); + w?.log('getting existing clusterID for faceID'); + if (existingClusterID != null) { + final fileIdsToClusterIds = + await FaceMLDataDB.instance.getFileIdToClusterIds(); + final files = await SearchService.instance.getAllFiles(); + final clusterFiles = files + .where( + (file) => + fileIdsToClusterIds[file.uploadedFileID] + ?.contains(existingClusterID) ?? + false, + ) + .toList(); + await Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => ClusterPage( + clusterFiles, + clusterID: existingClusterID, + ), + ), + ); + } + + // Create new clusterID for the faceID and update DB to assign the faceID to the new clusterID + final int newClusterID = DateTime.now().microsecondsSinceEpoch; + await FaceMLDataDB.instance.updateFaceIdToClusterId( + {widget.face.faceID: newClusterID}, + ); + + // Push page for the new cluster + await Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => ClusterPage( + [widget.file], + clusterID: newClusterID, + ), + ), + ); + } + if (widget.person != null) { + await Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => PeoplePage( + person: widget.person!, + ), + ), + ); + } else if (widget.clusterID != null) { + final fileIdsToClusterIds = + await FaceMLDataDB.instance.getFileIdToClusterIds(); + final files = await SearchService.instance.getAllFiles(); + 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!, + ), + ), + ); + } + }, + child: Column( + children: [ + Stack( + children: [ + Container( + height: 60, + width: 60, + decoration: ShapeDecoration( + shape: RoundedRectangleBorder( + borderRadius: const BorderRadius.all( + Radius.elliptical(16, 12), + ), + side: widget.highlight + ? BorderSide( + color: getEnteColorScheme(context).primary700, + width: 1.0, + ) + : BorderSide.none, + ), + ), + child: ClipRRect( + borderRadius: + const BorderRadius.all(Radius.elliptical(16, 12)), + child: SizedBox( + width: 60, + height: 60, + child: CroppedFaceImageView( + enteFile: widget.file, + face: widget.face, + ), + ), + ), + ), + 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.name.trim(), + style: Theme.of(context).textTheme.bodySmall, + overflow: TextOverflow.ellipsis, + maxLines: 1, + ), + if (kDebugMode) + Text( + 'S: ${widget.face.score.toStringAsFixed(3)}', + style: Theme.of(context).textTheme.bodySmall, + maxLines: 1, + ), + if (kDebugMode) + Text( + 'B: ${widget.face.blur.toStringAsFixed(0)}', + style: Theme.of(context).textTheme.bodySmall, + maxLines: 1, + ), + if (kDebugMode) + Text( + 'D: ${widget.face.detection.getFaceDirection().toDirectionString()}', + style: Theme.of(context).textTheme.bodySmall, + maxLines: 1, + ), + if (kDebugMode) + Text( + 'Sideways: ${widget.face.detection.faceIsSideways().toString()}', + style: Theme.of(context).textTheme.bodySmall, + maxLines: 1, + ), + ], + ), + ); + }, + ); + } }