From 31f36750cd5479fc05e2a86ade5153e6a65955f6 Mon Sep 17 00:00:00 2001 From: enes Date: Fri, 23 Aug 2024 11:06:25 +0200 Subject: [PATCH 1/9] fix(pdf): font style consistency --- src/components/DrawPDFFields/style.module.scss | 4 ++++ src/components/PDFView/PdfMarkItem.tsx | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/components/DrawPDFFields/style.module.scss b/src/components/DrawPDFFields/style.module.scss index b3150b3..d0085df 100644 --- a/src/components/DrawPDFFields/style.module.scss +++ b/src/components/DrawPDFFields/style.module.scss @@ -23,6 +23,10 @@ justify-content: center; align-items: center; + font-family: Arial; + font-size: 16px; + font-weight: normal; + &.nonEditable { cursor: default; visibility: hidden; diff --git a/src/components/PDFView/PdfMarkItem.tsx b/src/components/PDFView/PdfMarkItem.tsx index d93c2b2..138c5e1 100644 --- a/src/components/PDFView/PdfMarkItem.tsx +++ b/src/components/PDFView/PdfMarkItem.tsx @@ -1,6 +1,6 @@ import { CurrentUserMark } from '../../types/mark.ts' import styles from '../DrawPDFFields/style.module.scss' -import { inPx } from '../../utils/pdf.ts' +import { FONT_TYPE, inPx } from '../../utils/pdf.ts' interface PdfMarkItemProps { userMark: CurrentUserMark @@ -31,7 +31,8 @@ const PdfMarkItem = ({ left: inPx(location.left), top: inPx(location.top), width: inPx(location.width), - height: inPx(location.height) + height: inPx(location.height), + fontFamily: FONT_TYPE }} > {getMarkValue()} -- 2.34.1 From ac3186a02ed441c6efc31aaf462a5b8b229f5fa1 Mon Sep 17 00:00:00 2001 From: enes Date: Fri, 23 Aug 2024 13:39:49 +0200 Subject: [PATCH 2/9] fix(pdf): scaling and font styles consistency Closes #146 --- src/App.scss | 10 +++ .../DrawPDFFields/style.module.scss | 4 - src/components/PDFView/PdfMarkItem.tsx | 7 +- src/pages/verify/index.tsx | 10 ++- src/pages/verify/style.module.scss | 2 +- src/types/drawing.ts | 1 + src/utils/file.ts | 6 +- src/utils/pdf.ts | 83 +++++++++++-------- 8 files changed, 78 insertions(+), 45 deletions(-) diff --git a/src/App.scss b/src/App.scss index f21738d..a1c267a 100644 --- a/src/App.scss +++ b/src/App.scss @@ -121,6 +121,16 @@ input { object-fit: contain; /* Ensure the image fits within the container */ } +// Consistent styling for every file mark +// Reverts some of the design defaults for font +.file-mark { + font-family: Arial; + font-size: 16px; + font-weight: normal; + color: black; + letter-spacing: normal; +} + [data-dev='true'] { .image-wrapper { // outline: 1px solid #ccc; /* Optional: for visual debugging */ diff --git a/src/components/DrawPDFFields/style.module.scss b/src/components/DrawPDFFields/style.module.scss index d0085df..b3150b3 100644 --- a/src/components/DrawPDFFields/style.module.scss +++ b/src/components/DrawPDFFields/style.module.scss @@ -23,10 +23,6 @@ justify-content: center; align-items: center; - font-family: Arial; - font-size: 16px; - font-weight: normal; - &.nonEditable { cursor: default; visibility: hidden; diff --git a/src/components/PDFView/PdfMarkItem.tsx b/src/components/PDFView/PdfMarkItem.tsx index 138c5e1..9642499 100644 --- a/src/components/PDFView/PdfMarkItem.tsx +++ b/src/components/PDFView/PdfMarkItem.tsx @@ -1,6 +1,6 @@ import { CurrentUserMark } from '../../types/mark.ts' import styles from '../DrawPDFFields/style.module.scss' -import { FONT_TYPE, inPx } from '../../utils/pdf.ts' +import { FONT_SIZE, FONT_TYPE, inPx } from '../../utils/pdf.ts' interface PdfMarkItemProps { userMark: CurrentUserMark @@ -26,13 +26,14 @@ const PdfMarkItem = ({ return (
{getMarkValue()} diff --git a/src/pages/verify/index.tsx b/src/pages/verify/index.tsx index 4e21a82..f442cd7 100644 --- a/src/pages/verify/index.tsx +++ b/src/pages/verify/index.tsx @@ -29,6 +29,8 @@ import axios from 'axios' import { addMarks, convertToPdfBlob, + FONT_SIZE, + FONT_TYPE, groupMarksByFileNamePage, inPx } from '../../utils/pdf.ts' @@ -105,13 +107,15 @@ const SlimPdfView = ({ {marks.map((m) => { return (
{m.value} @@ -427,7 +431,7 @@ export const VerifyPage = () => { for (const [fileName, file] of Object.entries(files)) { if (file.isPdf) { // Draw marks into PDF file and generate a brand new blob - const pages = await addMarks(file, marksByPage[fileName]) + const pages = await addMarks(file, file.pages!, marksByPage[fileName]) const blob = await convertToPdfBlob(pages) zip.file(`files/${fileName}`, blob) } else { diff --git a/src/pages/verify/style.module.scss b/src/pages/verify/style.module.scss index af93107..b63ba60 100644 --- a/src/pages/verify/style.module.scss +++ b/src/pages/verify/style.module.scss @@ -61,6 +61,6 @@ [data-dev='true'] { .mark { - border: 1px dotted black; + outline: 1px dotted black; } } diff --git a/src/types/drawing.ts b/src/types/drawing.ts index b8abe73..bb7c970 100644 --- a/src/types/drawing.ts +++ b/src/types/drawing.ts @@ -10,6 +10,7 @@ export interface MouseState { export interface PdfPage { image: string + scale: number drawnFields: DrawnField[] } diff --git a/src/utils/file.ts b/src/utils/file.ts index aad31c7..26f03ef 100644 --- a/src/utils/file.ts +++ b/src/utils/file.ts @@ -22,7 +22,11 @@ export const getZipWithFiles = async ( for (const [fileName, file] of Object.entries(files)) { if (file.isPdf) { // Handle PDF Files - const pages = await addMarks(file, marksByFileNamePage[fileName]) + const pages = await addMarks( + file, + file.pages!, + marksByFileNamePage[fileName] + ) const blob = await convertToPdfBlob(pages) zip.file(`files/${fileName}`, blob) } else { diff --git a/src/utils/pdf.ts b/src/utils/pdf.ts index 8abafae..c7eca36 100644 --- a/src/utils/pdf.ts +++ b/src/utils/pdf.ts @@ -8,11 +8,16 @@ PDFJS.GlobalWorkerOptions.workerSrc = new URL( import.meta.url ).toString() +/** + * Default width of the rendered element on the website + * @constant {number} + */ +export const DEFAULT_VIEWPORT_WIDTH = 550 /** * Scale between the PDF page's natural size and rendered size * @constant {number} */ -export const SCALE: number = 3 +export const DEFAULT_SCALE: number = 1 /** * Defined font size used when generating a PDF. Currently it is difficult to fully * correlate font size used at the time of filling in / drawing on the PDF @@ -20,7 +25,7 @@ export const SCALE: number = 3 * This should be fixed going forward. * Switching to PDF-Lib will most likely make this problem redundant. */ -export const FONT_SIZE: number = 40 +export const FONT_SIZE: number = 16 /** * Current font type used when generating a PDF. */ @@ -72,28 +77,30 @@ export const readPdf = (file: File): Promise => { export const pdfToImages = async ( data: string | ArrayBuffer ): Promise => { - const images: string[] = [] + const pages: PdfPage[] = [] const pdf = await PDFJS.getDocument(data).promise const canvas = document.createElement('canvas') for (let i = 0; i < pdf.numPages; i++) { const page = await pdf.getPage(i + 1) - const viewport = page.getViewport({ scale: SCALE }) + + const originalViewport = page.getViewport({ scale: 1 }) + const scale = originalViewport.width / DEFAULT_VIEWPORT_WIDTH + + const viewport = page.getViewport({ scale }) const context = canvas.getContext('2d') canvas.height = viewport.height canvas.width = viewport.width + await page.render({ canvasContext: context!, viewport: viewport }).promise - images.push(canvas.toDataURL()) + pages.push({ + image: canvas.toDataURL(), + scale, + drawnFields: [] + }) } - return Promise.resolve( - images.map((image) => { - return { - image, - drawnFields: [] - } - }) - ) + return pages } /** @@ -103,6 +110,7 @@ export const pdfToImages = async ( */ export const addMarks = async ( file: File, + pages: PdfPage[], marksPerPage: { [key: string]: Mark[] } ) => { const p = await readPdf(file) @@ -113,34 +121,39 @@ export const addMarks = async ( for (let i = 0; i < pdf.numPages; i++) { const page = await pdf.getPage(i + 1) - const viewport = page.getViewport({ scale: SCALE }) + const viewport = page.getViewport({ scale: 1 }) const context = canvas.getContext('2d') canvas.height = viewport.height canvas.width = viewport.width - await page.render({ canvasContext: context!, viewport: viewport }).promise + if (context) { + await page.render({ canvasContext: context, viewport: viewport }).promise - if (marksPerPage && Object.hasOwn(marksPerPage, i)) - marksPerPage[i]?.forEach((mark) => draw(mark, context!)) + if (marksPerPage && Object.hasOwn(marksPerPage, i)) { + marksPerPage[i]?.forEach((mark) => draw(mark, context, pages[i].scale)) + } - images.push(canvas.toDataURL()) + images.push(canvas.toDataURL()) + } } - return Promise.resolve(images) + canvas.remove() + + return images } /** * Utility to scale mark in line with the PDF-to-PNG scale */ -export const scaleMark = (mark: Mark): Mark => { +export const scaleMark = (mark: Mark, scale: number): Mark => { const { location } = mark return { ...mark, location: { ...location, - width: location.width * SCALE, - height: location.height * SCALE, - left: location.left * SCALE, - top: location.top * SCALE + width: location.width * scale, + height: location.height * scale, + left: location.left * scale, + top: location.top * scale } } } @@ -156,15 +169,21 @@ export const hasValue = (mark: Mark): boolean => !!mark.value * @param mark to be drawn * @param ctx a Canvas representation of a specific PDF Page */ -export const draw = (mark: Mark, ctx: CanvasRenderingContext2D) => { - const { location } = mark +export const draw = ( + mark: Mark, + ctx: CanvasRenderingContext2D, + scale: number +) => { + const { location } = scaleMark(mark, scale) - ctx!.font = FONT_SIZE + 'px ' + FONT_TYPE - ctx!.fillStyle = 'black' - const textMetrics = ctx!.measureText(mark.value!) + ctx.font = scale * FONT_SIZE + 'px ' + FONT_TYPE + ctx.fillStyle = 'black' + const textMetrics = ctx.measureText(mark.value!) + const textHeight = + textMetrics.actualBoundingBoxAscent + textMetrics.actualBoundingBoxDescent const textX = location.left + (location.width - textMetrics.width) / 2 - const textY = location.top + (location.height + parseInt(ctx!.font)) / 2 - ctx!.fillText(mark.value!, textX, textY) + const textY = location.top + (location.height + textHeight) / 2 + ctx.fillText(mark.value!, textX, textY) } /** @@ -194,13 +213,11 @@ export const convertToPdfBlob = async ( /** * @param marks - an array of Marks * @function hasValue removes any Mark without a property - * @function scaleMark scales remaining marks in line with SCALE * @function byPage groups remaining Marks by their page marks.location.page */ export const groupMarksByFileNamePage = (marks: Mark[]) => { return marks .filter(hasValue) - .map(scaleMark) .reduce<{ [fileName: string]: { [page: number]: Mark[] } }>(byPage, {}) } -- 2.34.1 From ecc1707212fdee75775d38154ffbddc22619fb88 Mon Sep 17 00:00:00 2001 From: enes Date: Fri, 23 Aug 2024 13:49:47 +0200 Subject: [PATCH 3/9] fix(pdf): add border to style --- src/App.scss | 1 + src/pages/verify/style.module.scss | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/App.scss b/src/App.scss index a1c267a..1b8ae10 100644 --- a/src/App.scss +++ b/src/App.scss @@ -129,6 +129,7 @@ input { font-weight: normal; color: black; letter-spacing: normal; + border: 1px solid transparent; } [data-dev='true'] { diff --git a/src/pages/verify/style.module.scss b/src/pages/verify/style.module.scss index b63ba60..af93107 100644 --- a/src/pages/verify/style.module.scss +++ b/src/pages/verify/style.module.scss @@ -61,6 +61,6 @@ [data-dev='true'] { .mark { - outline: 1px dotted black; + border: 1px dotted black; } } -- 2.34.1 From ea09daa6692e905c703d3800b8a8adbdb391f6b5 Mon Sep 17 00:00:00 2001 From: enes Date: Fri, 23 Aug 2024 21:30:32 +0200 Subject: [PATCH 4/9] fix(pdf): dynamic mark scaling Caveat: scaling is not fluid, refresh is required --- src/App.scss | 6 ++-- src/components/DrawPDFFields/index.tsx | 39 ++++++++++++----------- src/components/PDFView/PdfMarkItem.tsx | 14 ++++---- src/components/PDFView/PdfPageItem.tsx | 35 +++++++++++--------- src/layouts/StickySideColumns.module.scss | 4 --- src/layouts/StickySideColumns.tsx | 4 ++- src/pages/verify/index.tsx | 12 +++---- src/types/drawing.ts | 8 ++--- src/types/mark.ts | 13 +++++--- src/utils/file.ts | 7 ++-- src/utils/pdf.ts | 33 ++++++++----------- 11 files changed, 87 insertions(+), 88 deletions(-) diff --git a/src/App.scss b/src/App.scss index 1b8ae10..b24e16a 100644 --- a/src/App.scss +++ b/src/App.scss @@ -100,12 +100,10 @@ input { -webkit-user-select: none; user-select: none; - overflow: hidden; /* Ensure no overflow */ - > img { display: block; - max-width: 100%; - max-height: 100%; + width: 100%; + height: auto; object-fit: contain; /* Ensure the image fits within the container */ } } diff --git a/src/components/DrawPDFFields/index.tsx b/src/components/DrawPDFFields/index.tsx index e5e33ca..35de444 100644 --- a/src/components/DrawPDFFields/index.tsx +++ b/src/components/DrawPDFFields/index.tsx @@ -17,6 +17,7 @@ import { settleAllFullfilfedPromises, hexToNpub } from '../../utils' import { getSigitFile, SigitFile } from '../../utils/file' import { FileDivider } from '../FileDivider' import { ExtensionFileBox } from '../ExtensionFileBox' +import { inPx } from '../../utils/pdf' PDFJS.GlobalWorkerOptions.workerSrc = new URL( 'pdfjs-dist/build/pdf.worker.min.mjs', @@ -105,8 +106,8 @@ export const DrawPDFFields = (props: Props) => { const { mouseX, mouseY } = getMouseCoordinates(event) const newField: DrawnField = { - left: mouseX, - top: mouseY, + left: mouseX / page.scale, + top: mouseY / page.scale, width: 0, height: 0, counterpart: '', @@ -160,8 +161,8 @@ export const DrawPDFFields = (props: Props) => { const { mouseX, mouseY } = getMouseCoordinates(event) - const width = mouseX - lastDrawnField.left - const height = mouseY - lastDrawnField.top + const width = mouseX / page.scale - lastDrawnField.left + const height = mouseY / page.scale - lastDrawnField.top lastDrawnField.width = width lastDrawnField.height = height @@ -209,7 +210,8 @@ export const DrawPDFFields = (props: Props) => { */ const onDrawnFieldMouseMove = ( event: React.MouseEvent, - drawnField: DrawnField + drawnField: DrawnField, + scale: number ) => { if (mouseState.dragging) { const { mouseX, mouseY, rect } = getMouseCoordinates( @@ -219,11 +221,11 @@ export const DrawPDFFields = (props: Props) => { const coordsOffset = mouseState.coordsInWrapper if (coordsOffset) { - let left = mouseX - coordsOffset.mouseX - let top = mouseY - coordsOffset.mouseY + let left = (mouseX - coordsOffset.mouseX) / scale + let top = (mouseY - coordsOffset.mouseY) / scale - const rightLimit = rect.width - drawnField.width - 3 - const bottomLimit = rect.height - drawnField.height - 3 + const rightLimit = rect.width / scale - drawnField.width - 3 + const bottomLimit = rect.height / scale - drawnField.height - 3 if (left < 0) left = 0 if (top < 0) top = 0 @@ -263,7 +265,8 @@ export const DrawPDFFields = (props: Props) => { */ const onResizeHandleMouseMove = ( event: React.MouseEvent, - drawnField: DrawnField + drawnField: DrawnField, + scale: number ) => { if (mouseState.resizing) { const { mouseX, mouseY } = getMouseCoordinates( @@ -274,8 +277,8 @@ export const DrawPDFFields = (props: Props) => { event.currentTarget.parentElement?.parentElement ) - const width = mouseX - drawnField.left - const height = mouseY - drawnField.top + const width = mouseX / scale - drawnField.left + const height = mouseY / scale - drawnField.top drawnField.width = width drawnField.height = height @@ -372,21 +375,21 @@ export const DrawPDFFields = (props: Props) => { key={drawnFieldIndex} onMouseDown={onDrawnFieldMouseDown} onMouseMove={(event) => { - onDrawnFieldMouseMove(event, drawnField) + onDrawnFieldMouseMove(event, drawnField, page.scale) }} className={styles.drawingRectangle} style={{ - left: `${drawnField.left}px`, - top: `${drawnField.top}px`, - width: `${drawnField.width}px`, - height: `${drawnField.height}px`, + left: inPx(drawnField.left * page.scale), + top: inPx(drawnField.top * page.scale), + width: inPx(drawnField.width * page.scale), + height: inPx(drawnField.height * page.scale), pointerEvents: mouseState.clicked ? 'none' : 'all' }} > { - onResizeHandleMouseMove(event, drawnField) + onResizeHandleMouseMove(event, drawnField, page.scale) }} className={styles.resizeHandle} > diff --git a/src/components/PDFView/PdfMarkItem.tsx b/src/components/PDFView/PdfMarkItem.tsx index 9642499..cc9c9b2 100644 --- a/src/components/PDFView/PdfMarkItem.tsx +++ b/src/components/PDFView/PdfMarkItem.tsx @@ -7,6 +7,7 @@ interface PdfMarkItemProps { handleMarkClick: (id: number) => void selectedMarkValue: string selectedMark: CurrentUserMark | null + scale: number } /** @@ -16,7 +17,8 @@ const PdfMarkItem = ({ selectedMark, handleMarkClick, selectedMarkValue, - userMark + userMark, + scale }: PdfMarkItemProps) => { const { location } = userMark.mark const handleClick = () => handleMarkClick(userMark.mark.id) @@ -28,12 +30,12 @@ const PdfMarkItem = ({ onClick={handleClick} className={`file-mark ${styles.drawingRectangle} ${isEdited() && styles.edited}`} style={{ - left: inPx(location.left), - top: inPx(location.top), - width: inPx(location.width), - height: inPx(location.height), + left: inPx(location.left * scale), + top: inPx(location.top * scale), + width: inPx(location.width * scale), + height: inPx(location.height * scale), fontFamily: FONT_TYPE, - fontSize: inPx(FONT_SIZE) + fontSize: inPx(FONT_SIZE * scale) }} > {getMarkValue()} diff --git a/src/components/PDFView/PdfPageItem.tsx b/src/components/PDFView/PdfPageItem.tsx index 65ea322..f5f310d 100644 --- a/src/components/PDFView/PdfPageItem.tsx +++ b/src/components/PDFView/PdfPageItem.tsx @@ -4,7 +4,7 @@ import { CurrentUserMark, Mark } from '../../types/mark.ts' import PdfMarkItem from './PdfMarkItem.tsx' import { useEffect, useRef } from 'react' import pdfViewStyles from './style.module.scss' -import { inPx } from '../../utils/pdf.ts' +import { FONT_SIZE, FONT_TYPE, inPx } from '../../utils/pdf.ts' interface PdfPageProps { currentUserMarks: CurrentUserMark[] handleMarkClick: (id: number) => void @@ -44,23 +44,28 @@ const PdfPageItem = ({ selectedMarkValue={selectedMarkValue} userMark={m} selectedMark={selectedMark} + scale={page.scale} />
))} - {otherUserMarks.map((m, i) => ( -
- {m.value} -
- ))} + {otherUserMarks.map((m, i) => { + return ( +
+ {m.value} +
+ ) + })}
) } diff --git a/src/layouts/StickySideColumns.module.scss b/src/layouts/StickySideColumns.module.scss index 7495cad..77daa03 100644 --- a/src/layouts/StickySideColumns.module.scss +++ b/src/layouts/StickySideColumns.module.scss @@ -29,8 +29,4 @@ padding: 10px; border: 10px solid $overlay-background-color; border-radius: 4px; - - max-width: 590px; - width: 590px; - margin: 0 auto; } diff --git a/src/layouts/StickySideColumns.tsx b/src/layouts/StickySideColumns.tsx index 1ada87f..43dc430 100644 --- a/src/layouts/StickySideColumns.tsx +++ b/src/layouts/StickySideColumns.tsx @@ -17,7 +17,9 @@ export const StickySideColumns = ({
{left}
-
{children}
+
+ {children} +
{right}
diff --git a/src/pages/verify/index.tsx b/src/pages/verify/index.tsx index f442cd7..6ff679a 100644 --- a/src/pages/verify/index.tsx +++ b/src/pages/verify/index.tsx @@ -110,12 +110,12 @@ const SlimPdfView = ({ className={`file-mark ${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), + left: inPx(m.location.left * page.scale), + top: inPx(m.location.top * page.scale), + width: inPx(m.location.width * page.scale), + height: inPx(m.location.height * page.scale), fontFamily: FONT_TYPE, - fontSize: inPx(FONT_SIZE) + fontSize: inPx(FONT_SIZE * page.scale) }} > {m.value} @@ -431,7 +431,7 @@ export const VerifyPage = () => { for (const [fileName, file] of Object.entries(files)) { if (file.isPdf) { // Draw marks into PDF file and generate a brand new blob - const pages = await addMarks(file, file.pages!, marksByPage[fileName]) + const pages = await addMarks(file, marksByPage[fileName]) const blob = await convertToPdfBlob(pages) zip.file(`files/${fileName}`, blob) } else { diff --git a/src/types/drawing.ts b/src/types/drawing.ts index bb7c970..d8c5cc3 100644 --- a/src/types/drawing.ts +++ b/src/types/drawing.ts @@ -1,3 +1,5 @@ +import { MarkRect } from './mark' + export interface MouseState { clicked?: boolean dragging?: boolean @@ -14,11 +16,7 @@ export interface PdfPage { drawnFields: DrawnField[] } -export interface DrawnField { - left: number - top: number - width: number - height: number +export interface DrawnField extends MarkRect { type: MarkType /** * npub of a counter part diff --git a/src/types/mark.ts b/src/types/mark.ts index efc1899..df733d6 100644 --- a/src/types/mark.ts +++ b/src/types/mark.ts @@ -18,10 +18,13 @@ export interface Mark { value?: string } -export interface MarkLocation { - top: number - left: number - height: number - width: number +export interface MarkLocation extends MarkRect { page: number } + +export interface MarkRect { + left: number + top: number + width: number + height: number +} diff --git a/src/utils/file.ts b/src/utils/file.ts index 26f03ef..63d40e5 100644 --- a/src/utils/file.ts +++ b/src/utils/file.ts @@ -22,11 +22,7 @@ export const getZipWithFiles = async ( for (const [fileName, file] of Object.entries(files)) { if (file.isPdf) { // Handle PDF Files - const pages = await addMarks( - file, - file.pages!, - marksByFileNamePage[fileName] - ) + const pages = await addMarks(file, marksByFileNamePage[fileName]) const blob = await convertToPdfBlob(pages) zip.file(`files/${fileName}`, blob) } else { @@ -78,6 +74,7 @@ export const getSigitFile = async (file: File) => { const sigitFile = new SigitFile(file) // Process sigit file // - generate pages for PDF files + // - generate ObjectRL for image files await sigitFile.process() return sigitFile } diff --git a/src/utils/pdf.ts b/src/utils/pdf.ts index c7eca36..15bcba7 100644 --- a/src/utils/pdf.ts +++ b/src/utils/pdf.ts @@ -8,11 +8,6 @@ PDFJS.GlobalWorkerOptions.workerSrc = new URL( import.meta.url ).toString() -/** - * Default width of the rendered element on the website - * @constant {number} - */ -export const DEFAULT_VIEWPORT_WIDTH = 550 /** * Scale between the PDF page's natural size and rendered size * @constant {number} @@ -32,11 +27,17 @@ export const FONT_SIZE: number = 16 export const FONT_TYPE: string = 'Arial' /** - * A utility that transforms a drawing coordinate number into a CSS-compatible string + * A utility that transforms a drawing coordinate number into a CSS-compatible pixel string * @param coordinate */ export const inPx = (coordinate: number): string => `${coordinate}px` +/** + * A utility that transforms a drawing coordinate number into a CSS-compatible percentage string + * @param coordinate + */ +export const inPerc = (coordinate: number): string => `${coordinate}%` + /** * A utility that checks if a given file is of the pdf type * @param file @@ -80,14 +81,14 @@ export const pdfToImages = async ( const pages: PdfPage[] = [] const pdf = await PDFJS.getDocument(data).promise const canvas = document.createElement('canvas') + const width = document.querySelector('#content-preview > *')?.clientWidth || 1 for (let i = 0; i < pdf.numPages; i++) { const page = await pdf.getPage(i + 1) const originalViewport = page.getViewport({ scale: 1 }) - const scale = originalViewport.width / DEFAULT_VIEWPORT_WIDTH - - const viewport = page.getViewport({ scale }) + const scale = width / originalViewport.width + const viewport = page.getViewport({ scale: scale }) const context = canvas.getContext('2d') canvas.height = viewport.height canvas.width = viewport.width @@ -110,7 +111,6 @@ export const pdfToImages = async ( */ export const addMarks = async ( file: File, - pages: PdfPage[], marksPerPage: { [key: string]: Mark[] } ) => { const p = await readPdf(file) @@ -129,7 +129,7 @@ export const addMarks = async ( await page.render({ canvasContext: context, viewport: viewport }).promise if (marksPerPage && Object.hasOwn(marksPerPage, i)) { - marksPerPage[i]?.forEach((mark) => draw(mark, context, pages[i].scale)) + marksPerPage[i]?.forEach((mark) => draw(mark, context)) } images.push(canvas.toDataURL()) @@ -169,14 +169,9 @@ export const hasValue = (mark: Mark): boolean => !!mark.value * @param mark to be drawn * @param ctx a Canvas representation of a specific PDF Page */ -export const draw = ( - mark: Mark, - ctx: CanvasRenderingContext2D, - scale: number -) => { - const { location } = scaleMark(mark, scale) - - ctx.font = scale * FONT_SIZE + 'px ' + FONT_TYPE +export const draw = (mark: Mark, ctx: CanvasRenderingContext2D) => { + const { location } = mark + ctx.font = FONT_SIZE + 'px ' + FONT_TYPE ctx.fillStyle = 'black' const textMetrics = ctx.measureText(mark.value!) const textHeight = -- 2.34.1 From 8c5be3713ddbcf49520323f259741e365be0cdc9 Mon Sep 17 00:00:00 2001 From: enes Date: Mon, 26 Aug 2024 14:10:11 +0200 Subject: [PATCH 5/9] refactor(pdf): remove unused code --- src/utils/pdf.ts | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/utils/pdf.ts b/src/utils/pdf.ts index 15bcba7..8716ef5 100644 --- a/src/utils/pdf.ts +++ b/src/utils/pdf.ts @@ -8,11 +8,6 @@ PDFJS.GlobalWorkerOptions.workerSrc = new URL( import.meta.url ).toString() -/** - * Scale between the PDF page's natural size and rendered size - * @constant {number} - */ -export const DEFAULT_SCALE: number = 1 /** * Defined font size used when generating a PDF. Currently it is difficult to fully * correlate font size used at the time of filling in / drawing on the PDF @@ -32,12 +27,6 @@ export const FONT_TYPE: string = 'Arial' */ export const inPx = (coordinate: number): string => `${coordinate}px` -/** - * A utility that transforms a drawing coordinate number into a CSS-compatible percentage string - * @param coordinate - */ -export const inPerc = (coordinate: number): string => `${coordinate}%` - /** * A utility that checks if a given file is of the pdf type * @param file -- 2.34.1 From 47120316152a7a3157f7cd089cb2184053ae25ec Mon Sep 17 00:00:00 2001 From: enes Date: Tue, 27 Aug 2024 15:24:19 +0200 Subject: [PATCH 6/9] fix(pdf): scaling on resize, add avatars to counterpart select --- package-lock.json | 23 +++- package.json | 3 +- src/components/DrawPDFFields/index.tsx | 102 ++++++++++++++---- .../DrawPDFFields/style.module.scss | 2 +- src/components/PDFView/PdfMarkItem.tsx | 16 +-- src/components/PDFView/PdfPageItem.tsx | 15 +-- src/hooks/useScale.tsx | 52 +++++++++ src/pages/verify/index.tsx | 12 ++- src/types/drawing.ts | 2 +- src/utils/pdf.ts | 2 +- 10 files changed, 185 insertions(+), 44 deletions(-) create mode 100644 src/hooks/useScale.tsx diff --git a/package-lock.json b/package-lock.json index ef46577..479088b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,13 +1,14 @@ { - "name": "web", + "name": "sigit", "version": "0.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "web", + "name": "sigit", "version": "0.0.0", "hasInstallScript": true, + "license": "AGPL-3.0-or-later ", "dependencies": { "@emotion/react": "11.11.4", "@emotion/styled": "11.11.0", @@ -40,6 +41,7 @@ "react-dropzone": "^14.2.3", "react-redux": "9.1.0", "react-router-dom": "6.22.1", + "react-singleton-hook": "^4.0.1", "react-toastify": "10.0.4", "redux": "5.0.1", "tseep": "1.2.1" @@ -5832,6 +5834,23 @@ "react-dom": ">=16.8" } }, + "node_modules/react-singleton-hook": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/react-singleton-hook/-/react-singleton-hook-4.0.1.tgz", + "integrity": "sha512-fWuk8VxcZPChrkQasDLM8pgd/7kyi+Cr/5FfCiD99FicjEru+JmtEZNnN4lJ8Z7KbqAST5CYPlpz6lmNsZFGNw==", + "license": "MIT", + "peerDependencies": { + "react": "18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, "node_modules/react-toastify": { "version": "10.0.4", "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-10.0.4.tgz", diff --git a/package.json b/package.json index c835018..a2f074d 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "react-dropzone": "^14.2.3", "react-redux": "9.1.0", "react-router-dom": "6.22.1", + "react-singleton-hook": "^4.0.1", "react-toastify": "10.0.4", "redux": "5.0.1", "tseep": "1.2.1" @@ -82,4 +83,4 @@ ], "*.{ts,tsx,js,jsx,html,css,sass,less,yml,md,graphql}": "npm run formatter:staged" } -} \ No newline at end of file +} diff --git a/src/components/DrawPDFFields/index.tsx b/src/components/DrawPDFFields/index.tsx index 35de444..b808c40 100644 --- a/src/components/DrawPDFFields/index.tsx +++ b/src/components/DrawPDFFields/index.tsx @@ -4,6 +4,8 @@ import { CircularProgress, FormControl, InputLabel, + ListItemIcon, + ListItemText, MenuItem, Select } from '@mui/material' @@ -13,11 +15,13 @@ import * as PDFJS from 'pdfjs-dist' import { ProfileMetadata, User, UserRole } from '../../types' import { MouseState, PdfPage, DrawnField, DrawTool } from '../../types/drawing' import { truncate } from 'lodash' -import { settleAllFullfilfedPromises, hexToNpub } from '../../utils' +import { settleAllFullfilfedPromises, hexToNpub, npubToHex } from '../../utils' import { getSigitFile, SigitFile } from '../../utils/file' import { FileDivider } from '../FileDivider' import { ExtensionFileBox } from '../ExtensionFileBox' import { inPx } from '../../utils/pdf' +import { useScale } from '../../hooks/useScale' +import { AvatarIconButton } from '../UserAvatarIconButton' PDFJS.GlobalWorkerOptions.workerSrc = new URL( 'pdfjs-dist/build/pdf.worker.min.mjs', @@ -34,6 +38,7 @@ interface Props { export const DrawPDFFields = (props: Props) => { const { selectedFiles, selectedTool, onDrawFieldsChange, users } = props + const { to, from } = useScale() const [sigitFiles, setSigitFiles] = useState([]) const [parsingPdf, setIsParsing] = useState(false) @@ -106,8 +111,8 @@ export const DrawPDFFields = (props: Props) => { const { mouseX, mouseY } = getMouseCoordinates(event) const newField: DrawnField = { - left: mouseX / page.scale, - top: mouseY / page.scale, + left: to(page.width, mouseX), + top: to(page.width, mouseY), width: 0, height: 0, counterpart: '', @@ -161,8 +166,8 @@ export const DrawPDFFields = (props: Props) => { const { mouseX, mouseY } = getMouseCoordinates(event) - const width = mouseX / page.scale - lastDrawnField.left - const height = mouseY / page.scale - lastDrawnField.top + const width = to(page.width, mouseX) - lastDrawnField.left + const height = to(page.width, mouseY) - lastDrawnField.top lastDrawnField.width = width lastDrawnField.height = height @@ -211,7 +216,7 @@ export const DrawPDFFields = (props: Props) => { const onDrawnFieldMouseMove = ( event: React.MouseEvent, drawnField: DrawnField, - scale: number + pageWidth: number ) => { if (mouseState.dragging) { const { mouseX, mouseY, rect } = getMouseCoordinates( @@ -221,11 +226,11 @@ export const DrawPDFFields = (props: Props) => { const coordsOffset = mouseState.coordsInWrapper if (coordsOffset) { - let left = (mouseX - coordsOffset.mouseX) / scale - let top = (mouseY - coordsOffset.mouseY) / scale + let left = to(pageWidth, mouseX - coordsOffset.mouseX) + let top = to(pageWidth, mouseY - coordsOffset.mouseY) - const rightLimit = rect.width / scale - drawnField.width - 3 - const bottomLimit = rect.height / scale - drawnField.height - 3 + const rightLimit = to(pageWidth, rect.width) - drawnField.width - 3 + const bottomLimit = to(pageWidth, rect.height) - drawnField.height - 3 if (left < 0) left = 0 if (top < 0) top = 0 @@ -266,7 +271,7 @@ export const DrawPDFFields = (props: Props) => { const onResizeHandleMouseMove = ( event: React.MouseEvent, drawnField: DrawnField, - scale: number + pageWidth: number ) => { if (mouseState.resizing) { const { mouseX, mouseY } = getMouseCoordinates( @@ -277,8 +282,8 @@ export const DrawPDFFields = (props: Props) => { event.currentTarget.parentElement?.parentElement ) - const width = mouseX / scale - drawnField.left - const height = mouseY / scale - drawnField.top + const width = to(pageWidth, mouseX) - drawnField.left + const height = to(pageWidth, mouseY) - drawnField.top drawnField.width = width drawnField.height = height @@ -375,21 +380,21 @@ export const DrawPDFFields = (props: Props) => { key={drawnFieldIndex} onMouseDown={onDrawnFieldMouseDown} onMouseMove={(event) => { - onDrawnFieldMouseMove(event, drawnField, page.scale) + onDrawnFieldMouseMove(event, drawnField, page.width) }} className={styles.drawingRectangle} style={{ - left: inPx(drawnField.left * page.scale), - top: inPx(drawnField.top * page.scale), - width: inPx(drawnField.width * page.scale), - height: inPx(drawnField.height * page.scale), + left: inPx(from(page.width, drawnField.left)), + top: inPx(from(page.width, drawnField.top)), + width: inPx(from(page.width, drawnField.width)), + height: inPx(from(page.width, drawnField.height)), pointerEvents: mouseState.clicked ? 'none' : 'all' }} > { - onResizeHandleMouseMove(event, drawnField, page.scale) + onResizeHandleMouseMove(event, drawnField, page.width) }} className={styles.resizeHandle} > @@ -423,6 +428,9 @@ export const DrawPDFFields = (props: Props) => { sx={{ background: 'white' }} + renderValue={(value) => + renderCounterpartValue(drawnField, value) + } > {users .filter((u) => u.role === UserRole.signer) @@ -451,7 +459,22 @@ export const DrawPDFFields = (props: Props) => { key={index} value={hexToNpub(user.pubkey)} > - {displayValue} + + img': { + width: '30px', + height: '30px' + } + }} + /> + + {displayValue} ) })} @@ -468,6 +491,45 @@ export const DrawPDFFields = (props: Props) => { ) } + const renderCounterpartValue = (drawnField: DrawnField, value: string) => { + const user = users.find((u) => u.pubkey === npubToHex(value)) + if (user) { + let displayValue = truncate(value, { + length: 16 + }) + + const metadata = props.metadata[value] + + if (metadata) { + displayValue = truncate( + metadata.name || metadata.display_name || metadata.username || value, + { + length: 16 + } + ) + } + return ( + <> + img': { + width: '21px', + height: '21px' + } + }} + /> + {displayValue} + + ) + } + + return value + } + if (parsingPdf) { return ( diff --git a/src/components/DrawPDFFields/style.module.scss b/src/components/DrawPDFFields/style.module.scss index b3150b3..62fa688 100644 --- a/src/components/DrawPDFFields/style.module.scss +++ b/src/components/DrawPDFFields/style.module.scss @@ -73,7 +73,7 @@ justify-content: center; align-items: center; bottom: -60px; - min-width: 170px; + min-width: 193px; min-height: 30px; padding: 5px 0; } diff --git a/src/components/PDFView/PdfMarkItem.tsx b/src/components/PDFView/PdfMarkItem.tsx index cc9c9b2..d5a7c78 100644 --- a/src/components/PDFView/PdfMarkItem.tsx +++ b/src/components/PDFView/PdfMarkItem.tsx @@ -1,13 +1,14 @@ import { CurrentUserMark } from '../../types/mark.ts' import styles from '../DrawPDFFields/style.module.scss' import { FONT_SIZE, FONT_TYPE, inPx } from '../../utils/pdf.ts' +import { useScale } from '../../hooks/useScale.tsx' interface PdfMarkItemProps { userMark: CurrentUserMark handleMarkClick: (id: number) => void selectedMarkValue: string selectedMark: CurrentUserMark | null - scale: number + pageWidth: number } /** @@ -18,24 +19,25 @@ const PdfMarkItem = ({ handleMarkClick, selectedMarkValue, userMark, - scale + pageWidth }: PdfMarkItemProps) => { const { location } = userMark.mark const handleClick = () => handleMarkClick(userMark.mark.id) const isEdited = () => selectedMark?.mark.id === userMark.mark.id const getMarkValue = () => isEdited() ? selectedMarkValue : userMark.currentValue + const { from } = useScale() return (
{getMarkValue()} diff --git a/src/components/PDFView/PdfPageItem.tsx b/src/components/PDFView/PdfPageItem.tsx index f5f310d..518f06d 100644 --- a/src/components/PDFView/PdfPageItem.tsx +++ b/src/components/PDFView/PdfPageItem.tsx @@ -5,6 +5,7 @@ import PdfMarkItem from './PdfMarkItem.tsx' import { useEffect, useRef } from 'react' import pdfViewStyles from './style.module.scss' import { FONT_SIZE, FONT_TYPE, inPx } from '../../utils/pdf.ts' +import { useScale } from '../../hooks/useScale.tsx' interface PdfPageProps { currentUserMarks: CurrentUserMark[] handleMarkClick: (id: number) => void @@ -33,6 +34,8 @@ const PdfPageItem = ({ } }, [selectedMark]) const markRefs = useRef<(HTMLDivElement | null)[]>([]) + const { from } = useScale() + return (
@@ -44,7 +47,7 @@ const PdfPageItem = ({ selectedMarkValue={selectedMarkValue} userMark={m} selectedMark={selectedMark} - scale={page.scale} + pageWidth={page.width} />
))} @@ -54,12 +57,12 @@ const PdfPageItem = ({ key={i} className={pdfViewStyles.otherUserMarksDisplay} style={{ - left: inPx(m.location.left * page.scale), - top: inPx(m.location.top * page.scale), - width: inPx(m.location.width * page.scale), - height: inPx(m.location.height * page.scale), + left: inPx(from(page.width, m.location.left)), + top: inPx(from(page.width, m.location.top)), + width: inPx(from(page.width, m.location.width)), + height: inPx(from(page.width, m.location.height)), fontFamily: FONT_TYPE, - fontSize: inPx(FONT_SIZE * page.scale) + fontSize: inPx(from(page.width, FONT_SIZE)) }} > {m.value} diff --git a/src/hooks/useScale.tsx b/src/hooks/useScale.tsx new file mode 100644 index 0000000..89eb8a5 --- /dev/null +++ b/src/hooks/useScale.tsx @@ -0,0 +1,52 @@ +import { useEffect, useState } from 'react' +import { singletonHook } from 'react-singleton-hook' + +const noScaleInit = { + to: (_: number, v: number) => v, + from: (_: number, v: number) => v +} + +const useScaleImpl = () => { + const [width, setWidth] = useState( + document.querySelector('#content-preview > *')?.clientWidth || 1 + ) + + // Get the scale based on the original width + const scale = (originalWidth: number) => { + return width / originalWidth + } + + // Get the original pixel value + const to = (originalWidth: number, value: number) => { + return value / scale(originalWidth) + } + + // Get the scaled pixel value + const from = (originalWidth: number, value: number) => { + return value * scale(originalWidth) + } + + useEffect(() => { + const resize = () => { + // Fetch the first container element we find + const element = document.querySelector('#content-preview > *') + + // Set the width state + if (element) { + setWidth(element.clientWidth) + } + } + resize() + + window.addEventListener('resize', resize) + return () => { + window.removeEventListener('resize', resize) + } + }, []) + + return { to, from } +} + +export const useScale = singletonHook(noScaleInit, useScaleImpl, { + unmountIfNoConsumers: true +}) diff --git a/src/pages/verify/index.tsx b/src/pages/verify/index.tsx index 6ff679a..8619806 100644 --- a/src/pages/verify/index.tsx +++ b/src/pages/verify/index.tsx @@ -52,6 +52,7 @@ import React from 'react' import { convertToSigitFile, SigitFile } from '../../utils/file.ts' import { FileDivider } from '../../components/FileDivider.tsx' import { ExtensionFileBox } from '../../components/ExtensionFileBox.tsx' +import { useScale } from '../../hooks/useScale.tsx' interface PdfViewProps { files: CurrentUserFile[] @@ -67,6 +68,7 @@ const SlimPdfView = ({ parsedSignatureEvents }: PdfViewProps) => { const pdfRefs = useRef<(HTMLDivElement | null)[]>([]) + const { from } = useScale() useEffect(() => { if (currentFile !== null && !!pdfRefs.current[currentFile.id]) { pdfRefs.current[currentFile.id]?.scrollIntoView({ @@ -110,12 +112,12 @@ const SlimPdfView = ({ className={`file-mark ${styles.mark}`} key={m.id} style={{ - left: inPx(m.location.left * page.scale), - top: inPx(m.location.top * page.scale), - width: inPx(m.location.width * page.scale), - height: inPx(m.location.height * page.scale), + left: inPx(from(page.width, m.location.left)), + top: inPx(from(page.width, m.location.top)), + width: inPx(from(page.width, m.location.width)), + height: inPx(from(page.width, m.location.height)), fontFamily: FONT_TYPE, - fontSize: inPx(FONT_SIZE * page.scale) + fontSize: inPx(from(page.width, FONT_SIZE)) }} > {m.value} diff --git a/src/types/drawing.ts b/src/types/drawing.ts index d8c5cc3..677b68c 100644 --- a/src/types/drawing.ts +++ b/src/types/drawing.ts @@ -12,7 +12,7 @@ export interface MouseState { export interface PdfPage { image: string - scale: number + width: number drawnFields: DrawnField[] } diff --git a/src/utils/pdf.ts b/src/utils/pdf.ts index 8716ef5..b1e9847 100644 --- a/src/utils/pdf.ts +++ b/src/utils/pdf.ts @@ -85,7 +85,7 @@ export const pdfToImages = async ( await page.render({ canvasContext: context!, viewport: viewport }).promise pages.push({ image: canvas.toDataURL(), - scale, + width: originalViewport.width, drawnFields: [] }) } -- 2.34.1 From 923a47b4d086563fc1f514b962cfdecb281d6b87 Mon Sep 17 00:00:00 2001 From: enes Date: Tue, 27 Aug 2024 16:10:57 +0200 Subject: [PATCH 7/9] fix(drawfield): match label and select --- src/components/DrawPDFFields/index.tsx | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/components/DrawPDFFields/index.tsx b/src/components/DrawPDFFields/index.tsx index b808c40..66f6952 100644 --- a/src/components/DrawPDFFields/index.tsx +++ b/src/components/DrawPDFFields/index.tsx @@ -428,9 +428,7 @@ export const DrawPDFFields = (props: Props) => { sx={{ background: 'white' }} - renderValue={(value) => - renderCounterpartValue(drawnField, value) - } + renderValue={(value) => renderCounterpartValue(value)} > {users .filter((u) => u.role === UserRole.signer) @@ -491,14 +489,14 @@ export const DrawPDFFields = (props: Props) => { ) } - const renderCounterpartValue = (drawnField: DrawnField, value: string) => { + const renderCounterpartValue = (value: string) => { const user = users.find((u) => u.pubkey === npubToHex(value)) if (user) { let displayValue = truncate(value, { length: 16 }) - const metadata = props.metadata[value] + const metadata = props.metadata[user.pubkey] if (metadata) { displayValue = truncate( @@ -511,8 +509,8 @@ export const DrawPDFFields = (props: Props) => { return ( <> Date: Tue, 27 Aug 2024 17:28:18 +0200 Subject: [PATCH 8/9] fix(pdf): add proper default width value --- src/hooks/useScale.tsx | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/src/hooks/useScale.tsx b/src/hooks/useScale.tsx index 89eb8a5..86de61f 100644 --- a/src/hooks/useScale.tsx +++ b/src/hooks/useScale.tsx @@ -6,10 +6,26 @@ const noScaleInit = { from: (_: number, v: number) => v } +const getInnerContentWidth = () => { + // Fetch the first container element we find + const element = document.querySelector('#content-preview') + + if (element) { + const style = getComputedStyle(element) + + // Calculate width without padding + const widthWithoutPadding = + element.clientWidth - parseFloat(style.padding) * 2 + + return widthWithoutPadding + } + + // Default value + return 620 +} + const useScaleImpl = () => { - const [width, setWidth] = useState( - document.querySelector('#content-preview > *')?.clientWidth || 1 - ) + const [width, setWidth] = useState(getInnerContentWidth()) // Get the scale based on the original width const scale = (originalWidth: number) => { @@ -26,16 +42,11 @@ const useScaleImpl = () => { return value * scale(originalWidth) } - useEffect(() => { - const resize = () => { - // Fetch the first container element we find - const element = document.querySelector('#content-preview > *') + const resize = () => { + setWidth(getInnerContentWidth()) + } - // Set the width state - if (element) { - setWidth(element.clientWidth) - } - } + useEffect(() => { resize() window.addEventListener('resize', resize) -- 2.34.1 From 59c3fc69a255c54475daa6a2efad3ae8a4b3efd8 Mon Sep 17 00:00:00 2001 From: enes Date: Wed, 28 Aug 2024 11:41:29 +0200 Subject: [PATCH 9/9] fix(pdf): reuse content width function --- src/hooks/useScale.tsx | 19 +------------------ src/utils/pdf.ts | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/hooks/useScale.tsx b/src/hooks/useScale.tsx index 86de61f..406928b 100644 --- a/src/hooks/useScale.tsx +++ b/src/hooks/useScale.tsx @@ -1,29 +1,12 @@ import { useEffect, useState } from 'react' import { singletonHook } from 'react-singleton-hook' +import { getInnerContentWidth } from '../utils/pdf' const noScaleInit = { to: (_: number, v: number) => v, from: (_: number, v: number) => v } -const getInnerContentWidth = () => { - // Fetch the first container element we find - const element = document.querySelector('#content-preview') - - if (element) { - const style = getComputedStyle(element) - - // Calculate width without padding - const widthWithoutPadding = - element.clientWidth - parseFloat(style.padding) * 2 - - return widthWithoutPadding - } - - // Default value - return 620 -} - const useScaleImpl = () => { const [width, setWidth] = useState(getInnerContentWidth()) diff --git a/src/utils/pdf.ts b/src/utils/pdf.ts index b1e9847..1dd75f6 100644 --- a/src/utils/pdf.ts +++ b/src/utils/pdf.ts @@ -60,6 +60,24 @@ export const readPdf = (file: File): Promise => { }) } +export const getInnerContentWidth = () => { + // Fetch the first container element we find + const element = document.querySelector('#content-preview') + + if (element) { + const style = getComputedStyle(element) + + // Calculate width without padding + const widthWithoutPadding = + element.clientWidth - parseFloat(style.padding) * 2 + + return widthWithoutPadding + } + + // Default value + return 620 +} + /** * Converts pdf to the images * @param data pdf file bytes @@ -70,7 +88,7 @@ export const pdfToImages = async ( const pages: PdfPage[] = [] const pdf = await PDFJS.getDocument(data).promise const canvas = document.createElement('canvas') - const width = document.querySelector('#content-preview > *')?.clientWidth || 1 + const width = getInnerContentWidth() for (let i = 0; i < pdf.numPages; i++) { const page = await pdf.getPage(i + 1) -- 2.34.1