diff --git a/package-lock.json b/package-lock.json
index 2bcd952..71e0923 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -21,6 +21,7 @@
"@mui/material": "5.15.11",
"@noble/hashes": "^1.4.0",
"@nostr-dev-kit/ndk": "2.5.0",
+ "@pdf-lib/fontkit": "^1.1.1",
"@reduxjs/toolkit": "2.2.1",
"axios": "^1.7.4",
"crypto-hash": "3.0.0",
@@ -1749,6 +1750,15 @@
}
}
},
+ "node_modules/@pdf-lib/fontkit": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@pdf-lib/fontkit/-/fontkit-1.1.1.tgz",
+ "integrity": "sha512-KjMd7grNapIWS/Dm0gvfHEilSyAmeLvrEGVcqLGi0VYebuqqzTbgF29efCx7tvx+IEbG3zQciRSWl3GkUSvjZg==",
+ "license": "MIT",
+ "dependencies": {
+ "pako": "^1.0.6"
+ }
+ },
"node_modules/@pdf-lib/standard-fonts": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@pdf-lib/standard-fonts/-/standard-fonts-1.0.0.tgz",
diff --git a/package.json b/package.json
index aaeba6e..a833103 100644
--- a/package.json
+++ b/package.json
@@ -31,6 +31,7 @@
"@mui/material": "5.15.11",
"@noble/hashes": "^1.4.0",
"@nostr-dev-kit/ndk": "2.5.0",
+ "@pdf-lib/fontkit": "^1.1.1",
"@reduxjs/toolkit": "2.2.1",
"axios": "^1.7.4",
"crypto-hash": "3.0.0",
diff --git a/src/App.scss b/src/App.scss
index 4d95be6..c4fa323 100644
--- a/src/App.scss
+++ b/src/App.scss
@@ -135,12 +135,18 @@ li {
// Consistent styling for every file mark
// Reverts some of the design defaults for font
.file-mark {
- font-family: Arial;
- font-size: 16px;
+ font-family: 'Roboto';
+ font-style: normal;
font-weight: normal;
- color: black;
letter-spacing: normal;
- border: 1px solid transparent;
+ line-height: 1;
+
+ font-size: 16px;
+ color: black;
+ outline: 1px solid transparent;
+
+ justify-content: start;
+ align-items: start;
scroll-margin-top: $header-height + $body-vertical-padding;
}
diff --git a/src/assets/fonts/roboto-regular.ttf b/src/assets/fonts/roboto-regular.ttf
new file mode 100644
index 0000000..2d116d9
Binary files /dev/null and b/src/assets/fonts/roboto-regular.ttf differ
diff --git a/src/components/AppBar/AppBar.tsx b/src/components/AppBar/AppBar.tsx
index 8c7ac63..aaabbd3 100644
--- a/src/components/AppBar/AppBar.tsx
+++ b/src/components/AppBar/AppBar.tsx
@@ -37,7 +37,7 @@ import { setUserRobotImage } from '../../store/userRobotImage/action'
import { Container } from '../Container'
import { ButtonIcon } from '../ButtonIcon'
-const metadataController = new MetadataController()
+const metadataController = MetadataController.getInstance()
export const AppBar = () => {
const navigate = useNavigate()
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/DrawPDFFields/index.tsx b/src/components/DrawPDFFields/index.tsx
index 7efae8b..7c1227d 100644
--- a/src/components/DrawPDFFields/index.tsx
+++ b/src/components/DrawPDFFields/index.tsx
@@ -14,9 +14,10 @@ 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 { getToolboxLabelByMarkType } from '../../utils/mark'
import { FileDivider } from '../FileDivider'
import { ExtensionFileBox } from '../ExtensionFileBox'
-import { inPx } from '../../utils/pdf'
+import { FONT_SIZE, FONT_TYPE, inPx } from '../../utils/pdf'
import { useScale } from '../../hooks/useScale'
import { AvatarIconButton } from '../UserAvatarIconButton'
import { LoadingSpinner } from '../LoadingSpinner'
@@ -390,7 +391,7 @@ export const DrawPDFFields = (props: Props) => {
backgroundColor: drawnField.counterpart
? `#${npubToHex(drawnField.counterpart)?.substring(0, 6)}4b`
: undefined,
- borderColor: drawnField.counterpart
+ outlineColor: drawnField.counterpart
? `#${npubToHex(drawnField.counterpart)?.substring(0, 6)}`
: undefined,
left: inPx(from(page.width, drawnField.left)),
@@ -406,6 +407,16 @@ export const DrawPDFFields = (props: Props) => {
: undefined
}}
>
+
+ {getToolboxLabelByMarkType(drawnField.type) ||
+ 'placeholder'}
+
handleResizePointerDown(event, drawnFieldIndex)
diff --git a/src/components/DrawPDFFields/style.module.scss b/src/components/DrawPDFFields/style.module.scss
index 62fa688..13afb9f 100644
--- a/src/components/DrawPDFFields/style.module.scss
+++ b/src/components/DrawPDFFields/style.module.scss
@@ -13,9 +13,15 @@
}
}
+.placeholder {
+ position: absolute;
+ opacity: 0.5;
+ inset: 0;
+}
+
.drawingRectangle {
position: absolute;
- border: 1px solid #01aaad;
+ outline: 1px solid #01aaad;
z-index: 50;
background-color: #01aaad4b;
cursor: pointer;
@@ -29,7 +35,7 @@
}
&.edited {
- border: 1px dotted #01aaad;
+ outline: 1px dotted #01aaad;
}
.resizeHandle {
diff --git a/src/components/LoadingSpinner/index.tsx b/src/components/LoadingSpinner/index.tsx
index 2c6f4e5..d19d01f 100644
--- a/src/components/LoadingSpinner/index.tsx
+++ b/src/components/LoadingSpinner/index.tsx
@@ -1,12 +1,14 @@
+import { createPortal } from 'react-dom'
import styles from './style.module.scss'
+import { PropsWithChildren } from 'react'
interface Props {
desc?: string
variant?: 'small' | 'default'
}
-export const LoadingSpinner = (props: Props) => {
- const { desc, variant = 'default' } = props
+export const LoadingSpinner = (props: PropsWithChildren) => {
+ const { desc, children, variant = 'default' } = props
switch (variant) {
case 'small':
@@ -20,16 +22,22 @@ export const LoadingSpinner = (props: Props) => {
)
default:
- return (
+ return createPortal(
- {desc &&
{desc}
}
+ {desc && (
+
+ {desc}
+ {children}
+
+ )}
-
+ ,
+ document.getElementById('root')!
)
}
}
diff --git a/src/components/LoadingSpinner/style.module.scss b/src/components/LoadingSpinner/style.module.scss
index e1a5978..d51b743 100644
--- a/src/components/LoadingSpinner/style.module.scss
+++ b/src/components/LoadingSpinner/style.module.scss
@@ -42,11 +42,15 @@
width: 100%;
padding: 15px;
border-top: solid 1px rgba(0, 0, 0, 0.1);
- text-align: center;
color: rgba(0, 0, 0, 0.5);
font-size: 16px;
font-weight: 400;
+
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 10px;
}
@keyframes spin {
diff --git a/src/components/PDFView/PdfMarkItem.tsx b/src/components/PDFView/PdfMarkItem.tsx
index db57800..cb06455 100644
--- a/src/components/PDFView/PdfMarkItem.tsx
+++ b/src/components/PDFView/PdfMarkItem.tsx
@@ -36,7 +36,7 @@ const PdfMarkItem = forwardRef(
backgroundColor: selectedMark?.mark.npub
? `#${npubToHex(selectedMark?.mark.npub)?.substring(0, 6)}4b`
: undefined,
- borderColor: selectedMark?.mark.npub
+ outlineColor: selectedMark?.mark.npub
? `#${npubToHex(selectedMark?.mark.npub)?.substring(0, 6)}`
: undefined,
left: inPx(from(pageWidth, location.left)),
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..3a5c358 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,12 @@ export const UsersDetails = ({ meta }: UsersDetailsProps) => {
{signers.map((signer) => {
const pubkey = npubToHex(signer)!
- const profile = profiles[pubkey]
-
return (
-
-
-
-
-
+
)
})}
@@ -128,34 +89,28 @@ 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/controllers/AuthController.ts b/src/controllers/AuthController.ts
index 09b20df..cc8def5 100644
--- a/src/controllers/AuthController.ts
+++ b/src/controllers/AuthController.ts
@@ -25,7 +25,7 @@ export class AuthController {
constructor() {
this.nostrController = NostrController.getInstance()
- this.metadataController = new MetadataController()
+ this.metadataController = MetadataController.getInstance()
}
/**
diff --git a/src/controllers/MetadataController.ts b/src/controllers/MetadataController.ts
index 8053874..984afd3 100644
--- a/src/controllers/MetadataController.ts
+++ b/src/controllers/MetadataController.ts
@@ -22,6 +22,7 @@ import {
import { DEFAULT_LOOK_UP_RELAY_LIST } from '../utils/const'
export class MetadataController extends EventEmitter {
+ private static instance: MetadataController
private nostrController: NostrController
private specialMetadataRelay = 'wss://purplepag.es'
private pendingFetches = new Map
>() // Track pending fetches
@@ -31,6 +32,13 @@ export class MetadataController extends EventEmitter {
this.nostrController = NostrController.getInstance()
}
+ public static getInstance(): MetadataController {
+ if (!MetadataController.instance) {
+ MetadataController.instance = new MetadataController()
+ }
+ return MetadataController.instance
+ }
+
/**
* Asynchronously checks for more recent metadata events authored by a specific key.
* If a more recent metadata event is found, it is handled and returned.
@@ -119,7 +127,6 @@ export class MetadataController extends EventEmitter {
// Check if the cached metadata is older than one day
if (isOlderThanOneDay(cachedMetadataEvent.cachedAt)) {
// If older than one week, find the metadata from relays in background
-
this.checkForMoreRecentMetadata(hexKey, cachedMetadataEvent.event)
}
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/useSigitMeta.tsx b/src/hooks/useSigitMeta.tsx
index 088940e..22a6a6d 100644
--- a/src/hooks/useSigitMeta.tsx
+++ b/src/hooks/useSigitMeta.tsx
@@ -33,6 +33,10 @@ export interface FlatMeta
// Remove pubkey and use submittedBy as `npub1${string}`
submittedBy?: `npub1${string}`
+ // Optional field only present on exported sigits
+ // Exporting adds user's pubkey
+ exportedBy?: `npub1${string}`
+
// Remove created_at and replace with createdAt
createdAt?: number
@@ -68,6 +72,7 @@ export const useSigitMeta = (meta: Meta): FlatMeta => {
const [tags, setTags] = useState()
const [createdAt, setCreatedAt] = useState()
const [submittedBy, setSubmittedBy] = useState<`npub1${string}`>() // submittedBy, pubkey from nostr event
+ const [exportedBy, setExportedBy] = useState<`npub1${string}`>() // pubkey from export signature nostr event
const [id, setId] = useState()
const [sig, setSig] = useState()
@@ -99,6 +104,18 @@ export const useSigitMeta = (meta: Meta): FlatMeta => {
if (!meta) return
;(async function () {
try {
+ if (meta.exportSignature) {
+ const exportSignatureEvent = await parseNostrEvent(
+ meta.exportSignature
+ )
+ if (
+ verifyEvent(exportSignatureEvent) &&
+ exportSignatureEvent.pubkey
+ ) {
+ setExportedBy(exportSignatureEvent.pubkey as `npub1${string}`)
+ }
+ }
+
const createSignatureEvent = await parseNostrEvent(meta.createSignature)
const { kind, tags, created_at, pubkey, id, sig, content } =
@@ -265,6 +282,7 @@ export const useSigitMeta = (meta: Meta): FlatMeta => {
tags,
createdAt,
submittedBy,
+ exportedBy,
id,
sig,
signers,
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/layouts/Main.tsx b/src/layouts/Main.tsx
index 9402e97..3a1f10e 100644
--- a/src/layouts/Main.tsx
+++ b/src/layouts/Main.tsx
@@ -38,7 +38,7 @@ export const MainLayout = () => {
const hasSubscribed = useRef(false)
useEffect(() => {
- const metadataController = new MetadataController()
+ const metadataController = MetadataController.getInstance()
const logout = () => {
dispatch(
diff --git a/src/pages/create/index.tsx b/src/pages/create/index.tsx
index f0bd6b9..dd17450 100644
--- a/src/pages/create/index.tsx
+++ b/src/pages/create/index.tsx
@@ -36,44 +36,26 @@ import {
npubToHex,
queryNip05,
sendNotification,
- shorten,
signEventForMetaFile,
updateUsersAppData,
- uploadToFileStorage
+ uploadToFileStorage,
+ DEFAULT_TOOLBOX
} from '../../utils'
import { Container } from '../../components/Container'
import fileListStyles from '../../components/FileList/style.module.scss'
-import { DrawTool, MarkType } from '../../types/drawing'
+import { DrawTool } from '../../types/drawing'
import { DrawPDFFields } from '../../components/DrawPDFFields'
import { Mark } from '../../types/mark.ts'
import { StickySideColumns } from '../../layouts/StickySideColumns.tsx'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import {
- fa1,
- faBriefcase,
- faCalendarDays,
- faCheckDouble,
- faCircleDot,
- faClock,
- faCreditCard,
faEllipsis,
faEye,
faFile,
faFileCirclePlus,
faGripLines,
- faHeading,
- faIdCard,
- faImage,
- faPaperclip,
faPen,
- faPhone,
faPlus,
- faSignature,
- faSquareCaretDown,
- faSquareCheck,
- faStamp,
- faT,
- faTableCellsLarge,
faToolbox,
faTrash,
faUpload
@@ -113,6 +95,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)
@@ -124,116 +108,7 @@ export const CreatePage = () => {
const [drawnFiles, setDrawnFiles] = useState([])
const [selectedTool, setSelectedTool] = useState()
- const [toolbox] = useState([
- {
- identifier: MarkType.TEXT,
- icon: faT,
- label: 'Text',
- active: true
- },
- {
- identifier: MarkType.SIGNATURE,
- icon: faSignature,
- label: 'Signature',
- active: false
- },
- {
- identifier: MarkType.JOBTITLE,
- icon: faBriefcase,
- label: 'Job Title',
- active: false
- },
- {
- identifier: MarkType.FULLNAME,
- icon: faIdCard,
- label: 'Full Name',
- active: false
- },
- {
- identifier: MarkType.INITIALS,
- icon: faHeading,
- label: 'Initials',
- active: false
- },
- {
- identifier: MarkType.DATETIME,
- icon: faClock,
- label: 'Date Time',
- active: false
- },
- {
- identifier: MarkType.DATE,
- icon: faCalendarDays,
- label: 'Date',
- active: false
- },
- {
- identifier: MarkType.NUMBER,
- icon: fa1,
- label: 'Number',
- active: false
- },
- {
- identifier: MarkType.IMAGES,
- icon: faImage,
- label: 'Images',
- active: false
- },
- {
- identifier: MarkType.CHECKBOX,
- icon: faSquareCheck,
- label: 'Checkbox',
- active: false
- },
- {
- identifier: MarkType.MULTIPLE,
- icon: faCheckDouble,
- label: 'Multiple',
- active: false
- },
- {
- identifier: MarkType.FILE,
- icon: faPaperclip,
- label: 'File',
- active: false
- },
- {
- identifier: MarkType.RADIO,
- icon: faCircleDot,
- label: 'Radio',
- active: false
- },
- {
- identifier: MarkType.SELECT,
- icon: faSquareCaretDown,
- label: 'Select',
- active: false
- },
- {
- identifier: MarkType.CELLS,
- icon: faTableCellsLarge,
- label: 'Cells',
- active: false
- },
- {
- identifier: MarkType.STAMP,
- icon: faStamp,
- label: 'Stamp',
- active: false
- },
- {
- identifier: MarkType.PAYMENT,
- icon: faCreditCard,
- label: 'Payment',
- active: false
- },
- {
- identifier: MarkType.PHONE,
- icon: faPhone,
- label: 'Phone',
- active: false
- }
- ])
+ const [toolbox] = useState(DEFAULT_TOOLBOX)
/**
* Changes the drawing tool
@@ -252,7 +127,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 +522,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 +552,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 +580,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 +661,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 +788,6 @@ export const CreatePage = () => {
{
-
{toolbox.map((drawTool: DrawTool, index: number) => {
@@ -987,6 +857,10 @@ export const CreatePage = () => {
})}
+
+
{!!error && (
{error}
)}
@@ -1010,7 +884,6 @@ export const CreatePage = () => {
}
type DisplayUsersProps = {
- metadata: { [key: string]: ProfileMetadata }
users: User[]
handleUserRoleChange: (role: UserRole, pubkey: string) => void
handleRemoveUser: (pubkey: string) => void
@@ -1018,7 +891,6 @@ type DisplayUsersProps = {
}
const DisplayUser = ({
- metadata,
users,
handleUserRoleChange,
handleRemoveUser,
@@ -1032,7 +904,6 @@ const DisplayUser = ({
.map((user, index) => (
void
handleRemoveUser: (pubkey: string) => void
@@ -1078,7 +947,6 @@ type SignerCounterpartProps = CounterpartProps & {
}
const SignerCounterpart = ({
- userMeta,
user,
index,
moveSigner,
@@ -1171,7 +1039,6 @@ const SignerCounterpart = ({
@@ -1180,7 +1047,6 @@ const SignerCounterpart = ({
}
const Counterpart = ({
- userMeta,
user,
handleUserRoleChange,
handleRemoveUser
@@ -1188,15 +1054,7 @@ const Counterpart = ({
return (
<>
-
+