This commit is contained in:
Manav Rathi
2024-09-12 11:41:20 +05:30
parent ae7134a80f
commit 18f622d007

View File

@@ -22,8 +22,7 @@ import type {
Searchable, Searchable,
SearchableData, SearchableData,
SearchDateComponents, SearchDateComponents,
SearchQuery, SearchSuggestion,
Suggestion,
} from "./types"; } from "./types";
/** /**
@@ -88,7 +87,7 @@ export class SearchWorker {
/** /**
* Return {@link EnteFile}s that satisfy the given {@link suggestion}. * Return {@link EnteFile}s that satisfy the given {@link suggestion}.
*/ */
filterSearchableFiles(suggestion: SearchQuery) { filterSearchableFiles(suggestion: SearchSuggestion) {
return this.searchableData.files.filter((f) => return this.searchableData.files.filter((f) =>
isMatchingFile(f, suggestion), isMatchingFile(f, suggestion),
); );
@@ -108,7 +107,7 @@ const suggestionsForString = (
{ locale, holidays, labelledFileTypes }: LocalizedSearchData, { locale, holidays, labelledFileTypes }: LocalizedSearchData,
locationTags: Searchable<LocationTag>[], locationTags: Searchable<LocationTag>[],
cities: Searchable<City>[], cities: Searchable<City>[],
): Suggestion[] => ): SearchSuggestion[] =>
[ [
// <-- caption suggestions will be inserted here by our caller. // <-- caption suggestions will be inserted here by our caller.
fileTypeSuggestions(s, labelledFileTypes), fileTypeSuggestions(s, labelledFileTypes),
@@ -119,7 +118,10 @@ const suggestionsForString = (
fileCaptionSuggestion(s, searchString, files), fileCaptionSuggestion(s, searchString, files),
].flat(); ].flat();
const collectionSuggestions = (s: string, collections: Collection[]) => const collectionSuggestions = (
s: string,
collections: Collection[],
): SearchSuggestion[] =>
collections collections
.filter(({ name }) => name.toLowerCase().includes(s)) .filter(({ name }) => name.toLowerCase().includes(s))
.map(({ id, name }) => ({ .map(({ id, name }) => ({
@@ -131,7 +133,7 @@ const collectionSuggestions = (s: string, collections: Collection[]) =>
const fileTypeSuggestions = ( const fileTypeSuggestions = (
s: string, s: string,
labelledFileTypes: Searchable<LabelledFileType>[], labelledFileTypes: Searchable<LabelledFileType>[],
) => ): SearchSuggestion[] =>
labelledFileTypes labelledFileTypes
.filter(({ lowercasedName }) => lowercasedName.startsWith(s)) .filter(({ lowercasedName }) => lowercasedName.startsWith(s))
.map(({ fileType, label }) => ({ type: "fileType", fileType, label })); .map(({ fileType, label }) => ({ type: "fileType", fileType, label }));
@@ -140,7 +142,7 @@ const fileNameSuggestion = (
s: string, s: string,
searchString: string, searchString: string,
files: EnteFile[], files: EnteFile[],
) => { ): SearchSuggestion[] => {
// Convert the search string to a number. This allows searching a file by // Convert the search string to a number. This allows searching a file by
// its exact (integral) ID. // its exact (integral) ID.
const sn = Number(s) || undefined; const sn = Number(s) || undefined;
@@ -153,7 +155,7 @@ const fileNameSuggestion = (
.map((f) => f.id); .map((f) => f.id);
return fileIDs.length return fileIDs.length
? { type: "fileName", fileIDs, label: searchString } ? [{ type: "fileName", fileIDs, label: searchString }]
: []; : [];
}; };
@@ -161,7 +163,7 @@ const fileCaptionSuggestion = (
s: string, s: string,
searchString: string, searchString: string,
files: EnteFile[], files: EnteFile[],
) => { ): SearchSuggestion[] => {
const fileIDs = files const fileIDs = files
.filter((file) => .filter((file) =>
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
@@ -170,7 +172,7 @@ const fileCaptionSuggestion = (
.map((f) => f.id); .map((f) => f.id);
return fileIDs.length return fileIDs.length
? { type: "fileCaption", fileIDs, label: searchString } ? [{ type: "fileCaption", fileIDs, label: searchString }]
: []; : [];
}; };
@@ -178,7 +180,7 @@ const dateSuggestions = (
s: string, s: string,
locale: string, locale: string,
holidays: Searchable<DateSearchResult>[], holidays: Searchable<DateSearchResult>[],
) => ): SearchSuggestion[] =>
parseDateComponents(s, locale, holidays).map(({ components, label }) => ({ parseDateComponents(s, locale, holidays).map(({ components, label }) => ({
type: "date", type: "date",
dateComponents: components, dateComponents: components,
@@ -291,7 +293,7 @@ const locationSuggestions = (
s: string, s: string,
locationTags: Searchable<LocationTag>[], locationTags: Searchable<LocationTag>[],
cities: Searchable<City>[], cities: Searchable<City>[],
) => { ): SearchSuggestion[] => {
const matchingLocationTags = locationTags.filter(searchableIncludes(s)); const matchingLocationTags = locationTags.filter(searchableIncludes(s));
const matchingLocationTagLNames = new Set( const matchingLocationTagLNames = new Set(
@@ -305,65 +307,68 @@ const locationSuggestions = (
); );
return [ return [
matchingLocationTags.map((locationTag) => ({ matchingLocationTags.map(
(locationTag): SearchSuggestion => ({
type: "location", type: "location",
locationTag, locationTag,
label: locationTag.name, label: locationTag.name,
})), }),
matchingCities.map((city) => ({ ),
matchingCities.map(
(city): SearchSuggestion => ({
type: "city", type: "city",
city, city,
label: city.name, label: city.name,
})), }),
),
].flat(); ].flat();
}; };
/** /**
* Return true if file satisfies the given {@link query}. * Return true if file satisfies the given {@link query}.
*/ */
const isMatchingFile = (file: EnteFile, query: SearchQuery) => { const isMatchingFile = (file: EnteFile, suggestion: SearchSuggestion) => {
if (query.collection) { switch (suggestion.type) {
return query.collection === file.collectionID; case "collection":
} return suggestion.collectionID === file.collectionID;
if (query.date) { case "fileType":
return suggestion.fileType === file.metadata.fileType;
case "fileName":
return suggestion.fileIDs.includes(file.id);
case "fileCaption":
return suggestion.fileIDs.includes(file.id);
case "date":
return isDateComponentsMatch( return isDateComponentsMatch(
query.date, suggestion.dateComponents,
fileCreationPhotoDate(file, getPublicMagicMetadataSync(file)), fileCreationPhotoDate(file, getPublicMagicMetadataSync(file)),
); );
}
if (query.location) { case "location": {
const location = fileLocation(file); const location = fileLocation(file);
if (!location) return false; if (!location) return false;
return isInsideLocationTag(location, query.location); return isInsideLocationTag(location, suggestion.locationTag);
} }
if (query.city) { case "city": {
const location = fileLocation(file); const location = fileLocation(file);
if (!location) return false; if (!location) return false;
return isInsideCity(location, query.city); return isInsideCity(location, suggestion.city);
} }
if (query.files) { case "clip":
return query.files.includes(file.id); return suggestion.clipScoreForFileID.has(file.id);
}
if (query.person) {
return query.person.files.includes(file.id);
}
if (typeof query.fileType !== "undefined") {
return query.fileType === file.metadata.fileType;
}
if (typeof query.clip !== "undefined") {
return query.clip.has(file.id);
}
case "cgroup":
// return query.person.files.includes(file.id);
// TODO-Cluster implement me
return false; return false;
}
}; };
const isDateComponentsMatch = ( const isDateComponentsMatch = (