user profile btn in social nav now only is active for current logged in user, added NSFW tag for admin tagged ones, mod search under a specific game, search term and some filters added to url, filter state is saved locally in cache, user search now works #108
@ -4,11 +4,11 @@ import {
|
||||
NDKKind,
|
||||
NDKSubscriptionCacheUsage,
|
||||
NDKUserProfile,
|
||||
NostrEvent,
|
||||
profileFromEvent
|
||||
} from '@nostr-dev-kit/ndk'
|
||||
import { ErrorBoundary } from 'components/ErrorBoundary'
|
||||
import { GameCard } from 'components/GameCard'
|
||||
import { LoadingSpinner } from 'components/LoadingSpinner'
|
||||
import { ModCard } from 'components/ModCard'
|
||||
import { ModFilter } from 'components/ModsFilter'
|
||||
import { Pagination } from 'components/Pagination'
|
||||
@ -35,10 +35,7 @@ import {
|
||||
DEFAULT_FILTER_OPTIONS,
|
||||
extractModData,
|
||||
isModDataComplete,
|
||||
log,
|
||||
LogType,
|
||||
scrollIntoView,
|
||||
timeout
|
||||
scrollIntoView
|
||||
} from 'utils'
|
||||
|
||||
enum SearchKindEnum {
|
||||
@ -364,48 +361,70 @@ const UsersResult = ({
|
||||
moderationFilter,
|
||||
muteLists
|
||||
}: UsersResultProps) => {
|
||||
const { fetchEvents } = useNDKContext()
|
||||
const [isFetching, setIsFetching] = useState(false)
|
||||
const { ndk } = useNDKContext()
|
||||
const [profiles, setProfiles] = useState<NDKUserProfile[]>([])
|
||||
|
||||
const userState = useAppSelector((state) => state.user)
|
||||
|
||||
useEffect(() => {
|
||||
if (searchTerm === '') {
|
||||
setProfiles([])
|
||||
} else {
|
||||
const fetchProfiles = async () => {
|
||||
setIsFetching(true)
|
||||
|
||||
const filter: NDKFilter = {
|
||||
const sub = ndk.subscribe(
|
||||
{
|
||||
kinds: [NDKKind.Metadata],
|
||||
search: searchTerm
|
||||
},
|
||||
{
|
||||
closeOnEose: true,
|
||||
cacheUsage: NDKSubscriptionCacheUsage.PARALLEL
|
||||
},
|
||||
undefined,
|
||||
false
|
||||
)
|
||||
|
||||
// Stop the sub after 10 seconds if we are still searching the same term as before
|
||||
window.setTimeout(() => {
|
||||
if (sub.filter.search === searchTerm) {
|
||||
sub.stop()
|
||||
}
|
||||
}, 10000)
|
||||
|
||||
const profiles = await Promise.race([
|
||||
fetchEvents(filter),
|
||||
timeout(10 * 1000)
|
||||
])
|
||||
.then((events) => {
|
||||
const results = events.map((event) => {
|
||||
const ndkEvent = new NDKEvent(undefined, event)
|
||||
const profile = profileFromEvent(ndkEvent)
|
||||
return profile
|
||||
})
|
||||
return results
|
||||
})
|
||||
.catch((err) => {
|
||||
log(true, LogType.Error, 'An error occurred in fetching users', err)
|
||||
return []
|
||||
})
|
||||
const onEvent = (event: NostrEvent | NDKEvent) => {
|
||||
if (!(event instanceof NDKEvent)) event = new NDKEvent(undefined, event)
|
||||
const dedupKey = event.deduplicationKey()
|
||||
const existingEvent = events.get(dedupKey)
|
||||
if (existingEvent) {
|
||||
event = dedup(existingEvent, event)
|
||||
}
|
||||
event.ndk = this
|
||||
events.set(dedupKey, event)
|
||||
|
||||
// We can't rely on the 'eose' to arrive
|
||||
// Instead we repeat and sort results on each event
|
||||
const ndkEvents = Array.from(events.values())
|
||||
const profiles: NDKUserProfile[] = []
|
||||
ndkEvents.forEach((event) => {
|
||||
try {
|
||||
const profile = profileFromEvent(event)
|
||||
profiles.push(profile)
|
||||
} catch (error) {
|
||||
// If we are unable to parse silently skip over the errors
|
||||
}
|
||||
})
|
||||
setProfiles(profiles)
|
||||
setIsFetching(false)
|
||||
}
|
||||
|
||||
fetchProfiles()
|
||||
// Clear previous results
|
||||
const events = new Map<string, NDKEvent>()
|
||||
|
||||
// Bind handler and start the sub
|
||||
sub.on('event', onEvent)
|
||||
sub.start()
|
||||
return () => {
|
||||
sub.stop()
|
||||
}
|
||||
}, [fetchEvents, searchTerm])
|
||||
}
|
||||
}, [ndk, searchTerm])
|
||||
|
||||
const filteredProfiles = useMemo(() => {
|
||||
let filtered = [...profiles]
|
||||
@ -430,7 +449,6 @@ const UsersResult = ({
|
||||
}, [userState.user?.npub, moderationFilter, profiles, muteLists])
|
||||
return (
|
||||
<>
|
||||
{isFetching && <LoadingSpinner desc='Fetching Profiles' />}
|
||||
<div className='IBMSecMain IBMSMListWrapper'>
|
||||
<div className='IBMSMList'>
|
||||
{filteredProfiles.map((profile) => {
|
||||
@ -505,3 +523,11 @@ const GamesResult = ({ searchTerm }: GamesResultProps) => {
|
||||
</>
|
||||
)
|
||||
}
|
||||
function dedup(event1: NDKEvent, event2: NDKEvent) {
|
||||
// return the newest of the two
|
||||
if (event1.created_at! > event2.created_at!) {
|
||||
return event1
|
||||
}
|
||||
|
||||
return event2
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user