mirror of
https://github.com/truewhile/MeBox.git
synced 2026-10-02 12:26:36 +08:00
86 lines
2.2 KiB
TypeScript
86 lines
2.2 KiB
TypeScript
import { useEffect, useMemo, useRef, useState, type FormEvent } from 'react'
|
|
import type { NavigateFunction } from 'react-router-dom'
|
|
|
|
import { mediaAPI } from '../api/library'
|
|
import type { Media } from '../types'
|
|
import { groupSeries } from '../utils/groupSeries'
|
|
|
|
type UseLayoutSearchOptions = {
|
|
pathname: string
|
|
locationSearch: string
|
|
navigate: NavigateFunction
|
|
}
|
|
|
|
export function useLayoutSearch({ pathname, locationSearch, navigate }: UseLayoutSearchOptions) {
|
|
const [focused, setFocused] = useState(false)
|
|
const [query, setQuery] = useState('')
|
|
const [items, setItems] = useState<Media[]>([])
|
|
const [loading, setLoading] = useState(false)
|
|
const [total, setTotal] = useState(0)
|
|
const [error, setError] = useState('')
|
|
const searchSeq = useRef(0)
|
|
const cards = useMemo(() => groupSeries(items).slice(0, 8), [items])
|
|
|
|
useEffect(() => {
|
|
if (pathname === '/search') {
|
|
setQuery(new URLSearchParams(locationSearch).get('q') ?? '')
|
|
}
|
|
}, [pathname, locationSearch])
|
|
|
|
useEffect(() => {
|
|
const trimmedQuery = query.trim()
|
|
const seq = ++searchSeq.current
|
|
if (!focused || !trimmedQuery) {
|
|
setItems([])
|
|
setTotal(0)
|
|
setError('')
|
|
setLoading(false)
|
|
return
|
|
}
|
|
|
|
setLoading(true)
|
|
setError('')
|
|
const timer = window.setTimeout(() => {
|
|
mediaAPI
|
|
.search(trimmedQuery, 24)
|
|
.then((data) => {
|
|
if (seq !== searchSeq.current) return
|
|
setItems(data.items ?? [])
|
|
setTotal(data.total ?? (data.items ?? []).length)
|
|
})
|
|
.catch(() => {
|
|
if (seq !== searchSeq.current) return
|
|
setItems([])
|
|
setTotal(0)
|
|
setError('搜索失败,请稍后再试')
|
|
})
|
|
.finally(() => {
|
|
if (seq === searchSeq.current) setLoading(false)
|
|
})
|
|
}, 220)
|
|
|
|
return () => window.clearTimeout(timer)
|
|
}, [focused, query])
|
|
|
|
const submit = (event: FormEvent) => {
|
|
event.preventDefault()
|
|
const trimmedQuery = query.trim()
|
|
if (trimmedQuery) {
|
|
navigate(`/search?q=${encodeURIComponent(trimmedQuery)}`)
|
|
setFocused(false)
|
|
}
|
|
}
|
|
|
|
return {
|
|
cards,
|
|
error,
|
|
focused,
|
|
loading,
|
|
query,
|
|
total,
|
|
setFocused,
|
|
setQuery,
|
|
submit,
|
|
}
|
|
}
|