From e1c750495efe8d1875426931bc93ac7c2dd713f0 Mon Sep 17 00:00:00 2001 From: enes Date: Fri, 13 Sep 2024 18:13:34 +0200 Subject: [PATCH] refactor: useSigitProfiles removed, per user profile hook in avatar, refactor name tooltip --- src/components/DisplaySigit/index.tsx | 67 ++++------------- src/components/DisplaySigner/index.tsx | 48 ++++++------ src/components/UserAvatar/index.tsx | 48 ++++++++---- src/components/UsersDetails.tsx/index.tsx | 91 +++++------------------ src/hooks/useProfileMetadata.tsx | 46 ++++++++++++ src/hooks/useSigitProfiles.tsx | 71 ------------------ src/pages/create/index.tsx | 37 +++------ src/pages/sign/internal/displayMeta.tsx | 31 +------- 8 files changed, 148 insertions(+), 291 deletions(-) create mode 100644 src/hooks/useProfileMetadata.tsx delete mode 100644 src/hooks/useSigitProfiles.tsx diff --git a/src/components/DisplaySigit/index.tsx b/src/components/DisplaySigit/index.tsx index 473a942..62f397c 100644 --- a/src/components/DisplaySigit/index.tsx +++ b/src/components/DisplaySigit/index.tsx @@ -1,7 +1,7 @@ import { Meta } from '../../types' import { SigitCardDisplayInfo, SigitStatus, SignStatus } from '../../utils' import { Link } from 'react-router-dom' -import { formatTimestamp, hexToNpub, npubToHex, shorten } from '../../utils' +import { formatTimestamp, npubToHex } from '../../utils' import { appPublicRoutes, appPrivateRoutes } from '../../routes' import { Button, Divider, Tooltip } from '@mui/material' import { DisplaySigner } from '../DisplaySigner' @@ -17,9 +17,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { UserAvatarGroup } from '../UserAvatarGroup' import styles from './style.module.scss' -import { TooltipChild } from '../TooltipChild' import { getExtensionIconLabel } from '../getExtensionIconLabel' -import { useSigitProfiles } from '../../hooks/useSigitProfiles' import { useSigitMeta } from '../../hooks/useSigitMeta' import { extractFileExtensions } from '../../utils/file' @@ -33,12 +31,6 @@ export const DisplaySigit = ({ meta, parsedMeta }: SigitProps) => { parsedMeta const { signersStatus, fileHashes } = useSigitMeta(meta) - - const profiles = useSigitProfiles([ - ...(submittedBy ? [submittedBy] : []), - ...signers - ]) - const { extensions, isSame } = extractFileExtensions(Object.keys(fileHashes)) return ( @@ -54,62 +46,29 @@ export const DisplaySigit = ({ meta, parsedMeta }: SigitProps) => { >

{title}

- {submittedBy && - (function () { - const profile = profiles[submittedBy] - return ( - - - - - - ) - })()} + {submittedBy && ( + + )} {submittedBy && signers.length ? ( ) : null} {signers.map((signer) => { const pubkey = npubToHex(signer)! - const profile = profiles[pubkey] - return ( - - - - - + ) })}
-
+
{createdAt ? formatTimestamp(createdAt) : null}
diff --git a/src/components/DisplaySigner/index.tsx b/src/components/DisplaySigner/index.tsx index 63aa154..e05dcae 100644 --- a/src/components/DisplaySigner/index.tsx +++ b/src/components/DisplaySigner/index.tsx @@ -1,5 +1,4 @@ import { Badge } from '@mui/material' -import { ProfileMetadata } from '../../types' import styles from './style.module.scss' import { UserAvatar } from '../UserAvatar' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' @@ -15,38 +14,33 @@ import { SignStatus } from '../../utils' import { Spinner } from '../Spinner' type DisplaySignerProps = { - profile: ProfileMetadata pubkey: string status: SignStatus } -export const DisplaySigner = ({ - status, - profile, - pubkey -}: DisplaySignerProps) => { - const getStatusIcon = (status: SignStatus) => { - switch (status) { - case SignStatus.Signed: - return - case SignStatus.Awaiting: - return ( - - - - ) - case SignStatus.Pending: - return - case SignStatus.Invalid: - return - case SignStatus.Viewer: - return +const getStatusIcon = (status: SignStatus) => { + switch (status) { + case SignStatus.Signed: + return + case SignStatus.Awaiting: + return ( + + + + ) + case SignStatus.Pending: + return + case SignStatus.Invalid: + return + case SignStatus.Viewer: + return - default: - return - } + default: + return } +} +export const DisplaySigner = ({ status, pubkey }: DisplaySignerProps) => { return ( {getStatusIcon(status)}
} > - + ) } diff --git a/src/components/UserAvatar/index.tsx b/src/components/UserAvatar/index.tsx index 6049a07..0ea1fc1 100644 --- a/src/components/UserAvatar/index.tsx +++ b/src/components/UserAvatar/index.tsx @@ -3,34 +3,56 @@ import { getProfileRoute } from '../../routes' import styles from './styles.module.scss' import { AvatarIconButton } from '../UserAvatarIconButton' import { Link } from 'react-router-dom' +import { useProfileMetadata } from '../../hooks/useProfileMetadata' +import { Tooltip } from '@mui/material' +import { shorten } from '../../utils' +import { TooltipChild } from '../TooltipChild' interface UserAvatarProps { - name?: string pubkey: string - image?: string + isNameVisible?: boolean } /** * This component will be used for the displaying username and profile picture. * Clicking will navigate to the user's profile. */ -export const UserAvatar = ({ pubkey, name, image }: UserAvatarProps) => { +export const UserAvatar = ({ + pubkey, + isNameVisible = false +}: UserAvatarProps) => { + const profile = useProfileMetadata(pubkey) + const name = profile?.display_name || profile?.name || shorten(pubkey) + const image = profile?.picture + return ( - - {name ? {name} : null} + + + + + + {isNameVisible && name ? ( + {name} + ) : null} ) } diff --git a/src/components/UsersDetails.tsx/index.tsx b/src/components/UsersDetails.tsx/index.tsx index bddae82..bfb4d11 100644 --- a/src/components/UsersDetails.tsx/index.tsx +++ b/src/components/UsersDetails.tsx/index.tsx @@ -1,11 +1,9 @@ import { Divider, Tooltip } from '@mui/material' -import { useSigitProfiles } from '../../hooks/useSigitProfiles' import { formatTimestamp, fromUnixTimestamp, hexToNpub, npubToHex, - shorten, SignStatus } from '../../utils' import { useSigitMeta } from '../../hooks/useSigitMeta' @@ -24,10 +22,10 @@ import { import { getExtensionIconLabel } from '../getExtensionIconLabel' import { useSelector } from 'react-redux' import { State } from '../../store/rootReducer' -import { TooltipChild } from '../TooltipChild' import { DisplaySigner } from '../DisplaySigner' import { Meta } from '../../types' import { extractFileExtensions } from '../../utils/file' +import { UserAvatar } from '../UserAvatar' interface UsersDetailsProps { meta: Meta @@ -36,6 +34,7 @@ interface UsersDetailsProps { export const UsersDetails = ({ meta }: UsersDetailsProps) => { const { submittedBy, + exportedBy, signers, viewers, fileHashes, @@ -47,11 +46,6 @@ export const UsersDetails = ({ meta }: UsersDetailsProps) => { isValid } = useSigitMeta(meta) const { usersPubkey } = useSelector((state: State) => state.auth) - const profiles = useSigitProfiles([ - ...(submittedBy ? [submittedBy] : []), - ...signers, - ...viewers - ]) const userCanSign = typeof usersPubkey !== 'undefined' && signers.includes(hexToNpub(usersPubkey)) @@ -63,31 +57,12 @@ export const UsersDetails = ({ meta }: UsersDetailsProps) => {

Signers

- {submittedBy && - (function () { - const profile = profiles[submittedBy] - return ( - - - - - - ) - })()} + {submittedBy && ( + + )} {submittedBy && signers.length ? ( @@ -96,26 +71,8 @@ export const UsersDetails = ({ meta }: UsersDetailsProps) => { {signers.map((signer) => { const pubkey = npubToHex(signer)! - const profile = profiles[pubkey] - return ( - - - - - + ) })} @@ -128,34 +85,24 @@ export const UsersDetails = ({ meta }: UsersDetailsProps) => { {viewers.map((signer) => { const pubkey = npubToHex(signer)! - const profile = profiles[pubkey] return ( - - - - - + ) })}
)} + + {exportedBy && ( + <> +

Exported By

+
+ +
+ + )}

Details

diff --git a/src/hooks/useProfileMetadata.tsx b/src/hooks/useProfileMetadata.tsx new file mode 100644 index 0000000..f746f0d --- /dev/null +++ b/src/hooks/useProfileMetadata.tsx @@ -0,0 +1,46 @@ +import { useEffect, useState } from 'react' +import { ProfileMetadata } from '../types/profile' +import { MetadataController } from '../controllers/MetadataController' +import { Event, kinds } from 'nostr-tools' + +export const useProfileMetadata = (pubkey: string) => { + const [profileMetadata, setProfileMetadata] = useState() + + useEffect(() => { + const metadataController = MetadataController.getInstance() + const handleMetadataEvent = (event: Event) => { + const metadataContent = + metadataController.extractProfileMetadataContent(event) + + if (metadataContent) { + setProfileMetadata(metadataContent) + } + } + + if (pubkey) { + metadataController.on(pubkey, (kind: number, event: Event) => { + if (kind === kinds.Metadata) { + handleMetadataEvent(event) + } + }) + + metadataController + .findMetadata(pubkey) + .then((metadataEvent) => { + if (metadataEvent) handleMetadataEvent(metadataEvent) + }) + .catch((err) => { + console.error( + `error occurred in finding metadata for: ${pubkey}`, + err + ) + }) + } + + return () => { + metadataController.off(pubkey, handleMetadataEvent) + } + }, [pubkey]) + + return profileMetadata +} diff --git a/src/hooks/useSigitProfiles.tsx b/src/hooks/useSigitProfiles.tsx deleted file mode 100644 index 88d6c50..0000000 --- a/src/hooks/useSigitProfiles.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import { useEffect, useState } from 'react' -import { ProfileMetadata } from '../types' -import { MetadataController } from '../controllers' -import { npubToHex } from '../utils' -import { Event, kinds } from 'nostr-tools' - -/** - * Extracts profiles from metadata events - * @param pubkeys Array of npubs to check - * @returns ProfileMetadata - */ -export const useSigitProfiles = ( - pubkeys: `npub1${string}`[] -): { [key: string]: ProfileMetadata } => { - const [profileMetadata, setProfileMetadata] = useState<{ - [key: string]: ProfileMetadata - }>({}) - - useEffect(() => { - if (pubkeys.length) { - const metadataController = new MetadataController() - - // Remove duplicate keys - const users = new Set([...pubkeys]) - - const handleMetadataEvent = (key: string) => (event: Event) => { - const metadataContent = - metadataController.extractProfileMetadataContent(event) - - if (metadataContent) { - setProfileMetadata((prev) => ({ - ...prev, - [key]: metadataContent - })) - } - } - - users.forEach((user) => { - const hexKey = npubToHex(user) - if (hexKey && !(hexKey in profileMetadata)) { - metadataController.on(hexKey, (kind: number, event: Event) => { - if (kind === kinds.Metadata) { - handleMetadataEvent(hexKey)(event) - } - }) - - metadataController - .findMetadata(hexKey) - .then((metadataEvent) => { - if (metadataEvent) handleMetadataEvent(hexKey)(metadataEvent) - }) - .catch((err) => { - console.error( - `error occurred in finding metadata for: ${user}`, - err - ) - }) - } - }) - - return () => { - users.forEach((key) => { - metadataController.off(key, handleMetadataEvent(key)) - }) - } - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [pubkeys]) - - return profileMetadata -} diff --git a/src/pages/create/index.tsx b/src/pages/create/index.tsx index f0bd6b9..2218620 100644 --- a/src/pages/create/index.tsx +++ b/src/pages/create/index.tsx @@ -36,7 +36,6 @@ import { npubToHex, queryNip05, sendNotification, - shorten, signEventForMetaFile, updateUsersAppData, uploadToFileStorage @@ -113,6 +112,8 @@ export const CreatePage = () => { const [error, setError] = useState() const [users, setUsers] = useState([]) + const signers = users.filter((u) => u.role === UserRole.signer) + const viewers = users.filter((u) => u.role === UserRole.viewer) const usersPubkey = useSelector((state: State) => state.auth.usersPubkey) @@ -252,7 +253,7 @@ export const CreatePage = () => { useEffect(() => { users.forEach((user) => { if (!(user.pubkey in metadata)) { - const metadataController = new MetadataController() + const metadataController = MetadataController.getInstance() const handleMetadataEvent = (event: Event) => { const metadataContent = @@ -647,6 +648,11 @@ export const CreatePage = () => { } saveAs(finalZipFile, `request-${unixNow()}.sigit.zip`) + + // If user is the next signer, we can navigate directly to sign page + if (signers[0].pubkey === usersPubkey) { + navigate(appPrivateRoutes.sign, { state: { uploadedZip: finalZipFile } }) + } setIsLoading(false) } @@ -672,9 +678,6 @@ export const CreatePage = () => { }, zipUrl: string ) => { - const signers = users.filter((user) => user.role === UserRole.signer) - const viewers = users.filter((user) => user.role === UserRole.viewer) - const content: CreateSignatureEventContent = { signers: signers.map((signer) => hexToNpub(signer.pubkey)), viewers: viewers.map((viewer) => hexToNpub(viewer.pubkey)), @@ -703,9 +706,6 @@ export const CreatePage = () => { // Send notifications to signers and viewers const sendNotifications = (meta: Meta) => { - const signers = users.filter((user) => user.role === UserRole.signer) - const viewers = users.filter((user) => user.role === UserRole.viewer) - // no need to send notification to self so remove it from the list const receivers = ( signers.length > 0 @@ -787,7 +787,7 @@ export const CreatePage = () => { toast.error('Failed to publish notifications') }) - navigate(appPrivateRoutes.sign, { state: { meta: meta } }) + navigate(appPrivateRoutes.sign, { state: { meta } }) } else { const zip = new JSZip() @@ -914,7 +914,6 @@ export const CreatePage = () => {
{ } type DisplayUsersProps = { - metadata: { [key: string]: ProfileMetadata } users: User[] handleUserRoleChange: (role: UserRole, pubkey: string) => void handleRemoveUser: (pubkey: string) => void @@ -1018,7 +1016,6 @@ type DisplayUsersProps = { } const DisplayUser = ({ - metadata, users, handleUserRoleChange, handleRemoveUser, @@ -1032,7 +1029,6 @@ const DisplayUser = ({ .map((user, index) => ( void handleRemoveUser: (pubkey: string) => void @@ -1078,7 +1072,6 @@ type SignerCounterpartProps = CounterpartProps & { } const SignerCounterpart = ({ - userMeta, user, index, moveSigner, @@ -1171,7 +1164,6 @@ const SignerCounterpart = ({ @@ -1180,7 +1172,6 @@ const SignerCounterpart = ({ } const Counterpart = ({ - userMeta, user, handleUserRoleChange, handleRemoveUser @@ -1188,15 +1179,7 @@ const Counterpart = ({ return ( <>
- +