[mob] Search & filter by uploader's name (#5443)

## Description

## Tests
This commit is contained in:
Neeraj
2025-03-27 00:17:13 +05:30
committed by GitHub
6 changed files with 114 additions and 0 deletions

View File

@@ -12,6 +12,7 @@ enum FilterTypeNames {
locationFilter,
magicFilter,
topLevelGenericFilter,
uploaderFilter,
onlyThemFilter,
}

View File

@@ -0,0 +1,44 @@
import "package:flutter/material.dart";
import "package:photos/models/file/extensions/file_props.dart";
import "package:photos/models/file/file.dart";
import "package:photos/models/search/hierarchical/hierarchical_search_filter.dart";
class UploaderFilter extends HierarchicalSearchFilter {
final String uploaderName;
final int occurrence;
UploaderFilter({
required this.uploaderName,
required this.occurrence,
super.filterTypeName = "uploaderFilter",
super.matchedUploadedIDs,
});
@override
String name() {
return uploaderName;
}
@override
int relevance() {
return occurrence;
}
@override
bool isMatch(EnteFile file) {
return file.uploaderName == uploaderName;
}
@override
bool isSameFilter(HierarchicalSearchFilter other) {
if (other is UploaderFilter) {
return other.uploaderName == uploaderName;
}
return false;
}
@override
IconData? icon() {
return Icons.person_outlined;
}
}

View File

@@ -26,6 +26,7 @@ import "package:photos/utils/share_util.dart";
enum ResultType {
collection,
file,
uploader,
location,
locationSuggestion,
month,

View File

@@ -35,6 +35,7 @@ import "package:photos/models/search/hierarchical/hierarchical_search_filter.dar
import "package:photos/models/search/hierarchical/location_filter.dart";
import "package:photos/models/search/hierarchical/magic_filter.dart";
import "package:photos/models/search/hierarchical/top_level_generic_filter.dart";
import "package:photos/models/search/hierarchical/uploader_filter.dart";
import "package:photos/models/search/search_constants.dart";
import "package:photos/models/search/search_types.dart";
import "package:photos/service_locator.dart";
@@ -551,6 +552,7 @@ class SearchService {
final List<EnteFile> allFiles = await getAllFilesForSearch();
final List<EnteFile> captionMatch = <EnteFile>[];
final List<EnteFile> displayNameMatch = <EnteFile>[];
final Map<String, List<EnteFile>> uploaderToFile = {};
for (EnteFile eachFile in allFiles) {
if (eachFile.caption != null && pattern.hasMatch(eachFile.caption!)) {
captionMatch.add(eachFile);
@@ -558,6 +560,13 @@ class SearchService {
if (pattern.hasMatch(eachFile.displayName)) {
displayNameMatch.add(eachFile);
}
if (eachFile.uploaderName != null &&
pattern.hasMatch(eachFile.uploaderName!)) {
if (!uploaderToFile.containsKey(eachFile.uploaderName!)) {
uploaderToFile[eachFile.uploaderName!] = [];
}
uploaderToFile[eachFile.uploaderName!]!.add(eachFile);
}
}
if (captionMatch.isNotEmpty) {
searchResults.add(
@@ -590,6 +599,22 @@ class SearchService {
),
);
}
if (uploaderToFile.isNotEmpty) {
for (MapEntry<String, List<EnteFile>> entry in uploaderToFile.entries) {
searchResults.add(
GenericSearchResult(
ResultType.uploader,
entry.key,
entry.value,
hierarchicalSearchFilter: UploaderFilter(
uploaderName: entry.key,
occurrence: kMostRelevantFilter,
matchedUploadedIDs: filesToUploadedFileIDs(entry.value),
),
),
);
}
}
return searchResults;
}

View File

@@ -164,6 +164,8 @@ class SearchResultWidget extends StatelessWidget {
return "Shared";
case ResultType.faces:
return "Person";
case ResultType.uploader:
return "Uploaded by";
}
}
}

View File

@@ -5,6 +5,7 @@ import "package:photos/core/constants.dart";
import "package:photos/db/files_db.dart";
import "package:photos/db/ml/db.dart";
import "package:photos/generated/l10n.dart";
import "package:photos/models/file/extensions/file_props.dart";
import "package:photos/models/file/file.dart";
import "package:photos/models/file/file_type.dart";
import "package:photos/models/location_tag/location_tag.dart";
@@ -18,6 +19,7 @@ import "package:photos/models/search/hierarchical/location_filter.dart";
import "package:photos/models/search/hierarchical/magic_filter.dart";
import "package:photos/models/search/hierarchical/only_them_filter.dart";
import "package:photos/models/search/hierarchical/top_level_generic_filter.dart";
import "package:photos/models/search/hierarchical/uploader_filter.dart";
import "package:photos/service_locator.dart";
import "package:photos/services/collections_service.dart";
import "package:photos/services/machine_learning/face_ml/face_filtering/face_filtering_constants.dart";
@@ -155,6 +157,7 @@ Future<void> curateFilters(
files,
);
final contactsFilters = _curateContactsFilter(files);
final uploaderFilters = _curateUploaderFilter(files);
final faceFilters = await curateFaceFilters(files);
final magicFilters = await curateMagicFilters(files, context);
final onlyThemFilter = getOnlyThemFilter(
@@ -169,6 +172,7 @@ Future<void> curateFilters(
...faceFilters,
...fileTypeFilters,
...contactsFilters,
...uploaderFilters,
...albumFilters,
...locationFilters,
],
@@ -346,6 +350,31 @@ List<ContactsFilter> _curateContactsFilter(
return contactsFilters;
}
List<UploaderFilter> _curateUploaderFilter(
List<EnteFile> files,
) {
final uploaderFilter = <UploaderFilter>[];
final ownerIdToOccurrence = <String, int>{};
for (EnteFile file in files) {
if (file.uploaderName == null) {
continue;
}
ownerIdToOccurrence[file.uploaderName!] =
(ownerIdToOccurrence[file.uploaderName!] ?? 0) + 1;
}
for (String uploader in ownerIdToOccurrence.keys) {
uploaderFilter.add(
UploaderFilter(
uploaderName: uploader,
occurrence: ownerIdToOccurrence[uploader]!,
),
);
}
return uploaderFilter;
}
Future<List<FaceFilter>> curateFaceFilters(
List<EnteFile> files,
) async {
@@ -502,6 +531,13 @@ Map<String, List<HierarchicalSearchFilter>> getFiltersForBottomSheet(
searchFilterDataProvider.recommendations.whereType<ContactsFilter>(),
);
final uploaderFilters = searchFilterDataProvider.appliedFilters
.whereType<UploaderFilter>()
.toList();
uploaderFilters.addAll(
searchFilterDataProvider.recommendations.whereType<UploaderFilter>(),
);
final magicFilters =
searchFilterDataProvider.appliedFilters.whereType<MagicFilter>().toList();
magicFilters.addAll(
@@ -518,6 +554,7 @@ Map<String, List<HierarchicalSearchFilter>> getFiltersForBottomSheet(
"magicFilters": magicFilters,
"locationFilters": locationFilters,
"contactsFilters": contactsFilters,
"uploaderFilters": uploaderFilters,
"albumFilters": albumFilters,
"fileTypeFilters": fileTypeFilters,
"topLevelGenericFilter": topLevelGenericFilter,
@@ -567,6 +604,7 @@ List<HierarchicalSearchFilter> getRecommendedFiltersForAppBar(
final magicReccos = <MagicFilter>[];
final locationReccos = <LocationFilter>[];
final contactsReccos = <ContactsFilter>[];
final uploaderReccos = <UploaderFilter>[];
final albumReccos = <AlbumFilter>[];
final fileTypeReccos = <FileTypeFilter>[];
final onlyThemFilter = <OnlyThemFilter>[];
@@ -582,6 +620,8 @@ List<HierarchicalSearchFilter> getRecommendedFiltersForAppBar(
locationReccos.add(recommendation);
} else if (recommendation is ContactsFilter) {
contactsReccos.add(recommendation);
} else if (recommendation is UploaderFilter) {
uploaderReccos.add(recommendation);
} else if (recommendation is AlbumFilter) {
albumReccos.add(recommendation);
} else if (recommendation is FileTypeFilter) {
@@ -595,6 +635,7 @@ List<HierarchicalSearchFilter> getRecommendedFiltersForAppBar(
...magicReccos,
...locationReccos,
...contactsReccos,
...uploaderReccos,
...albumReccos,
...fileTypeReccos,
];