Take activeAt in account when using fuse.js index
This commit is contained in:
parent
28ab6e11f6
commit
9f8ea5b202
1 changed files with 34 additions and 6 deletions
|
@ -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) => {
|
||||
|
|
Loading…
Add table
Reference in a new issue