Take activeAt in account when using fuse.js index

This commit is contained in:
Fedor Indutny 2022-05-23 12:09:40 -07:00 committed by GitHub
parent 28ab6e11f6
commit 9f8ea5b202
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 34 additions and 6 deletions

View File

@ -5,12 +5,19 @@ import Fuse from 'fuse.js';
import type { ConversationType } from '../state/ducks/conversations';
import { parseAndFormatPhoneNumber } from './libphonenumberInstance';
import { WEEK } from './durations';
// Fuse.js scores have order of 0.01
const ACTIVE_AT_SCORE_FACTOR = (1 / WEEK) * 0.01;
const FUSE_OPTIONS: Fuse.IFuseOptions<ConversationType> = {
// A small-but-nonzero threshold lets us match parts of E164s better, and makes the
// search a little more forgiving.
threshold: 0.2,
includeScore: true,
useExtendedSearch: true,
// We sort manually anyway
shouldSort: true,
keys: [
{
name: 'searchableTitle',
@ -71,14 +78,14 @@ function searchConversations(
conversations: ReadonlyArray<ConversationType>,
searchTerm: string,
regionCode: string | undefined
): Array<ConversationType> {
): ReadonlyArray<Pick<Fuse.FuseResult<ConversationType>, 'item' | 'score'>> {
const maybeCommand = searchTerm.match(/^!([^\s]+):(.*)$/);
if (maybeCommand) {
const [, commandName, query] = maybeCommand;
const command = COMMANDS.get(commandName);
if (command) {
return command(conversations, query);
return command(conversations, query).map(item => ({ item }));
}
}
@ -98,8 +105,7 @@ function searchConversations(
cachedIndices.set(conversations, index);
}
const results = index.search(extendedSearchTerm);
return results.map(result => result.item);
return index.search(extendedSearchTerm);
}
export function filterAndSortConversationsByRecent(
@ -108,7 +114,24 @@ export function filterAndSortConversationsByRecent(
regionCode: string | undefined
): Array<ConversationType> {
if (searchTerm.length) {
return searchConversations(conversations, searchTerm, regionCode);
const now = Date.now();
return searchConversations(conversations, searchTerm, regionCode)
.slice()
.sort((a, b) => {
const { activeAt: aActiveAt = 0 } = a.item;
const { activeAt: bActiveAt = 0 } = b.item;
// See: https://fusejs.io/api/options.html#includescore
// 0 score is a perfect match, 1 - complete mismatch
const aScore =
(now - aActiveAt) * ACTIVE_AT_SCORE_FACTOR + (a.score ?? 0);
const bScore =
(now - bActiveAt) * ACTIVE_AT_SCORE_FACTOR + (b.score ?? 0);
return aScore - bScore;
})
.map(result => result.item);
}
return conversations.concat().sort((a, b) => {
@ -126,7 +149,12 @@ export function filterAndSortConversationsByTitle(
regionCode: string | undefined
): Array<ConversationType> {
if (searchTerm.length) {
return searchConversations(conversations, searchTerm, regionCode);
return searchConversations(conversations, searchTerm, regionCode)
.slice()
.sort((a, b) => {
return (a.score ?? 0) - (b.score ?? 0);
})
.map(result => result.item);
}
return conversations.concat().sort((a, b) => {