import { Skeleton } from '@/components/ui/skeleton' import { useFetchProfile } from '@/hooks' import { toProfile } from '@/lib/link' import { formatPubkey, userIdToPubkey, pubkeyToNpub, formatNpub } from '@/lib/pubkey' import { cn } from '@/lib/utils' import { useSmartProfileNavigationOptional } from '@/PageManager' import { useMemo } from 'react' export default function Username({ userId, showAt = false, className, skeletonClassName, withoutSkeleton = false, style, onNavigate }: { userId: string showAt?: boolean className?: string skeletonClassName?: string withoutSkeleton?: boolean style?: React.CSSProperties onNavigate?: () => void }) { const { profile, isFetching } = useFetchProfile(userId) const { navigateToProfile } = useSmartProfileNavigationOptional() // Get pubkey from userId (works even if profile isn't loaded) const pubkey = useMemo(() => { if (profile?.pubkey) return profile.pubkey return userIdToPubkey(userId) || '' }, [userId, profile?.pubkey]) // Never block on profile fetch when we can already show npub/hex fallback (feeds batch-fetch profiles). const canShowWithoutProfile = Boolean(pubkey) if (isFetching && !withoutSkeleton && !canShowWithoutProfile) { return (
) } // If we have a profile, show the username if (profile) { const { username, pubkey: profilePubkey } = profile return ( { e.stopPropagation() onNavigate?.() navigateToProfile(toProfile(profilePubkey)) }} > {showAt && '@'} {username} ) } // Fallback: show formatted npub (bech32) if we have a pubkey (even if profile fetch failed) if (pubkey) { // Convert to npub (bech32) format for display const npub = pubkeyToNpub(pubkey) const displayName = npub ? formatNpub(npub) : formatPubkey(pubkey) return ( { e.stopPropagation() onNavigate?.() navigateToProfile(toProfile(pubkey)) }} > {showAt && '@'} {displayName} ) } // No pubkey available - return null or skeleton based on withoutSkeleton if (!withoutSkeleton) { return (
) } return null } export function SimpleUsername({ userId, showAt = false, className, skeletonClassName, withoutSkeleton = false, style }: { userId: string showAt?: boolean className?: string skeletonClassName?: string withoutSkeleton?: boolean style?: React.CSSProperties }) { const { profile, isFetching } = useFetchProfile(userId) // Get pubkey from userId (works even if profile isn't loaded) const pubkey = useMemo(() => { if (profile?.pubkey) return profile.pubkey return userIdToPubkey(userId) || '' }, [userId, profile?.pubkey]) const canShowWithoutProfile = Boolean(pubkey) if (isFetching && !withoutSkeleton && !canShowWithoutProfile) { return (
) } // If we have a profile, show the username if (profile) { const { username } = profile return ( {showAt && '@'} {username} ) } // Fallback: show formatted npub (bech32) if we have a pubkey (even if profile fetch failed) if (pubkey) { // Convert to npub (bech32) format for display const npub = pubkeyToNpub(pubkey) const displayName = npub ? formatNpub(npub) : formatPubkey(pubkey) return ( {showAt && '@'} {displayName} ) } // No pubkey available - return null or skeleton based on withoutSkeleton if (!withoutSkeleton) { return (
) } return null }