mirror of
https://github.com/elk-zone/elk.git
synced 2024-11-20 07:49:57 +00:00
refactor: search
This commit is contained in:
parent
d386a2dbbe
commit
cf561870f0
8 changed files with 74 additions and 86 deletions
|
@ -1,5 +1,5 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { ResolvedCommand } from '@/composables/command'
|
import type { ResolvedCommand } from '~/composables/command'
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(event: 'activate'): void
|
(event: 'activate'): void
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { AccountResult, HashTagResult, SearchResult as SearchResultType } from '@/components/search/types'
|
import type { SearchResult as SearchResultType } from '~/composables/masto/search'
|
||||||
import type { CommandScope, QueryResult, QueryResultItem } from '@/composables/command'
|
import type { CommandScope, QueryResult, QueryResultItem } from '~/composables/command'
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
(event: 'close'): void
|
(event: 'close'): void
|
||||||
|
@ -39,22 +39,8 @@ const searchResult = $computed<QueryResult>(() => {
|
||||||
|
|
||||||
// TODO extract this scope
|
// TODO extract this scope
|
||||||
// duplicate in SearchWidget.vue
|
// duplicate in SearchWidget.vue
|
||||||
const hashtagList = hashtags.value.slice(0, 3)
|
const hashtagList = hashtags.value.slice(0, 3).map(toSearchQueryResultItem)
|
||||||
.map<HashTagResult>(hashtag => ({
|
const accountList = accounts.value.map(toSearchQueryResultItem)
|
||||||
type: 'hashtag',
|
|
||||||
id: `hashtag-${hashtag.name}`,
|
|
||||||
hashtag,
|
|
||||||
to: getTagRoute(hashtag.name),
|
|
||||||
}))
|
|
||||||
.map(toSearchQueryResultItem)
|
|
||||||
const accountList = accounts.value
|
|
||||||
.map<AccountResult>(account => ({
|
|
||||||
type: 'account',
|
|
||||||
id: account.id,
|
|
||||||
account,
|
|
||||||
to: getAccountRoute(account),
|
|
||||||
}))
|
|
||||||
.map(toSearchQueryResultItem)
|
|
||||||
|
|
||||||
const grouped: QueryResult['grouped'] = new Map()
|
const grouped: QueryResult['grouped'] = new Map()
|
||||||
grouped.set('Hashtags', hashtagList)
|
grouped.set('Hashtags', hashtagList)
|
||||||
|
|
|
@ -22,7 +22,10 @@ const totalTrend = $computed(() =>
|
||||||
<CommonTrending :history="hashtag.history" text-xs text-secondary truncate />
|
<CommonTrending :history="hashtag.history" text-xs text-secondary truncate />
|
||||||
</div>
|
</div>
|
||||||
<div v-if="totalTrend" absolute left-15 right-0 top-0 bottom-4 op35 flex place-items-center place-content-center ml-auto>
|
<div v-if="totalTrend" absolute left-15 right-0 top-0 bottom-4 op35 flex place-items-center place-content-center ml-auto>
|
||||||
<CommonTrendingCharts :history="hashtag.history" text-xs text-secondary width="150" height="20" h-full w-full />
|
<CommonTrendingCharts
|
||||||
|
:history="hashtag.history" :width="150" :height="20"
|
||||||
|
text-xs text-secondary h-full w-full
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { SearchResult } from './types'
|
import type { SearchResult } from '~/composables/masto/search'
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
result: SearchResult
|
result: SearchResult
|
||||||
|
@ -21,9 +21,9 @@ const onActivate = () => {
|
||||||
:class="{ 'bg-active': active }"
|
:class="{ 'bg-active': active }"
|
||||||
@click="() => onActivate()"
|
@click="() => onActivate()"
|
||||||
>
|
>
|
||||||
<SearchHashtagInfo v-if="result.type === 'hashtag'" :hashtag="result.hashtag" />
|
<SearchHashtagInfo v-if="result.type === 'hashtag'" :hashtag="result.data" />
|
||||||
<SearchAccountInfo v-else-if="result.type === 'account' && result.account" :account="result.account" />
|
<SearchAccountInfo v-else-if="result.type === 'account'" :account="result.data" />
|
||||||
<StatusCard v-else-if="result.type === 'status' && result.status" :status="result.status" :actions="false" :show-reply-to="false" />
|
<StatusCard v-else-if="result.type === 'status'" :status="result.data" :actions="false" :show-reply-to="false" />
|
||||||
<!-- <div v-else-if="result.type === 'action'" text-center>
|
<!-- <div v-else-if="result.type === 'action'" text-center>
|
||||||
{{ result.action!.label }}
|
{{ result.action!.label }}
|
||||||
</div> -->
|
</div> -->
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { AccountResult, HashTagResult, StatusResult } from './types'
|
|
||||||
|
|
||||||
const query = ref('')
|
const query = ref('')
|
||||||
const { accounts, hashtags, loading, statuses } = useSearch(query)
|
const { accounts, hashtags, loading, statuses } = useSearch(query)
|
||||||
const index = ref(0)
|
const index = ref(0)
|
||||||
|
@ -15,24 +13,9 @@ const results = computed(() => {
|
||||||
return []
|
return []
|
||||||
|
|
||||||
const results = [
|
const results = [
|
||||||
...hashtags.value.slice(0, 3).map<HashTagResult>(hashtag => ({
|
...hashtags.value.slice(0, 3),
|
||||||
type: 'hashtag',
|
...accounts.value,
|
||||||
id: `hashtag-${hashtag.name}`,
|
...statuses.value,
|
||||||
hashtag,
|
|
||||||
to: getTagRoute(hashtag.name),
|
|
||||||
})),
|
|
||||||
...accounts.value.map<AccountResult>(account => ({
|
|
||||||
type: 'account',
|
|
||||||
id: account.id,
|
|
||||||
account,
|
|
||||||
to: getAccountRoute(account),
|
|
||||||
})),
|
|
||||||
...statuses.value.map<StatusResult>(status => ({
|
|
||||||
type: 'status',
|
|
||||||
id: status.id,
|
|
||||||
status,
|
|
||||||
to: getStatusRoute(status),
|
|
||||||
})),
|
|
||||||
|
|
||||||
// Disable until search page is implemented
|
// Disable until search page is implemented
|
||||||
// {
|
// {
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
import type { Account, Status, Tag } from 'masto'
|
|
||||||
import type { RouteLocation } from 'vue-router'
|
|
||||||
|
|
||||||
export type BuildResult<K extends keyof any, T> = {
|
|
||||||
[P in K]: T
|
|
||||||
} & {
|
|
||||||
id: string
|
|
||||||
type: K
|
|
||||||
to: RouteLocation & {
|
|
||||||
href: string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export type HashTagResult = BuildResult<'hashtag', Tag>
|
|
||||||
export type AccountResult = BuildResult<'account', Account>
|
|
||||||
export type StatusResult = BuildResult<'status', Status>
|
|
||||||
|
|
||||||
export type SearchResult = HashTagResult | AccountResult | StatusResult
|
|
|
@ -2,7 +2,7 @@ import type { ComputedRef } from 'vue'
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import Fuse from 'fuse.js'
|
import Fuse from 'fuse.js'
|
||||||
import type { LocaleObject } from '#i18n'
|
import type { LocaleObject } from '#i18n'
|
||||||
import type { SearchResult } from '@/components/search/types'
|
import type { SearchResult } from '~/composables/masto/search'
|
||||||
|
|
||||||
// @unocss-include
|
// @unocss-include
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,61 @@
|
||||||
import type { MaybeRef } from '@vueuse/core'
|
import type { MaybeRef } from '@vueuse/core'
|
||||||
import type { Account, Paginator, Results, SearchParams, Status, Tag } from 'masto'
|
import type { Account, Paginator, Results, SearchParams, SearchType, Status, Tag } from 'masto'
|
||||||
|
import type { RouteLocation } from 'vue-router'
|
||||||
|
|
||||||
export interface UseSearchOptions {
|
export interface UseSearchOptions {
|
||||||
type?: MaybeRef<'accounts' | 'hashtags' | 'statuses'>
|
type?: MaybeRef<SearchType>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface BuildSearchResult<K extends keyof any, T> {
|
||||||
|
id: string
|
||||||
|
type: K
|
||||||
|
data: T
|
||||||
|
to: RouteLocation & {
|
||||||
|
href: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export type AccountSearchResult = BuildSearchResult<'account', Account>
|
||||||
|
export type HashTagSearchResult = BuildSearchResult<'hashtag', Tag>
|
||||||
|
export type StatusSearchResult = BuildSearchResult<'status', Status>
|
||||||
|
|
||||||
|
export type SearchResult = HashTagSearchResult | AccountSearchResult | StatusSearchResult
|
||||||
|
|
||||||
export function useSearch(query: MaybeRef<string>, options?: UseSearchOptions) {
|
export function useSearch(query: MaybeRef<string>, options?: UseSearchOptions) {
|
||||||
const done = ref(false)
|
const done = ref(false)
|
||||||
const masto = useMasto()
|
const masto = useMasto()
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const statuses = ref<Status[]>([])
|
const accounts = ref<AccountSearchResult[]>([])
|
||||||
const accounts = ref<Account[]>([])
|
const hashtags = ref<HashTagSearchResult[]>([])
|
||||||
const hashtags = ref<Tag[]>([])
|
const statuses = ref<StatusSearchResult[]>([])
|
||||||
|
|
||||||
let paginator: Paginator<SearchParams, Results> | undefined
|
let paginator: Paginator<SearchParams, Results> | undefined
|
||||||
|
|
||||||
|
const appendResults = (results: Results, empty = false) => {
|
||||||
|
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),
|
||||||
|
}))]
|
||||||
|
}
|
||||||
|
|
||||||
debouncedWatch(() => unref(query), async () => {
|
debouncedWatch(() => unref(query), async () => {
|
||||||
if (!unref(query) || !isMastoInitialised.value)
|
if (!unref(query) || !isMastoInitialised.value)
|
||||||
return
|
return
|
||||||
|
@ -25,14 +66,16 @@ export function useSearch(query: MaybeRef<string>, options?: UseSearchOptions) {
|
||||||
* Based on the source it seems like modifying the params when calling next would result in a new search,
|
* 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.
|
* but that doesn't seem to be the case. So instead we just create a new paginator with the new params.
|
||||||
*/
|
*/
|
||||||
paginator = masto.search({ q: unref(query), resolve: !!currentUser.value, type: unref(options?.type) })
|
paginator = masto.search({
|
||||||
|
q: unref(query),
|
||||||
|
resolve: !!currentUser.value,
|
||||||
|
type: unref(options?.type),
|
||||||
|
})
|
||||||
const nextResults = await paginator.next()
|
const nextResults = await paginator.next()
|
||||||
|
|
||||||
done.value = nextResults.done || false
|
done.value = !!nextResults.done
|
||||||
|
if (!nextResults.done)
|
||||||
statuses.value = nextResults.value?.statuses || []
|
appendResults(nextResults.value, true)
|
||||||
accounts.value = nextResults.value?.accounts || []
|
|
||||||
hashtags.value = nextResults.value?.hashtags || []
|
|
||||||
|
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}, { debounce: 500 })
|
}, { debounce: 500 })
|
||||||
|
@ -45,19 +88,9 @@ export function useSearch(query: MaybeRef<string>, options?: UseSearchOptions) {
|
||||||
const nextResults = await paginator.next()
|
const nextResults = await paginator.next()
|
||||||
loading.value = false
|
loading.value = false
|
||||||
|
|
||||||
done.value = nextResults.done || false
|
done.value = !!nextResults.done
|
||||||
statuses.value = [
|
if (!nextResults.done)
|
||||||
...statuses.value,
|
appendResults(nextResults.value)
|
||||||
...(nextResults.value.statuses || []),
|
|
||||||
]
|
|
||||||
accounts.value = [
|
|
||||||
...statuses.value,
|
|
||||||
...(nextResults.value.accounts || []),
|
|
||||||
]
|
|
||||||
hashtags.value = [
|
|
||||||
...statuses.value,
|
|
||||||
...(nextResults.value.statuses || []),
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
Loading…
Reference in a new issue