From d42065e3385e49086e9c9f3c5f6948cd51d16443 Mon Sep 17 00:00:00 2001 From: Reece Browne <74901996+reecebrowne@users.noreply.github.com> Date: Mon, 24 Nov 2025 14:00:43 +0000 Subject: [PATCH] Feature/v2/add image (#4956) # Description of Changes --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### Translations (if applicable) - [ ] I ran [`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --- .../public/locales/en-GB/translation.json | 45 ++++++++++++++++--- .../annotation/shared/ImageUploader.tsx | 10 +++-- .../core/components/viewer/EmbedPdfViewer.tsx | 2 +- .../core/data/useTranslatedToolRegistry.tsx | 24 +++++----- frontend/src/core/tools/AddImage.tsx | 13 ++++++ frontend/src/core/tools/AddText.tsx | 1 + 6 files changed, 74 insertions(+), 21 deletions(-) create mode 100644 frontend/src/core/tools/AddImage.tsx diff --git a/frontend/public/locales/en-GB/translation.json b/frontend/public/locales/en-GB/translation.json index ba09ada23..9e90c636c 100644 --- a/frontend/public/locales/en-GB/translation.json +++ b/frontend/public/locales/en-GB/translation.json @@ -1262,10 +1262,44 @@ "addImage": { "tags": "img,jpg,picture,photo", "title": "Add Image", - "header": "Add image to PDF", - "everyPage": "Every Page?", - "upload": "Add image", - "submit": "Add image" + "header": "Add images to PDFs", + "image": { + "name": "Image", + "placeholder": "Upload an image", + "label": "Image file" + }, + "steps": { + "configure": "Configure Image" + }, + "step": { + "createDesc": "Upload the image you want to add", + "place": "Place image", + "placeDesc": "Click on the PDF to add your image" + }, + "instructions": { + "title": "How to add images", + "text": "After uploading your image above, click anywhere on the PDF to place it.", + "paused": "Placement paused", + "resumeHint": "Resume placement to click and add your image.", + "noSignature": "Upload an image above to enable placement." + }, + "mode": { + "move": "Move Image", + "place": "Place Image", + "pause": "Pause placement", + "resume": "Resume placement" + }, + "results": { + "title": "Add Image Results" + }, + "error": { + "failed": "An error occurred while adding image to the PDF." + }, + "saved": { + "defaultLabel": "Image", + "defaultImageLabel": "Uploaded image" + }, + "applySignatures": "Apply Images" }, "attachments": { "tags": "attachments,add,remove,embed,file", @@ -5799,6 +5833,7 @@ "error": { "failed": "An error occurred while adding text to the PDF." }, - "tags": "text,annotation,label" + "tags": "text,annotation,label", + "applySignatures": "Apply Text" } } \ No newline at end of file diff --git a/frontend/src/core/components/annotation/shared/ImageUploader.tsx b/frontend/src/core/components/annotation/shared/ImageUploader.tsx index d339eb4be..9b4945100 100644 --- a/frontend/src/core/components/annotation/shared/ImageUploader.tsx +++ b/frontend/src/core/components/annotation/shared/ImageUploader.tsx @@ -43,16 +43,18 @@ export const ImageUploader: React.FC = ({ - - {hint || t('sign.image.hint', 'Upload an image of your signature')} - + {hint && ( + + {hint} + + )} ); }; \ No newline at end of file diff --git a/frontend/src/core/components/viewer/EmbedPdfViewer.tsx b/frontend/src/core/components/viewer/EmbedPdfViewer.tsx index 87ad05568..9ca8bac0a 100644 --- a/frontend/src/core/components/viewer/EmbedPdfViewer.tsx +++ b/frontend/src/core/components/viewer/EmbedPdfViewer.tsx @@ -83,7 +83,7 @@ const EmbedPdfViewerContent = ({ // Check if we're in signature mode OR viewer annotation mode const { selectedTool } = useNavigationState(); // Tools that use the stamp/signature placement system with hover preview - const isSignatureMode = selectedTool === 'sign' || selectedTool === 'addText'; + const isSignatureMode = selectedTool === 'sign' || selectedTool === 'addText' || selectedTool === 'addImage'; // Enable annotations when: in sign mode, OR annotation mode is active, OR we want to show existing annotations const shouldEnableAnnotations = isSignatureMode || isAnnotationMode || isAnnotationsVisible; diff --git a/frontend/src/core/data/useTranslatedToolRegistry.tsx b/frontend/src/core/data/useTranslatedToolRegistry.tsx index 140653a8f..cda99dc40 100644 --- a/frontend/src/core/data/useTranslatedToolRegistry.tsx +++ b/frontend/src/core/data/useTranslatedToolRegistry.tsx @@ -47,6 +47,7 @@ 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 { compressOperationConfig } from "@app/hooks/tools/compress/useCompressOperation"; import { splitOperationConfig } from "@app/hooks/tools/split/useSplitOperation"; import { addPasswordOperationConfig } from "@app/hooks/tools/addPassword/useAddPasswordOperation"; @@ -213,6 +214,18 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog { synonyms: getSynonyms(t, 'addText'), supportsAutomate: false, }, + addImage: { + icon: , + name: t('home.addImage.title', 'Add Image'), + component: AddImage, + description: t('home.addImage.desc', 'Add images anywhere in your PDF'), + categoryId: ToolCategoryId.STANDARD_TOOLS, + subcategoryId: SubcategoryId.GENERAL, + operationConfig: signOperationConfig, + automationSettings: null, + synonyms: getSynonyms(t, 'addImage'), + supportsAutomate: false, + }, // Document Security @@ -717,17 +730,6 @@ export function useTranslatedToolCatalog(): TranslatedToolCatalog { automationSettings: ReplaceColorSettings, synonyms: getSynonyms(t, "replaceColor"), }, - addImage: { - icon: , - name: t("home.addImage.title", "Add Image"), - component: null, - description: t("home.addImage.desc", "Add images to PDF documents"), - categoryId: ToolCategoryId.ADVANCED_TOOLS, - subcategoryId: SubcategoryId.ADVANCED_FORMATTING, - endpoints: ["add-image"], - synonyms: getSynonyms(t, "addImage"), - automationSettings: null - }, scannerEffect: { icon: , name: t("home.scannerEffect.title", "Scanner Effect"), diff --git a/frontend/src/core/tools/AddImage.tsx b/frontend/src/core/tools/AddImage.tsx new file mode 100644 index 000000000..474e14a6e --- /dev/null +++ b/frontend/src/core/tools/AddImage.tsx @@ -0,0 +1,13 @@ +import { createStampTool } from '@app/tools/stamp/createStampTool'; + +// AddImage allows users to place image-only stamps +const AddImage = createStampTool({ + toolId: 'addImage', + translationScope: 'addImage', + allowedSignatureSources: ['image'], + defaultSignatureSource: 'image', + defaultSignatureType: 'image', + enableApplyAction: true, +}); + +export default AddImage; diff --git a/frontend/src/core/tools/AddText.tsx b/frontend/src/core/tools/AddText.tsx index ede0d8fc0..c2e1af00a 100644 --- a/frontend/src/core/tools/AddText.tsx +++ b/frontend/src/core/tools/AddText.tsx @@ -7,6 +7,7 @@ const AddText = createStampTool({ allowedSignatureSources: ['text'], defaultSignatureSource: 'text', defaultSignatureType: 'text', + enableApplyAction: true, }); export default AddText;