index.tsx raw

   1  import { useSecondaryPage } from '@/PageManager'
   2  import { Button } from '@/components/ui/button'
   3  import { Drawer, DrawerContent, DrawerOverlay } from '@/components/ui/drawer'
   4  import {
   5    DropdownMenu,
   6    DropdownMenuContent,
   7    DropdownMenuItem,
   8    DropdownMenuTrigger
   9  } from '@/components/ui/dropdown-menu'
  10  import { toExternalContent } from '@/lib/link'
  11  import { truncateUrl } from '@/lib/url'
  12  import { cn } from '@/lib/utils'
  13  import { useScreenSize } from '@/providers/ScreenSizeProvider'
  14  import { ExternalLink as ExternalLinkIcon, MessageSquare } from 'lucide-react'
  15  import { useMemo, useState } from 'react'
  16  import { useTranslation } from 'react-i18next'
  17  
  18  export default function ExternalLink({
  19    url,
  20    className,
  21    justOpenLink
  22  }: {
  23    url: string
  24    className?: string
  25    justOpenLink?: boolean
  26  }) {
  27    const { t } = useTranslation()
  28    const { isSmallScreen } = useScreenSize()
  29    const { push } = useSecondaryPage()
  30    const [isDrawerOpen, setIsDrawerOpen] = useState(false)
  31    const displayUrl = useMemo(() => truncateUrl(url), [url])
  32  
  33    const handleOpenLink = (e: React.MouseEvent) => {
  34      e.stopPropagation()
  35      if (isSmallScreen) {
  36        setIsDrawerOpen(false)
  37      }
  38      window.open(url, '_blank', 'noreferrer')
  39    }
  40  
  41    const handleViewDiscussions = (e: React.MouseEvent) => {
  42      e.stopPropagation()
  43      if (isSmallScreen) {
  44        setIsDrawerOpen(false)
  45        setTimeout(() => push(toExternalContent(url)), 100) // wait for drawer to close
  46        return
  47      }
  48      push(toExternalContent(url))
  49    }
  50  
  51    if (justOpenLink) {
  52      return (
  53        <a
  54          href={url}
  55          target="_blank"
  56          rel="noreferrer"
  57          className={cn('cursor-pointer text-primary hover:underline', className)}
  58          onClick={(e) => e.stopPropagation()}
  59        >
  60          {displayUrl}
  61        </a>
  62      )
  63    }
  64  
  65    const trigger = (
  66      <span
  67        className={cn('cursor-pointer text-primary hover:underline', className)}
  68        onClick={(e) => {
  69          e.stopPropagation()
  70          if (isSmallScreen) {
  71            setIsDrawerOpen(true)
  72          }
  73        }}
  74        title={url}
  75      >
  76        {displayUrl}
  77      </span>
  78    )
  79  
  80    if (isSmallScreen) {
  81      return (
  82        <>
  83          {trigger}
  84          <Drawer open={isDrawerOpen} onOpenChange={setIsDrawerOpen}>
  85            <DrawerOverlay
  86              onClick={(e) => {
  87                e.stopPropagation()
  88                setIsDrawerOpen(false)
  89              }}
  90            />
  91            <DrawerContent hideOverlay>
  92              <div className="py-2">
  93                <Button
  94                  onClick={handleOpenLink}
  95                  className="w-full p-6 justify-start text-lg gap-4 [&_svg]:size-5"
  96                  variant="ghost"
  97                >
  98                  <ExternalLinkIcon />
  99                  {t('Open link')}
 100                </Button>
 101                <Button
 102                  onClick={handleViewDiscussions}
 103                  className="w-full p-6 justify-start text-lg gap-4 [&_svg]:size-5"
 104                  variant="ghost"
 105                >
 106                  <MessageSquare />
 107                  {t('View Nostr discussions')}
 108                </Button>
 109              </div>
 110            </DrawerContent>
 111          </Drawer>
 112        </>
 113      )
 114    }
 115  
 116    return (
 117      <DropdownMenu>
 118        <DropdownMenuTrigger>
 119          <span className={cn('cursor-pointer text-primary hover:underline', className)} title={url}>
 120            {displayUrl}
 121          </span>
 122        </DropdownMenuTrigger>
 123        <DropdownMenuContent align="start" onClick={(e) => e.stopPropagation()}>
 124          <DropdownMenuItem onClick={handleOpenLink}>
 125            <ExternalLinkIcon />
 126            {t('Open link')}
 127          </DropdownMenuItem>
 128          <DropdownMenuItem onClick={handleViewDiscussions}>
 129            <MessageSquare />
 130            {t('View Nostr discussions')}
 131          </DropdownMenuItem>
 132        </DropdownMenuContent>
 133      </DropdownMenu>
 134    )
 135  }
 136