pinafore/src/routes/_actions/autosuggestAccountSearch.js

80 lines
2.2 KiB
JavaScript
Raw Normal View History

import { database } from '../_database/database'
import { store } from '../_store/store'
import { search } from '../_api/search'
import { SEARCH_RESULTS_LIMIT } from '../_static/autosuggest'
import { USERNAME_LOWERCASE } from '../_database/constants'
import { concat } from '../_utils/arrays'
import uniqBy from 'lodash-es/uniqBy'
import { scheduleIdleTask } from '../_utils/scheduleIdleTask'
const DATABASE_SEARCH_RESULTS_LIMIT = 30
function byAccountRelevance (a, b) {
// accounts you're following go first
if (a.following !== b.following) {
return a.following ? -1 : 1
}
// after that, just sort by username
if (a[USERNAME_LOWERCASE] !== b[USERNAME_LOWERCASE]) {
return a[USERNAME_LOWERCASE] < b[USERNAME_LOWERCASE] ? -1 : 1
}
return 0
}
function byAccountId (a) {
return a.id
}
export function doAccountSearch (searchText) {
let canceled = false
let localResults
let remoteResults
let { currentInstance, accessToken } = store.get()
async function searchAccountsLocally (searchText) {
localResults = await database.searchAccountsByUsername(
currentInstance, searchText.substring(1), DATABASE_SEARCH_RESULTS_LIMIT)
}
async function searchAccountsRemotely (searchText) {
remoteResults = (await search(currentInstance, accessToken, searchText, false, SEARCH_RESULTS_LIMIT)).accounts
}
function mergeAndTruncateResults () {
return uniqBy(concat(localResults || [], remoteResults || []), byAccountId)
.sort(byAccountRelevance)
.slice(0, SEARCH_RESULTS_LIMIT)
}
function onNewResults () {
if (canceled) {
return
}
let results = mergeAndTruncateResults()
store.setForCurrentAutosuggest({
autosuggestType: 'account',
autosuggestSelected: 0,
autosuggestSearchResults: results
})
}
scheduleIdleTask(() => {
if (canceled) {
return
}
// run the two searches in parallel
searchAccountsLocally(searchText).then(onNewResults).catch(err => {
console.error('could not search locally', err)
})
searchAccountsRemotely(searchText).then(onNewResults).catch(err => {
console.error('could not search remotely', err)
})
})
return {
cancel: () => {
canceled = true
}
}
}