feat: replace user search service

This commit is contained in:
codytseng 2026-01-15 22:58:55 +08:00
parent 400da44543
commit b6cb701ff1
5 changed files with 86 additions and 84 deletions

View file

@ -1,76 +1,48 @@
import { SEARCHABLE_RELAY_URLS } from '@/constants'
import client from '@/services/client.service'
import dayjs from 'dayjs'
import { useEffect, useRef, useState } from 'react'
import { useInfiniteScroll } from '@/hooks'
import fayan from '@/services/fayan.service'
import { useCallback, useEffect, useState } from 'react'
import UserItem, { UserItemSkeleton } from '../UserItem'
const LIMIT = 50
const SHOW_COUNT = 20
export function ProfileListBySearch({ search }: { search: string }) {
const [until, setUntil] = useState<number>(() => dayjs().unix())
const [hasMore, setHasMore] = useState<boolean>(true)
const [pubkeySet, setPubkeySet] = useState(new Set<string>())
const bottomRef = useRef<HTMLDivElement>(null)
const [pubkeys, setPubkeys] = useState<string[]>([])
useEffect(() => {
setUntil(dayjs().unix())
setHasMore(true)
setPubkeySet(new Set<string>())
loadMore()
setPubkeys([])
}, [search])
useEffect(() => {
if (!hasMore) return
const options = {
root: null,
rootMargin: '10px',
threshold: 1
const handleLoadMore = useCallback(async () => {
const profiles = await fayan.searchUsers(search, LIMIT, pubkeys.length)
if (profiles.length === 0) {
return false
}
const observerInstance = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting && hasMore) {
loadMore()
}
}, options)
const currentBottomRef = bottomRef.current
if (currentBottomRef) {
observerInstance.observe(currentBottomRef)
}
return () => {
if (observerInstance && currentBottomRef) {
observerInstance.unobserve(currentBottomRef)
}
}
}, [hasMore, search, until])
const loadMore = async () => {
const profiles = await client.searchProfiles(SEARCHABLE_RELAY_URLS, {
search,
until,
limit: LIMIT
})
const newPubkeySet = new Set<string>()
const pubkeySet = new Set(pubkeys)
const newPubkeys = [...pubkeys]
profiles.forEach((profile) => {
if (!pubkeySet.has(profile.pubkey)) {
newPubkeySet.add(profile.pubkey)
pubkeySet.add(profile.pubkey)
newPubkeys.push(profile.pubkey)
}
})
setPubkeySet((prev) => new Set([...prev, ...newPubkeySet]))
setHasMore(profiles.length >= LIMIT)
const lastProfileCreatedAt = profiles[profiles.length - 1].created_at
setUntil(lastProfileCreatedAt ? lastProfileCreatedAt - 1 : 0)
}
setPubkeys(newPubkeys)
return profiles.length >= LIMIT
}, [search, pubkeys])
const { visibleItems, shouldShowLoadingIndicator, bottomRef } = useInfiniteScroll({
items: pubkeys,
showCount: SHOW_COUNT,
onLoadMore: handleLoadMore
})
return (
<div className="px-4">
{Array.from(pubkeySet).map((pubkey, index) => (
{visibleItems.map((pubkey, index) => (
<UserItem key={`${index}-${pubkey}`} userId={pubkey} />
))}
{hasMore && <UserItemSkeleton />}
{hasMore && <div ref={bottomRef} />}
<div ref={bottomRef} />
{shouldShowLoadingIndicator && <UserItemSkeleton />}
</div>
)
}