diff --git a/mobile/lib/models/ml/face/person.dart b/mobile/lib/models/ml/face/person.dart index 0a00ca5fc1..b758285461 100644 --- a/mobile/lib/models/ml/face/person.dart +++ b/mobile/lib/models/ml/face/person.dart @@ -50,11 +50,12 @@ class PersonData { final String name; final bool isHidden; String? avatarFaceID; - List? assigned = List.empty(); - List? rejectedFaceIDs = List.empty(); + List assigned = List.empty(); + List rejectedFaceIDs = List.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 [], + this.rejectedFaceIDs = const [], 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 ?? [])) { + 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 toJson() => { 'name': name, - 'assigned': assigned?.map((e) => e.toJson()).toList(), + 'assigned': assigned.map((e) => e.toJson()).toList(), 'rejectedFaceIDs': rejectedFaceIDs, 'avatarFaceID': avatarFaceID, 'isHidden': isHidden, 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 95dfd7af5b..d3f4f5e66e 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 @@ -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', diff --git a/mobile/lib/services/machine_learning/face_ml/person/person_service.dart b/mobile/lib/services/machine_learning/face_ml/person/person_service.dart index 8a13ab893c..3d795432ca 100644 --- a/mobile/lib/services/machine_learning/face_ml/person/person_service.dart +++ b/mobile/lib/services/machine_learning/face_ml/person/person_service.dart @@ -136,14 +136,14 @@ class PersonService { PersonData personData, Map> 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 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); diff --git a/mobile/lib/services/machine_learning/ml_service.dart b/mobile/lib/services/machine_learning/ml_service.dart index 623e46c29e..268fd74774 100644 --- a/mobile/lib/services/machine_learning/ml_service.dart +++ b/mobile/lib/services/machine_learning/ml_service.dart @@ -261,13 +261,10 @@ class MLService { final persons = await PersonService.instance.getPersons(); final faceIdNotToCluster = >{}; 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; } } } diff --git a/mobile/lib/ui/viewer/people/people_app_bar.dart b/mobile/lib/ui/viewer/people/people_app_bar.dart index dfa3e05682..0271550c42 100644 --- a/mobile/lib/ui/viewer/people/people_app_bar.dart +++ b/mobile/lib/ui/viewer/people/people_app_bar.dart @@ -181,7 +181,7 @@ class _AppBarWidgetState extends State { 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 { 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) { diff --git a/mobile/lib/ui/viewer/people/save_or_edit_person.dart b/mobile/lib/ui/viewer/people/save_or_edit_person.dart index e53b743e4a..a3563a6b4c 100644 --- a/mobile/lib/ui/viewer/people/save_or_edit_person.dart +++ b/mobile/lib/ui/viewer/people/save_or_edit_person.dart @@ -564,10 +564,8 @@ class _SaveOrEditPersonState extends State { final persons = _cachedPersons.map((e) => e.$1).toList(); final clusterToPerson = {}; 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