import { useEffect, useState } from 'react' import { Meta, ProfileMetadata } from '../../types' import { SigitCardDisplayInfo, SigitStatus } from '../../utils' import { Event, kinds } from 'nostr-tools' import { Link } from 'react-router-dom' import { MetadataController } from '../../controllers' import { formatTimestamp, hexToNpub, npubToHex, shorten } from '../../utils' import { appPublicRoutes, appPrivateRoutes } from '../../routes' import { Button, Divider, Tooltip } from '@mui/material' import { DisplaySigner } from '../DisplaySigner' import { faArchive, faCalendar, faCopy, faEye, faFile } from '@fortawesome/free-solid-svg-icons' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { UserAvatar } from '../UserAvatar' import { UserAvatarGroup } from '../UserAvatarGroup' import styles from './style.module.scss' import { TooltipChild } from '../TooltipChild' import { getExtensionIconLabel } from '../getExtensionIconLabel' type SigitProps = { meta: Meta parsedMeta: SigitCardDisplayInfo } export const DisplaySigit = ({ meta, parsedMeta }: SigitProps) => { const { title, createdAt, submittedBy, signers, signedStatus, fileExtensions } = parsedMeta const [profiles, setProfiles] = useState<{ [key: string]: ProfileMetadata }>( {} ) useEffect(() => { const hexKeys = new Set<string>([ ...signers.map((signer) => npubToHex(signer)!) ]) if (submittedBy) { hexKeys.add(npubToHex(submittedBy)!) } const metadataController = new MetadataController() const handleMetadataEvent = (key: string) => (event: Event) => { const metadataContent = metadataController.extractProfileMetadataContent(event) if (metadataContent) { setProfiles((prev) => ({ ...prev, [key]: metadataContent })) } } const handleEventListener = (key: string) => (kind: number, event: Event) => { if (kind === kinds.Metadata) { handleMetadataEvent(key)(event) } } hexKeys.forEach((key) => { if (!(key in profiles)) { metadataController.on(key, handleEventListener(key)) metadataController .findMetadata(key) .then((metadataEvent) => { if (metadataEvent) handleMetadataEvent(key)(metadataEvent) }) .catch((err) => { console.error(`error occurred in finding metadata for: ${key}`, err) }) } }) return () => { hexKeys.forEach((key) => { metadataController.off(key, handleEventListener(key)) }) } }, [submittedBy, signers, profiles]) return ( <div className={styles.itemWrapper}> <Link to={ signedStatus === SigitStatus.Complete ? appPublicRoutes.verify : appPrivateRoutes.sign } state={{ meta }} className={styles.insetLink} ></Link> <p className={`line-clamp-2 ${styles.title}`}>{title}</p> <div className={styles.users}> {submittedBy && (function () { const profile = profiles[submittedBy] return ( <Tooltip title={ profile?.display_name || profile?.name || shorten(hexToNpub(submittedBy)) } placement="top" arrow disableInteractive > <TooltipChild> <UserAvatar pubkey={submittedBy} image={profile?.picture} /> </TooltipChild> </Tooltip> ) })()} {submittedBy && signers.length ? ( <Divider orientation="vertical" flexItem /> ) : null} <UserAvatarGroup className={styles.signers} max={7}> {signers.map((signer) => { const pubkey = npubToHex(signer)! const profile = profiles[pubkey] return ( <Tooltip key={signer} title={ profile?.display_name || profile?.name || shorten(pubkey) } placement="top" arrow disableInteractive > <TooltipChild> <DisplaySigner meta={meta} profile={profile} pubkey={pubkey} /> </TooltipChild> </Tooltip> ) })} </UserAvatarGroup> </div> <div className={`${styles.details} ${styles.date} ${styles.iconLabel}`}> <FontAwesomeIcon icon={faCalendar} /> {createdAt ? formatTimestamp(createdAt) : null} </div> <div className={`${styles.details} ${styles.status}`}> <span className={styles.iconLabel}> <FontAwesomeIcon icon={faEye} /> {signedStatus} </span> {fileExtensions.length > 0 ? ( <span className={styles.iconLabel}> {fileExtensions.length > 1 ? ( <> <FontAwesomeIcon icon={faFile} /> Multiple File Types </> ) : ( getExtensionIconLabel(fileExtensions[0]) )} </span> ) : null} </div> <div className={styles.itemActions}> <Tooltip title="Duplicate" arrow placement="top" disableInteractive> <Button sx={{ color: 'var(--primary-main)', minWidth: '34px', padding: '10px' }} variant={'text'} > <FontAwesomeIcon icon={faCopy} /> </Button> </Tooltip> <Tooltip title="Archive" arrow placement="top" disableInteractive> <Button sx={{ color: 'var(--primary-main)', minWidth: '34px', padding: '10px' }} variant={'text'} > <FontAwesomeIcon icon={faArchive} /> </Button> </Tooltip> </div> </div> ) }