@originvault/ov-content-viewer
Version:
A Typescript, React-based UI library for fetching and viewing cheqd DIDs
127 lines • 18 kB
JavaScript
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