index.tsx raw

   1  import { Button } from '@/components/ui/button'
   2  import { Pubkey } from '@/domain'
   3  import { isSameAccount } from '@/lib/account'
   4  import { cn } from '@/lib/utils'
   5  import { useNostr } from '@/providers/NostrProvider'
   6  import { TAccountPointer } from '@/types'
   7  import { Loader, Trash2 } from 'lucide-react'
   8  import { useState } from 'react'
   9  import SignerTypeBadge from '../SignerTypeBadge'
  10  import { SimpleUserAvatar } from '../UserAvatar'
  11  import { SimpleUsername } from '../Username'
  12  
  13  export default function AccountList({
  14    className,
  15    afterSwitch
  16  }: {
  17    className?: string
  18    afterSwitch: () => void
  19  }) {
  20    const { accounts, account, switchAccount, removeAccount } = useNostr()
  21    const [switchingAccount, setSwitchingAccount] = useState<TAccountPointer | null>(null)
  22  
  23    return (
  24      <div className={cn('space-y-2', className)}>
  25        {accounts.map((act) => (
  26          <div
  27            key={`${act.pubkey}-${act.signerType}`}
  28            className={cn(
  29              'relative rounded-lg',
  30              isSameAccount(act, account) ? 'border border-primary' : 'clickable'
  31            )}
  32            onClick={() => {
  33              if (isSameAccount(act, account)) return
  34              setSwitchingAccount(act)
  35              switchAccount(act)
  36                .then(() => afterSwitch())
  37                .finally(() => setSwitchingAccount(null))
  38            }}
  39          >
  40            <div className="flex justify-between items-center p-2">
  41              <div className="flex-1 flex items-center gap-2 relative">
  42                <SimpleUserAvatar userId={act.pubkey} />
  43                <div className="flex-1 w-0">
  44                  <SimpleUsername userId={act.pubkey} className="font-semibold truncate" />
  45                  <div className="text-sm rounded-full bg-muted px-2 w-fit">
  46                    {Pubkey.tryFromString(act.pubkey)?.formatNpub(12) ?? act.pubkey.slice(0, 8)}
  47                  </div>
  48                </div>
  49              </div>
  50              <div className="flex items-center gap-2">
  51                <div className="flex gap-2 items-center">
  52                  <SignerTypeBadge signerType={act.signerType} />
  53                </div>
  54                <Button
  55                  variant="ghost"
  56                  size="icon"
  57                  className="text-muted-foreground hover:text-destructive"
  58                  onClick={(e) => {
  59                    e.stopPropagation()
  60                    removeAccount(act)
  61                  }}
  62                >
  63                  <Trash2 />
  64                </Button>
  65              </div>
  66            </div>
  67            {switchingAccount && isSameAccount(act, switchingAccount) && (
  68              <div className="absolute top-0 left-0 flex w-full h-full items-center justify-center rounded-lg bg-muted/60">
  69                <Loader size={16} className="animate-spin" />
  70              </div>
  71            )}
  72          </div>
  73        ))}
  74      </div>
  75    )
  76  }
  77