Feature/v2/watermark (#4215)

Add watermark feature

Auto scroll on review

---------

Co-authored-by: Connor Yoh <[email protected]>
This commit is contained in:
ConnorYoh
2025-08-19 10:31:44 +01:00
committed by GitHub
co-authored by Connor Yoh
parent acbebd67a3
commit c1b7911518
24 changed files with 1410 additions and 78 deletions
@@ -0,0 +1,46 @@
import { useTranslation } from 'react-i18next';
import { useToolOperation } from '../shared/useToolOperation';
import { createStandardErrorHandler } from '../../../utils/toolErrorHandler';
import { AddWatermarkParameters } from './useAddWatermarkParameters';
const buildFormData = (parameters: AddWatermarkParameters, file: File): FormData => {
const formData = new FormData();
formData.append("fileInput", file);
// Required: watermarkType as string
formData.append("watermarkType", parameters.watermarkType || "text");
// Add watermark content based on type
if (parameters.watermarkType === 'text') {
formData.append("watermarkText", parameters.watermarkText);
} else if (parameters.watermarkType === 'image' && parameters.watermarkImage) {
formData.append("watermarkImage", parameters.watermarkImage);
}
// Required parameters with correct formatting
formData.append("fontSize", parameters.fontSize.toString());
formData.append("rotation", parameters.rotation.toString());
formData.append("opacity", (parameters.opacity / 100).toString()); // Convert percentage to decimal
formData.append("widthSpacer", parameters.widthSpacer.toString());
formData.append("heightSpacer", parameters.heightSpacer.toString());
// Backend-expected parameters from user input
formData.append("alphabet", parameters.alphabet);
formData.append("customColor", parameters.customColor);
formData.append("convertPDFToImage", parameters.convertPDFToImage.toString());
return formData;
};
export const useAddWatermarkOperation = () => {
const { t } = useTranslation();
return useToolOperation<AddWatermarkParameters>({
operationType: 'watermark',
endpoint: '/api/v1/security/add-watermark',
buildFormData,
filePrefix: t('watermark.filenamePrefix', 'watermarked') + '_',
multiFileEndpoint: false, // Individual API calls per file
getErrorMessage: createStandardErrorHandler(t('watermark.error.failed', 'An error occurred while adding watermark to the PDF.'))
});
};
@@ -0,0 +1,50 @@
import { useState, useCallback } from 'react';
import { defaultWatermarkParameters } from '../../../constants/addWatermarkConstants';
export interface AddWatermarkParameters {
watermarkType?: 'text' | 'image';
watermarkText: string;
watermarkImage?: File;
fontSize: number; // Used for both text size and image size
rotation: number;
opacity: number;
widthSpacer: number;
heightSpacer: number;
alphabet: string;
customColor: string;
convertPDFToImage: boolean;
}
export const useAddWatermarkParameters = () => {
const [parameters, setParameters] = useState<AddWatermarkParameters>(defaultWatermarkParameters);
const updateParameter = useCallback(<K extends keyof AddWatermarkParameters>(
key: K,
value: AddWatermarkParameters[K]
) => {
setParameters(prev => ({ ...prev, [key]: value }));
}, []);
const resetParameters = useCallback(() => {
setParameters(defaultWatermarkParameters);
}, []);
const validateParameters = useCallback((): boolean => {
if (!parameters.watermarkType) {
return false;
}
if (parameters.watermarkType === 'text') {
return parameters.watermarkText.trim().length > 0;
} else {
return parameters.watermarkImage !== undefined;
}
}, [parameters]);
return {
parameters,
updateParameter,
resetParameters,
validateParameters
};
};