new release #190
@ -488,9 +488,7 @@ export const DrawPDFFields = (props: Props) => {
|
|||||||
{pdfFile ? (
|
{pdfFile ? (
|
||||||
getPdfPages(pdfFile, i)
|
getPdfPages(pdfFile, i)
|
||||||
) : (
|
) : (
|
||||||
<div className={styles.otherFile}>
|
<div className={'otherFile'}>This is a {extension} file</div>
|
||||||
This is a {extension} file
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{i < selectedFiles.length - 1 && (
|
{i < selectedFiles.length - 1 && (
|
||||||
|
@ -104,15 +104,3 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 25px;
|
gap: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.otherFile {
|
|
||||||
border-radius: 4px;
|
|
||||||
background: rgba(255, 255, 255, 0.5);
|
|
||||||
height: 100px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
color: rgba(0, 0, 0, 0.25);
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import { PdfFile } from '../../types/drawing.ts'
|
import { PdfFile } from '../../types/drawing.ts'
|
||||||
import { CurrentUserMark, Mark } from '../../types/mark.ts'
|
import { CurrentUserMark, Mark } from '../../types/mark.ts'
|
||||||
|
import { extractFileExtension } from '../../utils/meta.ts'
|
||||||
import PdfPageItem from './PdfPageItem.tsx'
|
import PdfPageItem from './PdfPageItem.tsx'
|
||||||
|
|
||||||
interface PdfItemProps {
|
interface PdfItemProps {
|
||||||
currentUserMarks: CurrentUserMark[]
|
currentUserMarks: CurrentUserMark[]
|
||||||
handleMarkClick: (id: number) => void
|
handleMarkClick: (id: number) => void
|
||||||
otherUserMarks: Mark[]
|
otherUserMarks: Mark[]
|
||||||
pdfFile: PdfFile
|
pdfFile: PdfFile | File
|
||||||
selectedMark: CurrentUserMark | null
|
selectedMark: CurrentUserMark | null
|
||||||
selectedMarkValue: string
|
selectedMarkValue: string
|
||||||
}
|
}
|
||||||
@ -31,19 +32,24 @@ const PdfItem = ({
|
|||||||
const filterMarksByPage = (marks: Mark[], page: number): Mark[] => {
|
const filterMarksByPage = (marks: Mark[], page: number): Mark[] => {
|
||||||
return marks.filter((mark) => mark.location.page === page)
|
return marks.filter((mark) => mark.location.page === page)
|
||||||
}
|
}
|
||||||
return pdfFile.pages.map((page, i) => {
|
if ('pages' in pdfFile) {
|
||||||
return (
|
return pdfFile.pages.map((page, i) => {
|
||||||
<PdfPageItem
|
return (
|
||||||
page={page}
|
<PdfPageItem
|
||||||
key={i}
|
page={page}
|
||||||
currentUserMarks={filterByPage(currentUserMarks, i)}
|
key={i}
|
||||||
handleMarkClick={handleMarkClick}
|
currentUserMarks={filterByPage(currentUserMarks, i)}
|
||||||
selectedMarkValue={selectedMarkValue}
|
handleMarkClick={handleMarkClick}
|
||||||
selectedMark={selectedMark}
|
selectedMarkValue={selectedMarkValue}
|
||||||
otherUserMarks={filterMarksByPage(otherUserMarks, i)}
|
selectedMark={selectedMark}
|
||||||
/>
|
otherUserMarks={filterMarksByPage(otherUserMarks, i)}
|
||||||
)
|
/>
|
||||||
})
|
)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
const extension = extractFileExtension(pdfFile.name)
|
||||||
|
return <div className={'otherFile'}>This is a {extension} file</div>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default PdfItem
|
export default PdfItem
|
||||||
|
@ -51,11 +51,12 @@ const PdfView = ({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{files.map((currentUserFile, index, arr) => {
|
{files.map((currentUserFile, index, arr) => {
|
||||||
const { hash, pdfFile, id } = currentUserFile
|
const { hash, pdfFile, id, filename } = currentUserFile
|
||||||
|
|
||||||
if (!hash) return
|
if (!hash) return
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
id={pdfFile.file.name}
|
id={filename}
|
||||||
ref={(el) => (pdfRefs.current[id] = el)}
|
ref={(el) => (pdfRefs.current[id] = el)}
|
||||||
key={index}
|
key={index}
|
||||||
>
|
>
|
||||||
|
@ -165,3 +165,15 @@ button:disabled {
|
|||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.otherFile {
|
||||||
|
border-radius: 4px;
|
||||||
|
background: rgba(255, 255, 255, 0.5);
|
||||||
|
height: 100px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
color: rgba(0, 0, 0, 0.25);
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
@ -33,13 +33,14 @@ import {
|
|||||||
sendNotification,
|
sendNotification,
|
||||||
signEventForMetaFile,
|
signEventForMetaFile,
|
||||||
updateUsersAppData,
|
updateUsersAppData,
|
||||||
findOtherUserMarks
|
findOtherUserMarks,
|
||||||
|
extractFileExtension
|
||||||
} from '../../utils'
|
} from '../../utils'
|
||||||
import { Container } from '../../components/Container'
|
import { Container } from '../../components/Container'
|
||||||
import { DisplayMeta } from './internal/displayMeta'
|
import { DisplayMeta } from './internal/displayMeta'
|
||||||
import styles from './style.module.scss'
|
import styles from './style.module.scss'
|
||||||
import { PdfFile } from '../../types/drawing.ts'
|
import { PdfFile } from '../../types/drawing.ts'
|
||||||
import { convertToPdfFile } from '../../utils/pdf.ts'
|
import { convertToPdfFile, toFile } from '../../utils/pdf.ts'
|
||||||
import { CurrentUserMark, Mark } from '../../types/mark.ts'
|
import { CurrentUserMark, Mark } from '../../types/mark.ts'
|
||||||
import { getLastSignersSig } from '../../utils/sign.ts'
|
import { getLastSignersSig } from '../../utils/sign.ts'
|
||||||
import {
|
import {
|
||||||
@ -76,7 +77,7 @@ export const SignPage = () => {
|
|||||||
|
|
||||||
const [selectedFile, setSelectedFile] = useState<File | null>(null)
|
const [selectedFile, setSelectedFile] = useState<File | null>(null)
|
||||||
|
|
||||||
const [files, setFiles] = useState<{ [filename: string]: PdfFile }>({})
|
const [files, setFiles] = useState<{ [filename: string]: PdfFile | File }>({})
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(true)
|
const [isLoading, setIsLoading] = useState(true)
|
||||||
const [loadingSpinnerDesc, setLoadingSpinnerDesc] = useState('')
|
const [loadingSpinnerDesc, setLoadingSpinnerDesc] = useState('')
|
||||||
@ -402,7 +403,7 @@ export const SignPage = () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const files: { [filename: string]: PdfFile } = {}
|
const files: { [filename: string]: PdfFile | File } = {}
|
||||||
const fileHashes: { [key: string]: string | null } = {}
|
const fileHashes: { [key: string]: string | null } = {}
|
||||||
const fileNames = Object.values(zip.files).map((entry) => entry.name)
|
const fileNames = Object.values(zip.files).map((entry) => entry.name)
|
||||||
|
|
||||||
@ -419,7 +420,11 @@ export const SignPage = () => {
|
|||||||
try {
|
try {
|
||||||
files[fileName] = await convertToPdfFile(arrayBuffer, fileName)
|
files[fileName] = await convertToPdfFile(arrayBuffer, fileName)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Not a .pdf file:', error)
|
files[fileName] = toFile(
|
||||||
|
arrayBuffer,
|
||||||
|
fileName,
|
||||||
|
'application/' + extractFileExtension(fileName)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
const hash = await getHash(arrayBuffer)
|
const hash = await getHash(arrayBuffer)
|
||||||
if (hash) {
|
if (hash) {
|
||||||
@ -767,8 +772,12 @@ export const SignPage = () => {
|
|||||||
|
|
||||||
zip.file('meta.json', stringifiedMeta)
|
zip.file('meta.json', stringifiedMeta)
|
||||||
|
|
||||||
for (const [fileName, pdf] of Object.entries(files)) {
|
for (const [fileName, file] of Object.entries(files)) {
|
||||||
zip.file(`files/${fileName}`, await pdf.file.arrayBuffer())
|
if ('pages' in file) {
|
||||||
|
zip.file(`files/${fileName}`, await file.file.arrayBuffer())
|
||||||
|
} else {
|
||||||
|
zip.file(`files/${fileName}`, await file.arrayBuffer())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const arrayBuffer = await zip
|
const arrayBuffer = await zip
|
||||||
@ -805,8 +814,12 @@ export const SignPage = () => {
|
|||||||
|
|
||||||
zip.file('meta.json', stringifiedMeta)
|
zip.file('meta.json', stringifiedMeta)
|
||||||
|
|
||||||
for (const [fileName, pdf] of Object.entries(files)) {
|
for (const [fileName, file] of Object.entries(files)) {
|
||||||
zip.file(`files/${fileName}`, await pdf.file.arrayBuffer())
|
if ('pages' in file) {
|
||||||
|
zip.file(`files/${fileName}`, await file.file.arrayBuffer())
|
||||||
|
} else {
|
||||||
|
zip.file(`files/${fileName}`, await file.arrayBuffer())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const arrayBuffer = await zip
|
const arrayBuffer = await zip
|
||||||
|
@ -38,7 +38,7 @@ import { PdfFile } from '../../../types/drawing.ts'
|
|||||||
|
|
||||||
type DisplayMetaProps = {
|
type DisplayMetaProps = {
|
||||||
meta: Meta
|
meta: Meta
|
||||||
files: { [filename: string]: PdfFile }
|
files: { [filename: string]: PdfFile | File }
|
||||||
submittedBy: string
|
submittedBy: string
|
||||||
signers: `npub1${string}`[]
|
signers: `npub1${string}`[]
|
||||||
viewers: `npub1${string}`[]
|
viewers: `npub1${string}`[]
|
||||||
@ -144,7 +144,14 @@ export const DisplayMeta = ({
|
|||||||
}, [users, submittedBy, metadata])
|
}, [users, submittedBy, metadata])
|
||||||
|
|
||||||
const downloadFile = async (filename: string) => {
|
const downloadFile = async (filename: string) => {
|
||||||
const arrayBuffer = await files[filename].file.arrayBuffer()
|
const file = files[filename]
|
||||||
|
|
||||||
|
let arrayBuffer: ArrayBuffer
|
||||||
|
if ('pages' in file) {
|
||||||
|
arrayBuffer = await file.file.arrayBuffer()
|
||||||
|
} else {
|
||||||
|
arrayBuffer = await file.arrayBuffer()
|
||||||
|
}
|
||||||
if (!arrayBuffer) return
|
if (!arrayBuffer) return
|
||||||
|
|
||||||
const blob = new Blob([arrayBuffer])
|
const blob = new Blob([arrayBuffer])
|
||||||
|
@ -21,7 +21,8 @@ import {
|
|||||||
readContentOfZipEntry,
|
readContentOfZipEntry,
|
||||||
signEventForMetaFile,
|
signEventForMetaFile,
|
||||||
shorten,
|
shorten,
|
||||||
getCurrentUserFiles
|
getCurrentUserFiles,
|
||||||
|
extractFileExtension
|
||||||
} from '../../utils'
|
} from '../../utils'
|
||||||
import styles from './style.module.scss'
|
import styles from './style.module.scss'
|
||||||
import { useLocation } from 'react-router-dom'
|
import { useLocation } from 'react-router-dom'
|
||||||
@ -32,7 +33,8 @@ import {
|
|||||||
convertToPdfBlob,
|
convertToPdfBlob,
|
||||||
convertToPdfFile,
|
convertToPdfFile,
|
||||||
groupMarksByFileNamePage,
|
groupMarksByFileNamePage,
|
||||||
inPx
|
inPx,
|
||||||
|
toFile
|
||||||
} from '../../utils/pdf.ts'
|
} from '../../utils/pdf.ts'
|
||||||
import { State } from '../../store/rootReducer.ts'
|
import { State } from '../../store/rootReducer.ts'
|
||||||
import { useSelector } from 'react-redux'
|
import { useSelector } from 'react-redux'
|
||||||
@ -85,41 +87,47 @@ const SlimPdfView = ({
|
|||||||
ref={(el) => (pdfRefs.current[id] = el)}
|
ref={(el) => (pdfRefs.current[id] = el)}
|
||||||
className={styles.fileWrapper}
|
className={styles.fileWrapper}
|
||||||
>
|
>
|
||||||
{pdfFile.pages.map((page, i) => {
|
{'pages' in pdfFile ? (
|
||||||
const marks: Mark[] = []
|
pdfFile.pages.map((page, i) => {
|
||||||
|
const marks: Mark[] = []
|
||||||
|
|
||||||
signatureEvents.forEach((e) => {
|
signatureEvents.forEach((e) => {
|
||||||
const m = parsedSignatureEvents[
|
const m = parsedSignatureEvents[
|
||||||
e as `npub1${string}`
|
e as `npub1${string}`
|
||||||
].parsedContent?.marks.filter(
|
].parsedContent?.marks.filter(
|
||||||
(m) => m.pdfFileHash == hash && m.location.page == i
|
(m) => m.pdfFileHash == hash && m.location.page == i
|
||||||
|
)
|
||||||
|
if (m) {
|
||||||
|
marks.push(...m)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return (
|
||||||
|
<div className={styles.imageWrapper} key={i}>
|
||||||
|
<img draggable="false" src={page.image} />
|
||||||
|
{marks.map((m) => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={styles.mark}
|
||||||
|
key={m.id}
|
||||||
|
style={{
|
||||||
|
left: inPx(m.location.left),
|
||||||
|
top: inPx(m.location.top),
|
||||||
|
width: inPx(m.location.width),
|
||||||
|
height: inPx(m.location.height)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{m.value}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
if (m) {
|
|
||||||
marks.push(...m)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
return (
|
) : (
|
||||||
<div className={styles.imageWrapper} key={i}>
|
<div className={'otherFile'}>
|
||||||
<img draggable="false" src={page.image} />
|
This is a {extractFileExtension(pdfFile.name)} file
|
||||||
{marks.map((m) => {
|
</div>
|
||||||
return (
|
)}
|
||||||
<div
|
|
||||||
className={styles.mark}
|
|
||||||
key={m.id}
|
|
||||||
style={{
|
|
||||||
left: inPx(m.location.left),
|
|
||||||
top: inPx(m.location.top),
|
|
||||||
width: inPx(m.location.width),
|
|
||||||
height: inPx(m.location.height)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{m.value}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{i < files.length - 1 && (
|
{i < files.length - 1 && (
|
||||||
@ -171,7 +179,7 @@ export const VerifyPage = () => {
|
|||||||
const [currentFileHashes, setCurrentFileHashes] = useState<{
|
const [currentFileHashes, setCurrentFileHashes] = useState<{
|
||||||
[key: string]: string | null
|
[key: string]: string | null
|
||||||
}>({})
|
}>({})
|
||||||
const [files, setFiles] = useState<{ [filename: string]: PdfFile }>({})
|
const [files, setFiles] = useState<{ [filename: string]: PdfFile | File }>({})
|
||||||
const [currentFile, setCurrentFile] = useState<CurrentUserFile | null>(null)
|
const [currentFile, setCurrentFile] = useState<CurrentUserFile | null>(null)
|
||||||
const [signatureFileHashes, setSignatureFileHashes] = useState<{
|
const [signatureFileHashes, setSignatureFileHashes] = useState<{
|
||||||
[key: string]: string
|
[key: string]: string
|
||||||
@ -230,7 +238,7 @@ export const VerifyPage = () => {
|
|||||||
|
|
||||||
if (!zip) return
|
if (!zip) return
|
||||||
|
|
||||||
const files: { [filename: string]: PdfFile } = {}
|
const files: { [filename: string]: PdfFile | File } = {}
|
||||||
const fileHashes: { [key: string]: string | null } = {}
|
const fileHashes: { [key: string]: string | null } = {}
|
||||||
const fileNames = Object.values(zip.files).map(
|
const fileNames = Object.values(zip.files).map(
|
||||||
(entry) => entry.name
|
(entry) => entry.name
|
||||||
@ -252,7 +260,11 @@ export const VerifyPage = () => {
|
|||||||
fileName!
|
fileName!
|
||||||
)
|
)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Not a .pdf file:', error)
|
files[fileName] = toFile(
|
||||||
|
arrayBuffer,
|
||||||
|
fileName,
|
||||||
|
'application/' + extractFileExtension(fileName)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
const hash = await getHash(arrayBuffer)
|
const hash = await getHash(arrayBuffer)
|
||||||
|
|
||||||
@ -428,8 +440,13 @@ export const VerifyPage = () => {
|
|||||||
const marksByPage = groupMarksByFileNamePage(marks)
|
const marksByPage = groupMarksByFileNamePage(marks)
|
||||||
|
|
||||||
for (const [fileName, pdf] of Object.entries(files)) {
|
for (const [fileName, pdf] of Object.entries(files)) {
|
||||||
const pages = await addMarks(pdf.file, marksByPage[fileName])
|
let blob: Blob
|
||||||
const blob = await convertToPdfBlob(pages)
|
if ('pages' in pdf) {
|
||||||
|
const pages = await addMarks(pdf.file, marksByPage[fileName])
|
||||||
|
blob = await convertToPdfBlob(pages)
|
||||||
|
} else {
|
||||||
|
blob = new Blob([pdf], { type: pdf.type })
|
||||||
|
}
|
||||||
zip.file(`files/${fileName}`, blob)
|
zip.file(`files/${fileName}`, blob)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import { PdfFile } from './drawing.ts'
|
|||||||
|
|
||||||
export interface CurrentUserFile {
|
export interface CurrentUserFile {
|
||||||
id: number
|
id: number
|
||||||
pdfFile: PdfFile
|
pdfFile: PdfFile | File
|
||||||
filename: string
|
filename: string
|
||||||
hash?: string
|
hash?: string
|
||||||
isHashValid: boolean
|
isHashValid: boolean
|
||||||
|
@ -6,15 +6,23 @@ import { PdfFile } from '../types/drawing.ts'
|
|||||||
|
|
||||||
const getZipWithFiles = async (
|
const getZipWithFiles = async (
|
||||||
meta: Meta,
|
meta: Meta,
|
||||||
files: { [filename: string]: PdfFile }
|
files: { [filename: string]: PdfFile | File }
|
||||||
): Promise<JSZip> => {
|
): Promise<JSZip> => {
|
||||||
const zip = new JSZip()
|
const zip = new JSZip()
|
||||||
const marks = extractMarksFromSignedMeta(meta)
|
const marks = extractMarksFromSignedMeta(meta)
|
||||||
const marksByFileNamePage = groupMarksByFileNamePage(marks)
|
const marksByFileNamePage = groupMarksByFileNamePage(marks)
|
||||||
|
|
||||||
for (const [fileName, pdf] of Object.entries(files)) {
|
for (const [fileName, file] of Object.entries(files)) {
|
||||||
const pages = await addMarks(pdf.file, marksByFileNamePage[fileName])
|
let blob: Blob
|
||||||
const blob = await convertToPdfBlob(pages)
|
if ('pages' in file) {
|
||||||
|
// Handle PDF Files
|
||||||
|
const pages = await addMarks(file.file, marksByFileNamePage[fileName])
|
||||||
|
blob = await convertToPdfBlob(pages)
|
||||||
|
} else {
|
||||||
|
// Handle other files
|
||||||
|
blob = new Blob([file], { type: file.type })
|
||||||
|
}
|
||||||
|
|
||||||
zip.file(`files/${fileName}`, blob)
|
zip.file(`files/${fileName}`, blob)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,10 +30,15 @@ const FONT_TYPE: string = 'Arial'
|
|||||||
* Converts a PDF ArrayBuffer to a generic PDF File
|
* Converts a PDF ArrayBuffer to a generic PDF File
|
||||||
* @param arrayBuffer of a PDF
|
* @param arrayBuffer of a PDF
|
||||||
* @param fileName identifier of the pdf file
|
* @param fileName identifier of the pdf file
|
||||||
|
* @param type optional file type (defaults to pdf)
|
||||||
*/
|
*/
|
||||||
const toFile = (arrayBuffer: ArrayBuffer, fileName: string): File => {
|
const toFile = (
|
||||||
const blob = new Blob([arrayBuffer], { type: 'application/pdf' })
|
arrayBuffer: ArrayBuffer,
|
||||||
return new File([blob], fileName, { type: 'application/pdf' })
|
fileName: string,
|
||||||
|
type: string = 'application/pdf'
|
||||||
|
): File => {
|
||||||
|
const blob = new Blob([arrayBuffer], { type })
|
||||||
|
return new File([blob], fileName, { type })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -75,7 +75,7 @@ export const timeout = (ms: number = 60000) => {
|
|||||||
* @param creatorFileHashes
|
* @param creatorFileHashes
|
||||||
*/
|
*/
|
||||||
export const getCurrentUserFiles = (
|
export const getCurrentUserFiles = (
|
||||||
files: { [filename: string]: PdfFile },
|
files: { [filename: string]: PdfFile | File },
|
||||||
fileHashes: { [key: string]: string | null },
|
fileHashes: { [key: string]: string | null },
|
||||||
creatorFileHashes: { [key: string]: string }
|
creatorFileHashes: { [key: string]: string }
|
||||||
): CurrentUserFile[] => {
|
): CurrentUserFile[] => {
|
||||||
|
Loading…
Reference in New Issue
Block a user