UNPKG

@originvault/ov-content-viewer

Version:

A Typescript, React-based UI library for fetching and viewing cheqd DIDs

127 lines 18 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { Box, Typography, Divider, Avatar, Chip, Tooltip, Popper, IconButton, Link } from "@mui/material"; import { CalendarToday, AccountBalanceWallet, Fingerprint, InfoOutlined, CopyAll, Check, OpenInNew, Close } from "@mui/icons-material"; import { SocialIcon } from 'react-social-icons'; import { useEffect, useState } from "react"; import ContentFingerprints from "./ContentFingerprint"; import ColorBarcode from "./ColorBarcode"; // interface VeridaProfile { // id: didKey; // name: username; // image: avatar; // description: user bio; // website: website; // } export const renderDIDDetails = ({ data, renderProps, handleClose }) => { const { isDarkMode, mnemonicId } = renderProps; const [contentResource, setContentResource] = useState(null); const [verifiedIdentities, setVerifiedIdentities] = useState([]); const [anchorEl, setAnchorEl] = useState(null); const [colorCodeAnchorEl, setColorCodeAnchorEl] = useState(null); const [copied, setCopied] = useState(null); useEffect(() => { const fetchContentRegistration = async () => { const resources = data?.didDocumentMetadata?.linkedResourceMetadata || []; const contentResources = resources.filter((r) => r.resourceType === "Content-Registration-Record"); if (!contentResources.length) return _jsx(Typography, { p: 2, children: "No content registered for this resource." }); const latest = contentResources.filter((r) => mnemonicId ? r.resourceName === mnemonicId : true).sort((a, b) => new Date(b.created).getTime() - new Date(a.created).getTime())[0]; try { const res = await fetch(`https://resolver.cheqd.net/1.0/identifiers/${latest.resourceURI}`); const json = await res.json(); // Extract the registration record from the response const registrationRecord = json.didResolutionMetadata?.contentStream ? JSON.parse(json.didResolutionMetadata.contentStream) : json; // Get the registered content from the credential subject const registeredContent = registrationRecord.vc?.credentialSubject?.registeredContent?.[0] || {}; // Set verified identities from the credential subject if (registrationRecord.vc?.credentialSubject?.verifiedIdentities) { setVerifiedIdentities(registrationRecord.vc.credentialSubject.verifiedIdentities); } // Get the profile information if available const profile = registrationRecord.vc?.credentialSubject?.profile || {}; setContentResource({ ...registeredContent, issuer: registrationRecord.vc?.issuer, issuanceDate: registrationRecord.vc?.issuanceDate, expirationDate: registrationRecord.vc?.expirationDate, profile: profile // Add the profile information }); } catch (error) { console.error("Error fetching content registration:", error); } }; fetchContentRegistration(); }, [data]); if (!contentResource) return _jsx(Typography, { p: 2, children: "Loading content info\u2026" }); return (_jsxs(Box, { p: 2, sx: { maxWidth: 420, backgroundColor: isDarkMode ? "#1c2a35" : "#c9b36d", color: isDarkMode ? "#add4ef" : "#1c2a35", borderRadius: 2, boxShadow: "0 4px 12px rgba(0,0,0,0.08)", position: "relative", }, children: [_jsx(IconButton, { onClick: handleClose, size: "small", sx: { position: 'absolute', top: 8, right: 8, color: isDarkMode ? "#add4ef" : "#1c2a35", backgroundColor: isDarkMode ? "rgba(0,0,0,0.2)" : "rgba(255,255,255,0.2)", '&:hover': { backgroundColor: isDarkMode ? "rgba(0,0,0,0.4)" : "rgba(255,255,255,0.4)", } }, "aria-label": "close", children: _jsx(Close, { fontSize: "small" }) }), _jsxs(Box, { my: 2, children: [_jsx("iframe", { src: contentResource.publicPath, style: { width: "100px", borderRadius: 4, border: 'none', overflow: 'hidden' } }), _jsx(Typography, { title: contentResource.fileName, variant: "body1", fontWeight: 500, mt: 1, style: { maxWidth: '90%', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }, children: contentResource.fileName }), _jsxs(Box, { display: "flex", flexDirection: "column", gap: 0.5, mt: 0.5, children: [_jsxs(Box, { display: "flex", alignItems: "center", children: [_jsxs(Typography, { variant: "caption", children: ["Mnemonic ID: ", contentResource.mnemonicId] }), _jsx(IconButton, { size: "small", title: "Copy Mnemonic ID", style: { marginLeft: '5px', color: isDarkMode ? '#add4ef' : '#1c2a35' }, onClick: () => { navigator.clipboard.writeText(contentResource.mnemonicId); setCopied('mnemonicId'); setTimeout(() => setCopied(null), 2000); }, children: copied === 'mnemonicId' ? _jsx(Check, { fontSize: "small" }) : _jsx(CopyAll, { fontSize: "small" }) })] }), _jsxs(Box, { display: "flex", alignItems: "center", children: [_jsxs(Typography, { variant: "caption", style: { maxWidth: '90%', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }, children: ["Content Hash: ", contentResource.contentHash] }), _jsx(IconButton, { size: "small", title: "Copy Content Hash", style: { marginLeft: '5px', color: isDarkMode ? '#add4ef' : '#1c2a35' }, onClick: () => { navigator.clipboard.writeText(contentResource.contentHash); setCopied('contentHash'); setTimeout(() => setCopied(null), 2000); }, children: copied === 'contentHash' ? _jsx(Check, { fontSize: "small" }) : _jsx(CopyAll, { fontSize: "small" }) })] }), contentResource.perceptualHashes && (_jsxs(Box, { style: { position: 'relative', display: 'flex', alignItems: 'center' }, children: [_jsx(Chip, { onMouseEnter: (event) => setAnchorEl(event.currentTarget), onMouseLeave: () => setAnchorEl(null), label: "Perceptual Hashing", size: "small", variant: "outlined", color: "info", sx: { alignSelf: 'flex-start', mt: 0.5 } }), _jsx(Tooltip, { title: _jsxs(Box, { children: [_jsxs(Typography, { textAlign: "left", fontWeight: "bold", variant: "subtitle2", sx: { color: '#add4ef' }, children: ["The following are color-coded perceptual fingerprints based on the file's contents we calculated using ", _jsx("a", { style: { color: '#f39c12' }, href: "https://github.com/jaehl/blockhash", target: "_blank", rel: "noopener noreferrer", children: " blockhash's Phash algorithm " }), " and then are translated into hex codes to create unique color-coded fingerprints for each file."] }), _jsx(Typography, { textAlign: "left", fontWeight: "bold", variant: "subtitle2", sx: { color: '#add4ef' }, style: { marginTop: '10px' }, children: "Each fingerprint is a degree more accurate than the last, with the soft print being the least accurate and the precise print being the most accurate." }), _jsx(Typography, { textAlign: "left", fontWeight: "bold", variant: "subtitle2", sx: { color: '#add4ef' }, style: { marginTop: '10px' }, children: contentResource.perceptualHashes.soft }), _jsx(Typography, { textAlign: "left", fontWeight: "bold", variant: "subtitle2", sx: { color: '#add4ef' }, style: { marginTop: '10px' }, children: contentResource.perceptualHashes.medium }), _jsx(Typography, { textAlign: "left", fontWeight: "bold", variant: "subtitle2", sx: { color: '#add4ef' }, style: { marginTop: '10px' }, children: contentResource.perceptualHashes.precise })] }), children: _jsx(InfoOutlined, { color: 'primary', fontSize: "small", style: { marginLeft: '10px', cursor: 'pointer' } }) }), _jsx(Popper, { open: Boolean(anchorEl), anchorEl: anchorEl, placement: "top", style: { zIndex: 1301, backgroundColor: '#1c2a35' }, children: _jsx(ContentFingerprints, { softPerceptualHash: contentResource.perceptualHashes.soft, mediumPerceptualHash: contentResource.perceptualHashes.medium, precisePerceptualHash: contentResource.perceptualHashes.precise }) })] })), contentResource.colorCode && (_jsxs(Box, { style: { position: 'relative', display: 'flex', alignItems: 'center' }, children: [_jsx(Chip, { onMouseEnter: (event) => setColorCodeAnchorEl(event.currentTarget), onMouseLeave: () => setColorCodeAnchorEl(null), label: "Color Code", size: "small", variant: "outlined", color: "info", sx: { alignSelf: 'flex-start', mt: 1 } }), _jsx(Tooltip, { title: _jsxs(Box, { maxWidth: 300, children: [_jsx(Typography, { variant: "body2", style: { color: '#add4ef' }, children: "We generate a unique hash for each file and convert that hash into a distinct hex color. This acts as a \"visual fingerprint.\"" }), _jsx(Typography, { variant: "body2", mt: 1, style: { color: '#add4ef' }, children: "The barcode above represents 24 fragments of the file, each encoded as a color\u2014giving you a visual way to verify authenticity." })] }), children: _jsx(InfoOutlined, { color: 'primary', fontSize: "small", style: { marginLeft: '10px', cursor: 'pointer' } }) }), _jsx(IconButton, { style: { height: 40, width: 40, }, onClick: () => { navigator.clipboard.writeText(contentResource.colorCode); setCopied('colorCode'); setTimeout(() => setCopied(null), 2000); }, children: copied === 'colorCode' ? _jsx(Check, { fontSize: "small" }) : _jsx(CopyAll, { fontSize: "small", style: { color: isDarkMode ? '#add4ef' : '#1c2a35' } }) }), _jsx(Popper, { open: Boolean(colorCodeAnchorEl), anchorEl: colorCodeAnchorEl, placement: "top", style: { zIndex: 1301, backgroundColor: '#1c2a35' }, children: _jsx(ColorBarcode, { contentHash: contentResource.contentHash, colorCode: contentResource.colorCode, color: contentResource.color, isDarkMode: isDarkMode }) })] }))] })] }), _jsx(Divider, { sx: { my: 2 }, style: { backgroundColor: isDarkMode ? "#add4ef" : "#1c2a35" } }), _jsxs(Box, { children: [_jsx(Typography, { variant: "h6", children: "Creator Profile" }), _jsxs(Box, { display: "flex", alignItems: "flex-start", gap: 1, mt: 0.5, children: [_jsx(Avatar, { src: contentResource.profile?.image || contentResource.issuer?.image || "https://originvault.io/favicon.ico", sx: { width: 64, height: 64, margin: '15px' } }), _jsxs(Box, { display: "flex", flexDirection: "column", alignItems: "flex-start", gap: 0.5, children: [_jsxs(Typography, { variant: "subtitle1", fontWeight: 600, style: { display: 'flex', gap: '10px', alignItems: 'center', flexDirection: 'row' }, children: [contentResource.profile?.name || contentResource.issuer?.name || "OriginVault", verifiedIdentities.some((v) => v.type === "cawg.document_verification") && (_jsx(Box, { ml: 0.5, children: _jsx(Chip, { icon: _jsx(Fingerprint, {}), label: "Government ID Verified", color: "success", variant: "outlined", style: { backgroundColor: isDarkMode ? "#add4ef" : "transparent" } }) }))] }), _jsxs(Typography, { variant: "body2", children: ["Username: ", contentResource.profile?.username || contentResource.issuer?.username || "OriginVault", _jsx(IconButton, { size: "small", title: "Copy Username", style: { marginLeft: '5px', color: isDarkMode ? '#add4ef' : '#1c2a35' }, onClick: () => { navigator.clipboard.writeText(contentResource.profile.username); setCopied('username'); setTimeout(() => setCopied(null), 2000); }, children: copied === 'username' ? _jsx(Check, { fontSize: "small" }) : _jsx(CopyAll, { fontSize: "small" }) })] }), _jsxs(Link, { href: contentResource.profile?.website || contentResource.issuer?.website, target: "_blank", rel: "noopener noreferrer", style: { color: isDarkMode ? '#add4ef' : '#1c2a35', display: 'flex', alignItems: 'center', gap: '5px', fontSize: '14px', cursor: 'pointer' }, onClick: () => { window.open(contentResource.profile?.website || contentResource.issuer?.website || "https://create.originvault.me", "_blank"); }, children: [_jsx(Typography, { variant: "body2", children: contentResource.profile?.website || contentResource.issuer?.website || "https://create.originvault.me" }), _jsx(OpenInNew, { fontSize: "small", style: { marginLeft: '5px' } })] }), contentResource.profile?.email && (_jsxs(Box, { display: "flex", alignItems: "center", gap: 1, mt: 0.5, children: [_jsxs(Typography, { variant: "body2", fontWeight: 500, children: ["Email: ", contentResource.profile.email] }), _jsx(IconButton, { size: "small", title: "Copy Email", style: { marginLeft: '5px', color: isDarkMode ? '#add4ef' : '#1c2a35' }, onClick: () => { navigator.clipboard.writeText(contentResource.profile.email); setCopied('email'); setTimeout(() => setCopied(null), 2000); }, children: copied === 'email' ? _jsx(Check, { fontSize: "small" }) : _jsx(CopyAll, { fontSize: "small" }) })] })), _jsx(Typography, { variant: "body2", children: contentResource.profile?.bio || contentResource.issuer?.description || "OriginVault is a platform for creating and managing decentralized identities." })] })] })] }), verifiedIdentities.length > 0 && (_jsxs(Box, { mt: 2, children: [_jsx(Typography, { variant: "h6", children: "Linked Accounts" }), _jsx(Box, { display: "flex", flexWrap: "wrap", gap: 1, mt: 0.5, children: verifiedIdentities .filter((v) => v.type === "cawg.social_media") .map((identity, i) => (_jsx(Tooltip, { title: `${identity.provider.name}: ${identity.username || identity.address}`, children: _jsxs(Box, { children: [_jsx(SocialIcon, { url: `https://${identity.provider.id}.com/`, style: { height: 32, width: 32 } }), _jsx(IconButton, { size: "small", title: "Copy Provider Name", style: { marginLeft: '5px', color: isDarkMode ? '#add4ef' : '#1c2a35' }, onClick: () => { navigator.clipboard.writeText(identity.provider.name); setCopied(identity.provider.name); setTimeout(() => setCopied(null), 2000); }, children: copied === identity.provider.name ? _jsx(Check, { fontSize: "small" }) : _jsx(CopyAll, { fontSize: "small" }) })] }) }, i))) })] })), _jsx(Box, { mt: 2, children: verifiedIdentities .filter((v) => v.type === "cawg.crypto_wallet") .map((wallet, i) => (_jsxs(Box, { display: "flex", alignItems: "center", gap: 1, mt: 0.5, children: [_jsx(AccountBalanceWallet, { fontSize: "small" }), _jsx(Typography, { variant: "body2", sx: { wordBreak: 'break-all', maxWidth: '90%', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }, children: wallet.address }), _jsx(IconButton, { size: "small", title: "Copy Wallet Address", style: { marginLeft: '5px', color: isDarkMode ? '#add4ef' : '#1c2a35' }, onClick: () => { navigator.clipboard.writeText(wallet.address); setCopied(wallet.address); setTimeout(() => setCopied(null), 2000); }, children: copied === wallet.address ? _jsx(Check, { fontSize: "small" }) : _jsx(CopyAll, { fontSize: "small" }) })] }, i))) }), _jsx(Divider, { sx: { my: 2 }, style: { backgroundColor: isDarkMode ? "#add4ef" : "#1c2a35" } }), _jsxs(Box, { display: "flex", alignItems: "center", gap: 1, mb: 1, children: [_jsx(Avatar, { src: contentResource.issuer?.image || "https://originvault.io/favicon.ico", sx: { width: 32, height: 32 } }), _jsxs(Typography, { variant: "subtitle1", fontWeight: 600, children: ["Verified by ", contentResource.issuer?.name || "OriginVault"] })] }), _jsxs(Box, { display: "flex", alignItems: "center", gap: 1, mt: 2, children: [_jsx(CalendarToday, { fontSize: "small" }), _jsxs(Typography, { variant: "body2", children: ["Issued on ", new Date(contentResource.issuanceDate || contentResource.createdAt).toLocaleString()] })] }), contentResource.expirationDate && (_jsxs(Box, { display: "flex", alignItems: "center", gap: 1, mt: 1, children: [_jsx(CalendarToday, { fontSize: "small", color: "warning" }), _jsxs(Typography, { variant: "body2", children: ["Expires on ", new Date(contentResource.expirationDate).toLocaleString()] })] }))] })); }; //# sourceMappingURL=renderDIDDetails.js.map