Placeholder avatar is incosistent across components #39

Merged
s merged 9 commits from issue-27 into main 2024-05-16 08:58:11 +00:00
5 changed files with 33 additions and 16 deletions

View File

@ -16,11 +16,12 @@ import { Dispatch } from '../../store/store'
import Username from '../username' import Username from '../username'
import { Link, useNavigate } from 'react-router-dom' import { Link, useNavigate } from 'react-router-dom'
import nostrichAvatar from '../../assets/images/avatar.png'
import { NostrController } from '../../controllers' import { NostrController } from '../../controllers'
import { appPublicRoutes, getProfileRoute } from '../../routes' import { appPublicRoutes, getProfileRoute } from '../../routes'
import { import {
clearAuthToken, clearAuthToken,
getRoboHashPicture,
hexToNpub,
saveNsecBunkerDelegatedKey, saveNsecBunkerDelegatedKey,
shorten shorten
} from '../../utils' } from '../../utils'
@ -32,7 +33,7 @@ export const AppBar = () => {
const dispatch: Dispatch = useDispatch() const dispatch: Dispatch = useDispatch()
const [username, setUsername] = useState('') const [username, setUsername] = useState('')
const [userAvatar, setUserAvatar] = useState(nostrichAvatar) const [userAvatar, setUserAvatar] = useState('')
const [anchorElUser, setAnchorElUser] = useState<null | HTMLElement>(null) const [anchorElUser, setAnchorElUser] = useState<null | HTMLElement>(null)
const authState = useSelector((state: State) => state.auth) const authState = useSelector((state: State) => state.auth)
@ -41,8 +42,13 @@ export const AppBar = () => {
useEffect(() => { useEffect(() => {
if (metadataState && metadataState.content) { if (metadataState && metadataState.content) {
const { picture, display_name, name } = JSON.parse(metadataState.content) const { picture, display_name, name } = JSON.parse(metadataState.content)
const pubkey = authState?.usersPubkey || ''
if (picture) setUserAvatar(picture) if (picture) {
setUserAvatar(picture)
} else {
setUserAvatar(getRoboHashPicture(pubkey))
}
setUsername(shorten(display_name || name || '', 7)) setUsername(shorten(display_name || name || '', 7))
} }

View File

@ -21,7 +21,6 @@ import {
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 { Link, useNavigate } from 'react-router-dom'
import placeholderAvatar from '../../assets/images/nostr-logo.jpg'
import { LoadingSpinner } from '../../components/LoadingSpinner' import { LoadingSpinner } from '../../components/LoadingSpinner'
import { MetadataController, NostrController } from '../../controllers' import { MetadataController, NostrController } from '../../controllers'
import { appPrivateRoutes, getProfileRoute } from '../../routes' import { appPrivateRoutes, getProfileRoute } from '../../routes'
@ -30,6 +29,7 @@ import {
encryptArrayBuffer, encryptArrayBuffer,
generateEncryptionKey, generateEncryptionKey,
getHash, getHash,
getRoboHashPicture,
hexToNpub, hexToNpub,
pubToHex, pubToHex,
queryNip05, queryNip05,
@ -489,8 +489,8 @@ const DisplayUser = ({
}) })
}, [users]) }, [users])
const imageLoadError = (event: any) => { const imageLoadError = (event: any, pubkey: string) => {
event.target.src = placeholderAvatar event.target.src = getRoboHashPicture(pubkey)
} }
return ( return (
@ -513,7 +513,7 @@ const DisplayUser = ({
<TableCell className={styles.tableCell}> <TableCell className={styles.tableCell}>
<Box className={styles.user}> <Box className={styles.user}>
<img <img
onError={imageLoadError} onError={(event) => {imageLoadError(event, user.pubkey)}}
src={userMeta?.picture || roboUrl} src={userMeta?.picture || roboUrl}
alt="Profile Image" alt="Profile Image"
className="profile-image" className="profile-image"

View File

@ -15,7 +15,6 @@ import { UnsignedEvent, nip19, kinds, VerifiedEvent } from 'nostr-tools'
import { useEffect, useMemo, useState } from 'react' import { useEffect, useMemo, useState } from 'react'
import { Link, useParams } from 'react-router-dom' import { Link, useParams } from 'react-router-dom'
import { toast } from 'react-toastify' import { toast } from 'react-toastify'
import placeholderAvatar from '../../assets/images/nostr-logo.jpg'
import { MetadataController, NostrController } from '../../controllers' import { MetadataController, NostrController } from '../../controllers'
import { NostrJoiningBlock, ProfileMetadata } from '../../types' import { NostrJoiningBlock, ProfileMetadata } from '../../types'
import styles from './style.module.scss' import styles from './style.module.scss'
@ -27,6 +26,7 @@ import { setMetadataEvent } from '../../store/actions'
import { LoadingSpinner } from '../../components/LoadingSpinner' import { LoadingSpinner } from '../../components/LoadingSpinner'
import { LoginMethods } from '../../store/auth/types' import { LoginMethods } from '../../store/auth/types'
import { SmartToy } from '@mui/icons-material' import { SmartToy } from '@mui/icons-material'
import { getRoboHashPicture } from '../../utils'
export const ProfilePage = () => { export const ProfilePage = () => {
const theme = useTheme() const theme = useTheme()
@ -282,13 +282,13 @@ export const ProfilePage = () => {
> >
<img <img
onError={(event: any) => { onError={(event: any) => {
event.target.src = placeholderAvatar event.target.src = npub ? getRoboHashPicture(npub) : ''
}} }}
onLoad={() => { onLoad={() => {
setAvatarLoading(false) setAvatarLoading(false)
}} }}
className={styles.img} className={styles.img}
src={profileMetadata.picture || placeholderAvatar} src={profileMetadata.picture || npub ? getRoboHashPicture(npub!) : ''}
alt="Profile Image" alt="Profile Image"
/> />

View File

@ -12,12 +12,12 @@ import { MuiFileInput } from 'mui-file-input'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { Link } from 'react-router-dom' 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 { MetadataController } from '../../controllers' import { MetadataController } from '../../controllers'
import { getProfileRoute } from '../../routes' import { getProfileRoute } from '../../routes'
import { Meta, ProfileMetadata } from '../../types' import { Meta, ProfileMetadata } from '../../types'
import { import {
getRoboHashPicture,
hexToNpub, hexToNpub,
parseJson, parseJson,
readContentOfZipEntry, readContentOfZipEntry,
@ -113,13 +113,13 @@ export const VerifyPage = () => {
setIsLoading(false) setIsLoading(false)
} }
const imageLoadError = (event: any) => { const imageLoadError = (event: any, pubkey: string) => {
event.target.src = placeholderAvatar const npub = hexToNpub(pubkey)
event.target.src = npub
} }
const getRoboImageUrl = (pubkey: string) => { const getRoboImageUrl = (pubkey: string) => {
const npub = hexToNpub(pubkey) return getRoboHashPicture(pubkey)
return `https://robohash.org/${npub}.png?set=set3`
} }
const displayUser = (pubkey: string, verifySignature = false) => { const displayUser = (pubkey: string, verifySignature = false) => {
@ -145,7 +145,7 @@ export const VerifyPage = () => {
return ( return (
<Box className={styles.user}> <Box className={styles.user}>
<img <img
onError={imageLoadError} onError={(event) => {imageLoadError(event, pubkey)}}
src={profile?.picture || getRoboImageUrl(pubkey)} src={profile?.picture || getRoboImageUrl(pubkey)}
alt="Profile Image" alt="Profile Image"
className="profile-image" className="profile-image"

View File

@ -58,6 +58,7 @@ export const nsecToHex = (nsec: string): string | null => {
export const hexToNpub = (hexPubkey: string | undefined): string => { export const hexToNpub = (hexPubkey: string | undefined): string => {
if (!hexPubkey) return 'n/a' if (!hexPubkey) return 'n/a'
if (hexPubkey.includes('npub')) return hexPubkey
return nip19.npubEncode(hexPubkey) return nip19.npubEncode(hexPubkey)
} }
@ -138,3 +139,13 @@ export const base64DecodeAuthToken = (authToken: string): SignedEvent => {
throw new Error('An error occurred in JSON.parse of the auth token') throw new Error('An error occurred in JSON.parse of the auth token')
} }
} }
/**
m marked this conversation as resolved Outdated
Outdated
Review

Allow this to accept both npub and hex, If provided value is not npub then convert it to npub

Allow this to accept both npub and hex, If provided value is not npub then convert it to npub
*
* @param pubkey in hex or npub format
* @returns robohash.org url for the avatar
*/
export const getRoboHashPicture = (pubkey: string): string => {
const npub = hexToNpub(pubkey)
return `https://robohash.org/${npub}.png?set=set3`
}