Highlight relevant face
This commit is contained in:
@@ -36,6 +36,14 @@ class ClusterFeedbackService {
|
||||
static final ClusterFeedbackService instance =
|
||||
ClusterFeedbackService._privateConstructor();
|
||||
|
||||
static int lastViewedClusterID = -1;
|
||||
static setLastViewedClusterID(int clusterID) {
|
||||
lastViewedClusterID = clusterID;
|
||||
}
|
||||
static resetLastViewedClusterID() {
|
||||
lastViewedClusterID = -1;
|
||||
}
|
||||
|
||||
/// Returns a map of person's clusterID to map of closest clusterID to with disstance
|
||||
Future<Map<int, List<(int, double)>>> getSuggestionsUsingMean(
|
||||
Person p, {
|
||||
|
||||
@@ -835,7 +835,7 @@ class SearchService {
|
||||
ClusterPage(
|
||||
files,
|
||||
tagPrefix: "${ResultType.faces.toString()}_$clusterName",
|
||||
cluserID: clusterId,
|
||||
clusterID: clusterId,
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
@@ -9,6 +9,7 @@ import "package:photos/face/model/face.dart";
|
||||
import "package:photos/face/model/person.dart";
|
||||
import 'package:photos/models/file/file.dart';
|
||||
import "package:photos/services/search_service.dart";
|
||||
import "package:photos/theme/ente_theme.dart";
|
||||
import "package:photos/ui/viewer/file/no_thumbnail_widget.dart";
|
||||
import "package:photos/ui/viewer/people/cluster_page.dart";
|
||||
import "package:photos/ui/viewer/people/cropped_face_image_view.dart";
|
||||
@@ -21,18 +22,20 @@ class FaceWidget extends StatelessWidget {
|
||||
final Face face;
|
||||
final Person? person;
|
||||
final int? clusterID;
|
||||
final bool highlight;
|
||||
|
||||
const FaceWidget(
|
||||
this.file,
|
||||
this.face, {
|
||||
this.person,
|
||||
this.clusterID,
|
||||
this.highlight = false,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (Platform.isIOS) {
|
||||
if (Platform.isIOS || Platform.isAndroid) {
|
||||
return FutureBuilder<Uint8List?>(
|
||||
future: getFaceCrop(),
|
||||
builder: (context, snapshot) {
|
||||
@@ -71,7 +74,7 @@ class FaceWidget extends StatelessWidget {
|
||||
MaterialPageRoute(
|
||||
builder: (context) => ClusterPage(
|
||||
clusterFiles,
|
||||
cluserID: clusterID!,
|
||||
clusterID: clusterID!,
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -79,15 +82,32 @@ class FaceWidget extends StatelessWidget {
|
||||
},
|
||||
child: Column(
|
||||
children: [
|
||||
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
|
||||
Container(
|
||||
height: 60,
|
||||
width: 60,
|
||||
decoration: ShapeDecoration(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius:
|
||||
const BorderRadius.all(Radius.elliptical(16, 12)),
|
||||
side: highlight
|
||||
? BorderSide(
|
||||
color: getEnteColorScheme(context).primary700,
|
||||
width: 2.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,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -105,6 +125,15 @@ class FaceWidget extends StatelessWidget {
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
maxLines: 1,
|
||||
),
|
||||
// if (kDebugMode)
|
||||
// if (highlight)
|
||||
// const Text(
|
||||
// "Highlighted",
|
||||
// style: TextStyle(
|
||||
// color: Colors.red,
|
||||
// fontSize: 12,
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -169,7 +198,7 @@ class FaceWidget extends StatelessWidget {
|
||||
MaterialPageRoute(
|
||||
builder: (context) => ClusterPage(
|
||||
clusterFiles,
|
||||
cluserID: clusterID!,
|
||||
clusterID: clusterID!,
|
||||
),
|
||||
),
|
||||
);
|
||||
@@ -177,15 +206,31 @@ class FaceWidget extends StatelessWidget {
|
||||
},
|
||||
child: Column(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius:
|
||||
const BorderRadius.all(Radius.elliptical(16, 12)),
|
||||
child: SizedBox(
|
||||
width: 60,
|
||||
height: 60,
|
||||
child: CroppedFaceImageView(
|
||||
enteFile: file,
|
||||
face: face,
|
||||
Container(
|
||||
height: 60,
|
||||
width: 60,
|
||||
decoration: ShapeDecoration(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius:
|
||||
const BorderRadius.all(Radius.elliptical(16, 12)),
|
||||
side: highlight
|
||||
? BorderSide(
|
||||
color: getEnteColorScheme(context).primary700,
|
||||
width: 2.0,
|
||||
)
|
||||
: BorderSide.none,
|
||||
),
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius:
|
||||
const BorderRadius.all(Radius.elliptical(16, 12)),
|
||||
child: SizedBox(
|
||||
width: 60,
|
||||
height: 60,
|
||||
child: CroppedFaceImageView(
|
||||
enteFile: file,
|
||||
face: face,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -4,6 +4,7 @@ import "package:photos/face/db.dart";
|
||||
import "package:photos/face/model/face.dart";
|
||||
import "package:photos/face/model/person.dart";
|
||||
import "package:photos/models/file/file.dart";
|
||||
import "package:photos/services/machine_learning/face_ml/feedback/cluster_feedback.dart";
|
||||
import "package:photos/ui/components/buttons/chip_button_widget.dart";
|
||||
import "package:photos/ui/components/info_item_widget.dart";
|
||||
import "package:photos/ui/viewer/file_details/face_widget.dart";
|
||||
@@ -68,16 +69,21 @@ class FacesItemWidget extends StatelessWidget {
|
||||
final (clusterIDToPerson, _) =
|
||||
await FaceMLDataDB.instance.getClusterIdToPerson();
|
||||
|
||||
final lastViewedClusterID = ClusterFeedbackService.lastViewedClusterID;
|
||||
|
||||
final faceWidgets = <FaceWidget>[];
|
||||
for (final Face face in faces) {
|
||||
final int? clusterID = faceIdsToClusterIds[face.faceID];
|
||||
final Person? person = clusterIDToPerson[clusterID];
|
||||
final highlight =
|
||||
(clusterID == lastViewedClusterID) && (person == null);
|
||||
faceWidgets.add(
|
||||
FaceWidget(
|
||||
file,
|
||||
face,
|
||||
clusterID: clusterID,
|
||||
person: person,
|
||||
highlight: highlight,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import 'package:photos/models/file/file.dart';
|
||||
import 'package:photos/models/file_load_result.dart';
|
||||
import 'package:photos/models/gallery_type.dart';
|
||||
import 'package:photos/models/selected_files.dart';
|
||||
import "package:photos/services/machine_learning/face_ml/feedback/cluster_feedback.dart";
|
||||
import "package:photos/ui/components/notification_widget.dart";
|
||||
import 'package:photos/ui/viewer/actions/file_selection_overlay_bar.dart';
|
||||
import 'package:photos/ui/viewer/gallery/gallery.dart';
|
||||
@@ -25,7 +26,7 @@ class ClusterPage extends StatefulWidget {
|
||||
final List<EnteFile> searchResult;
|
||||
final bool enableGrouping;
|
||||
final String tagPrefix;
|
||||
final int cluserID;
|
||||
final int clusterID;
|
||||
final Person? personID;
|
||||
|
||||
static const GalleryType appBarType = GalleryType.cluster;
|
||||
@@ -35,7 +36,7 @@ class ClusterPage extends StatefulWidget {
|
||||
this.searchResult, {
|
||||
this.enableGrouping = true,
|
||||
this.tagPrefix = "",
|
||||
required this.cluserID,
|
||||
required this.clusterID,
|
||||
this.personID,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
@@ -52,6 +53,7 @@ class _ClusterPageState extends State<ClusterPage> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
ClusterFeedbackService.setLastViewedClusterID(widget.clusterID);
|
||||
files = widget.searchResult;
|
||||
_filesUpdatedEvent =
|
||||
Bus.instance.on<LocalPhotosUpdatedEvent>().listen((event) {
|
||||
@@ -123,8 +125,8 @@ class _ClusterPageState extends State<ClusterPage> {
|
||||
child: NotificationWidget(
|
||||
startIcon: Icons.person_add_outlined,
|
||||
actionIcon: Icons.add_outlined,
|
||||
text: S.of(context).addAName,
|
||||
subText:S.of(context).findPeopleByName,
|
||||
text: S.of(context).addAName,
|
||||
subText: S.of(context).findPeopleByName,
|
||||
// text: S.of(context).addAName,
|
||||
// subText: S.of(context).findPersonsByName,
|
||||
type: NotificationType.greenBanner,
|
||||
@@ -132,7 +134,7 @@ class _ClusterPageState extends State<ClusterPage> {
|
||||
if (widget.personID == null) {
|
||||
final result = await showAssignPersonAction(
|
||||
context,
|
||||
clusterID: widget.cluserID,
|
||||
clusterID: widget.clusterID,
|
||||
);
|
||||
if (result != null && result is Person) {
|
||||
Navigator.pop(context);
|
||||
@@ -159,7 +161,7 @@ class _ClusterPageState extends State<ClusterPage> {
|
||||
FileSelectionOverlayBar(
|
||||
ClusterPage.overlayType,
|
||||
_selectedFiles,
|
||||
clusterID: widget.cluserID,
|
||||
clusterID: widget.clusterID,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -12,6 +12,7 @@ import 'package:photos/models/file/file.dart';
|
||||
import 'package:photos/models/file_load_result.dart';
|
||||
import 'package:photos/models/gallery_type.dart';
|
||||
import 'package:photos/models/selected_files.dart';
|
||||
import "package:photos/services/machine_learning/face_ml/feedback/cluster_feedback.dart";
|
||||
import "package:photos/services/search_service.dart";
|
||||
import 'package:photos/ui/viewer/actions/file_selection_overlay_bar.dart';
|
||||
import 'package:photos/ui/viewer/gallery/gallery.dart';
|
||||
@@ -45,6 +46,7 @@ class _PeoplePageState extends State<PeoplePage> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
ClusterFeedbackService.resetLastViewedClusterID();
|
||||
_peopleChangedEvent = Bus.instance.on<PeopleChangedEvent>().listen((event) {
|
||||
setState(() {});
|
||||
});
|
||||
|
||||
@@ -51,7 +51,7 @@ class _PersonClustersState extends State<PersonClusters> {
|
||||
builder: (context) => ClusterPage(
|
||||
files,
|
||||
personID: widget.person,
|
||||
cluserID: index,
|
||||
clusterID: index,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -31,8 +31,7 @@ class _PersonClustersState extends State<PersonReviewClusterSuggestion> {
|
||||
Key futureBuilderKey = UniqueKey();
|
||||
|
||||
// Declare a variable for the future
|
||||
late Future<List<ClusterSuggestion>>
|
||||
futureClusterSuggestions;
|
||||
late Future<List<ClusterSuggestion>> futureClusterSuggestions;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -74,7 +73,7 @@ class _PersonClustersState extends State<PersonReviewClusterSuggestion> {
|
||||
builder: (context) => ClusterPage(
|
||||
files,
|
||||
personID: widget.person,
|
||||
cluserID: clusterID,
|
||||
clusterID: clusterID,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user