2022-12-17 21:35:07 +00:00
|
|
|
import type { MaybeRef } from '@vueuse/core'
|
2023-01-08 06:21:09 +00:00
|
|
|
import type { Paginator, mastodon } from 'masto'
|
2023-01-07 14:52:58 +00:00
|
|
|
import type { RouteLocation } from 'vue-router'
|
2022-12-17 21:35:07 +00:00
|
|
|
|
|
|
|
export interface UseSearchOptions {
|
2023-01-08 06:21:09 +00:00
|
|
|
type?: MaybeRef<mastodon.v2.SearchType>
|
2022-12-17 21:35:07 +00:00
|
|
|
}
|
|
|
|
|
2023-01-07 14:52:58 +00:00
|
|
|
export interface BuildSearchResult<K extends keyof any, T> {
|
|
|
|
id: string
|
|
|
|
type: K
|
|
|
|
data: T
|
|
|
|
to: RouteLocation & {
|
|
|
|
href: string
|
|
|
|
}
|
|
|
|
}
|
2023-01-08 06:21:09 +00:00
|
|
|
export type AccountSearchResult = BuildSearchResult<'account', mastodon.v1.Account>
|
|
|
|
export type HashTagSearchResult = BuildSearchResult<'hashtag', mastodon.v1.Tag>
|
|
|
|
export type StatusSearchResult = BuildSearchResult<'status', mastodon.v1.Status>
|
2023-01-07 14:52:58 +00:00
|
|
|
|
|
|
|
export type SearchResult = HashTagSearchResult | AccountSearchResult | StatusSearchResult
|
|
|
|
|
2022-12-17 21:35:07 +00:00
|
|
|
export function useSearch(query: MaybeRef<string>, options?: UseSearchOptions) {
|
|
|
|
const done = ref(false)
|
2022-12-29 14:44:26 +00:00
|
|
|
const masto = useMasto()
|
2022-12-17 21:35:07 +00:00
|
|
|
const loading = ref(false)
|
2023-01-07 14:52:58 +00:00
|
|
|
const accounts = ref<AccountSearchResult[]>([])
|
|
|
|
const hashtags = ref<HashTagSearchResult[]>([])
|
|
|
|
const statuses = ref<StatusSearchResult[]>([])
|
2022-12-17 21:35:07 +00:00
|
|
|
|
2023-01-08 06:21:09 +00:00
|
|
|
let paginator: Paginator<mastodon.v2.Search, mastodon.v2.SearchParams> | undefined
|
2022-12-22 10:34:35 +00:00
|
|
|
|
2023-01-08 06:21:09 +00:00
|
|
|
const appendResults = (results: mastodon.v2.Search, empty = false) => {
|
2023-01-07 14:52:58 +00:00
|
|
|
if (empty) {
|
|
|
|
accounts.value = []
|
|
|
|
hashtags.value = []
|
|
|
|
statuses.value = []
|
|
|
|
}
|
|
|
|
accounts.value = [...accounts.value, ...results.accounts.map<AccountSearchResult>(account => ({
|
|
|
|
type: 'account',
|
|
|
|
id: account.id,
|
|
|
|
data: account,
|
|
|
|
to: getAccountRoute(account),
|
|
|
|
}))]
|
|
|
|
hashtags.value = [...hashtags.value, ...results.hashtags.map<HashTagSearchResult>(hashtag => ({
|
|
|
|
type: 'hashtag',
|
|
|
|
id: `hashtag-${hashtag.name}`,
|
|
|
|
data: hashtag,
|
|
|
|
to: getTagRoute(hashtag.name),
|
|
|
|
}))]
|
|
|
|
statuses.value = [...statuses.value, ...results.statuses.map<StatusSearchResult>(status => ({
|
|
|
|
type: 'status',
|
|
|
|
id: status.id,
|
|
|
|
data: status,
|
|
|
|
to: getStatusRoute(status),
|
|
|
|
}))]
|
|
|
|
}
|
|
|
|
|
2023-01-07 14:59:57 +00:00
|
|
|
watch(() => unref(query), () => {
|
2023-01-08 07:57:21 +00:00
|
|
|
loading.value = !!(unref(query) && isMastoInitialised.value)
|
2023-01-07 14:59:57 +00:00
|
|
|
})
|
|
|
|
|
2022-12-17 21:35:07 +00:00
|
|
|
debouncedWatch(() => unref(query), async () => {
|
2022-12-22 10:34:35 +00:00
|
|
|
if (!unref(query) || !isMastoInitialised.value)
|
2022-12-17 21:35:07 +00:00
|
|
|
return
|
|
|
|
|
|
|
|
loading.value = true
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Based on the source it seems like modifying the params when calling next would result in a new search,
|
|
|
|
* but that doesn't seem to be the case. So instead we just create a new paginator with the new params.
|
|
|
|
*/
|
2023-01-08 06:21:09 +00:00
|
|
|
paginator = masto.v2.search({
|
2023-01-07 14:52:58 +00:00
|
|
|
q: unref(query),
|
|
|
|
resolve: !!currentUser.value,
|
|
|
|
type: unref(options?.type),
|
|
|
|
})
|
2022-12-17 21:35:07 +00:00
|
|
|
const nextResults = await paginator.next()
|
|
|
|
|
2023-01-07 14:52:58 +00:00
|
|
|
done.value = !!nextResults.done
|
|
|
|
if (!nextResults.done)
|
|
|
|
appendResults(nextResults.value, true)
|
2022-12-17 21:35:07 +00:00
|
|
|
|
|
|
|
loading.value = false
|
2023-01-07 14:59:57 +00:00
|
|
|
}, { debounce: 300 })
|
2022-12-17 21:35:07 +00:00
|
|
|
|
|
|
|
const next = async () => {
|
2022-12-22 10:34:35 +00:00
|
|
|
if (!unref(query) || !isMastoInitialised.value || !paginator)
|
2022-12-17 21:35:07 +00:00
|
|
|
return
|
|
|
|
|
|
|
|
loading.value = true
|
|
|
|
const nextResults = await paginator.next()
|
|
|
|
loading.value = false
|
|
|
|
|
2023-01-07 14:52:58 +00:00
|
|
|
done.value = !!nextResults.done
|
|
|
|
if (!nextResults.done)
|
|
|
|
appendResults(nextResults.value)
|
2022-12-17 21:35:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
accounts,
|
|
|
|
hashtags,
|
|
|
|
statuses,
|
|
|
|
loading: readonly(loading),
|
|
|
|
next,
|
|
|
|
}
|
|
|
|
}
|