index.tsx raw

   1  import { HoverCard, HoverCardContent, HoverCardTrigger } from '@/components/ui/hover-card'
   2  import { Skeleton } from '@/components/ui/skeleton'
   3  import { useFetchProfile } from '@/hooks'
   4  import { toProfile } from '@/lib/link'
   5  import { cn, isTouchDevice } from '@/lib/utils'
   6  import { SecondaryPageLink } from '@/PageManager'
   7  import { useMemo } from 'react'
   8  import NpubQrCode from '../NpubQrCode'
   9  import ProfileCard from '../ProfileCard'
  10  import TextWithEmojis from '../TextWithEmojis'
  11  
  12  export default function Username({
  13    userId,
  14    showAt = false,
  15    className,
  16    skeletonClassName,
  17    withoutSkeleton = false,
  18    showQrCode = true
  19  }: {
  20    userId: string
  21    showAt?: boolean
  22    className?: string
  23    skeletonClassName?: string
  24    withoutSkeleton?: boolean
  25    showQrCode?: boolean
  26  }) {
  27    const { profile, isFetching } = useFetchProfile(userId)
  28    const supportTouch = useMemo(() => isTouchDevice(), [])
  29    if (!profile && isFetching && !withoutSkeleton) {
  30      return (
  31        <div className="py-1">
  32          <Skeleton className={cn('w-16', skeletonClassName)} />
  33        </div>
  34      )
  35    }
  36    if (!profile) return null
  37  
  38    const usernameLink = (
  39      <SecondaryPageLink
  40        to={toProfile(userId)}
  41        className="truncate hover:underline"
  42        onClick={(e) => e.stopPropagation()}
  43      >
  44        {showAt && '@'}
  45        <TextWithEmojis text={profile.username} emojis={profile.emojis} emojiClassName="mb-1" />
  46      </SecondaryPageLink>
  47    )
  48  
  49    const trigger = (
  50      <div className={cn('flex items-center gap-1', className)}>
  51        {usernameLink}
  52        {showQrCode && <NpubQrCode pubkey={userId} />}
  53      </div>
  54    )
  55  
  56    if (supportTouch) {
  57      return trigger
  58    }
  59  
  60    return (
  61      <HoverCard>
  62        <HoverCardTrigger asChild>{trigger}</HoverCardTrigger>
  63        <HoverCardContent className="w-80">
  64          <ProfileCard userId={userId} />
  65        </HoverCardContent>
  66      </HoverCard>
  67    )
  68  }
  69  
  70  export function SimpleUsername({
  71    userId,
  72    showAt = false,
  73    className,
  74    skeletonClassName,
  75    withoutSkeleton = false,
  76    showQrCode = true
  77  }: {
  78    userId: string
  79    showAt?: boolean
  80    className?: string
  81    skeletonClassName?: string
  82    withoutSkeleton?: boolean
  83    showQrCode?: boolean
  84  }) {
  85    const { profile, isFetching } = useFetchProfile(userId)
  86    if (!profile && isFetching && !withoutSkeleton) {
  87      return (
  88        <div className="py-1">
  89          <Skeleton className={cn('w-16', skeletonClassName)} />
  90        </div>
  91      )
  92    }
  93    if (!profile) return null
  94  
  95    const { username, emojis } = profile
  96  
  97    return (
  98      <div className={cn('flex items-center gap-1', className)}>
  99        <span className="truncate">
 100          {showAt && '@'}
 101          <TextWithEmojis text={username} emojis={emojis} emojiClassName="mb-1" />
 102        </span>
 103        {showQrCode && <NpubQrCode pubkey={userId} />}
 104      </div>
 105    )
 106  }
 107