feat: add note search to profile page
This commit is contained in:
@@ -1,13 +1,14 @@
|
|||||||
import KindFilter from '@/components/KindFilter'
|
import KindFilter from '@/components/KindFilter'
|
||||||
import NoteList, { TNoteListRef } from '@/components/NoteList'
|
import NoteList, { TNoteListRef } from '@/components/NoteList'
|
||||||
import Tabs from '@/components/Tabs'
|
import Tabs from '@/components/Tabs'
|
||||||
import { BIG_RELAY_URLS, MAX_PINNED_NOTES } from '@/constants'
|
import { BIG_RELAY_URLS, MAX_PINNED_NOTES, SEARCHABLE_RELAY_URLS } from '@/constants'
|
||||||
import { generateBech32IdFromETag } from '@/lib/tag'
|
import { generateBech32IdFromETag } from '@/lib/tag'
|
||||||
import { isTouchDevice } from '@/lib/utils'
|
import { isTouchDevice } from '@/lib/utils'
|
||||||
import { useKindFilter } from '@/providers/KindFilterProvider'
|
import { useKindFilter } from '@/providers/KindFilterProvider'
|
||||||
import { useNostr } from '@/providers/NostrProvider'
|
import { useNostr } from '@/providers/NostrProvider'
|
||||||
import client from '@/services/client.service'
|
import client from '@/services/client.service'
|
||||||
import storage from '@/services/local-storage.service'
|
import storage from '@/services/local-storage.service'
|
||||||
|
import relayInfoService from '@/services/relay-info.service'
|
||||||
import { TFeedSubRequest, TNoteListMode } from '@/types'
|
import { TFeedSubRequest, TNoteListMode } from '@/types'
|
||||||
import { NostrEvent } from 'nostr-tools'
|
import { NostrEvent } from 'nostr-tools'
|
||||||
import { useEffect, useMemo, useRef, useState } from 'react'
|
import { useEffect, useMemo, useRef, useState } from 'react'
|
||||||
@@ -15,10 +16,12 @@ import { RefreshButton } from '../RefreshButton'
|
|||||||
|
|
||||||
export default function ProfileFeed({
|
export default function ProfileFeed({
|
||||||
pubkey,
|
pubkey,
|
||||||
topSpace = 0
|
topSpace = 0,
|
||||||
|
search = ''
|
||||||
}: {
|
}: {
|
||||||
pubkey: string
|
pubkey: string
|
||||||
topSpace?: number
|
topSpace?: number
|
||||||
|
search?: string
|
||||||
}) {
|
}) {
|
||||||
const { pubkey: myPubkey, pinListEvent: myPinListEvent } = useNostr()
|
const { pubkey: myPubkey, pinListEvent: myPinListEvent } = useNostr()
|
||||||
const { showKinds } = useKindFilter()
|
const { showKinds } = useKindFilter()
|
||||||
@@ -106,6 +109,20 @@ export default function ProfileFeed({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const relayList = await client.fetchRelayList(pubkey)
|
const relayList = await client.fetchRelayList(pubkey)
|
||||||
|
|
||||||
|
if (search) {
|
||||||
|
const writeRelays = relayList.write.slice(0, 8)
|
||||||
|
const relayInfos = await relayInfoService.getRelayInfos(writeRelays)
|
||||||
|
const searchableRelays = writeRelays.filter((_, index) =>
|
||||||
|
relayInfos[index]?.supported_nips?.includes(50)
|
||||||
|
)
|
||||||
|
setSubRequests([
|
||||||
|
{
|
||||||
|
urls: searchableRelays.concat(SEARCHABLE_RELAY_URLS).slice(0, 8),
|
||||||
|
filter: { authors: [pubkey], search }
|
||||||
|
}
|
||||||
|
])
|
||||||
|
} else {
|
||||||
setSubRequests([
|
setSubRequests([
|
||||||
{
|
{
|
||||||
urls: relayList.write.concat(BIG_RELAY_URLS).slice(0, 8),
|
urls: relayList.write.concat(BIG_RELAY_URLS).slice(0, 8),
|
||||||
@@ -115,8 +132,9 @@ export default function ProfileFeed({
|
|||||||
}
|
}
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
}
|
||||||
init()
|
init()
|
||||||
}, [pubkey, listMode])
|
}, [pubkey, listMode, search])
|
||||||
|
|
||||||
const handleListModeChange = (mode: TNoteListMode) => {
|
const handleListModeChange = (mode: TNoteListMode) => {
|
||||||
setListMode(mode)
|
setListMode(mode)
|
||||||
@@ -150,7 +168,7 @@ export default function ProfileFeed({
|
|||||||
showKinds={temporaryShowKinds}
|
showKinds={temporaryShowKinds}
|
||||||
hideReplies={listMode === 'posts'}
|
hideReplies={listMode === 'posts'}
|
||||||
filterMutedNotes={false}
|
filterMutedNotes={false}
|
||||||
pinnedEventIds={listMode === 'you' ? [] : pinnedEventIds}
|
pinnedEventIds={listMode === 'you' || !!search ? [] : pinnedEventIds}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import { Link, Zap } from 'lucide-react'
|
|||||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import NotFound from '../NotFound'
|
import NotFound from '../NotFound'
|
||||||
|
import SearchInput from '../SearchInput'
|
||||||
import FollowedBy from './FollowedBy'
|
import FollowedBy from './FollowedBy'
|
||||||
import Followings from './Followings'
|
import Followings from './Followings'
|
||||||
import ProfileFeed from './ProfileFeed'
|
import ProfileFeed from './ProfileFeed'
|
||||||
@@ -32,6 +33,8 @@ export default function Profile({ id }: { id?: string }) {
|
|||||||
const { profile, isFetching } = useFetchProfile(id)
|
const { profile, isFetching } = useFetchProfile(id)
|
||||||
const { pubkey: accountPubkey } = useNostr()
|
const { pubkey: accountPubkey } = useNostr()
|
||||||
const { mutePubkeySet } = useMuteList()
|
const { mutePubkeySet } = useMuteList()
|
||||||
|
const [searchInput, setSearchInput] = useState('')
|
||||||
|
const [debouncedInput, setDebouncedInput] = useState(searchInput)
|
||||||
const { followings } = useFetchFollowings(profile?.pubkey)
|
const { followings } = useFetchFollowings(profile?.pubkey)
|
||||||
const isFollowingYou = useMemo(() => {
|
const isFollowingYou = useMemo(() => {
|
||||||
return (
|
return (
|
||||||
@@ -51,6 +54,16 @@ export default function Profile({ id }: { id?: string }) {
|
|||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handler = setTimeout(() => {
|
||||||
|
setDebouncedInput(searchInput.trim())
|
||||||
|
}, 1000)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
clearTimeout(handler)
|
||||||
|
}
|
||||||
|
}, [searchInput])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!profile?.pubkey) return
|
if (!profile?.pubkey) return
|
||||||
|
|
||||||
@@ -185,8 +198,15 @@ export default function Profile({ id }: { id?: string }) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="px-4 pt-2 pb-0.5">
|
||||||
|
<SearchInput
|
||||||
|
value={searchInput}
|
||||||
|
onChange={(e) => setSearchInput(e.target.value)}
|
||||||
|
placeholder={t('Search')}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<ProfileFeed pubkey={pubkey} topSpace={topContainerHeight + 100} />
|
</div>
|
||||||
|
<ProfileFeed pubkey={pubkey} topSpace={topContainerHeight + 100} search={debouncedInput} />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user