.
+const SignRequestWorkbenchView = lazy(
+ () => import("@app/components/tools/certSign/SignRequestWorkbenchView"),
+);
+const SessionDetailWorkbenchView = lazy(
+ () => import("@app/components/tools/certSign/SessionDetailWorkbenchView"),
+);
import { Z_INDEX_OVER_FULLSCREEN_SURFACE } from "@app/styles/zIndex";
export const SIGN_REQUEST_WORKBENCH_TYPE =
diff --git a/frontend/src/core/components/tools/automate/ToolConfigurationModal.tsx b/frontend/src/core/components/tools/automate/ToolConfigurationModal.tsx
index 267d88c23..60c21f6ae 100644
--- a/frontend/src/core/components/tools/automate/ToolConfigurationModal.tsx
+++ b/frontend/src/core/components/tools/automate/ToolConfigurationModal.tsx
@@ -1,6 +1,15 @@
-import { useState, useEffect } from "react";
+import { Suspense, useState, useEffect } from "react";
import { useTranslation } from "react-i18next";
-import { Modal, Title, Button, Group, Stack, Text, Alert } from "@mantine/core";
+import {
+ Modal,
+ Title,
+ Button,
+ Group,
+ Stack,
+ Text,
+ Alert,
+ Loader,
+} from "@mantine/core";
import { Z_INDEX_AUTOMATE_MODAL } from "@app/styles/zIndex";
import SettingsIcon from "@mui/icons-material/Settings";
import CheckIcon from "@mui/icons-material/Check";
@@ -124,7 +133,9 @@ export default function ToolConfigurationModal({
- {renderToolSettings()}
+ }>
+ {renderToolSettings()}
+
diff --git a/frontend/src/core/data/useTranslatedToolRegistry.tsx b/frontend/src/core/data/useTranslatedToolRegistry.tsx
index 5303a61ff..f6a3e793a 100644
--- a/frontend/src/core/data/useTranslatedToolRegistry.tsx
+++ b/frontend/src/core/data/useTranslatedToolRegistry.tsx
@@ -1,19 +1,8 @@
-import { useMemo } from "react";
+import { lazy, useMemo } from "react";
import LocalIcon from "@app/components/shared/LocalIcon";
import { useTranslation } from "react-i18next";
import { devApiLink } from "@app/constants/links";
-import SplitPdfPanel from "@app/tools/Split";
-import CompressPdfPanel from "@app/tools/Compress";
-import OCRPanel from "@app/tools/OCR";
-import ConvertPanel from "@app/tools/Convert";
-import Sanitize from "@app/tools/Sanitize";
-import AddPassword from "@app/tools/AddPassword";
-import ChangePermissions from "@app/tools/ChangePermissions";
-import RemoveBlanks from "@app/tools/RemoveBlanks";
-import RemovePages from "@app/tools/RemovePages";
-import ReorganizePages from "@app/tools/ReorganizePages";
import { reorganizePagesOperationConfig } from "@app/hooks/tools/reorganizePages/useReorganizePagesOperation";
-import RemovePassword from "@app/tools/RemovePassword";
import {
SubcategoryId,
ToolCategoryId,
@@ -23,37 +12,9 @@ import {
LinkToolRegistry,
} from "@app/data/toolsTaxonomy";
import { isSuperToolId, isLinkToolId } from "@app/types/toolId";
-import AdjustContrast from "@app/tools/AdjustContrast";
-import AdjustContrastSingleStepSettings from "@app/components/tools/adjustContrast/AdjustContrastSingleStepSettings";
import { adjustContrastOperationConfig } from "@app/hooks/tools/adjustContrast/useAdjustContrastOperation";
import { getSynonyms } from "@app/utils/toolSynonyms";
import { useProprietaryToolRegistry } from "@app/data/useProprietaryToolRegistry";
-import GetPdfInfo from "@app/tools/GetPdfInfo";
-import AddWatermark from "@app/tools/AddWatermark";
-import AddStamp from "@app/tools/AddStamp";
-import AddAttachments from "@app/tools/AddAttachments";
-import Merge from "@app/tools/Merge";
-import EditTableOfContents from "@app/tools/EditTableOfContents";
-import Repair from "@app/tools/Repair";
-import AutoRename from "@app/tools/AutoRename";
-import SingleLargePage from "@app/tools/SingleLargePage";
-import PageLayout from "@app/tools/PageLayout";
-import UnlockPdfForms from "@app/tools/UnlockPdfForms";
-import FormFill from "@app/tools/formFill/FormFill";
-import RemoveCertificateSign from "@app/tools/RemoveCertificateSign";
-import RemoveImage from "@app/tools/RemoveImage";
-import CertSign from "@app/tools/CertSign";
-import TimestampPdf from "@app/tools/TimestampPdf";
-import BookletImposition from "@app/tools/BookletImposition";
-import Flatten from "@app/tools/Flatten";
-import Rotate from "@app/tools/Rotate";
-import PdfTextEditor from "@app/tools/pdfTextEditor/PdfTextEditor";
-import ChangeMetadata from "@app/tools/ChangeMetadata";
-import Crop from "@app/tools/Crop";
-import Sign from "@app/tools/Sign";
-import AddText from "@app/tools/AddText";
-import AddImage from "@app/tools/AddImage";
-import Annotate from "@app/tools/Annotate";
import { compressOperationConfig } from "@app/hooks/tools/compress/useCompressOperation";
import { splitOperationConfig } from "@app/hooks/tools/split/useSplitOperation";
import { addPasswordOperationConfig } from "@app/hooks/tools/addPassword/useAddPasswordOperation";
@@ -93,50 +54,7 @@ import { scannerImageSplitOperationConfig } from "@app/hooks/tools/scannerImageS
import { addPageNumbersOperationConfig } from "@app/components/tools/addPageNumbers/useAddPageNumbersOperation";
import { extractPagesOperationConfig } from "@app/hooks/tools/extractPages/useExtractPagesOperation";
import { ENDPOINTS as SPLIT_ENDPOINT_NAMES } from "@app/constants/splitConstants";
-import CompressSettings from "@app/components/tools/compress/CompressSettings";
-import AddPasswordSettings from "@app/components/tools/addPassword/AddPasswordSettings";
-import RemovePasswordSettings from "@app/components/tools/removePassword/RemovePasswordSettings";
-import SanitizeSettings from "@app/components/tools/sanitize/SanitizeSettings";
-import AddWatermarkSingleStepSettings from "@app/components/tools/addWatermark/AddWatermarkSingleStepSettings";
-import OCRSettings from "@app/components/tools/ocr/OCRSettings";
-import ConvertSettings from "@app/components/tools/convert/ConvertSettings";
-import ChangePermissionsSettings from "@app/components/tools/changePermissions/ChangePermissionsSettings";
-import BookletImpositionSettings from "@app/components/tools/bookletImposition/BookletImpositionSettings";
-import FlattenSettings from "@app/components/tools/flatten/FlattenSettings";
-import RedactSingleStepSettings from "@app/components/tools/redact/RedactSingleStepSettings";
-import Redact from "@app/tools/Redact";
-import AdjustPageScale from "@app/tools/AdjustPageScale";
-import ReplaceColor from "@app/tools/ReplaceColor";
-import ScannerImageSplit from "@app/tools/ScannerImageSplit";
-import OverlayPdfs from "@app/tools/OverlayPdfs";
import { ToolId } from "@app/types/toolId";
-import MergeSettings from "@app/components/tools/merge/MergeSettings";
-import AdjustPageScaleSettings from "@app/components/tools/adjustPageScale/AdjustPageScaleSettings";
-import ScannerImageSplitSettings from "@app/components/tools/scannerImageSplit/ScannerImageSplitSettings";
-import ChangeMetadataSingleStep from "@app/components/tools/changeMetadata/ChangeMetadataSingleStep";
-import SignSettings from "@app/components/tools/sign/SignSettings";
-import AddPageNumbers from "@app/tools/AddPageNumbers";
-import RemoveAnnotations from "@app/tools/RemoveAnnotations";
-import PageLayoutSettings from "@app/components/tools/pageLayout/PageLayoutSettings";
-import ExtractImages from "@app/tools/ExtractImages";
-import ExtractPages from "@app/tools/ExtractPages";
-import ExtractImagesSettings from "@app/components/tools/extractImages/ExtractImagesSettings";
-import ExtractPagesSettings from "@app/components/tools/extractPages/ExtractPagesSettings";
-import ReplaceColorSettings from "@app/components/tools/replaceColor/ReplaceColorSettings";
-import AddStampAutomationSettings from "@app/components/tools/addStamp/AddStampAutomationSettings";
-import CertSignAutomationSettings from "@app/components/tools/certSign/CertSignAutomationSettings";
-import CropAutomationSettings from "@app/components/tools/crop/CropAutomationSettings";
-import RotateAutomationSettings from "@app/components/tools/rotate/RotateAutomationSettings";
-import SplitAutomationSettings from "@app/components/tools/split/SplitAutomationSettings";
-import AddAttachmentsSettings from "@app/components/tools/addAttachments/AddAttachmentsSettings";
-import RemovePagesSettings from "@app/components/tools/removePages/RemovePagesSettings";
-import RemoveBlanksSettings from "@app/components/tools/removeBlanks/RemoveBlanksSettings";
-import AddPageNumbersAutomationSettings from "@app/components/tools/addPageNumbers/AddPageNumbersAutomationSettings";
-import OverlayPdfsSettings from "@app/components/tools/overlayPdfs/OverlayPdfsSettings";
-import ValidateSignature from "@app/tools/ValidateSignature";
-import ShowJS from "@app/tools/ShowJS";
-import Automate from "@app/tools/Automate";
-import Compare from "@app/tools/Compare";
import { CONVERT_SUPPORTED_FORMATS } from "@app/constants/convertSupportedFornats";
export interface TranslatedToolCatalog {
@@ -170,7 +88,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
/>
),
name: t("home.pdfTextEditor.title", "PDF Text Editor"),
- component: PdfTextEditor,
+ component: lazy(() => import("@app/tools/pdfTextEditor/PdfTextEditor")),
description: t(
"home.pdfTextEditor.desc",
"Review and edit text and images in PDFs with grouped text editing and PDF regeneration",
@@ -216,7 +134,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
/>
),
name: t("home.merge.title", "Merge"),
- component: Merge,
+ component: lazy(() => import("@app/tools/Merge")),
description: t(
"home.merge.desc",
"Merge multiple PDFs into a single document",
@@ -226,7 +144,9 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
maxFiles: -1,
endpoints: ["merge-pdfs"],
operationConfig: mergeOperationConfig,
- automationSettings: MergeSettings,
+ automationSettings: lazy(
+ () => import("@app/components/tools/merge/MergeSettings"),
+ ),
synonyms: getSynonyms(t, "merge"),
},
// Signing
@@ -239,7 +159,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
/>
),
name: t("home.certSign.title", "Certificate Sign"),
- component: CertSign,
+ component: lazy(() => import("@app/tools/CertSign")),
description: t(
"home.certSign.desc",
"Sign PDF documents using digital certificates",
@@ -250,14 +170,17 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
maxFiles: -1,
endpoints: ["cert-sign"],
operationConfig: certSignOperationConfig,
- automationSettings: CertSignAutomationSettings,
+ automationSettings: lazy(
+ () =>
+ import("@app/components/tools/certSign/CertSignAutomationSettings"),
+ ),
},
timestampPdf: {
icon: (
),
name: t("home.timestampPdf.title", "Timestamp PDF"),
- component: TimestampPdf,
+ component: lazy(() => import("@app/tools/TimestampPdf")),
description: t(
"home.timestampPdf.desc",
"Add an RFC 3161 document timestamp to prove when your PDF existed",
@@ -275,7 +198,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
),
name: t("home.sign.title", "Sign"),
- component: Sign,
+ component: lazy(() => import("@app/tools/Sign")),
description: t(
"home.sign.desc",
"Adds signature to PDF by drawing, text or image",
@@ -284,7 +207,9 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
subcategoryId: SubcategoryId.SIGNING,
endpoints: ["sign"],
operationConfig: signOperationConfig,
- automationSettings: SignSettings, // TODO:: not all settings shown, suggested next tools shown
+ automationSettings: lazy(
+ () => import("@app/components/tools/sign/SignSettings"),
+ ), // TODO:: not all settings shown, suggested next tools shown
synonyms: getSynonyms(t, "sign"),
supportsAutomate: false, //TODO make support Sign
},
@@ -297,7 +222,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
/>
),
name: t("home.addText.title", "Add Text"),
- component: AddText,
+ component: lazy(() => import("@app/tools/AddText")),
description: t(
"home.addText.desc",
"Add custom text anywhere in your PDF",
@@ -313,7 +238,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
addImage: {
icon: ,
name: t("home.addImage.title", "Add Image"),
- component: AddImage,
+ component: lazy(() => import("@app/tools/AddImage")),
description: t("home.addImage.desc", "Add images anywhere in your PDF"),
categoryId: ToolCategoryId.STANDARD_TOOLS,
subcategoryId: SubcategoryId.GENERAL,
@@ -326,7 +251,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
annotate: {
icon: ,
name: t("home.annotate.title", "Annotate"),
- component: Annotate,
+ component: lazy(() => import("@app/tools/Annotate")),
description: t(
"home.annotate.desc",
"Highlight, draw, add notes, and shapes directly in the viewer",
@@ -348,7 +273,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
),
name: t("home.addPassword.title", "Add Password"),
- component: AddPassword,
+ component: lazy(() => import("@app/tools/AddPassword")),
description: t(
"home.addPassword.desc",
"Add password protection and restrictions to PDF files",
@@ -358,7 +283,9 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
maxFiles: -1,
endpoints: ["add-password"],
operationConfig: addPasswordOperationConfig,
- automationSettings: AddPasswordSettings,
+ automationSettings: lazy(
+ () => import("@app/components/tools/addPassword/AddPasswordSettings"),
+ ),
synonyms: getSynonyms(t, "addPassword"),
},
watermark: {
@@ -370,7 +297,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
/>
),
name: t("home.watermark.title", "Add Watermark"),
- component: AddWatermark,
+ component: lazy(() => import("@app/tools/AddWatermark")),
maxFiles: -1,
description: t(
"home.watermark.desc",
@@ -380,7 +307,10 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
subcategoryId: SubcategoryId.DOCUMENT_SECURITY,
endpoints: ["add-watermark"],
operationConfig: addWatermarkOperationConfig,
- automationSettings: AddWatermarkSingleStepSettings,
+ automationSettings: lazy(
+ () =>
+ import("@app/components/tools/addWatermark/AddWatermarkSingleStepSettings"),
+ ),
synonyms: getSynonyms(t, "watermark"),
},
addStamp: {
@@ -388,7 +318,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
),
name: t("home.addStamp.title", "Add Stamp to PDF"),
- component: AddStamp,
+ component: lazy(() => import("@app/tools/AddStamp")),
description: t(
"home.addStamp.desc",
"Add text or add image stamps at set locations",
@@ -399,7 +329,10 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
maxFiles: -1,
endpoints: ["add-stamp"],
operationConfig: addStampOperationConfig,
- automationSettings: AddStampAutomationSettings,
+ automationSettings: lazy(
+ () =>
+ import("@app/components/tools/addStamp/AddStampAutomationSettings"),
+ ),
},
sanitize: {
icon: (
@@ -410,7 +343,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
/>
),
name: t("home.sanitize.title", "Sanitize"),
- component: Sanitize,
+ component: lazy(() => import("@app/tools/Sanitize")),
maxFiles: -1,
categoryId: ToolCategoryId.STANDARD_TOOLS,
subcategoryId: SubcategoryId.DOCUMENT_SECURITY,
@@ -420,7 +353,9 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
),
endpoints: ["sanitize-pdf"],
operationConfig: sanitizeOperationConfig,
- automationSettings: SanitizeSettings,
+ automationSettings: lazy(
+ () => import("@app/components/tools/sanitize/SanitizeSettings"),
+ ),
synonyms: getSynonyms(t, "sanitize"),
},
flatten: {
@@ -432,7 +367,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
/>
),
name: t("home.flatten.title", "Flatten"),
- component: Flatten,
+ component: lazy(() => import("@app/tools/Flatten")),
description: t(
"home.flatten.desc",
"Remove all interactive elements and forms from a PDF",
@@ -442,7 +377,9 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
maxFiles: -1,
endpoints: ["flatten"],
operationConfig: flattenOperationConfig,
- automationSettings: FlattenSettings,
+ automationSettings: lazy(
+ () => import("@app/components/tools/flatten/FlattenSettings"),
+ ),
synonyms: getSynonyms(t, "flatten"),
},
unlockPDFForms: {
@@ -454,7 +391,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
/>
),
name: t("home.unlockPDFForms.title", "Unlock PDF Forms"),
- component: UnlockPdfForms,
+ component: lazy(() => import("@app/tools/UnlockPdfForms")),
description: t(
"home.unlockPDFForms.desc",
"Remove read-only property of form fields in a PDF document.",
@@ -476,7 +413,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
/>
),
name: t("home.formFill.title", "Fill Form"),
- component: FormFill,
+ component: lazy(() => import("@app/tools/formFill/FormFill")),
description: t(
"home.formFill.desc",
"Fill PDF form fields interactively with a visual editor",
@@ -492,7 +429,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
changePermissions: {
icon: ,
name: t("home.changePermissions.title", "Change Permissions"),
- component: ChangePermissions,
+ component: lazy(() => import("@app/tools/ChangePermissions")),
description: t(
"home.changePermissions.desc",
"Change document restrictions and permissions",
@@ -502,7 +439,10 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
maxFiles: -1,
endpoints: ["add-password"],
operationConfig: changePermissionsOperationConfig,
- automationSettings: ChangePermissionsSettings,
+ automationSettings: lazy(
+ () =>
+ import("@app/components/tools/changePermissions/ChangePermissionsSettings"),
+ ),
synonyms: getSynonyms(t, "changePermissions"),
},
getPdfInfo: {
@@ -510,7 +450,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
),
name: t("home.getPdfInfo.title", "Get ALL Info on PDF"),
- component: GetPdfInfo,
+ component: lazy(() => import("@app/tools/GetPdfInfo")),
description: t(
"home.getPdfInfo.desc",
"Grabs any and all information possible on PDFs",
@@ -528,7 +468,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
),
name: t("home.validateSignature.title", "Validate PDF Signature"),
- component: ValidateSignature,
+ component: lazy(() => import("@app/tools/ValidateSignature")),
description: t(
"home.validateSignature.desc",
"Verify digital signatures and certificates in PDF documents",
@@ -566,7 +506,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
),
name: t("home.changeMetadata.title", "Change Metadata"),
- component: ChangeMetadata,
+ component: lazy(() => import("@app/tools/ChangeMetadata")),
description: t(
"home.changeMetadata.desc",
"Change/Remove/Add metadata from a PDF document",
@@ -576,13 +516,16 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
maxFiles: -1,
endpoints: ["update-metadata"],
operationConfig: changeMetadataOperationConfig,
- automationSettings: ChangeMetadataSingleStep,
+ automationSettings: lazy(
+ () =>
+ import("@app/components/tools/changeMetadata/ChangeMetadataSingleStep"),
+ ),
synonyms: getSynonyms(t, "changeMetadata"),
},
editTableOfContents: {
icon: ,
name: t("home.editTableOfContents.title", "Edit Table of Contents"),
- component: EditTableOfContents,
+ component: lazy(() => import("@app/tools/EditTableOfContents")),
description: t(
"home.editTableOfContents.desc",
"Add or edit bookmarks and table of contents in PDF documents",
@@ -601,7 +544,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
crop: {
icon: ,
name: t("home.crop.title", "Crop PDF"),
- component: Crop,
+ component: lazy(() => import("@app/tools/Crop")),
description: t(
"home.crop.desc",
"Crop a PDF to reduce its size (maintains text!)",
@@ -611,7 +554,9 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
maxFiles: -1,
endpoints: ["crop"],
operationConfig: cropOperationConfig,
- automationSettings: CropAutomationSettings,
+ automationSettings: lazy(
+ () => import("@app/components/tools/crop/CropAutomationSettings"),
+ ),
},
rotate: {
icon: (
@@ -622,14 +567,16 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
/>
),
name: t("home.rotate.title", "Rotate"),
- component: Rotate,
+ component: lazy(() => import("@app/tools/Rotate")),
description: t("home.rotate.desc", "Easily rotate your PDFs."),
categoryId: ToolCategoryId.STANDARD_TOOLS,
subcategoryId: SubcategoryId.PAGE_FORMATTING,
maxFiles: -1,
endpoints: ["rotate-pdf"],
operationConfig: rotateOperationConfig,
- automationSettings: RotateAutomationSettings,
+ automationSettings: lazy(
+ () => import("@app/components/tools/rotate/RotateAutomationSettings"),
+ ),
synonyms: getSynonyms(t, "rotate"),
},
split: {
@@ -641,13 +588,15 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
/>
),
name: t("home.split.title", "Split"),
- component: SplitPdfPanel,
+ component: lazy(() => import("@app/tools/Split")),
description: t("home.split.desc", "Split PDFs into multiple documents"),
categoryId: ToolCategoryId.STANDARD_TOOLS,
subcategoryId: SubcategoryId.PAGE_FORMATTING,
endpoints: Array.from(new Set(Object.values(SPLIT_ENDPOINT_NAMES))),
operationConfig: splitOperationConfig,
- automationSettings: SplitAutomationSettings,
+ automationSettings: lazy(
+ () => import("@app/components/tools/split/SplitAutomationSettings"),
+ ),
synonyms: getSynonyms(t, "split"),
},
reorganizePages: {
@@ -655,7 +604,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
),
name: t("home.reorganizePages.title", "Reorganize Pages"),
- component: ReorganizePages,
+ component: lazy(() => import("@app/tools/ReorganizePages")),
description: t(
"home.reorganizePages.desc",
"Rearrange, duplicate, or delete PDF pages with visual drag-and-drop control.",
@@ -672,7 +621,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
),
name: t("home.scalePages.title", "Adjust page size/scale"),
- component: AdjustPageScale,
+ component: lazy(() => import("@app/tools/AdjustPageScale")),
description: t(
"home.scalePages.desc",
"Change the size/scale of a page and/or its contents.",
@@ -682,20 +631,26 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
maxFiles: -1,
endpoints: ["scale-pages"],
operationConfig: adjustPageScaleOperationConfig,
- automationSettings: AdjustPageScaleSettings,
+ automationSettings: lazy(
+ () =>
+ import("@app/components/tools/adjustPageScale/AdjustPageScaleSettings"),
+ ),
synonyms: getSynonyms(t, "scalePages"),
},
addPageNumbers: {
icon: ,
name: t("home.addPageNumbers.title", "Add Page Numbers"),
- component: AddPageNumbers,
+ component: lazy(() => import("@app/tools/AddPageNumbers")),
description: t(
"home.addPageNumbers.desc",
"Add Page numbers throughout a document in a set location",
),
categoryId: ToolCategoryId.STANDARD_TOOLS,
subcategoryId: SubcategoryId.PAGE_FORMATTING,
- automationSettings: AddPageNumbersAutomationSettings,
+ automationSettings: lazy(
+ () =>
+ import("@app/components/tools/addPageNumbers/AddPageNumbersAutomationSettings"),
+ ),
maxFiles: -1,
endpoints: ["add-page-numbers"],
operationConfig: addPageNumbersOperationConfig,
@@ -706,7 +661,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
),
name: t("home.pageLayout.title", "Multi-Page Layout"),
- component: PageLayout,
+ component: lazy(() => import("@app/tools/PageLayout")),
description: t(
"home.pageLayout.desc",
"Merge multiple pages of a PDF document into a single page",
@@ -715,7 +670,9 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
subcategoryId: SubcategoryId.PAGE_FORMATTING,
maxFiles: -1,
endpoints: ["multi-page-layout"],
- automationSettings: PageLayoutSettings,
+ automationSettings: lazy(
+ () => import("@app/components/tools/pageLayout/PageLayoutSettings"),
+ ),
synonyms: getSynonyms(t, "pageLayout"),
},
bookletImposition: {
@@ -723,9 +680,12 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
),
name: t("home.bookletImposition.title", "Booklet Imposition"),
- component: BookletImposition,
+ component: lazy(() => import("@app/tools/BookletImposition")),
operationConfig: bookletImpositionOperationConfig,
- automationSettings: BookletImpositionSettings,
+ automationSettings: lazy(
+ () =>
+ import("@app/components/tools/bookletImposition/BookletImpositionSettings"),
+ ),
description: t(
"home.bookletImposition.desc",
"Create booklets with proper page ordering and multi-page layout for printing and binding",
@@ -743,7 +703,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
/>
),
name: t("home.pdfToSinglePage.title", "PDF to Single Large Page"),
- component: SingleLargePage,
+ component: lazy(() => import("@app/tools/SingleLargePage")),
description: t(
"home.pdfToSinglePage.desc",
@@ -762,7 +722,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
),
name: t("home.addAttachments.title", "Add Attachments"),
- component: AddAttachments,
+ component: lazy(() => import("@app/tools/AddAttachments")),
description: t(
"home.addAttachments.desc",
"Add or remove embedded files (attachments) to/from a PDF",
@@ -773,7 +733,10 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
maxFiles: 1,
endpoints: ["add-attachments"],
operationConfig: addAttachmentsOperationConfig,
- automationSettings: AddAttachmentsSettings,
+ automationSettings: lazy(
+ () =>
+ import("@app/components/tools/addAttachments/AddAttachmentsSettings"),
+ ),
},
// Extraction
@@ -783,7 +746,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
),
name: t("home.extractPages.title", "Extract Pages"),
- component: ExtractPages,
+ component: lazy(() => import("@app/tools/ExtractPages")),
description: t(
"home.extractPages.desc",
"Extract specific pages from a PDF document",
@@ -791,7 +754,10 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
categoryId: ToolCategoryId.STANDARD_TOOLS,
subcategoryId: SubcategoryId.EXTRACTION,
synonyms: getSynonyms(t, "extractPages"),
- automationSettings: ExtractPagesSettings,
+ automationSettings: lazy(
+ () =>
+ import("@app/components/tools/extractPages/ExtractPagesSettings"),
+ ),
operationConfig: extractPagesOperationConfig,
endpoints: ["rearrange-pages"],
},
@@ -804,7 +770,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
/>
),
name: t("home.extractImages.title", "Extract Images"),
- component: ExtractImages,
+ component: lazy(() => import("@app/tools/ExtractImages")),
description: t(
"home.extractImages.desc",
"Extract images from PDF documents",
@@ -814,7 +780,10 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
maxFiles: -1,
endpoints: ["extract-images"],
operationConfig: extractImagesOperationConfig,
- automationSettings: ExtractImagesSettings,
+ automationSettings: lazy(
+ () =>
+ import("@app/components/tools/extractImages/ExtractImagesSettings"),
+ ),
synonyms: getSynonyms(t, "extractImages"),
},
@@ -829,7 +798,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
/>
),
name: t("home.removePages.title", "Remove Pages"),
- component: RemovePages,
+ component: lazy(() => import("@app/tools/RemovePages")),
description: t(
"home.removePages.desc",
"Remove specific pages from a PDF document",
@@ -840,7 +809,9 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
endpoints: ["remove-pages"],
synonyms: getSynonyms(t, "removePages"),
operationConfig: removePagesOperationConfig,
- automationSettings: RemovePagesSettings,
+ automationSettings: lazy(
+ () => import("@app/components/tools/removePages/RemovePagesSettings"),
+ ),
},
removeBlanks: {
icon: (
@@ -851,7 +822,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
/>
),
name: t("home.removeBlanks.title", "Remove Blank Pages"),
- component: RemoveBlanks,
+ component: lazy(() => import("@app/tools/RemoveBlanks")),
description: t(
"home.removeBlanks.desc",
"Remove blank pages from PDF documents",
@@ -862,7 +833,10 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
endpoints: ["remove-blanks"],
synonyms: getSynonyms(t, "removeBlanks"),
operationConfig: removeBlanksOperationConfig,
- automationSettings: RemoveBlanksSettings,
+ automationSettings: lazy(
+ () =>
+ import("@app/components/tools/removeBlanks/RemoveBlanksSettings"),
+ ),
},
removeAnnotations: {
icon: (
@@ -873,7 +847,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
/>
),
name: t("home.removeAnnotations.title", "Remove Annotations"),
- component: RemoveAnnotations,
+ component: lazy(() => import("@app/tools/RemoveAnnotations")),
description: t(
"home.removeAnnotations.desc",
"Remove annotations and comments from PDF documents",
@@ -895,7 +869,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
/>
),
name: t("home.removeImage.title", "Remove Images"),
- component: RemoveImage,
+ component: lazy(() => import("@app/tools/RemoveImage")),
description: t(
"home.removeImage.desc",
"Remove all images from a PDF document",
@@ -917,7 +891,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
/>
),
name: t("home.removePassword.title", "Remove Password"),
- component: RemovePassword,
+ component: lazy(() => import("@app/tools/RemovePassword")),
description: t(
"home.removePassword.desc",
"Remove password protection from PDF documents",
@@ -927,7 +901,10 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
endpoints: ["remove-password"],
maxFiles: -1,
operationConfig: removePasswordOperationConfig,
- automationSettings: RemovePasswordSettings,
+ automationSettings: lazy(
+ () =>
+ import("@app/components/tools/removePassword/RemovePasswordSettings"),
+ ),
synonyms: getSynonyms(t, "removePassword"),
},
removeCertSign: {
@@ -939,7 +916,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
/>
),
name: t("home.removeCertSign.title", "Remove Certificate Sign"),
- component: RemoveCertificateSign,
+ component: lazy(() => import("@app/tools/RemoveCertificateSign")),
description: t(
"home.removeCertSign.desc",
"Remove digital signature from PDF documents",
@@ -960,7 +937,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
),
name: t("home.automate.title", "Automate"),
- component: Automate,
+ component: lazy(() => import("@app/tools/Automate")),
description: t(
"home.automate.desc",
"Build multi-step workflows by chaining together PDF actions. Ideal for recurring tasks.",
@@ -978,7 +955,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
),
name: t("home.autoRename.title", "Auto Rename PDF File"),
- component: AutoRename,
+ component: lazy(() => import("@app/tools/AutoRename")),
maxFiles: -1,
endpoints: ["auto-rename"],
operationConfig: autoRenameOperationConfig,
@@ -996,7 +973,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
adjustContrast: {
icon: ,
name: t("home.adjustContrast.title", "Adjust Colors/Contrast"),
- component: AdjustContrast,
+ component: lazy(() => import("@app/tools/AdjustContrast")),
description: t(
"home.adjustContrast.desc",
"Adjust colors and contrast of PDF documents",
@@ -1006,7 +983,10 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
maxFiles: -1,
endpoints: ["adjust-contrast"],
operationConfig: adjustContrastOperationConfig,
- automationSettings: AdjustContrastSingleStepSettings,
+ automationSettings: lazy(
+ () =>
+ import("@app/components/tools/adjustContrast/AdjustContrastSingleStepSettings"),
+ ),
synonyms: getSynonyms(t, "adjustContrast"),
},
repair: {
@@ -1018,7 +998,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
/>
),
name: t("home.repair.title", "Repair"),
- component: Repair,
+ component: lazy(() => import("@app/tools/Repair")),
description: t(
"home.repair.desc",
"Repair corrupted or damaged PDF files",
@@ -1039,7 +1019,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
"home.scannerImageSplit.title",
"Detect & Split Scanned Photos",
),
- component: ScannerImageSplit,
+ component: lazy(() => import("@app/tools/ScannerImageSplit")),
description: t(
"home.scannerImageSplit.desc",
"Detect and split scanned photos into separate pages",
@@ -1049,7 +1029,10 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
maxFiles: -1,
endpoints: ["extract-image-scans"],
operationConfig: scannerImageSplitOperationConfig,
- automationSettings: ScannerImageSplitSettings,
+ automationSettings: lazy(
+ () =>
+ import("@app/components/tools/scannerImageSplit/ScannerImageSplitSettings"),
+ ),
synonyms: getSynonyms(t, "ScannerImageSplit"),
},
overlayPdfs: {
@@ -1057,7 +1040,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
),
name: t("home.overlay-pdfs.title", "Overlay PDFs"),
- component: OverlayPdfs,
+ component: lazy(() => import("@app/tools/OverlayPdfs")),
description: t(
"home.overlay-pdfs.desc",
"Overlay one PDF on top of another",
@@ -1067,7 +1050,9 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
endpoints: ["overlay-pdf"],
operationConfig: overlayPdfsOperationConfig,
synonyms: getSynonyms(t, "overlay-pdfs"),
- automationSettings: OverlayPdfsSettings,
+ automationSettings: lazy(
+ () => import("@app/components/tools/overlayPdfs/OverlayPdfsSettings"),
+ ),
},
replaceColor: {
icon: (
@@ -1078,7 +1063,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
/>
),
name: t("home.replaceColor.title", "Replace & Invert Color"),
- component: ReplaceColor,
+ component: lazy(() => import("@app/tools/ReplaceColor")),
description: t(
"home.replaceColor.desc",
"Replace or invert colors in PDF documents",
@@ -1088,7 +1073,10 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
maxFiles: -1,
endpoints: ["replace-invert-pdf"],
operationConfig: replaceColorOperationConfig,
- automationSettings: ReplaceColorSettings,
+ automationSettings: lazy(
+ () =>
+ import("@app/components/tools/replaceColor/ReplaceColorSettings"),
+ ),
synonyms: getSynonyms(t, "replaceColor"),
},
scannerEffect: {
@@ -1115,7 +1103,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
),
name: t("home.showJS.title", "Show JavaScript"),
- component: ShowJS,
+ component: lazy(() => import("@app/tools/ShowJS")),
description: t(
"home.showJS.desc",
"Extract and display JavaScript code from PDF documents",
@@ -1221,7 +1209,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
),
name: t("home.compare.title", "Compare"),
- component: Compare,
+ component: lazy(() => import("@app/tools/Compare")),
description: t(
"home.compare.desc",
"Compare two PDF documents and highlight differences",
@@ -1244,7 +1232,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
/>
),
name: t("home.compress.title", "Compress"),
- component: CompressPdfPanel,
+ component: lazy(() => import("@app/tools/Compress")),
description: t(
"home.compress.desc",
"Compress PDFs to reduce their file size.",
@@ -1254,7 +1242,9 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
maxFiles: -1,
endpoints: ["compress-pdf"],
operationConfig: compressOperationConfig,
- automationSettings: CompressSettings,
+ automationSettings: lazy(
+ () => import("@app/components/tools/compress/CompressSettings"),
+ ),
synonyms: getSynonyms(t, "compress"),
},
convert: {
@@ -1262,7 +1252,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
),
name: t("home.convert.title", "Convert"),
- component: ConvertPanel,
+ component: lazy(() => import("@app/tools/Convert")),
description: t(
"home.convert.desc",
"Convert files to and from PDF format",
@@ -1291,7 +1281,9 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
],
operationConfig: convertOperationConfig,
- automationSettings: ConvertSettings,
+ automationSettings: lazy(
+ () => import("@app/components/tools/convert/ConvertSettings"),
+ ),
synonyms: getSynonyms(t, "convert"),
},
@@ -1304,7 +1296,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
/>
),
name: t("home.ocr.title", "OCR"),
- component: OCRPanel,
+ component: lazy(() => import("@app/tools/OCR")),
description: t(
"home.ocr.desc",
"Extract text from scanned PDFs using Optical Character Recognition",
@@ -1314,7 +1306,9 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
maxFiles: -1,
endpoints: ["ocr-pdf"],
operationConfig: ocrOperationConfig,
- automationSettings: OCRSettings,
+ automationSettings: lazy(
+ () => import("@app/components/tools/ocr/OCRSettings"),
+ ),
synonyms: getSynonyms(t, "ocr"),
},
redact: {
@@ -1326,7 +1320,7 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
/>
),
name: t("home.redact.title", "Redact"),
- component: Redact,
+ component: lazy(() => import("@app/tools/Redact")),
description: t(
"home.redact.desc",
"Permanently remove sensitive information from PDF documents",
@@ -1336,7 +1330,9 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog {
maxFiles: -1,
endpoints: ["auto-redact"],
operationConfig: redactOperationConfig,
- automationSettings: RedactSingleStepSettings,
+ automationSettings: lazy(
+ () => import("@app/components/tools/redact/RedactSingleStepSettings"),
+ ),
synonyms: getSynonyms(t, "redact"),
},
};
diff --git a/frontend/src/core/pages/HomePage.tsx b/frontend/src/core/pages/HomePage.tsx
index bba73d824..2119c5323 100644
--- a/frontend/src/core/pages/HomePage.tsx
+++ b/frontend/src/core/pages/HomePage.tsx
@@ -24,7 +24,7 @@ import RightRail from "@app/components/shared/RightRail";
import FileManager from "@app/components/FileManager";
import LocalIcon from "@app/components/shared/LocalIcon";
import { useFilesModalContext } from "@app/contexts/FilesModalContext";
-import AppConfigModal from "@app/components/shared/AppConfigModal";
+import AppConfigModal from "@app/components/shared/AppConfigModalLazy";
import { getStartupNavigationAction } from "@app/utils/homePageNavigation";
import { HomePageExtensions } from "@app/components/home/HomePageExtensions";
diff --git a/frontend/src/proprietary/components/shared/config/configSections/AdminAuditSection.tsx b/frontend/src/proprietary/components/shared/config/configSections/AdminAuditSection.tsx
index 9558a3557..734334cde 100644
--- a/frontend/src/proprietary/components/shared/config/configSections/AdminAuditSection.tsx
+++ b/frontend/src/proprietary/components/shared/config/configSections/AdminAuditSection.tsx
@@ -1,4 +1,4 @@
-import React, { useState, useEffect } from "react";
+import React, { Suspense, lazy, useState, useEffect } from "react";
import { isAxiosError } from "axios";
import {
Tabs,
@@ -8,6 +8,7 @@ import {
Text,
Button,
Accordion,
+ Center,
} from "@mantine/core";
import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom";
@@ -16,7 +17,14 @@ import auditService, {
} from "@app/services/auditService";
import AuditSystemStatus from "@app/components/shared/config/configSections/audit/AuditSystemStatus";
import AuditStatsCards from "@app/components/shared/config/configSections/audit/AuditStatsCards";
-import AuditChartsSection from "@app/components/shared/config/configSections/audit/AuditChartsSection";
+
+// AuditChartsSection pulls in recharts (~200 kB gzip). It's only rendered when
+// the user expands the "Events Over Time" accordion on this page, so we keep
+// the rest of the audit page eager and lazy-load just the charts.
+const AuditChartsSection = lazy(
+ () =>
+ import("@app/components/shared/config/configSections/audit/AuditChartsSection"),
+);
import AuditEventsTable from "@app/components/shared/config/configSections/audit/AuditEventsTable";
import AuditExportSection from "@app/components/shared/config/configSections/audit/AuditExportSection";
import AuditClearDataSection from "@app/components/shared/config/configSections/audit/AuditClearDataSection";
@@ -217,11 +225,19 @@ const AdminAuditSection: React.FC = () => {
{t("audit.charts.overTime", "Events Over Time")}
-
+
+
+
+ }
+ >
+
+
diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts
index 0d6052c3c..65d2c0ae4 100644
--- a/frontend/vite.config.ts
+++ b/frontend/vite.config.ts
@@ -1,4 +1,4 @@
-import { defineConfig, loadEnv } from "vite";
+import { defineConfig, loadEnv, type PluginOption } from "vite";
import react from "@vitejs/plugin-react-swc";
import tsconfigPaths from "vite-tsconfig-paths";
import { viteStaticCopy } from "vite-plugin-static-copy";
@@ -20,7 +20,7 @@ const TSCONFIG_MAP: Record = {
prototypes: "./tsconfig.prototypes.vite.json",
};
-export default defineConfig(({ mode }) => {
+export default defineConfig(async ({ mode }) => {
// Load env file based on `mode` in the current working directory.
// Set the third parameter to '' to load all env regardless of the
// `VITE_` prefix.
@@ -55,6 +55,19 @@ export default defineConfig(({ mode }) => {
tsconfigPaths({
projects: [tsconfigProject],
}),
+ // Set ANALYZE=true to emit dist/stats.html (treemap) alongside the
+ // build; rollup-plugin-visualizer is ESM-only so we import dynamically.
+ ...(process.env.ANALYZE === "true"
+ ? [
+ (await import("rollup-plugin-visualizer")).visualizer({
+ filename: "dist/stats.html",
+ template: "treemap",
+ gzipSize: true,
+ brotliSize: true,
+ emitFile: false,
+ }) as PluginOption,
+ ]
+ : []),
viteStaticCopy({
targets: [
{