issue-38 #62

Closed
y wants to merge 48 commits from issue-38 into main
4 changed files with 102 additions and 133 deletions
Showing only changes of commit 2d06e21bf5 - Show all commits

View File

@ -1,6 +1,9 @@
import { Typography, IconButton } from '@mui/material' import { Typography, IconButton, Box, useTheme } from '@mui/material'
import { useSelector } from 'react-redux' import { useSelector } from 'react-redux'
import { State } from '../store/rootReducer' import { State } from '../store/rootReducer'
import { hexToNpub } from '../utils'
import { Link } from 'react-router-dom'
import { getProfileRoute } from '../routes'
type Props = { type Props = {
username: string username: string
@ -44,3 +47,43 @@ const Username = ({ username, avatarContent, handleClick }: Props) => {
} }
export default Username export default Username
type UserProps = {
pubkey: string
name: string
image?: string
}
export const UserComponent = ({ pubkey, name, image }: UserProps) => {
const theme = useTheme()
const npub = hexToNpub(pubkey)
const roboImage = `https://robohash.org/${npub}.png?set=set3`
return (
<Box sx={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
<img
src={image || roboImage}
alt="User Image"
className="profile-image"
style={{
borderWidth: '3px',
borderStyle: 'solid',
borderColor: `#${pubkey.substring(0, 6)}`
}}
/>
<Link to={getProfileRoute(pubkey)}>
<Typography
component="label"
sx={{
textAlign: 'center',
cursor: 'pointer',
color: theme.palette.text.primary
}}
>
{name}
</Typography>
</Link>
</Box>
)
}

View File

@ -18,18 +18,22 @@ import {
Tooltip, Tooltip,
Typography Typography
} from '@mui/material' } from '@mui/material'
import JSZip from 'jszip'
import { MuiFileInput } from 'mui-file-input' import { MuiFileInput } from 'mui-file-input'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { Link, useNavigate } from 'react-router-dom' import { useSelector } from 'react-redux'
import { useNavigate } from 'react-router-dom'
import { toast } from 'react-toastify'
import { LoadingSpinner } from '../../components/LoadingSpinner' import { LoadingSpinner } from '../../components/LoadingSpinner'
import { UserComponent } from '../../components/username'
import { MetadataController, NostrController } from '../../controllers' import { MetadataController, NostrController } from '../../controllers'
import { appPrivateRoutes, getProfileRoute } from '../../routes' import { appPrivateRoutes } from '../../routes'
import { State } from '../../store/rootReducer'
import { ProfileMetadata, User, UserRole } from '../../types' import { ProfileMetadata, User, UserRole } from '../../types'
import { import {
encryptArrayBuffer, encryptArrayBuffer,
generateEncryptionKey, generateEncryptionKey,
getHash, getHash,
getRoboHashPicture,
hexToNpub, hexToNpub,
pubToHex, pubToHex,
queryNip05, queryNip05,
@ -39,10 +43,6 @@ import {
uploadToFileStorage uploadToFileStorage
} from '../../utils' } from '../../utils'
import styles from './style.module.scss' import styles from './style.module.scss'
import { toast } from 'react-toastify'
import JSZip from 'jszip'
import { useSelector } from 'react-redux'
import { State } from '../../store/rootReducer'
export const CreatePage = () => { export const CreatePage = () => {
const navigate = useNavigate() const navigate = useNavigate()
@ -489,15 +489,6 @@ const DisplayUser = ({
}) })
}, [users]) }, [users])
/**
* Use robohash if any of the users images fail to load
* @param event img tag onError event
* @param pubkey of the user
*/
const imageLoadError = (event: any, pubkey: string) => {
event.target.src = getRoboHashPicture(pubkey)
}
return ( return (
<TableContainer component={Paper} elevation={3} sx={{ marginTop: '20px' }}> <TableContainer component={Paper} elevation={3} sx={{ marginTop: '20px' }}>
<Table> <Table>
@ -511,33 +502,18 @@ const DisplayUser = ({
<TableBody> <TableBody>
{users.map((user, index) => { {users.map((user, index) => {
const userMeta = metadata[user.pubkey] const userMeta = metadata[user.pubkey]
const npub = hexToNpub(user.pubkey)
const roboUrl = `https://robohash.org/${npub}.png?set=set3`
return ( return (
<TableRow key={index}> <TableRow key={index}>
<TableCell className={styles.tableCell}> <TableCell className={styles.tableCell}>
<Box className={styles.user}> <UserComponent
<img pubkey={user.pubkey}
onError={(event) => { name={
imageLoadError(event, user.pubkey) userMeta?.display_name ||
}} userMeta?.name ||
src={userMeta?.picture || roboUrl} shorten(hexToNpub(user.pubkey))
alt="Profile Image" }
className="profile-image" image={userMeta?.picture}
style={{ />
borderWidth: '3px',
borderStyle: 'solid',
borderColor: `#${user.pubkey.substring(0, 6)}`
}}
/>
<Link to={getProfileRoute(user.pubkey)}>
<Typography component="label" className={styles.name}>
{userMeta?.display_name ||
userMeta?.name ||
shorten(npub)}
</Typography>
</Link>
</Box>
</TableCell> </TableCell>
<TableCell className={styles.tableCell}> <TableCell className={styles.tableCell}>
<Select <Select

View File

@ -21,11 +21,12 @@ import { MuiFileInput } from 'mui-file-input'
import { EventTemplate } from 'nostr-tools' import { EventTemplate } from 'nostr-tools'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { useSelector } from 'react-redux' import { useSelector } from 'react-redux'
import { Link, useNavigate, useSearchParams } from 'react-router-dom' import { useNavigate, useSearchParams } from 'react-router-dom'
import { toast } from 'react-toastify' import { toast } from 'react-toastify'
import { LoadingSpinner } from '../../components/LoadingSpinner' import { LoadingSpinner } from '../../components/LoadingSpinner'
import { UserComponent } from '../../components/username'
import { MetadataController, NostrController } from '../../controllers' import { MetadataController, NostrController } from '../../controllers'
import { appPrivateRoutes, getProfileRoute } from '../../routes' import { appPrivateRoutes } from '../../routes'
import { State } from '../../store/rootReducer' import { State } from '../../store/rootReducer'
import { Meta, ProfileMetadata, User, UserRole } from '../../types' import { Meta, ProfileMetadata, User, UserRole } from '../../types'
import { import {
@ -401,7 +402,7 @@ export const SignPage = () => {
} }
/** /**
* *
* @returns exported.zip including signed files and meta info (about signers and viewers) * @returns exported.zip including signed files and meta info (about signers and viewers)
*/ */
const handleExport = async () => { const handleExport = async () => {
@ -639,15 +640,6 @@ const DisplayMeta = ({ meta, nextSigner }: DisplayMetaProps) => {
}) })
}, [users, meta.submittedBy]) }, [users, meta.submittedBy])
const imageLoadError = (event: any, pubkey: string) => {
const npub = hexToNpub(pubkey)
event.target.src = npub
}
const getRoboImageUrl = (pubkey: string) => {
return getRoboHashPicture(pubkey)
}
return ( return (
<List <List
sx={{ sx={{
@ -677,29 +669,15 @@ const DisplayMeta = ({ meta, nextSigner }: DisplayMetaProps) => {
<Typography variant="h6" sx={{ color: textColor }}> <Typography variant="h6" sx={{ color: textColor }}>
Submitted By Submitted By
</Typography> </Typography>
<Box className={styles.user}> <UserComponent
<img pubkey={meta.submittedBy}
onError={(event) => {imageLoadError(event, meta.submittedBy)}} name={
src={ metadata[meta.submittedBy]?.display_name ||
metadata[meta.submittedBy]?.picture || metadata[meta.submittedBy]?.name ||
getRoboImageUrl(meta.submittedBy) shorten(hexToNpub(meta.submittedBy))
} }
alt="Profile Image" image={metadata[meta.submittedBy]?.picture}
className="profile-image" />
style={{
borderWidth: '3px',
borderStyle: 'solid',
borderColor: `#${meta.submittedBy.substring(0, 6)}`
}}
/>
<Link to={getProfileRoute(meta.submittedBy)}>
<Typography component="label" className={styles.name}>
{metadata[meta.submittedBy]?.display_name ||
metadata[meta.submittedBy]?.name ||
shorten(hexToNpub(meta.submittedBy))}
</Typography>
</Link>
</Box>
</ListItem> </ListItem>
<ListItem <ListItem
sx={{ sx={{
@ -731,8 +709,6 @@ const DisplayMeta = ({ meta, nextSigner }: DisplayMetaProps) => {
<TableBody> <TableBody>
{users.map((user, index) => { {users.map((user, index) => {
const userMeta = metadata[user.pubkey] const userMeta = metadata[user.pubkey]
const npub = hexToNpub(user.pubkey)
const roboUrl = getRoboHashPicture(npub)
let signedStatus = '-' let signedStatus = '-'
@ -750,26 +726,15 @@ const DisplayMeta = ({ meta, nextSigner }: DisplayMetaProps) => {
return ( return (
<TableRow key={index}> <TableRow key={index}>
<TableCell className={styles.tableCell}> <TableCell className={styles.tableCell}>
<Box className={styles.user}> <UserComponent
<img pubkey={user.pubkey}
onError={(event) => {imageLoadError(event, meta.submittedBy)}} name={
src={userMeta?.picture || roboUrl} userMeta?.display_name ||
alt="Profile Image" userMeta?.name ||
className="profile-image" shorten(hexToNpub(user.pubkey))
style={{ }
borderWidth: '3px', image={userMeta?.picture}
borderStyle: 'solid', />
borderColor: `#${user.pubkey.substring(0, 6)}`
}}
/>
<Link to={getProfileRoute(user.pubkey)}>
<Typography component="label" className={styles.name}>
{userMeta?.display_name ||
userMeta?.name ||
shorten(npub)}
</Typography>
</Link>
</Box>
</TableCell> </TableCell>
<TableCell className={styles.tableCell}> <TableCell className={styles.tableCell}>
{user.role} {user.role}

View File

@ -9,23 +9,20 @@ import {
} from '@mui/material' } from '@mui/material'
import JSZip from 'jszip' import JSZip from 'jszip'
import { MuiFileInput } from 'mui-file-input' import { MuiFileInput } from 'mui-file-input'
import { Event, verifyEvent } from 'nostr-tools'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { Link } from 'react-router-dom'
import { toast } from 'react-toastify' import { toast } from 'react-toastify'
import placeholderAvatar from '../../assets/images/nostr-logo.jpg'
import { LoadingSpinner } from '../../components/LoadingSpinner' import { LoadingSpinner } from '../../components/LoadingSpinner'
import { UserComponent } from '../../components/username'
import { MetadataController } from '../../controllers' import { MetadataController } from '../../controllers'
import { getProfileRoute } from '../../routes'
import { Meta, ProfileMetadata } from '../../types' import { Meta, ProfileMetadata } from '../../types'
import { import {
getRoboHashPicture,
hexToNpub, hexToNpub,
parseJson, parseJson,
readContentOfZipEntry, readContentOfZipEntry,
shorten shorten
} from '../../utils' } from '../../utils'
import styles from './style.module.scss' import styles from './style.module.scss'
import { Event, verifyEvent } from 'nostr-tools'
export const VerifyPage = () => { export const VerifyPage = () => {
const theme = useTheme() const theme = useTheme()
@ -114,16 +111,6 @@ export const VerifyPage = () => {
setIsLoading(false) setIsLoading(false)
} }
const imageLoadError = (event: any, pubkey: string) => {
const npub = hexToNpub(pubkey)
event.target.src = getRoboImageUrl(npub)
}
const getRoboImageUrl = (pubkey: string) => {
const npub = hexToNpub(pubkey)
return `https://robohash.org/${npub}.png?set=set3`
}
const displayUser = (pubkey: string, verifySignature = false) => { const displayUser = (pubkey: string, verifySignature = false) => {
const profile = metadata[pubkey] const profile = metadata[pubkey]
@ -145,31 +132,21 @@ export const VerifyPage = () => {
} }
return ( return (
<Box className={styles.user}> <>
<img <UserComponent
onError={(event) => {imageLoadError(event, pubkey)}} pubkey={pubkey}
src={profile?.picture || getRoboImageUrl(pubkey)} name={
alt="Profile Image" profile?.display_name || profile?.name || shorten(hexToNpub(pubkey))
className="profile-image" }
style={{ image={profile?.picture}
borderWidth: '3px',
borderStyle: 'solid',
borderColor: `#${pubkey.substring(0, 6)}`
}}
/> />
<Link to={getProfileRoute(pubkey)}>
<Typography component="label" className={styles.name}>
{profile?.display_name ||
profile?.name ||
shorten(hexToNpub(pubkey))}
</Typography>
</Link>
{verifySignature && ( {verifySignature && (
<Typography component="label"> <Typography component="label">
({isValidSignature ? 'Valid' : 'Not Valid'} Signature) ({isValidSignature ? 'Valid' : 'Not Valid'} Signature)
</Typography> </Typography>
)} )}
</Box> </>
) )
} }
@ -278,7 +255,15 @@ export const VerifyPage = () => {
</Typography> </Typography>
<ul className={styles.usersList}> <ul className={styles.usersList}>
{meta.signers.map((signer) => ( {meta.signers.map((signer) => (
<li key={signer} style={{ color: textColor }}> <li
key={signer}
style={{
color: textColor,
display: 'flex',
alignItems: 'center',
gap: '15px'
}}
>
{displayUser(signer, true)} {displayUser(signer, true)}
</li> </li>
))} ))}