feat: min face count per-user

feat/min-face-count-mobile
Yaros 2026-06-03 18:13:39 +02:00
parent 911dde39c9
commit 62856cd501
5 changed files with 20 additions and 9 deletions

View File

@ -55,6 +55,7 @@ class Preferences {
final bool tagsEnabled; final bool tagsEnabled;
final AvatarColor userAvatarColor; final AvatarColor userAvatarColor;
final bool showSupportBadge; final bool showSupportBadge;
final int minimumFaces;
const Preferences({ const Preferences({
this.foldersEnabled = false, this.foldersEnabled = false,
@ -65,6 +66,7 @@ class Preferences {
this.tagsEnabled = false, this.tagsEnabled = false,
this.userAvatarColor = AvatarColor.primary, this.userAvatarColor = AvatarColor.primary,
this.showSupportBadge = true, this.showSupportBadge = true,
this.minimumFaces = 3,
}); });
Preferences copyWith({ Preferences copyWith({
@ -76,6 +78,7 @@ class Preferences {
bool? tagsEnabled, bool? tagsEnabled,
AvatarColor? userAvatarColor, AvatarColor? userAvatarColor,
bool? showSupportBadge, bool? showSupportBadge,
int? minimumFaces,
}) { }) {
return Preferences( return Preferences(
foldersEnabled: foldersEnabled ?? this.foldersEnabled, foldersEnabled: foldersEnabled ?? this.foldersEnabled,
@ -86,6 +89,7 @@ class Preferences {
tagsEnabled: tagsEnabled ?? this.tagsEnabled, tagsEnabled: tagsEnabled ?? this.tagsEnabled,
userAvatarColor: userAvatarColor ?? this.userAvatarColor, userAvatarColor: userAvatarColor ?? this.userAvatarColor,
showSupportBadge: showSupportBadge ?? this.showSupportBadge, showSupportBadge: showSupportBadge ?? this.showSupportBadge,
minimumFaces: minimumFaces ?? this.minimumFaces,
); );
} }
@ -99,6 +103,7 @@ class Preferences {
preferences["tags-Enabled"] = tagsEnabled; preferences["tags-Enabled"] = tagsEnabled;
preferences["avatar-Color"] = userAvatarColor.value; preferences["avatar-Color"] = userAvatarColor.value;
preferences["purchase-ShowSupportBadge"] = showSupportBadge; preferences["purchase-ShowSupportBadge"] = showSupportBadge;
preferences["minimumFaces"] = minimumFaces;
return preferences; return preferences;
} }
@ -115,6 +120,7 @@ class Preferences {
orElse: () => AvatarColor.primary, orElse: () => AvatarColor.primary,
), ),
showSupportBadge: (map["purchase"] as Map<String, Object?>?)?["showSupportBadge"] as bool? ?? true, showSupportBadge: (map["purchase"] as Map<String, Object?>?)?["showSupportBadge"] as bool? ?? true,
minimumFaces: (map["people"] as Map<String, Object?>?)?["minimumFaces"] as int? ?? 3,
); );
} }
@ -129,6 +135,7 @@ sharedLinksEnabled: $sharedLinksEnabled,
tagsEnabled: $tagsEnabled, tagsEnabled: $tagsEnabled,
userAvatarColor: $userAvatarColor, userAvatarColor: $userAvatarColor,
showSupportBadge: $showSupportBadge, showSupportBadge: $showSupportBadge,
minimumFaces: $minimumFaces,
}'''; }''';
} }
@ -145,7 +152,8 @@ showSupportBadge: $showSupportBadge,
other.sharedLinksEnabled == sharedLinksEnabled && other.sharedLinksEnabled == sharedLinksEnabled &&
other.tagsEnabled == tagsEnabled && other.tagsEnabled == tagsEnabled &&
other.userAvatarColor == userAvatarColor && other.userAvatarColor == userAvatarColor &&
other.showSupportBadge == showSupportBadge; other.showSupportBadge == showSupportBadge &&
other.minimumFaces == minimumFaces;
} }
@override @override
@ -157,7 +165,8 @@ showSupportBadge: $showSupportBadge,
sharedLinksEnabled.hashCode ^ sharedLinksEnabled.hashCode ^
tagsEnabled.hashCode ^ tagsEnabled.hashCode ^
userAvatarColor.hashCode ^ userAvatarColor.hashCode ^
showSupportBadge.hashCode; showSupportBadge.hashCode ^
minimumFaces.hashCode;
} }
} }

View File

@ -18,8 +18,8 @@ class DriftPeopleService {
return _repository.getAssetPeople(assetId); return _repository.getAssetPeople(assetId);
} }
Future<List<DriftPerson>> getAllPeople() { Future<List<DriftPerson>> getAllPeople({int minFaces = 3}) {
return _repository.getAllPeople(); return _repository.getAllPeople(minFaces: minFaces);
} }
Future<int> updateName(String personId, String name) async { Future<int> updateName(String personId, String name) async {

View File

@ -32,7 +32,7 @@ class DriftPeopleRepository extends DriftDatabaseRepository {
}).get(); }).get();
} }
Future<List<DriftPerson>> getAllPeople() async { Future<List<DriftPerson>> getAllPeople({int minFaces = 3}) async {
final people = _db.personEntity; final people = _db.personEntity;
final faces = _db.assetFaceEntity; final faces = _db.assetFaceEntity;
final assets = _db.remoteAssetEntity; final assets = _db.remoteAssetEntity;
@ -49,7 +49,7 @@ class DriftPeopleRepository extends DriftDatabaseRepository {
faces.isVisible.equals(true) & faces.isVisible.equals(true) &
faces.deletedAt.isNull(), faces.deletedAt.isNull(),
) )
..groupBy([people.id], having: faces.id.count().isBiggerOrEqualValue(3) | people.name.equals('').not()) ..groupBy([people.id], having: faces.id.count().isBiggerOrEqualValue(minFaces) | people.name.equals('').not())
..orderBy([ ..orderBy([
OrderingTerm(expression: people.name.equals('').not(), mode: OrderingMode.desc), OrderingTerm(expression: people.name.equals('').not(), mode: OrderingMode.desc),
OrderingTerm(expression: faces.id.count(), mode: OrderingMode.desc), OrderingTerm(expression: faces.id.count(), mode: OrderingMode.desc),

View File

@ -3,6 +3,7 @@ import 'package:immich_mobile/domain/models/person.model.dart';
import 'package:immich_mobile/domain/services/people.service.dart'; import 'package:immich_mobile/domain/services/people.service.dart';
import 'package:immich_mobile/infrastructure/repositories/people.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/people.repository.dart';
import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
import 'package:immich_mobile/providers/infrastructure/user_metadata.provider.dart';
import 'package:immich_mobile/repositories/person_api.repository.dart'; import 'package:immich_mobile/repositories/person_api.repository.dart';
final driftPeopleRepositoryProvider = Provider<DriftPeopleRepository>( final driftPeopleRepositoryProvider = Provider<DriftPeopleRepository>(
@ -20,5 +21,6 @@ final driftPeopleAssetProvider = FutureProvider.family<List<DriftPerson>, String
final driftGetAllPeopleProvider = FutureProvider<List<DriftPerson>>((ref) async { final driftGetAllPeopleProvider = FutureProvider<List<DriftPerson>>((ref) async {
final service = ref.watch(driftPeopleServiceProvider); final service = ref.watch(driftPeopleServiceProvider);
return service.getAllPeople(); final prefs = await ref.watch(userMetadataPreferencesProvider.future);
return service.getAllPeople(minFaces: prefs?.minimumFaces ?? 3);
}); });

View File

@ -1,3 +1,4 @@
import 'package:collection/collection.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/domain/models/user_metadata.model.dart'; import 'package:immich_mobile/domain/models/user_metadata.model.dart';
import 'package:immich_mobile/infrastructure/repositories/user_metadata.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/user_metadata.repository.dart';
@ -19,6 +20,5 @@ final userMetadataProvider = FutureProvider<List<UserMetadata>>((ref) async {
final userMetadataPreferencesProvider = FutureProvider<Preferences?>((ref) async { final userMetadataPreferencesProvider = FutureProvider<Preferences?>((ref) async {
final metadataList = await ref.watch(userMetadataProvider.future); final metadataList = await ref.watch(userMetadataProvider.future);
final metadataWithPrefs = metadataList.firstWhere((meta) => meta.preferences != null); return metadataList.firstWhereOrNull((meta) => meta.preferences != null)?.preferences;
return metadataWithPrefs.preferences;
}); });