new release #190

Merged
b merged 68 commits from staging into main 2024-09-06 18:59:34 +00:00
12 changed files with 145 additions and 90 deletions
Showing only changes of commit c9d7d0a6f5 - Show all commits

View File

@ -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 && (

View File

@ -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;
}

View File

@ -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,6 +32,7 @@ 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)
} }
if ('pages' in pdfFile) {
return pdfFile.pages.map((page, i) => { return pdfFile.pages.map((page, i) => {
return ( return (
<PdfPageItem <PdfPageItem
@ -44,6 +46,10 @@ const PdfItem = ({
/> />
) )
}) })
} else {
const extension = extractFileExtension(pdfFile.name)
return <div className={'otherFile'}>This is a {extension} file</div>
}
} }
export default PdfItem export default PdfItem

View File

@ -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}
> >

View File

@ -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;
}

View File

@ -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

View File

@ -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])

View File

@ -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,7 +87,8 @@ 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 ? (
pdfFile.pages.map((page, i) => {
const marks: Mark[] = [] const marks: Mark[] = []
signatureEvents.forEach((e) => { signatureEvents.forEach((e) => {
@ -119,7 +122,12 @@ const SlimPdfView = ({
})} })}
</div> </div>
) )
})} })
) : (
<div className={'otherFile'}>
This is a {extractFileExtension(pdfFile.name)} file
</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)) {
let blob: Blob
if ('pages' in pdf) {
const pages = await addMarks(pdf.file, marksByPage[fileName]) const pages = await addMarks(pdf.file, marksByPage[fileName])
const blob = await convertToPdfBlob(pages) blob = await convertToPdfBlob(pages)
} else {
blob = new Blob([pdf], { type: pdf.type })
}
zip.file(`files/${fileName}`, blob) zip.file(`files/${fileName}`, blob)
} }

View File

@ -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

View File

@ -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)
} }

View File

@ -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 })
} }
/** /**

View File

@ -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[] => {