You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

77 lines
2.7 KiB

import { buildExplorePopularRelayUrls } from '@/lib/explore-popular-relays'
import { toRelay } from '@/lib/link'
import { normalizeAnyRelayUrl, simplifyUrl } from '@/lib/url'
import { useSmartRelayNavigation } from '@/PageManager'
import { useFavoriteRelays } from '@/providers/FavoriteRelaysProvider'
import { useNostr } from '@/providers/NostrProvider'
import indexedDb from '@/services/indexed-db.service'
import { useEffect, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
/**
* Lightweight Explore relay list: URLs from the viewer's NIP-65 / favorites / defaults and optional
* cached NIP-66 data — no GitHub collections fetch and no NIP-11 storm on mount.
*/
export default function ExplorePopularRelays() {
const { t } = useTranslation()
const { relayList } = useNostr()
const { favoriteRelays, blockedRelays } = useFavoriteRelays()
const { navigateToRelay } = useSmartRelayNavigation()
const [nip66Cached, setNip66Cached] = useState<string[]>([])
useEffect(() => {
let cancelled = false
void indexedDb
.getPublicLivelyRelayUrlsCache()
.then((c) => {
if (!cancelled && c?.urls?.length) setNip66Cached(c.urls)
})
.catch(() => {})
return () => {
cancelled = true
}
}, [])
const urls = useMemo(
() =>
buildExplorePopularRelayUrls({
relayList,
favoriteRelays,
blockedRelays,
nip66CachedUrls: nip66Cached
}),
[relayList, favoriteRelays, blockedRelays, nip66Cached]
)
if (urls.length === 0) {
return (
<p className="px-4 py-6 text-sm text-muted-foreground">{t('No relays in your lists yet.')}</p>
)
}
return (
<section className="min-w-0 pb-6" aria-label={t('Popular relays')}>
<h2 className="mb-2 px-4 text-base font-semibold tracking-tight">{t('Popular relays')}</h2>
<p className="mb-3 px-4 text-sm text-muted-foreground">
{t('From your mailbox, favorites, and cached relay lists on this device.')}
</p>
<ul className="grid min-w-0 gap-2 px-2 md:grid-cols-2 md:px-4">
{urls.map((url) => {
const key = normalizeAnyRelayUrl(url) || url
return (
<li key={key}>
<button
type="button"
className="flex w-full min-w-0 flex-col rounded-lg border bg-card px-3 py-2.5 text-left shadow-sm transition-colors hover:bg-accent/40"
onClick={() => navigateToRelay(toRelay(url))}
>
<span className="truncate font-mono text-sm font-semibold">{simplifyUrl(url)}</span>
<span className="mt-0.5 truncate text-xs text-muted-foreground">{url}</span>
</button>
</li>
)
})}
</ul>
</section>
)
}