PDF Markings #114

Merged
eugene merged 33 commits from issue-99 into staging 2024-08-06 10:02:04 +00:00
Showing only changes of commit e1808726aa - Show all commits

View File

@ -16,10 +16,10 @@ import { State } from '../../store/rootReducer'
import { CreateSignatureEventContent, Meta, SignedEvent } from '../../types' import { CreateSignatureEventContent, Meta, SignedEvent } from '../../types'
import { import {
decryptArrayBuffer, decryptArrayBuffer,
encryptArrayBuffer, encryptArrayBuffer, extractMarksFromSignedMeta,
extractZipUrlAndEncryptionKey, extractZipUrlAndEncryptionKey,
generateEncryptionKey, generateEncryptionKey,
generateKeysFile, generateKeysFile, getFilesWithHashes,
getHash, getHash,
hexToNpub, hexToNpub,
isOnline, loadZip, isOnline, loadZip,
@ -35,10 +35,15 @@ 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 } from '../../utils/pdf.ts'
import PdfView from '../../components/PDFView' // import PdfView from '../../components/PDFView'
import { CurrentUserMark, Mark, MarkConfig } from '../../types/mark.ts' import { CurrentUserMark, Mark } from '../../types/mark.ts'
import MarkFormField from './MarkFormField.tsx'
import { getLastSignersSig } from '../../utils/sign.ts' import { getLastSignersSig } from '../../utils/sign.ts'
import {
filterMarksByPubkey,
getCurrentUserMarks,
isCurrentUserMarksComplete, updateMarks
} from '../../utils/mark.ts'
import PdfMarking from '../../components/PDFView/PdfMarking.tsx'
enum SignedStatus { enum SignedStatus {
Fully_Signed, Fully_Signed,
User_Is_Next_Signer, User_Is_Next_Signer,
@ -95,10 +100,8 @@ export const SignPage = () => {
const [authUrl, setAuthUrl] = useState<string>() const [authUrl, setAuthUrl] = useState<string>()
const nostrController = NostrController.getInstance() const nostrController = NostrController.getInstance()
const [currentUserMark, setCurrentUserMark] = useState<CurrentUserMark | null>(null);
const [currentUserMarks, setCurrentUserMarks] = useState<CurrentUserMark[]>([]); const [currentUserMarks, setCurrentUserMarks] = useState<CurrentUserMark[]>([]);
const [currentMarkValue, setCurrentMarkValue] = useState<string>(''); const [isReadyToSign, setIsReadyToSign] = useState(false);
const [isMarksCompleted, setIsMarksCompleted] = useState(false);
useEffect(() => { useEffect(() => {
if (signers.length > 0) { if (signers.length > 0) {
@ -191,22 +194,13 @@ export const SignPage = () => {
setSubmittedBy(createSignatureEvent.pubkey) setSubmittedBy(createSignatureEvent.pubkey)
setMarks(createSignatureContent.markConfig); setMarks(createSignatureContent.markConfig);
console.log('createSignatureContent markConfig', createSignatureContent);
if (usersPubkey) { if (usersPubkey) {
console.log('this runs behind users pubkey'); const metaMarks = filterMarksByPubkey(createSignatureContent.markConfig, usersPubkey!)
const curMarks = getCurrentUserMarks(createSignatureContent.markConfig, usersPubkey) const signedMarks = extractMarksFromSignedMeta(meta)
if (curMarks.length === 0) { const currentUserMarks = getCurrentUserMarks(metaMarks, signedMarks);
setIsMarksCompleted(true) setCurrentUserMarks(currentUserMarks);
} else { // setCurrentUserMark(findNextCurrentUserMark(currentUserMarks) || null)
const nextMark = findNextIncompleteMark(curMarks) setIsReadyToSign(isCurrentUserMarksComplete(currentUserMarks))
if (!nextMark) {
setIsMarksCompleted(true)
} else {
setCurrentUserMark(nextMark)
setIsMarksCompleted(false)
}
setCurrentUserMarks(curMarks)
}
} }
setSignedBy(Object.keys(meta.docSignatures) as `npub1${string}`[]) setSignedBy(Object.keys(meta.docSignatures) as `npub1${string}`[])
@ -218,6 +212,7 @@ export const SignPage = () => {
}, [meta]) }, [meta])
useEffect(() => { useEffect(() => {
// online mode - from create and home page views
if (metaInNavState) { if (metaInNavState) {
const processSigit = async () => { const processSigit = async () => {
setIsLoading(true) setIsLoading(true)
@ -239,7 +234,7 @@ export const SignPage = () => {
.then((res) => { .then((res) => {
handleArrayBufferFromBlossom(res.data, encryptionKey) handleArrayBufferFromBlossom(res.data, encryptionKey)
setMeta(metaInNavState) setMeta(metaInNavState)
console.log('meta in nav state: ', metaInNavState) console.log('meta in nav state runs.')
}) })
.catch((err) => { .catch((err) => {
console.error(`error occurred in getting file from ${zipUrl}`, err) console.error(`error occurred in getting file from ${zipUrl}`, err)
@ -330,6 +325,11 @@ export const SignPage = () => {
setCurrentFileHashes(fileHashes) setCurrentFileHashes(fileHashes)
} }
const setUpdatedMarks = (markToUpdate: Mark) => {
const updatedMarks = updateMarks(marks, markToUpdate)
setMarks(updatedMarks)
}
const parseKeysJson = async (zip: JSZip) => { const parseKeysJson = async (zip: JSZip) => {
const keysFileContent = await readContentOfZipEntry( const keysFileContent = await readContentOfZipEntry(
zip, zip,
@ -540,56 +540,41 @@ export const SignPage = () => {
return currentUserMarks.map(( { mark }: CurrentUserMark) => mark); return currentUserMarks.map(( { mark }: CurrentUserMark) => mark);
} }
const handleMarkClick = (id: number) => { // const handleMarkClick = (id: number) => {
const nextMark = currentUserMarks.find(mark => mark.mark.id === id) // const nextMark = currentUserMarks.find(mark => mark.mark.id === id)
setCurrentUserMark(nextMark!) // setCurrentUserMark(nextMark!)
setCurrentMarkValue(nextMark?.mark.value || "") // setCurrentMarkValue(nextMark?.mark.value || "")
} // }
const getMarkConfigPerUser = (markConfig: MarkConfig) => { // const getMarkConfigPerUser = (markConfig: MarkConfig) => {
if (!usersPubkey) return; // if (!usersPubkey) return;
return markConfig[hexToNpub(usersPubkey)]; // return markConfig[hexToNpub(usersPubkey)];
} // }
const handleChange = (event: any) => setCurrentMarkValue(event.target.value); // const handleChange = (event: any) => setCurrentMarkValue(event.target.value);
//
const handleSubmit = (event: any) => { // const handleSubmit = (event: any) => {
event.preventDefault(); // event.preventDefault();
if (!currentMarkValue || !currentUserMark) return; // if (!currentMarkValue || !currentUserMark) return;
//
const curMark = { // const curMark: Mark = {
...currentUserMark.mark, // ...currentUserMark.mark,
value: currentMarkValue // value: currentMarkValue
}; // };
//
const indexToUpdate = marks.findIndex(mark => mark.id === curMark.id); // const updatedMarks: Mark[] = updateMarks(marks, curMark)
//
const updatedMarks: Mark[] = [ // setMarks(updatedMarks)
...marks.slice(0, indexToUpdate), // setCurrentMarkValue("")
curMark, //
...marks.slice(indexToUpdate + 1) // // do the similar thing to the thing above
]; // const metaMarks = filterMarksByPubkey(updatedMarks, usersPubkey!)
// const signedMarks = extractMarksFromSignedMeta(meta!)
setMarks(updatedMarks) // const currentUserMarks = getCurrentUserMarks(metaMarks, signedMarks)
setCurrentMarkValue("") // setCurrentUserMarks(currentUserMarks)
// setCurrentUserMark(findNextCurrentUserMark(currentUserMarks) || null)
const updatedCurUserMarks = getCurrentUserMarks(updatedMarks, usersPubkey!) // setIsReadyToSign(isCurrentUserMarksComplete(currentUserMarks))
console.log('updatedCurUserMarks: ', updatedCurUserMarks) // }
setCurrentUserMarks(updatedCurUserMarks)
const nextMark = findNextIncompleteMark(updatedCurUserMarks)
console.log('next mark: ', nextMark)
if (!nextMark) {
setCurrentUserMark(null)
setIsMarksCompleted(true)
} else {
setCurrentUserMark(nextMark)
setIsMarksCompleted(false)
}
}
const findNextIncompleteMark = (usersMarks: CurrentUserMark[]): CurrentUserMark | undefined => {
return usersMarks.find(mark => !mark.isCompleted);
}
// Update the meta signatures // Update the meta signatures
const updateMetaSignatures = (meta: Meta, signedEvent: SignedEvent): Meta => { const updateMetaSignatures = (meta: Meta, signedEvent: SignedEvent): Meta => {
@ -599,7 +584,6 @@ export const SignPage = () => {
[hexToNpub(signedEvent.pubkey)]: JSON.stringify(signedEvent, null, 2) [hexToNpub(signedEvent.pubkey)]: JSON.stringify(signedEvent, null, 2)
} }
metaCopy.modifiedAt = now() metaCopy.modifiedAt = now()
console.log('meta copy: ', metaCopy);
return metaCopy return metaCopy
} }
@ -724,7 +708,6 @@ export const SignPage = () => {
await Promise.all(promises) await Promise.all(promises)
.then(() => { .then(() => {
toast.success('Notifications sent successfully') toast.success('Notifications sent successfully')
console.log('meta: ', meta);
setMeta(meta) setMeta(meta)
}) })
.catch(() => { .catch(() => {
@ -816,25 +799,6 @@ export const SignPage = () => {
navigate(appPublicRoutes.verify) navigate(appPublicRoutes.verify)
} }
const getCurrentUserMarks = (marks: Mark[], pubkey: string): CurrentUserMark[] => {
console.log('marks: ', marks);
const filteredMarks = marks
.filter(mark => mark.npub === hexToNpub(pubkey))
const currentMarks = filteredMarks
.map((mark, index, arr) => {
return {
mark,
isLast: isLast(index, arr),
isCompleted: !!mark.value
}
})
console.log('current marks: ', currentMarks)
return currentMarks;
}
const isLast = (index: number, arr: any[]) => (index === (arr.length -1))
const handleExportSigit = async () => { const handleExportSigit = async () => {
if (Object.entries(files).length === 0 || !meta) return if (Object.entries(files).length === 0 || !meta) return
@ -925,105 +889,111 @@ export const SignPage = () => {
return <LoadingSpinner desc={loadingSpinnerDesc} /> return <LoadingSpinner desc={loadingSpinnerDesc} />
} }
if (!isMarksCompleted) { if (isReadyToSign) {
return ( return (
<> <>
<Box className={styles.container}> <Box className={styles.container}>
{ {displayInput && (
marks.length > 0 && ( <>
<PdfView <Typography component="label" variant="h6">
files={files} Select sigit file
marks={marks} </Typography>
fileHashes={currentFileHashes}
handleMarkClick={handleMarkClick} <Box className={styles.inputBlock}>
currentMarkValue={currentMarkValue} <MuiFileInput
currentUserMark={currentUserMark} placeholder="Select file"
/>)} inputProps={{ accept: '.sigit.zip' }}
{ value={selectedFile}
currentUserMark !== null && ( onChange={(value) => setSelectedFile(value)}
<MarkFormField />
handleSubmit={handleSubmit} </Box>
handleChange={handleChange}
currentMark={currentUserMark} {selectedFile && (
currentMarkValue={currentMarkValue} <Box sx={{ mt: 2, display: 'flex', justifyContent: 'center' }}>
/> <Button onClick={handleDecrypt} variant="contained">
Decrypt
</Button>
</Box>
)}
</>
)}
{submittedBy && Object.entries(files).length > 0 && meta && (
<>
<DisplayMeta
meta={meta}
files={files}
submittedBy={submittedBy}
signers={signers}
viewers={viewers}
creatorFileHashes={creatorFileHashes}
currentFileHashes={currentFileHashes}
signedBy={signedBy}
nextSigner={nextSinger}
getPrevSignersSig={getPrevSignersSig}
/>
{signedStatus === SignedStatus.Fully_Signed && (
<Box sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}>
<Button onClick={handleExport} variant="contained">
Export
</Button>
</Box>
)}
{signedStatus === SignedStatus.User_Is_Next_Signer && (
<Box sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}>
<Button onClick={handleSign} variant="contained">
Sign
</Button>
</Box>
)}
{isSignerOrCreator && (
<Box sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}>
<Button onClick={handleExportSigit} variant="contained">
Export Sigit
</Button>
</Box>
)}
</>
)} )}
</Box> </Box>
</> </>
)
}
)} return <PdfMarking
files={getFilesWithHashes(files, currentFileHashes)}
currentUserMarks={currentUserMarks}
setIsReadyToSign={setIsReadyToSign}
setCurrentUserMarks={setCurrentUserMarks}
setUpdatedMarks={setUpdatedMarks}
/>
return ( // return (
<> // <>
<Box className={styles.container}> // <Box className={styles.container}>
{displayInput && ( // {
<> // marks.length > 0 && (
<Typography component="label" variant="h6"> // <PdfView
Select sigit file // files={files}
</Typography> // marks={marks}
// fileHashes={currentFileHashes}
<Box className={styles.inputBlock}> // handleMarkClick={handleMarkClick}
<MuiFileInput // currentMarkValue={currentMarkValue}
placeholder="Select file" // currentUserMark={currentUserMark}
inputProps={{ accept: '.sigit.zip' }} // />)}
value={selectedFile} // {
onChange={(value) => setSelectedFile(value)} // currentUserMark !== null && (
/> // <MarkFormField
</Box> // handleSubmit={handleSubmit}
// handleChange={handleChange}
{selectedFile && ( // currentMark={currentUserMark}
<Box sx={{ mt: 2, display: 'flex', justifyContent: 'center' }}> // currentMarkValue={currentMarkValue}
<Button onClick={handleDecrypt} variant="contained"> // />
Decrypt // )}
</Button> // </Box>
</Box> // </>
)} // )
</>
)}
{submittedBy && Object.entries(files).length > 0 && meta && (
<>
<DisplayMeta
meta={meta}
files={files}
submittedBy={submittedBy}
signers={signers}
viewers={viewers}
creatorFileHashes={creatorFileHashes}
currentFileHashes={currentFileHashes}
signedBy={signedBy}
nextSigner={nextSinger}
getPrevSignersSig={getPrevSignersSig}
/>
{signedStatus === SignedStatus.Fully_Signed && (
<Box sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}>
<Button onClick={handleExport} variant="contained">
Export
</Button>
</Box>
)}
{signedStatus === SignedStatus.User_Is_Next_Signer && (
<Box sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}>
<Button onClick={handleSign} variant="contained">
Sign
</Button>
</Box>
)}
{isSignerOrCreator && (
<Box sx={{ mt: 1, display: 'flex', justifyContent: 'center' }}>
<Button onClick={handleExportSigit} variant="contained">
Export Sigit
</Button>
</Box>
)}
</>
)}
</Box>
</>
)
} }