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 type { ConversationType } from '../state/ducks/conversations';
|
||||||
import { parseAndFormatPhoneNumber } from './libphonenumberInstance';
|
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> = {
|
const FUSE_OPTIONS: Fuse.IFuseOptions<ConversationType> = {
|
||||||
// A small-but-nonzero threshold lets us match parts of E164s better, and makes the
|
// A small-but-nonzero threshold lets us match parts of E164s better, and makes the
|
||||||
// search a little more forgiving.
|
// search a little more forgiving.
|
||||||
threshold: 0.2,
|
threshold: 0.2,
|
||||||
|
includeScore: true,
|
||||||
useExtendedSearch: true,
|
useExtendedSearch: true,
|
||||||
|
// We sort manually anyway
|
||||||
|
shouldSort: true,
|
||||||
keys: [
|
keys: [
|
||||||
{
|
{
|
||||||
name: 'searchableTitle',
|
name: 'searchableTitle',
|
||||||
|
@ -71,14 +78,14 @@ function searchConversations(
|
||||||
conversations: ReadonlyArray<ConversationType>,
|
conversations: ReadonlyArray<ConversationType>,
|
||||||
searchTerm: string,
|
searchTerm: string,
|
||||||
regionCode: string | undefined
|
regionCode: string | undefined
|
||||||
): Array<ConversationType> {
|
): ReadonlyArray<Pick<Fuse.FuseResult<ConversationType>, 'item' | 'score'>> {
|
||||||
const maybeCommand = searchTerm.match(/^!([^\s]+):(.*)$/);
|
const maybeCommand = searchTerm.match(/^!([^\s]+):(.*)$/);
|
||||||
if (maybeCommand) {
|
if (maybeCommand) {
|
||||||
const [, commandName, query] = maybeCommand;
|
const [, commandName, query] = maybeCommand;
|
||||||
|
|
||||||
const command = COMMANDS.get(commandName);
|
const command = COMMANDS.get(commandName);
|
||||||
if (command) {
|
if (command) {
|
||||||
return command(conversations, query);
|
return command(conversations, query).map(item => ({ item }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,8 +105,7 @@ function searchConversations(
|
||||||
cachedIndices.set(conversations, index);
|
cachedIndices.set(conversations, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
const results = index.search(extendedSearchTerm);
|
return index.search(extendedSearchTerm);
|
||||||
return results.map(result => result.item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function filterAndSortConversationsByRecent(
|
export function filterAndSortConversationsByRecent(
|
||||||
|
@ -108,7 +114,24 @@ export function filterAndSortConversationsByRecent(
|
||||||
regionCode: string | undefined
|
regionCode: string | undefined
|
||||||
): Array<ConversationType> {
|
): Array<ConversationType> {
|
||||||
if (searchTerm.length) {
|
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) => {
|
return conversations.concat().sort((a, b) => {
|
||||||
|
@ -126,7 +149,12 @@ export function filterAndSortConversationsByTitle(
|
||||||
regionCode: string | undefined
|
regionCode: string | undefined
|
||||||
): Array<ConversationType> {
|
): Array<ConversationType> {
|
||||||
if (searchTerm.length) {
|
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) => {
|
return conversations.concat().sort((a, b) => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue