[mob] Search & filter by uploader's name (#5443)
## Description ## Tests
This commit is contained in:
@@ -12,6 +12,7 @@ enum FilterTypeNames {
|
||||
locationFilter,
|
||||
magicFilter,
|
||||
topLevelGenericFilter,
|
||||
uploaderFilter,
|
||||
onlyThemFilter,
|
||||
}
|
||||
|
||||
|
||||
44
mobile/lib/models/search/hierarchical/uploader_filter.dart
Normal file
44
mobile/lib/models/search/hierarchical/uploader_filter.dart
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import "package:photos/utils/share_util.dart";
|
||||
enum ResultType {
|
||||
collection,
|
||||
file,
|
||||
uploader,
|
||||
location,
|
||||
locationSuggestion,
|
||||
month,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -164,6 +164,8 @@ class SearchResultWidget extends StatelessWidget {
|
||||
return "Shared";
|
||||
case ResultType.faces:
|
||||
return "Person";
|
||||
case ResultType.uploader:
|
||||
return "Uploaded by";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user