perf: cache following favorite relays
This commit is contained in:
@@ -1,9 +1,8 @@
|
||||
import { useFetchRelayInfo } from '@/hooks'
|
||||
import { toRelay } from '@/lib/link'
|
||||
import { useSecondaryPage } from '@/PageManager'
|
||||
import { useNostr } from '@/providers/NostrProvider'
|
||||
import client from '@/services/client.service'
|
||||
import relayInfoService from '@/services/relay-info.service'
|
||||
import { TNip66RelayInfo } from '@/types'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import RelaySimpleInfo, { RelaySimpleInfoSkeleton } from '../RelaySimpleInfo'
|
||||
@@ -12,10 +11,9 @@ const SHOW_COUNT = 10
|
||||
|
||||
export default function FollowingFavoriteRelayList() {
|
||||
const { t } = useTranslation()
|
||||
const { push } = useSecondaryPage()
|
||||
const { pubkey } = useNostr()
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [relays, setRelays] = useState<(TNip66RelayInfo & { users: string[] })[]>([])
|
||||
const [relays, setRelays] = useState<[string, string[]][]>([])
|
||||
const [showCount, setShowCount] = useState(SHOW_COUNT)
|
||||
const bottomRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
@@ -25,21 +23,8 @@ export default function FollowingFavoriteRelayList() {
|
||||
const init = async () => {
|
||||
if (!pubkey) return
|
||||
|
||||
const relayMap =
|
||||
(await client.fetchFollowingFavoriteRelays(pubkey)) ?? new Map<string, Set<string>>()
|
||||
const relayUrls = Array.from(relayMap.keys())
|
||||
const relayInfos = await relayInfoService.getRelayInfos(relayUrls ?? [])
|
||||
setRelays(
|
||||
(relayInfos.filter(Boolean) as TNip66RelayInfo[])
|
||||
.map((relayInfo) => {
|
||||
const users = Array.from(relayMap.get(relayInfo.url) ?? [])
|
||||
return {
|
||||
...relayInfo,
|
||||
users
|
||||
}
|
||||
})
|
||||
.sort((a, b) => b.users.length - a.users.length)
|
||||
)
|
||||
const relays = (await client.fetchFollowingFavoriteRelays(pubkey)) ?? []
|
||||
setRelays(relays)
|
||||
}
|
||||
init().finally(() => {
|
||||
setLoading(false)
|
||||
@@ -73,16 +58,8 @@ export default function FollowingFavoriteRelayList() {
|
||||
|
||||
return (
|
||||
<div>
|
||||
{relays.slice(0, showCount).map((relay) => (
|
||||
<RelaySimpleInfo
|
||||
key={relay.url}
|
||||
relayInfo={relay}
|
||||
className="clickable p-4 border-b"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
push(toRelay(relay.url))
|
||||
}}
|
||||
/>
|
||||
{relays.slice(0, showCount).map(([url, users]) => (
|
||||
<RelayItem key={url} url={url} users={users} />
|
||||
))}
|
||||
{showCount < relays.length && <div ref={bottomRef} />}
|
||||
{loading && <RelaySimpleInfoSkeleton />}
|
||||
@@ -94,3 +71,21 @@ export default function FollowingFavoriteRelayList() {
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function RelayItem({ url, users }: { url: string; users: string[] }) {
|
||||
const { push } = useSecondaryPage()
|
||||
const { relayInfo } = useFetchRelayInfo(url)
|
||||
|
||||
return (
|
||||
<RelaySimpleInfo
|
||||
key={url}
|
||||
relayInfo={relayInfo}
|
||||
users={users}
|
||||
className="clickable p-4 border-b"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
push(toRelay(url))
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -10,11 +10,13 @@ import { SimpleUserAvatar } from '../UserAvatar'
|
||||
|
||||
export default function RelaySimpleInfo({
|
||||
relayInfo,
|
||||
users,
|
||||
hideBadge = false,
|
||||
className,
|
||||
...props
|
||||
}: HTMLProps<HTMLDivElement> & {
|
||||
relayInfo?: TNip66RelayInfo & { users?: string[] }
|
||||
relayInfo?: TNip66RelayInfo
|
||||
users?: string[]
|
||||
hideBadge?: boolean
|
||||
}) {
|
||||
const { t } = useTranslation()
|
||||
@@ -35,16 +37,16 @@ export default function RelaySimpleInfo({
|
||||
</div>
|
||||
{!hideBadge && relayInfo && <RelayBadges relayInfo={relayInfo} />}
|
||||
{!!relayInfo?.description && <div className="line-clamp-4">{relayInfo.description}</div>}
|
||||
{!!relayInfo?.users?.length && (
|
||||
{!!users?.length && (
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="text-muted-foreground">{t('Favorited by')} </div>
|
||||
<div className="flex items-center gap-1">
|
||||
{relayInfo.users.slice(0, 10).map((user) => (
|
||||
{users.slice(0, 10).map((user) => (
|
||||
<SimpleUserAvatar key={user} userId={user} size="xSmall" />
|
||||
))}
|
||||
{relayInfo.users.length > 10 && (
|
||||
{users.length > 10 && (
|
||||
<div className="text-muted-foreground text-xs rounded-full bg-muted w-5 h-5 flex items-center justify-center">
|
||||
+{relayInfo.users.length - 10}
|
||||
+{users.length - 10}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user