diff --git a/apps/remix/app/components/general/envelope-editor/envelope-editor-fields-page-renderer.tsx b/apps/remix/app/components/general/envelope-editor/envelope-editor-fields-page-renderer.tsx index 88839a4dd..c9a4e8612 100644 --- a/apps/remix/app/components/general/envelope-editor/envelope-editor-fields-page-renderer.tsx +++ b/apps/remix/app/components/general/envelope-editor/envelope-editor-fields-page-renderer.tsx @@ -11,10 +11,6 @@ import type { TLocalField } from '@documenso/lib/client-only/hooks/use-editor-fi import { usePageRenderer } from '@documenso/lib/client-only/hooks/use-page-renderer'; import { useCurrentEnvelopeEditor } from '@documenso/lib/client-only/providers/envelope-editor-provider'; import { useCurrentEnvelopeRender } from '@documenso/lib/client-only/providers/envelope-render-provider'; -import { - registerPageCanvas, - unregisterPageCanvas, -} from '@documenso/lib/client-only/utils/page-canvas-registry'; import { FIELD_META_DEFAULT_VALUES } from '@documenso/lib/types/field-meta'; import { MIN_FIELD_HEIGHT_PX, @@ -62,15 +58,6 @@ export default function EnvelopeEditorFieldsPageRenderer() { [editorFields.localFields, pageContext.pageNumber], ); - /** - * Cleanup: Unregister canvas when component unmounts - */ - useEffect(() => { - return () => { - unregisterPageCanvas(pageContext.pageNumber); - }; - }, [pageContext.pageNumber]); - const handleResizeOrMove = (event: KonvaEventObject) => { const { current: container } = canvasElement; @@ -231,15 +218,6 @@ export default function EnvelopeEditorFieldsPageRenderer() { currentStage.on('transformend', () => setIsFieldChanging(false)); currentPageLayer.batchDraw(); - - // Register this page's canvas references now that everything is initialized - if (canvasElement.current && currentStage) { - registerPageCanvas({ - pageNumber: pageContext.pageNumber, - pdfCanvas: canvasElement.current, - konvaStage: currentStage, - }); - } }; /** diff --git a/apps/remix/app/components/general/envelope-editor/envelope-editor-fields-page.tsx b/apps/remix/app/components/general/envelope-editor/envelope-editor-fields-page.tsx index 4ad05e507..13c8aa288 100644 --- a/apps/remix/app/components/general/envelope-editor/envelope-editor-fields-page.tsx +++ b/apps/remix/app/components/general/envelope-editor/envelope-editor-fields-page.tsx @@ -11,7 +11,6 @@ import { match } from 'ts-pattern'; import { useCurrentEnvelopeEditor } from '@documenso/lib/client-only/providers/envelope-editor-provider'; import { useCurrentEnvelopeRender } from '@documenso/lib/client-only/providers/envelope-render-provider'; -import { getPageCanvasRefs } from '@documenso/lib/client-only/utils/page-canvas-registry'; import type { TDetectedFormField } from '@documenso/lib/types/document-analysis'; import type { TCheckboxFieldMeta, @@ -54,63 +53,6 @@ const EnvelopeEditorFieldsPageRenderer = lazy( async () => import('./envelope-editor-fields-page-renderer'), ); -const enforceMinimumFieldDimensions = (params: { - positionX: number; - positionY: number; - width: number; - height: number; - pageWidth: number; - pageHeight: number; -}): { - positionX: number; - positionY: number; - width: number; - height: number; -} => { - const MIN_HEIGHT_PX = 30; - const MIN_WIDTH_PX = 36; - - const widthPx = (params.width / 100) * params.pageWidth; - const heightPx = (params.height / 100) * params.pageHeight; - - let adjustedWidth = params.width; - let adjustedHeight = params.height; - let adjustedPositionX = params.positionX; - let adjustedPositionY = params.positionY; - - if (widthPx < MIN_WIDTH_PX) { - const centerXPx = (params.positionX / 100) * params.pageWidth + widthPx / 2; - adjustedWidth = (MIN_WIDTH_PX / params.pageWidth) * 100; - adjustedPositionX = ((centerXPx - MIN_WIDTH_PX / 2) / params.pageWidth) * 100; - - if (adjustedPositionX < 0) { - adjustedPositionX = 0; - } else if (adjustedPositionX + adjustedWidth > 100) { - adjustedPositionX = 100 - adjustedWidth; - } - } - - if (heightPx < MIN_HEIGHT_PX) { - const centerYPx = (params.positionY / 100) * params.pageHeight + heightPx / 2; - adjustedHeight = (MIN_HEIGHT_PX / params.pageHeight) * 100; - - adjustedPositionY = ((centerYPx - MIN_HEIGHT_PX / 2) / params.pageHeight) * 100; - - if (adjustedPositionY < 0) { - adjustedPositionY = 0; - } else if (adjustedPositionY + adjustedHeight > 100) { - adjustedPositionY = 100 - adjustedHeight; - } - } - - return { - positionX: adjustedPositionX, - positionY: adjustedPositionY, - width: adjustedWidth, - height: adjustedHeight, - }; -}; - const detectFormFieldsInDocument = async (params: { envelopeId: string; onProgress: (current: number, total: number) => void; @@ -247,30 +189,12 @@ export const EnvelopeEditorFieldsPage = () => { } for (const [pageNumber, fields] of fieldsPerPage.entries()) { - const pageCanvasRefs = getPageCanvasRefs(pageNumber); - for (const detected of fields) { const [ymin, xmin, ymax, xmax] = detected.boundingBox; - let positionX = (xmin / 1000) * 100; - let positionY = (ymin / 1000) * 100; - let width = ((xmax - xmin) / 1000) * 100; - let height = ((ymax - ymin) / 1000) * 100; - - if (pageCanvasRefs) { - const adjusted = enforceMinimumFieldDimensions({ - positionX, - positionY, - width, - height, - pageWidth: pageCanvasRefs.pdfCanvas.width, - pageHeight: pageCanvasRefs.pdfCanvas.height, - }); - - positionX = adjusted.positionX; - positionY = adjusted.positionY; - width = adjusted.width; - height = adjusted.height; - } + const positionX = (xmin / 1000) * 100; + const positionY = (ymin / 1000) * 100; + const width = ((xmax - xmin) / 1000) * 100; + const height = ((ymax - ymin) / 1000) * 100; const fieldType = detected.label as FieldType; const resolvedRecipientId = @@ -482,30 +406,12 @@ export const EnvelopeEditorFieldsPage = () => { let totalAdded = 0; for (const [pageNumber, detectedFields] of fieldsPerPage.entries()) { - const pageCanvasRefs = getPageCanvasRefs(pageNumber); - for (const detected of detectedFields) { const [ymin, xmin, ymax, xmax] = detected.boundingBox; - let positionX = (xmin / 1000) * 100; - let positionY = (ymin / 1000) * 100; - let width = ((xmax - xmin) / 1000) * 100; - let height = ((ymax - ymin) / 1000) * 100; - - if (pageCanvasRefs) { - const adjusted = enforceMinimumFieldDimensions({ - positionX, - positionY, - width, - height, - pageWidth: pageCanvasRefs.pdfCanvas.width, - pageHeight: pageCanvasRefs.pdfCanvas.height, - }); - - positionX = adjusted.positionX; - positionY = adjusted.positionY; - width = adjusted.width; - height = adjusted.height; - } + const positionX = (xmin / 1000) * 100; + const positionY = (ymin / 1000) * 100; + const width = ((xmax - xmin) / 1000) * 100; + const height = ((ymax - ymin) / 1000) * 100; const fieldType = detected.label as FieldType; const resolvedRecipientId = diff --git a/apps/remix/server/api/document-analysis/index.ts b/apps/remix/server/api/document-analysis/index.ts index 0333b5e2f..b180599dd 100644 --- a/apps/remix/server/api/document-analysis/index.ts +++ b/apps/remix/server/api/document-analysis/index.ts @@ -445,12 +445,6 @@ export const aiRoute = new Hono() ], }); - console.info('AI analyze recipients raw response', { - envelopeId, - pageNumber: page.pageNumber, - recipients: result.object, - }); - return { pageNumber: page.pageNumber, recipients: result.object, @@ -467,7 +461,7 @@ export const aiRoute = new Hono() continue; } - const { pageNumber, recipients } = result.value; + const { recipients } = result.value; const recipientsWithEmails = recipients.map((recipient) => { const email = resolveRecipientEmail(recipient.email); @@ -482,12 +476,6 @@ export const aiRoute = new Hono() return normalizedRecipient; }); - console.info('AI analyze recipients normalized response', { - envelopeId, - pageNumber, - recipients: recipientsWithEmails, - }); - allRecipients.push(...recipientsWithEmails); } diff --git a/packages/lib/client-only/utils/page-canvas-registry.ts b/packages/lib/client-only/utils/page-canvas-registry.ts deleted file mode 100644 index a96b06432..000000000 --- a/packages/lib/client-only/utils/page-canvas-registry.ts +++ /dev/null @@ -1,110 +0,0 @@ -import type Konva from 'konva'; - -/** - * Represents canvas references for a specific PDF page. - */ -export interface PageCanvasRefs { - /** The page number (1-indexed) */ - pageNumber: number; - /** The canvas element containing the rendered PDF */ - pdfCanvas: HTMLCanvasElement; - /** The Konva stage containing field overlays */ - konvaStage: Konva.Stage; -} - -/** - * Module-level registry to store canvas references by page number. - * This allows any component to access page canvases without prop drilling. - */ -const pageCanvasRegistry = new Map(); - -/** - * Register a page's canvas references. - * Call this when a page renderer mounts and has valid canvas refs. - * - * @param refs - The canvas references to register - */ -export const registerPageCanvas = (refs: PageCanvasRefs): void => { - pageCanvasRegistry.set(refs.pageNumber, refs); -}; - -/** - * Unregister a page's canvas references. - * Call this when a page renderer unmounts to prevent memory leaks. - * - * @param pageNumber - The page number to unregister - */ -export const unregisterPageCanvas = (pageNumber: number): void => { - pageCanvasRegistry.delete(pageNumber); -}; - -/** - * Get canvas references for a specific page. - * - * @param pageNumber - The page number to retrieve - * @returns The canvas references, or undefined if not registered - */ -export const getPageCanvasRefs = (pageNumber: number): PageCanvasRefs | undefined => { - return pageCanvasRegistry.get(pageNumber); -}; - -/** - * Get all registered page numbers. - * - * @returns Array of page numbers currently registered - */ -export const getRegisteredPageNumbers = (): number[] => { - return Array.from(pageCanvasRegistry.keys()).sort((a, b) => a - b); -}; - -/** - * Composite a PDF page with its field overlays into a single PNG Blob. - * This creates a temporary canvas, draws the PDF canvas first (background), - * then draws the Konva canvas on top (field overlays). - * - * @param pageNumber - The page number to composite (1-indexed) - * @returns Promise that resolves to a PNG Blob, or null if page not found or compositing fails - */ -export const compositePageToBlob = async (pageNumber: number): Promise => { - const refs = getPageCanvasRefs(pageNumber); - - if (!refs) { - console.warn(`Page ${pageNumber} is not registered for canvas capture`); - return null; - } - - try { - // Create temporary canvas with same dimensions as PDF canvas - const tempCanvas = document.createElement('canvas'); - tempCanvas.width = refs.pdfCanvas.width; - tempCanvas.height = refs.pdfCanvas.height; - - const ctx = tempCanvas.getContext('2d'); - if (!ctx) { - console.error('Failed to get 2D context for temporary canvas'); - return null; - } - - // Draw PDF canvas first (background layer) - ctx.drawImage(refs.pdfCanvas, 0, 0); - - // Get Konva canvas and draw on top (field overlays) - // Note: Konva's toCanvas() returns a new canvas with all layers rendered - const konvaCanvas = refs.konvaStage.toCanvas(); - ctx.drawImage(konvaCanvas, 0, 0); - - // Convert to PNG Blob - return new Promise((resolve, reject) => { - tempCanvas.toBlob((blob) => { - if (blob) { - resolve(blob); - } else { - reject(new Error('Failed to convert canvas to blob')); - } - }, 'image/png'); - }); - } catch (error) { - console.error(`Error compositing page ${pageNumber}:`, error); - return null; - } -}; diff --git a/packages/lib/server-only/pdf/render-pdf-to-image.ts b/packages/lib/server-only/pdf/render-pdf-to-image.ts index 841222367..fb8c030bc 100644 --- a/packages/lib/server-only/pdf/render-pdf-to-image.ts +++ b/packages/lib/server-only/pdf/render-pdf-to-image.ts @@ -26,7 +26,7 @@ export const renderPdfToImage = async (pdfBytes: Uint8Array) => { const pdf = await loadingTask.promise; try { - const scale = 4; + const scale = 2; const pages = await Promise.all( Array.from({ length: pdf.numPages }, async (_, index) => { diff --git a/packages/lib/universal/field-renderer/field-constants.ts b/packages/lib/universal/field-renderer/field-constants.ts deleted file mode 100644 index 4473b439e..000000000 --- a/packages/lib/universal/field-renderer/field-constants.ts +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Shared constants for field dimension enforcement. - * - * These constants ensure consistency between: - * 1. AI prompt (server/api/ai.ts) - instructs Gemini on minimum field dimensions - * 2. Client enforcement (envelope-editor-fields-page.tsx) - fallback validation - */ - -/** - * Minimum field height in pixels. - * Fields smaller than this will be expanded to meet minimum usability requirements. - */ -export const MIN_FIELD_HEIGHT_PX = 30; - -/** - * Minimum field width in pixels. - * Fields smaller than this will be expanded to meet minimum usability requirements. - */ -export const MIN_FIELD_WIDTH_PX = 36;