diff --git a/src/components/AppBar/AppBar.tsx b/src/components/AppBar/AppBar.tsx index 4176a42..495e9dc 100644 --- a/src/components/AppBar/AppBar.tsx +++ b/src/components/AppBar/AppBar.tsx @@ -28,9 +28,9 @@ import { } from '../../routes' import { clearAuthToken, + getProfileUsername, hexToNpub, - saveNsecBunkerDelegatedKey, - shorten + saveNsecBunkerDelegatedKey } from '../../utils' import styles from './style.module.scss' import { setUserRobotImage } from '../../store/userRobotImage/action' @@ -58,9 +58,8 @@ export const AppBar = () => { useEffect(() => { if (metadataState) { if (metadataState.content) { - const { picture, display_name, name } = JSON.parse( - metadataState.content - ) + const profileMetadata = JSON.parse(metadataState.content) + const { picture } = profileMetadata if (picture || userRobotImage) { setUserAvatar(picture || userRobotImage) @@ -70,7 +69,7 @@ export const AppBar = () => { ? hexToNpub(authState.usersPubkey) : '' - setUsername(shorten(display_name || name || npub, 7)) + setUsername(getProfileUsername(npub, profileMetadata)) } else { setUserAvatar(userRobotImage || '') setUsername('') diff --git a/src/components/DrawPDFFields/index.tsx b/src/components/DrawPDFFields/index.tsx index 7c1227d..076c6fb 100644 --- a/src/components/DrawPDFFields/index.tsx +++ b/src/components/DrawPDFFields/index.tsx @@ -11,16 +11,16 @@ import styles from './style.module.scss' import React, { useEffect, useState } from 'react' import { ProfileMetadata, User, UserRole } from '../../types' import { MouseState, PdfPage, DrawnField, DrawTool } from '../../types/drawing' -import { truncate } from 'lodash' -import { settleAllFullfilfedPromises, hexToNpub, npubToHex } from '../../utils' -import { getSigitFile, SigitFile } from '../../utils/file' +import { hexToNpub, npubToHex, getProfileUsername } from '../../utils' +import { SigitFile } from '../../utils/file' import { getToolboxLabelByMarkType } from '../../utils/mark' import { FileDivider } from '../FileDivider' import { ExtensionFileBox } from '../ExtensionFileBox' import { FONT_SIZE, FONT_TYPE, inPx } from '../../utils/pdf' import { useScale } from '../../hooks/useScale' import { AvatarIconButton } from '../UserAvatarIconButton' -import { LoadingSpinner } from '../LoadingSpinner' +import { UserAvatar } from '../UserAvatar' +import _ from 'lodash' const DEFAULT_START_SIZE = { width: 140, @@ -28,52 +28,50 @@ const DEFAULT_START_SIZE = { } as const interface Props { - selectedFiles: File[] users: User[] metadata: { [key: string]: ProfileMetadata } - onDrawFieldsChange: (sigitFiles: SigitFile[]) => void + sigitFiles: SigitFile[] + setSigitFiles: React.Dispatch> selectedTool?: DrawTool } export const DrawPDFFields = (props: Props) => { - const { selectedFiles, selectedTool, onDrawFieldsChange, users } = props - const { to, from } = useScale() + const { selectedTool, sigitFiles, setSigitFiles, users } = props - const [sigitFiles, setSigitFiles] = useState([]) - const [parsingPdf, setIsParsing] = useState(false) + const signers = users.filter((u) => u.role === UserRole.signer) + const defaultSignerNpub = signers.length ? hexToNpub(signers[0].pubkey) : '' + const [lastSigner, setLastSigner] = useState(defaultSignerNpub) + /** + * Return first pubkey that is present in the signers list + * @param pubkeys + * @returns available pubkey or empty string + */ + const getAvailableSigner = (...pubkeys: string[]) => { + const availableSigner: string | undefined = pubkeys.find((pubkey) => + signers.some((s) => s.pubkey === npubToHex(pubkey)) + ) + return availableSigner || '' + } + + const { to, from } = useScale() const [mouseState, setMouseState] = useState({ clicked: false }) - const [activeDrawField, setActiveDrawField] = useState() - - useEffect(() => { - if (selectedFiles) { - /** - * Reads the binary files and converts to internal file type - * and sets to a state (adds images if it's a PDF) - */ - const parsePages = async () => { - const files = await settleAllFullfilfedPromises( - selectedFiles, - getSigitFile - ) - - setSigitFiles(files) - } - - setIsParsing(true) - - parsePages().finally(() => { - setIsParsing(false) - }) - } - }, [selectedFiles]) - - useEffect(() => { - if (sigitFiles) onDrawFieldsChange(sigitFiles) - }, [onDrawFieldsChange, sigitFiles]) + const [activeDrawnField, setActiveDrawnField] = useState<{ + fileIndex: number + pageIndex: number + drawnFieldIndex: number + }>() + const isActiveDrawnField = ( + fileIndex: number, + pageIndex: number, + drawnFieldIndex: number + ) => + activeDrawnField?.fileIndex === fileIndex && + activeDrawnField?.pageIndex === pageIndex && + activeDrawnField?.drawnFieldIndex === drawnFieldIndex /** * Drawing events @@ -100,7 +98,12 @@ export const DrawPDFFields = (props: Props) => { * @param event Pointer event * @param page PdfPage where press happened */ - const handlePointerDown = (event: React.PointerEvent, page: PdfPage) => { + const handlePointerDown = ( + event: React.PointerEvent, + page: PdfPage, + fileIndex: number, + pageIndex: number + ) => { // Proceed only if left click if (event.button !== 0) return @@ -115,12 +118,17 @@ export const DrawPDFFields = (props: Props) => { top: to(page.width, y), width: event.pointerType === 'mouse' ? 0 : DEFAULT_START_SIZE.width, height: event.pointerType === 'mouse' ? 0 : DEFAULT_START_SIZE.height, - counterpart: '', + counterpart: getAvailableSigner(lastSigner, defaultSignerNpub), type: selectedTool.identifier } page.drawnFields.push(newField) + setActiveDrawnField({ + fileIndex, + pageIndex, + drawnFieldIndex: page.drawnFields.length - 1 + }) setMouseState((prev) => { return { ...prev, @@ -189,6 +197,8 @@ export const DrawPDFFields = (props: Props) => { */ const handleDrawnFieldPointerDown = ( event: React.PointerEvent, + fileIndex: number, + pageIndex: number, drawnFieldIndex: number ) => { event.stopPropagation() @@ -198,7 +208,7 @@ export const DrawPDFFields = (props: Props) => { const drawingRectangleCoords = getPointerCoordinates(event) - setActiveDrawField(drawnFieldIndex) + setActiveDrawnField({ fileIndex, pageIndex, drawnFieldIndex }) setMouseState({ dragging: true, clicked: false, @@ -254,13 +264,15 @@ export const DrawPDFFields = (props: Props) => { */ const handleResizePointerDown = ( event: React.PointerEvent, + fileIndex: number, + pageIndex: number, drawnFieldIndex: number ) => { // Proceed only if left click if (event.button !== 0) return event.stopPropagation() - setActiveDrawField(drawnFieldIndex) + setActiveDrawnField({ fileIndex, pageIndex, drawnFieldIndex }) setMouseState({ resizing: true }) @@ -369,7 +381,7 @@ export const DrawPDFFields = (props: Props) => { handlePointerMove(event, page) }} onPointerDown={(event) => { - handlePointerDown(event, page) + handlePointerDown(event, page, fileIndex, pageIndex) }} draggable="false" src={page.image} @@ -381,7 +393,12 @@ export const DrawPDFFields = (props: Props) => {
- handleDrawnFieldPointerDown(event, drawnFieldIndex) + handleDrawnFieldPointerDown( + event, + fileIndex, + pageIndex, + drawnFieldIndex + ) } onPointerMove={(event) => { handleDrawnFieldPointerMove(event, drawnField, page.width) @@ -402,7 +419,11 @@ export const DrawPDFFields = (props: Props) => { touchAction: 'none', opacity: mouseState.dragging && - activeDrawField === drawnFieldIndex + isActiveDrawnField( + fileIndex, + pageIndex, + drawnFieldIndex + ) ? 0.8 : undefined }} @@ -419,7 +440,12 @@ export const DrawPDFFields = (props: Props) => {
- handleResizePointerDown(event, drawnFieldIndex) + handleResizePointerDown( + event, + fileIndex, + pageIndex, + drawnFieldIndex + ) } onPointerMove={(event) => { handleResizePointerMove(event, drawnField, page.width) @@ -428,7 +454,11 @@ export const DrawPDFFields = (props: Props) => { style={{ background: mouseState.resizing && - activeDrawField === drawnFieldIndex + isActiveDrawnField( + fileIndex, + pageIndex, + drawnFieldIndex + ) ? 'var(--primary-main)' : undefined }} @@ -446,56 +476,59 @@ export const DrawPDFFields = (props: Props) => { > -
- - Counterpart - { + drawnField.counterpart = event.target.value + setLastSigner(event.target.value) + refreshPdfFiles() + }} + labelId="counterparts" + label="Counterparts" + sx={{ + background: 'white' + }} + renderValue={(value) => + renderCounterpartValue(value) + } + > + {signers.map((signer, index) => { + const npub = hexToNpub(signer.pubkey) + const metadata = props.metadata[signer.pubkey] + const displayValue = getProfileUsername( + npub, + metadata + ) return ( - + { ) })} - - -
+ + + + )} ) })} @@ -524,28 +558,19 @@ export const DrawPDFFields = (props: Props) => { ) } - const renderCounterpartValue = (value: string) => { - const user = users.find((u) => u.pubkey === npubToHex(value)) - if (user) { - let displayValue = truncate(value, { - length: 16 - }) + const renderCounterpartValue = (npub: string) => { + let displayValue = _.truncate(npub, { length: 16 }) - const metadata = props.metadata[user.pubkey] + const signer = signers.find((u) => u.pubkey === npubToHex(npub)) + if (signer) { + const metadata = props.metadata[signer.pubkey] + displayValue = getProfileUsername(npub, metadata) - if (metadata) { - displayValue = truncate( - metadata.name || metadata.display_name || metadata.username || value, - { - length: 16 - } - ) - } return ( - <> +
{ }} /> {displayValue} - +
) } - return value - } - - if (parsingPdf) { - return - } - - if (!sigitFiles.length) { - return '' + return displayValue } return ( @@ -589,7 +606,7 @@ export const DrawPDFFields = (props: Props) => { )} - {i < selectedFiles.length - 1 && } + {i < sigitFiles.length - 1 && } ) })} diff --git a/src/components/DrawPDFFields/style.module.scss b/src/components/DrawPDFFields/style.module.scss index 13afb9f..8c0b3b8 100644 --- a/src/components/DrawPDFFields/style.module.scss +++ b/src/components/DrawPDFFields/style.module.scss @@ -84,3 +84,14 @@ padding: 5px 0; } } + +.counterpartSelectValue { + display: flex; +} + +.counterpartAvatar { + img { + width: 21px; + height: 21px; + } +} diff --git a/src/components/UserAvatar/index.tsx b/src/components/UserAvatar/index.tsx index 0ea1fc1..4c49e33 100644 --- a/src/components/UserAvatar/index.tsx +++ b/src/components/UserAvatar/index.tsx @@ -5,7 +5,7 @@ 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 { getProfileUsername } from '../../utils' import { TooltipChild } from '../TooltipChild' interface UserAvatarProps { @@ -22,7 +22,7 @@ export const UserAvatar = ({ isNameVisible = false }: UserAvatarProps) => { const profile = useProfileMetadata(pubkey) - const name = profile?.display_name || profile?.name || shorten(pubkey) + const name = getProfileUsername(pubkey, profile) const image = profile?.picture return ( diff --git a/src/pages/create/index.tsx b/src/pages/create/index.tsx index 7f39b11..59fdb4f 100644 --- a/src/pages/create/index.tsx +++ b/src/pages/create/index.tsx @@ -39,7 +39,8 @@ import { signEventForMetaFile, updateUsersAppData, uploadToFileStorage, - DEFAULT_TOOLBOX + DEFAULT_TOOLBOX, + settleAllFullfilfedPromises } from '../../utils' import { Container } from '../../components/Container' import fileListStyles from '../../components/FileList/style.module.scss' @@ -60,7 +61,8 @@ import { faTrash, faUpload } from '@fortawesome/free-solid-svg-icons' -import { SigitFile } from '../../utils/file.ts' +import { getSigitFile, SigitFile } from '../../utils/file.ts' +import _ from 'lodash' export const CreatePage = () => { const navigate = useNavigate() @@ -106,9 +108,31 @@ export const CreatePage = () => { {} ) const [drawnFiles, setDrawnFiles] = useState([]) + const [parsingPdf, setIsParsing] = useState(false) + useEffect(() => { + if (selectedFiles) { + /** + * Reads the binary files and converts to internal file type + * and sets to a state (adds images if it's a PDF) + */ + const parsePages = async () => { + const files = await settleAllFullfilfedPromises( + selectedFiles, + getSigitFile + ) + + setDrawnFiles(files) + } + + setIsParsing(true) + + parsePages().finally(() => { + setIsParsing(false) + }) + } + }, [selectedFiles]) const [selectedTool, setSelectedTool] = useState() - const [toolbox] = useState(DEFAULT_TOOLBOX) /** * Changes the drawing tool @@ -282,6 +306,19 @@ export const CreatePage = () => { const handleRemoveUser = (pubkey: string) => { setUsers((prev) => prev.filter((user) => user.pubkey !== pubkey)) + + // Set counterpart to '' + const drawnFilesCopy = _.cloneDeep(drawnFiles) + drawnFilesCopy.forEach((s) => { + s.pages?.forEach((p) => { + p.drawnFields.forEach((d) => { + if (d.counterpart === hexToNpub(pubkey)) { + d.counterpart = '' + } + }) + }) + }) + setDrawnFiles(drawnFilesCopy) } /** @@ -724,10 +761,6 @@ export const CreatePage = () => { } } - const onDrawFieldsChange = (sigitFiles: SigitFile[]) => { - setDrawnFiles(sigitFiles) - } - if (authUrl) { return (