Person assigned (#4867)

## Description

Make PersonData.assigned and PersonData.rejectedFaceIds non-nullable to
fix issue.

## Tests

Tested in debug mode on my pixel phone.
This commit is contained in:
Laurens Priem
2025-01-27 15:40:16 +05:30
committed by GitHub
6 changed files with 39 additions and 50 deletions

View File

@@ -50,11 +50,12 @@ class PersonData {
final String name;
final bool isHidden;
String? avatarFaceID;
List<ClusterInfo>? assigned = List<ClusterInfo>.empty();
List<String>? rejectedFaceIDs = List<String>.empty();
List<ClusterInfo> assigned = List<ClusterInfo>.empty();
List<String> rejectedFaceIDs = List<String>.empty();
final String? birthDate;
// email should be always looked via userID as user might have changed
// their email ids.
/// email should be always looked via userID as user might have changed
/// their email ids.
final String? email;
final int? userID;
@@ -65,8 +66,8 @@ class PersonData {
PersonData({
required this.name,
this.assigned,
this.rejectedFaceIDs,
this.assigned = const <ClusterInfo>[],
this.rejectedFaceIDs = const <String>[],
this.avatarFaceID,
this.isHidden = false,
this.birthDate,
@@ -101,15 +102,13 @@ class PersonData {
final StringBuffer sb = StringBuffer();
sb.writeln('Person: $name');
int assignedCount = 0;
for (final a in (assigned ?? <ClusterInfo>[])) {
for (final a in assigned) {
assignedCount += a.faces.length;
}
sb.writeln('Assigned: ${assigned?.length} withFaces $assignedCount');
sb.writeln('Rejected faceIDs: ${rejectedFaceIDs?.length}');
if (assigned != null) {
for (var cluster in assigned!) {
sb.writeln('Cluster: ${cluster.id} - ${cluster.faces.length}');
}
sb.writeln('Assigned: ${assigned.length} withFaces $assignedCount');
sb.writeln('Rejected faceIDs: ${rejectedFaceIDs.length}');
for (var cluster in assigned) {
sb.writeln('Cluster: ${cluster.id} - ${cluster.faces.length}');
}
debugPrint(sb.toString());
}
@@ -117,7 +116,7 @@ class PersonData {
// toJson
Map<String, dynamic> toJson() => {
'name': name,
'assigned': assigned?.map((e) => e.toJson()).toList(),
'assigned': assigned.map((e) => e.toJson()).toList(),
'rejectedFaceIDs': rejectedFaceIDs,
'avatarFaceID': avatarFaceID,
'isHidden': isHidden,

View File

@@ -338,14 +338,13 @@ class ClusterFeedbackService {
required PersonEntity person,
required String clusterID,
}) async {
if (person.data.rejectedFaceIDs != null &&
person.data.rejectedFaceIDs!.isNotEmpty) {
if (person.data.rejectedFaceIDs.isNotEmpty) {
final clusterFaceIDs =
await MLDataDB.instance.getFaceIDsForCluster(clusterID);
final rejectedLengthBefore = person.data.rejectedFaceIDs!.length;
person.data.rejectedFaceIDs!
final rejectedLengthBefore = person.data.rejectedFaceIDs.length;
person.data.rejectedFaceIDs
.removeWhere((faceID) => clusterFaceIDs.contains(faceID));
final rejectedLengthAfter = person.data.rejectedFaceIDs!.length;
final rejectedLengthAfter = person.data.rejectedFaceIDs.length;
if (rejectedLengthBefore != rejectedLengthAfter) {
_logger.info(
'Removed ${rejectedLengthBefore - rejectedLengthAfter} rejected faces from person ${person.data.name} due to adding cluster $clusterID',

View File

@@ -136,14 +136,14 @@ class PersonService {
PersonData personData,
Map<String, Set<String>> dbPersonCluster,
) {
if ((personData.assigned?.length ?? 0) != dbPersonCluster.length) {
if (personData.assigned.length != dbPersonCluster.length) {
log(
"Person ${personData.name} has ${personData.assigned?.length} clusters, but ${dbPersonCluster.length} clusters found in DB",
"Person ${personData.name} has ${personData.assigned.length} clusters, but ${dbPersonCluster.length} clusters found in DB",
name: "PersonService",
);
return true;
} else {
for (ClusterInfo info in personData.assigned!) {
for (ClusterInfo info in personData.assigned) {
final dbCluster = dbPersonCluster[info.id];
if (dbCluster == null) {
log(
@@ -213,7 +213,7 @@ class PersonService {
}) async {
final person = (await getPerson(personID))!;
final personData = person.data;
final clusterInfo = personData.assigned!.firstWhere(
final clusterInfo = personData.assigned.firstWhere(
(element) => element.id == clusterID,
orElse: () => ClusterInfo(id: "noSuchClusterInRemotePerson", faces: {}),
);
@@ -224,9 +224,8 @@ class PersonService {
);
return;
}
personData.rejectedFaceIDs ??= [];
personData.rejectedFaceIDs!.addAll(clusterInfo.faces);
personData.assigned!.removeWhere((element) => element.id == clusterID);
personData.rejectedFaceIDs.addAll(clusterInfo.faces);
personData.assigned.removeWhere((element) => element.id == clusterID);
await entityService.addOrUpdate(
EntityType.cgroup,
personData.toJson(),
@@ -247,7 +246,7 @@ class PersonService {
// Remove faces from clusters
final List<String> emptiedClusters = [];
for (final cluster in personData.assigned!) {
for (final cluster in personData.assigned) {
cluster.faces.removeWhere((faceID) => faceIDs.contains(faceID));
if (cluster.faces.isEmpty) {
emptiedClusters.add(cluster.id);
@@ -256,7 +255,7 @@ class PersonService {
// Safety check to make sure we haven't created an empty cluster now, if so delete it
for (final emptyClusterID in emptiedClusters) {
personData.assigned!
personData.assigned
.removeWhere((element) => element.id != emptyClusterID);
await faceMLDataDB.removeClusterToPerson(
personID: person.remoteID,
@@ -265,8 +264,7 @@ class PersonService {
}
// Add removed faces to rejected faces
personData.rejectedFaceIDs ??= [];
personData.rejectedFaceIDs!.addAll(faceIDs);
personData.rejectedFaceIDs.addAll(faceIDs);
await entityService.addOrUpdate(
EntityType.cgroup,
@@ -333,14 +331,13 @@ class PersonService {
bool shouldCheckRejectedFaces = false;
for (var e in entities) {
final personData = PersonData.fromJson(json.decode(e.data));
if (personData.rejectedFaceIDs != null &&
personData.rejectedFaceIDs!.isNotEmpty) {
if (personData.rejectedFaceIDs.isNotEmpty) {
shouldCheckRejectedFaces = true;
}
int faceCount = 0;
// Locally store the assignment of faces to clusters and people
for (var cluster in personData.assigned!) {
for (var cluster in personData.assigned) {
faceCount += cluster.faces.length;
for (var faceId in cluster.faces) {
if (faceIdToClusterID.containsKey(faceId)) {
@@ -362,7 +359,7 @@ class PersonService {
}
if (kDebugMode) {
logger.info(
"Person ${e.id} ${personData.name} has ${personData.assigned!.length} clusters with $faceCount faces",
"Person ${e.id} ${personData.name} has ${personData.assigned.length} clusters with $faceCount faces",
);
}
}
@@ -375,11 +372,10 @@ class PersonService {
await faceMLDataDB.getPersonToClusterIdToFaceIds();
for (var e in entities) {
final personData = PersonData.fromJson(json.decode(e.data));
if (personData.rejectedFaceIDs != null &&
personData.rejectedFaceIDs!.isNotEmpty) {
if (personData.rejectedFaceIDs.isNotEmpty) {
final personFaceIDs =
dbPeopleClusterInfo[e.id]!.values.expand((e) => e).toSet();
final rejectedFaceIDsSet = personData.rejectedFaceIDs!.toSet();
final rejectedFaceIDsSet = personData.rejectedFaceIDs.toSet();
final assignedAndRejectedFaceIDs =
rejectedFaceIDsSet.intersection(personFaceIDs);

View File

@@ -261,13 +261,10 @@ class MLService {
final persons = await PersonService.instance.getPersons();
final faceIdNotToCluster = <String, List<String>>{};
for (final person in persons) {
if (person.data.rejectedFaceIDs != null &&
person.data.rejectedFaceIDs!.isNotEmpty) {
final personClusters = person.data.assigned?.map((e) => e.id).toList();
if (personClusters != null) {
for (final faceID in person.data.rejectedFaceIDs!) {
faceIdNotToCluster[faceID] = personClusters;
}
if (person.data.rejectedFaceIDs.isNotEmpty) {
final personClusters = person.data.assigned.map((e) => e.id).toList();
for (final faceID in person.data.rejectedFaceIDs) {
faceIdNotToCluster[faceID] = personClusters;
}
}
}

View File

@@ -181,7 +181,7 @@ class _AppBarWidgetState extends State<PeopleAppBar> {
final result = await routeToPage(
context,
SaveOrEditPerson(
person.data.assigned?.first.id ?? "",
person.data.assigned.first.id,
person: person,
isEditing: true,
),
@@ -364,7 +364,7 @@ class _AppBarWidgetState extends State<PeopleAppBar> {
if (assignName) {
final result = await showAssignPersonAction(
context,
clusterID: widget.person.data.assigned!.first.id,
clusterID: widget.person.data.assigned.first.id,
);
Navigator.pop(context);
if (result != null) {

View File

@@ -564,10 +564,8 @@ class _SaveOrEditPersonState extends State<SaveOrEditPerson> {
final persons = _cachedPersons.map((e) => e.$1).toList();
final clusterToPerson = <String, String>{};
for (final person in persons) {
if (person.data.assigned != null) {
for (final cluster in person.data.assigned!) {
clusterToPerson[cluster.id] = person.remoteID;
}
for (final cluster in person.data.assigned) {
clusterToPerson[cluster.id] = person.remoteID;
}
}
allClusterSummary