import { useEffect, useState } from "react"; import { useUIStore } from "../../stores/ui"; import { useUserStore } from "../../stores/user"; import { useNotificationsStore } from "../../stores/notifications"; import { useProfile } from "../../hooks/useProfile"; import { useNip05Verified } from "../../hooks/useNip05Verified"; import { fetchFollowers, ensureConnected } from "../../lib/nostr"; import { shortenPubkey } from "../../lib/utils"; function FollowRow({ pubkey, followsYou, }: { pubkey: string; followsYou?: boolean; }) { const profile = useProfile(pubkey); const name = profile?.displayName || profile?.name || shortenPubkey(pubkey); const avatar = profile?.picture; const nip05 = profile?.nip05; const verified = useNip05Verified(pubkey, nip05); const { follows, follow, unfollow, pubkey: ownPubkey } = useUserStore(); const { openProfile } = useUIStore(); const isFollowing = follows.includes(pubkey); const isSelf = pubkey === ownPubkey; return (
{nip05 && ( {verified === "valid" ? "✓ " : ""}{nip05} )} {followsYou && ( follows you )}
{!isSelf && ( )}
); } export function FollowsView() { const { followsTab, setFollowsTab } = useUIStore(); const { pubkey, follows } = useUserStore(); const { clearNewFollowers } = useNotificationsStore(); const [followers, setFollowers] = useState([]); const [followersLoading, setFollowersLoading] = useState(false); const [followersError, setFollowersError] = useState(null); const [followersFetched, setFollowersFetched] = useState(false); // Clear badge when view opens useEffect(() => { clearNewFollowers(); }, []); // Fetch followers when tab is selected useEffect(() => { if (followsTab !== "followers" || !pubkey || followersFetched) return; let cancelled = false; setFollowersLoading(true); setFollowersError(null); (async () => { try { await ensureConnected(); let result = await fetchFollowers(pubkey); // Retry once if empty — relays may not be ready yet if (result.length === 0) { await new Promise((r) => setTimeout(r, 3000)); if (cancelled) return; result = await fetchFollowers(pubkey); } if (!cancelled) { setFollowers(result); setFollowersFetched(true); } } catch (err) { if (!cancelled) setFollowersError(`Failed to load followers: ${err}`); } finally { if (!cancelled) setFollowersLoading(false); } })(); return () => { cancelled = true; }; }, [followsTab, pubkey]); // Build followers set for "follows you" badge on Following tab const followersSet = new Set(followers); const tabs: Array<{ id: "followers" | "following"; label: string; count?: number }> = [ { id: "followers", label: "followers", count: followersFetched ? followers.length : undefined }, { id: "following", label: "following", count: follows.length }, ]; return (
{/* Header */}
follows
{tabs.map((t) => ( ))}
{/* Content */}
{followsTab === "followers" && ( <> {followersLoading && (
Loading followers…
)} {followersError && (

{followersError}

)} {!followersLoading && !followersError && followers.length === 0 && followersFetched && (

No followers found yet.

)} {followers.map((pk) => ( ))} )} {followsTab === "following" && ( <> {follows.length === 0 && (

Not following anyone yet.

)} {follows.map((pk) => ( ))} )}
); }