feat: followed by
This commit is contained in:
50
src/pages/secondary/ProfilePage/FollowedBy.tsx
Normal file
50
src/pages/secondary/ProfilePage/FollowedBy.tsx
Normal file
@@ -0,0 +1,50 @@
|
||||
import UserAvatar from '@/components/UserAvatar'
|
||||
import { useNostr } from '@/providers/NostrProvider'
|
||||
import { useScreenSize } from '@/providers/ScreenSizeProvider'
|
||||
import client from '@/services/client.service'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
export default function FollowedBy({ pubkey }: { pubkey: string }) {
|
||||
const { t } = useTranslation()
|
||||
const { isSmallScreen } = useScreenSize()
|
||||
const [followedBy, setFollowedBy] = useState<string[]>([])
|
||||
const { pubkey: accountPubkey } = useNostr()
|
||||
|
||||
useEffect(() => {
|
||||
if (!pubkey || !accountPubkey) return
|
||||
|
||||
const init = async () => {
|
||||
const followings = (await client.fetchFollowings(accountPubkey)).reverse()
|
||||
const followingsOfFollowings = await Promise.all(
|
||||
followings.map(async (following) => {
|
||||
return client.fetchFollowings(following)
|
||||
})
|
||||
)
|
||||
const _followedBy: string[] = []
|
||||
const limit = isSmallScreen ? 3 : 5
|
||||
for (const [index, following] of followings.entries()) {
|
||||
if (following === pubkey) continue
|
||||
if (followingsOfFollowings[index].includes(pubkey)) {
|
||||
_followedBy.push(following)
|
||||
}
|
||||
if (_followedBy.length >= limit) {
|
||||
break
|
||||
}
|
||||
}
|
||||
setFollowedBy(_followedBy)
|
||||
}
|
||||
init()
|
||||
}, [pubkey, accountPubkey])
|
||||
|
||||
if (followedBy.length === 0) return null
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-1">
|
||||
<div className="text-muted-foreground">{t('Followed by')}</div>
|
||||
{followedBy.map((p) => (
|
||||
<UserAvatar userId={p} key={p} size="xSmall" />
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import { Link, Zap } from 'lucide-react'
|
||||
import { forwardRef, useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import NotFoundPage from '../NotFoundPage'
|
||||
import FollowedBy from './FollowedBy'
|
||||
import Followings from './Followings'
|
||||
import Relays from './Relays'
|
||||
|
||||
@@ -176,15 +177,18 @@ const ProfilePage = forwardRef(({ id, index }: { id?: string; index?: number },
|
||||
</a>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex gap-4 items-center mt-2 text-sm">
|
||||
<Followings pubkey={pubkey} />
|
||||
<Relays pubkey={pubkey} />
|
||||
{isSelf && (
|
||||
<SecondaryPageLink to={toMuteList()} className="flex gap-1 hover:underline w-fit">
|
||||
{mutePubkeys.length}
|
||||
<div className="text-muted-foreground">{t('Muted')}</div>
|
||||
</SecondaryPageLink>
|
||||
)}
|
||||
<div className="flex justify-between items-center mt-2 text-sm">
|
||||
<div className="flex gap-4 items-center">
|
||||
<Followings pubkey={pubkey} />
|
||||
<Relays pubkey={pubkey} />
|
||||
{isSelf && (
|
||||
<SecondaryPageLink to={toMuteList()} className="flex gap-1 hover:underline w-fit">
|
||||
{mutePubkeys.length}
|
||||
<div className="text-muted-foreground">{t('Muted')}</div>
|
||||
</SecondaryPageLink>
|
||||
)}
|
||||
</div>
|
||||
{!isSelf && <FollowedBy pubkey={pubkey} />}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user