index.tsx raw

   1  import { Button } from '@/components/ui/button'
   2  import { SimpleUserAvatar } from '@/components/UserAvatar'
   3  import { cn } from '@/lib/utils'
   4  import { useScreenSize } from '@/providers/ScreenSizeProvider'
   5  import { useUserPreferences } from '@/providers/UserPreferencesProvider'
   6  import { hasBackgroundAudioAtom } from '@/services/media-manager.service'
   7  import { useAtomValue } from 'jotai'
   8  import { ArrowUp } from 'lucide-react'
   9  import { Event } from 'nostr-tools'
  10  import { useMemo } from 'react'
  11  import { useTranslation } from 'react-i18next'
  12  
  13  export default function NewNotesButton({
  14    newEvents = [],
  15    onClick
  16  }: {
  17    newEvents?: Event[]
  18    onClick?: () => void
  19  }) {
  20    const { t } = useTranslation()
  21    const { enableSingleColumnLayout } = useUserPreferences()
  22    const { isSmallScreen } = useScreenSize()
  23    const hasBackgroundAudio = useAtomValue(hasBackgroundAudioAtom)
  24    const pubkeys = useMemo(() => {
  25      const arr: string[] = []
  26      for (const event of newEvents) {
  27        if (!arr.includes(event.pubkey)) {
  28          arr.push(event.pubkey)
  29        }
  30        if (arr.length >= 3) break
  31      }
  32      return arr
  33    }, [newEvents])
  34  
  35    return (
  36      <>
  37        {newEvents.length > 0 && (
  38          <div
  39            className={cn(
  40              'w-full flex justify-center z-40 pointer-events-none',
  41              enableSingleColumnLayout ? 'sticky' : 'absolute'
  42            )}
  43            style={{
  44              bottom: isSmallScreen
  45                ? `calc(${hasBackgroundAudio ? 7.35 : 4}rem + env(safe-area-inset-bottom))`
  46                : '1rem'
  47            }}
  48          >
  49            <Button
  50              onClick={onClick}
  51              className="group rounded-full h-fit py-2 pl-2 pr-3 hover:bg-primary-hover pointer-events-auto"
  52            >
  53              {pubkeys.length > 0 && (
  54                <div className="*:data-[slot=avatar]:ring-background flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:grayscale">
  55                  {pubkeys.map((pubkey) => (
  56                    <SimpleUserAvatar key={pubkey} userId={pubkey} size="small" />
  57                  ))}
  58                </div>
  59              )}
  60              <span className="text-xs opacity-70">⇧↵</span>
  61              <ArrowUp />
  62              <div className="text-md font-medium">
  63                {t('Show n new notes', { n: newEvents.length > 99 ? '99+' : newEvents.length })}
  64              </div>
  65            </Button>
  66          </div>
  67        )}
  68      </>
  69    )
  70  }
  71