diff --git a/components/search/HashtagInfo.vue b/components/search/HashtagInfo.vue new file mode 100644 index 00000000..20e53228 --- /dev/null +++ b/components/search/HashtagInfo.vue @@ -0,0 +1,19 @@ + + + diff --git a/components/search/SearchResult.vue b/components/search/SearchResult.vue new file mode 100644 index 00000000..cdfbe54a --- /dev/null +++ b/components/search/SearchResult.vue @@ -0,0 +1,26 @@ + + + diff --git a/components/search/SearchResultSkeleton.vue b/components/search/SearchResultSkeleton.vue new file mode 100644 index 00000000..0ac0aca1 --- /dev/null +++ b/components/search/SearchResultSkeleton.vue @@ -0,0 +1,13 @@ + diff --git a/components/search/SearchWidget.vue b/components/search/SearchWidget.vue new file mode 100644 index 00000000..25563771 --- /dev/null +++ b/components/search/SearchWidget.vue @@ -0,0 +1,92 @@ + + + diff --git a/components/search/types.ts b/components/search/types.ts new file mode 100644 index 00000000..a32c22bc --- /dev/null +++ b/components/search/types.ts @@ -0,0 +1,12 @@ +import type { Account } from 'masto' + +export interface SearchResult { + type: 'account' | 'hashtag' | 'action' + to: string + label?: string + account?: Account + hashtag?: any + action?: { + label: string + } +} diff --git a/composables/search.ts b/composables/search.ts new file mode 100644 index 00000000..d9434291 --- /dev/null +++ b/composables/search.ts @@ -0,0 +1,68 @@ +import type { MaybeRef } from '@vueuse/core' +import type { Account, Status } from 'masto' + +export interface UseSearchOptions { + type?: MaybeRef<'accounts' | 'hashtags' | 'statuses'> +} + +export function useSearch(query: MaybeRef, options?: UseSearchOptions) { + let paginator = useMasto().search({ q: unref(query), type: unref(options?.type) }) + const done = ref(false) + const loading = ref(false) + const statuses = ref([]) + const accounts = ref([]) + const hashtags = ref([]) + + debouncedWatch(() => unref(query), async () => { + if (!unref(query)) + 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. + */ + paginator = useMasto().search({ q: unref(query), type: unref(options?.type) }) + const nextResults = await paginator.next() + + done.value = nextResults.done || false + + statuses.value = nextResults.value?.statuses || [] + accounts.value = nextResults.value?.accounts || [] + hashtags.value = nextResults.value?.hashtags || [] + + loading.value = false + }, { debounce: 500 }) + + const next = async () => { + if (!unref(query)) + return + + loading.value = true + const nextResults = await paginator.next() + loading.value = false + + done.value = nextResults.done || false + statuses.value = [ + ...statuses.value, + ...(nextResults.value.statuses || []), + ] + accounts.value = [ + ...statuses.value, + ...(nextResults.value.accounts || []), + ] + hashtags.value = [ + ...statuses.value, + ...(nextResults.value.statuses || []), + ] + } + + return { + accounts, + hashtags, + statuses, + loading: readonly(loading), + next, + } +} diff --git a/layouts/default.vue b/layouts/default.vue index d11819e6..d08587e6 100644 --- a/layouts/default.vue +++ b/layouts/default.vue @@ -25,6 +25,7 @@