Normalise tool IDs and fix file history to render IDs properly

This commit is contained in:
James Brunton 2025-09-19 11:46:38 +01:00
parent ae7be50ec2
commit 075ad462b2
18 changed files with 178 additions and 145 deletions

View File

@ -414,7 +414,7 @@
"title": "Extract Images", "title": "Extract Images",
"desc": "Extracts all images from a PDF and saves them to zip" "desc": "Extracts all images from a PDF and saves them to zip"
}, },
"ScannerImageSplit": { "scannerImageSplit": {
"title": "Detect/Split Scanned photos", "title": "Detect/Split Scanned photos",
"desc": "Splits multiple photos from within a photo/PDF" "desc": "Splits multiple photos from within a photo/PDF"
}, },
@ -458,15 +458,11 @@
"title": "Adjust page size/scale", "title": "Adjust page size/scale",
"desc": "Change the size/scale of a page and/or its contents." "desc": "Change the size/scale of a page and/or its contents."
}, },
"pipeline": {
"title": "Pipeline",
"desc": "Run multiple actions on PDFs by defining pipeline scripts"
},
"addPageNumbers": { "addPageNumbers": {
"title": "Add Page Numbers", "title": "Add Page Numbers",
"desc": "Add Page numbers throughout a document in a set location" "desc": "Add Page numbers throughout a document in a set location"
}, },
"auto-rename": { "autoRename": {
"title": "Auto Rename PDF File", "title": "Auto Rename PDF File",
"desc": "Auto renames a PDF file based on its detected header" "desc": "Auto renames a PDF file based on its detected header"
}, },
@ -502,15 +498,15 @@
"title": "Redact", "title": "Redact",
"desc": "Redacts (blacks out) a PDF based on selected text, drawn shapes and/or selected page(s)" "desc": "Redacts (blacks out) a PDF based on selected text, drawn shapes and/or selected page(s)"
}, },
"overlay-pdfs": { "overlayPdfs": {
"title": "Overlay PDFs", "title": "Overlay PDFs",
"desc": "Overlays PDFs on-top of another PDF" "desc": "Overlays PDFs on-top of another PDF"
}, },
"split-by-sections": { "splitBySections": {
"title": "Split PDF by Sections", "title": "Split PDF by Sections",
"desc": "Divide each page of a PDF into smaller horizontal and vertical sections" "desc": "Divide each page of a PDF into smaller horizontal and vertical sections"
}, },
"AddStampRequest": { "addStamp": {
"title": "Add Stamp to PDF", "title": "Add Stamp to PDF",
"desc": "Add text or add image stamps at set locations" "desc": "Add text or add image stamps at set locations"
}, },
@ -530,10 +526,6 @@
"title": "API Documentation", "title": "API Documentation",
"desc": "View API documentation and test endpoints" "desc": "View API documentation and test endpoints"
}, },
"replace-color": {
"title": "Advanced Colour options",
"desc": "Replace colour for text and background in PDF and invert full colour of pdf to reduce file size"
},
"fakeScan": { "fakeScan": {
"title": "Fake Scan", "title": "Fake Scan",
"desc": "Create a PDF that looks like it was scanned" "desc": "Create a PDF that looks like it was scanned"
@ -562,18 +554,10 @@
"title": "Remove Pages", "title": "Remove Pages",
"desc": "Remove specific pages from a PDF document" "desc": "Remove specific pages from a PDF document"
}, },
"removeImagePdf": {
"title": "Remove Image",
"desc": "Remove images from PDF documents"
},
"autoSizeSplitPDF": { "autoSizeSplitPDF": {
"title": "Auto Split by Size/Count", "title": "Auto Split by Size/Count",
"desc": "Automatically split PDFs by file size or page count" "desc": "Automatically split PDFs by file size or page count"
}, },
"adjust-contrast": {
"title": "Adjust Colours/Contrast",
"desc": "Adjust colours and contrast of PDF documents"
},
"replaceColorPdf": { "replaceColorPdf": {
"title": "Replace & Invert Colour", "title": "Replace & Invert Colour",
"desc": "Replace or invert colours in PDF documents" "desc": "Replace or invert colours in PDF documents"

View File

@ -41,29 +41,29 @@ const CompactFileDetails: React.FC<CompactFileDetailsProps> = ({
{/* Small preview */} {/* Small preview */}
<Box style={{ width: '7.5rem', height: '9.375rem', flexShrink: 0, position: 'relative', display: 'flex', alignItems: 'center', justifyContent: 'center' }}> <Box style={{ width: '7.5rem', height: '9.375rem', flexShrink: 0, position: 'relative', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
{currentFile && thumbnail ? ( {currentFile && thumbnail ? (
<img <img
src={thumbnail} src={thumbnail}
alt={currentFile.name} alt={currentFile.name}
style={{ style={{
maxWidth: '100%', maxWidth: '100%',
maxHeight: '100%', maxHeight: '100%',
objectFit: 'contain', objectFit: 'contain',
borderRadius: '0.25rem', borderRadius: '0.25rem',
boxShadow: '0 2px 4px rgba(0, 0, 0, 0.1)' boxShadow: '0 2px 4px rgba(0, 0, 0, 0.1)'
}} }}
/> />
) : currentFile ? ( ) : currentFile ? (
<Center style={{ <Center style={{
width: '100%', width: '100%',
height: '100%', height: '100%',
backgroundColor: 'var(--mantine-color-gray-1)', backgroundColor: 'var(--mantine-color-gray-1)',
borderRadius: 4 borderRadius: 4
}}> }}>
<PictureAsPdfIcon style={{ fontSize: 20, color: 'var(--mantine-color-gray-6)' }} /> <PictureAsPdfIcon style={{ fontSize: 20, color: 'var(--mantine-color-gray-6)' }} />
</Center> </Center>
) : null} ) : null}
</Box> </Box>
{/* File info */} {/* File info */}
<Box style={{ flex: 1, minWidth: 0 }}> <Box style={{ flex: 1, minWidth: 0 }}>
<Text size="sm" fw={500} truncate> <Text size="sm" fw={500} truncate>
@ -82,11 +82,11 @@ const CompactFileDetails: React.FC<CompactFileDetailsProps> = ({
{/* Compact tool chain for mobile */} {/* Compact tool chain for mobile */}
{currentFile?.toolHistory && currentFile.toolHistory.length > 0 && ( {currentFile?.toolHistory && currentFile.toolHistory.length > 0 && (
<Text size="xs" c="dimmed"> <Text size="xs" c="dimmed">
{currentFile.toolHistory.map((tool: any) => tool.toolName).join(' → ')} {currentFile.toolHistory.map((tool) => t(`home.${tool.toolId}.title`, tool.toolId)).join(' → ')}
</Text> </Text>
)} )}
</Box> </Box>
{/* Navigation arrows for multiple files */} {/* Navigation arrows for multiple files */}
{hasMultipleFiles && ( {hasMultipleFiles && (
<Box style={{ display: 'flex', gap: '0.25rem' }}> <Box style={{ display: 'flex', gap: '0.25rem' }}>
@ -109,19 +109,19 @@ const CompactFileDetails: React.FC<CompactFileDetailsProps> = ({
</Box> </Box>
)} )}
</Box> </Box>
{/* Action Button */} {/* Action Button */}
<Button <Button
size="sm" size="sm"
onClick={onOpenFiles} onClick={onOpenFiles}
disabled={!hasSelection} disabled={!hasSelection}
fullWidth fullWidth
style={{ style={{
backgroundColor: hasSelection ? 'var(--btn-open-file)' : 'var(--mantine-color-gray-4)', backgroundColor: hasSelection ? 'var(--btn-open-file)' : 'var(--mantine-color-gray-4)',
color: 'white' color: 'white'
}} }}
> >
{selectedFiles.length > 1 {selectedFiles.length > 1
? t('fileManager.openFiles', `Open ${selectedFiles.length} Files`) ? t('fileManager.openFiles', `Open ${selectedFiles.length} Files`)
: t('fileManager.openFile', 'Open File') : t('fileManager.openFile', 'Open File')
} }
@ -130,4 +130,4 @@ const CompactFileDetails: React.FC<CompactFileDetailsProps> = ({
); );
}; };
export default CompactFileDetails; export default CompactFileDetails;

View File

@ -6,6 +6,8 @@
import React from 'react'; import React from 'react';
import { Text, Tooltip, Badge, Group } from '@mantine/core'; import { Text, Tooltip, Badge, Group } from '@mantine/core';
import { ToolOperation } from '../../types/file'; import { ToolOperation } from '../../types/file';
import { useTranslation } from 'react-i18next';
import { ToolId } from '../../types/toolId';
interface ToolChainProps { interface ToolChainProps {
toolChain: ToolOperation[]; toolChain: ToolOperation[];
@ -24,15 +26,21 @@ const ToolChain: React.FC<ToolChainProps> = ({
}) => { }) => {
if (!toolChain || toolChain.length === 0) return null; if (!toolChain || toolChain.length === 0) return null;
const toolNames = toolChain.map(tool => tool.toolName); const { t } = useTranslation();
const toolIds = toolChain.map(tool => tool.toolId);
const getToolName = (toolId: ToolId) => {
return t(`home.${toolId}.title`, toolId);
}
// Create full tool chain for tooltip // Create full tool chain for tooltip
const fullChainDisplay = displayStyle === 'badges' ? ( const fullChainDisplay = displayStyle === 'badges' ? (
<Group gap="xs" wrap="wrap"> <Group gap="xs" wrap="wrap">
{toolChain.map((tool, index) => ( {toolChain.map((tool, index) => (
<React.Fragment key={`${tool.toolName}-${index}`}> <React.Fragment key={`${tool.toolId}-${index}`}>
<Badge size="sm" variant="light" color="blue"> <Badge size="sm" variant="light" color="blue">
{tool.toolName} {getToolName(tool.toolId)}
</Badge> </Badge>
{index < toolChain.length - 1 && ( {index < toolChain.length - 1 && (
<Text size="sm" c="dimmed"></Text> <Text size="sm" c="dimmed"></Text>
@ -41,19 +49,19 @@ const ToolChain: React.FC<ToolChainProps> = ({
))} ))}
</Group> </Group>
) : ( ) : (
<Text size="sm">{toolNames.join(' → ')}</Text> <Text size="sm">{toolIds.map(getToolName).join(' → ')}</Text>
); );
// Create truncated display based on available space // Create truncated display based on available space
const getTruncatedDisplay = () => { const getTruncatedDisplay = () => {
if (toolNames.length <= 2) { if (toolIds.length <= 2) {
// Show all tools if 2 or fewer // Show all tools if 2 or fewer
return { text: toolNames.join(' → '), isTruncated: false }; return { text: toolIds.map(getToolName).join(' → '), isTruncated: false };
} else { } else {
// Show first tool ... last tool for longer chains // Show first tool ... last tool for longer chains
return { return {
text: `${toolNames[0]} → +${toolNames.length-2}${toolNames[toolNames.length - 1]}`, text: `${getToolName(toolIds[0])} → +${toolIds.length-2}${getToolName(toolIds[toolIds.length - 1])}`,
isTruncated: true isTruncated: true,
}; };
} }
}; };
@ -62,8 +70,8 @@ const ToolChain: React.FC<ToolChainProps> = ({
// Compact style for very small spaces // Compact style for very small spaces
if (displayStyle === 'compact') { if (displayStyle === 'compact') {
const compactText = toolNames.length === 1 ? toolNames[0] : `${toolNames.length} tools`; const compactText = toolIds.length === 1 ? getToolName(toolIds[0]) : `${toolIds.length} tools`;
const isCompactTruncated = toolNames.length > 1; const isCompactTruncated = toolIds.length > 1;
const compactElement = ( const compactElement = (
<Text <Text
@ -97,9 +105,9 @@ const ToolChain: React.FC<ToolChainProps> = ({
<div style={{ maxWidth: `${maxWidth}`, overflow: 'hidden' }}> <div style={{ maxWidth: `${maxWidth}`, overflow: 'hidden' }}>
<Group gap="2px" wrap="nowrap"> <Group gap="2px" wrap="nowrap">
{toolChain.slice(0, 3).map((tool, index) => ( {toolChain.slice(0, 3).map((tool, index) => (
<React.Fragment key={`${tool.toolName}-${index}`}> <React.Fragment key={`${tool.toolId}-${index}`}>
<Badge size={size} variant="light" color="blue"> <Badge size={size} variant="light" color="blue">
{tool.toolName} {getToolName(tool.toolId)}
</Badge> </Badge>
{index < Math.min(toolChain.length - 1, 2) && ( {index < Math.min(toolChain.length - 1, 2) && (
<Text size="xs" c="dimmed"></Text> <Text size="xs" c="dimmed"></Text>
@ -110,7 +118,7 @@ const ToolChain: React.FC<ToolChainProps> = ({
<> <>
<Text size="xs" c="dimmed">...</Text> <Text size="xs" c="dimmed">...</Text>
<Badge size={size} variant="light" color="blue"> <Badge size={size} variant="light" color="blue">
{toolChain[toolChain.length - 1].toolName} {getToolName(toolChain[toolChain.length - 1].toolId)}
</Badge> </Badge>
</> </>
)} )}
@ -119,7 +127,7 @@ const ToolChain: React.FC<ToolChainProps> = ({
); );
return isBadgesTruncated ? ( return isBadgesTruncated ? (
<Tooltip label={`${toolNames.join(' → ')}`} withinPortal> <Tooltip label={`${toolIds.map(getToolName).join(' → ')}`} withinPortal>
{badgesElement} {badgesElement}
</Tooltip> </Tooltip>
) : badgesElement; ) : badgesElement;

View File

@ -12,7 +12,7 @@ import {
createStirlingFile, createStirlingFile,
ProcessedFileMetadata, ProcessedFileMetadata,
} from '../../types/fileContext'; } from '../../types/fileContext';
import { FileId } from '../../types/file'; import { FileId, ToolOperation } from '../../types/file';
import { generateThumbnailWithMetadata } from '../../utils/thumbnailUtils'; import { generateThumbnailWithMetadata } from '../../utils/thumbnailUtils';
import { FileLifecycleManager } from './lifecycle'; import { FileLifecycleManager } from './lifecycle';
import { buildQuickKeySet } from './fileSelectors'; import { buildQuickKeySet } from './fileSelectors';
@ -104,7 +104,7 @@ export async function generateProcessedFileMetadata(file: File): Promise<Process
*/ */
export function createChildStub( export function createChildStub(
parentStub: StirlingFileStub, parentStub: StirlingFileStub,
operation: { toolName: string; timestamp: number }, operation: ToolOperation,
resultingFile: File, resultingFile: File,
thumbnail?: string, thumbnail?: string,
processedFileMetadata?: ProcessedFileMetadata processedFileMetadata?: ProcessedFileMetadata

View File

@ -185,7 +185,7 @@ export function useFlatToolRegistry(): ToolRegistry {
operationConfig: addPasswordOperationConfig, operationConfig: addPasswordOperationConfig,
settingsComponent: AddPasswordSettings, settingsComponent: AddPasswordSettings,
}, },
addWatermark: { watermark: {
icon: <LocalIcon icon="branding-watermark-outline-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="branding-watermark-outline-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.watermark.title", "Add Watermark"), name: t("home.watermark.title", "Add Watermark"),
component: AddWatermark, component: AddWatermark,
@ -197,11 +197,11 @@ export function useFlatToolRegistry(): ToolRegistry {
operationConfig: addWatermarkOperationConfig, operationConfig: addWatermarkOperationConfig,
settingsComponent: AddWatermarkSingleStepSettings, settingsComponent: AddWatermarkSingleStepSettings,
}, },
"add-stamp": { addStamp: {
icon: <LocalIcon icon="approval-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="approval-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.AddStampRequest.title", "Add Stamp to PDF"), name: t("home.addStamp.title", "Add Stamp to PDF"),
component: null, component: null,
description: t("home.AddStampRequest.desc", "Add text or add image stamps at set locations"), description: t("home.addStamp.desc", "Add text or add image stamps at set locations"),
categoryId: ToolCategoryId.STANDARD_TOOLS, categoryId: ToolCategoryId.STANDARD_TOOLS,
subcategoryId: SubcategoryId.DOCUMENT_SECURITY, subcategoryId: SubcategoryId.DOCUMENT_SECURITY,
}, },
@ -229,7 +229,7 @@ export function useFlatToolRegistry(): ToolRegistry {
operationConfig: flattenOperationConfig, operationConfig: flattenOperationConfig,
settingsComponent: FlattenSettings, settingsComponent: FlattenSettings,
}, },
"unlock-pdf-forms": { unlockPDFForms: {
icon: <LocalIcon icon="preview-off-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="preview-off-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.unlockPDFForms.title", "Unlock PDF Forms"), name: t("home.unlockPDFForms.title", "Unlock PDF Forms"),
component: UnlockPdfForms, component: UnlockPdfForms,
@ -241,7 +241,7 @@ export function useFlatToolRegistry(): ToolRegistry {
operationConfig: unlockPdfFormsOperationConfig, operationConfig: unlockPdfFormsOperationConfig,
settingsComponent: UnlockPdfFormsSettings, settingsComponent: UnlockPdfFormsSettings,
}, },
"manage-certificates": { manageCertificates: {
icon: <LocalIcon icon="license-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="license-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.manageCertificates.title", "Manage Certificates"), name: t("home.manageCertificates.title", "Manage Certificates"),
component: null, component: null,
@ -252,7 +252,7 @@ export function useFlatToolRegistry(): ToolRegistry {
categoryId: ToolCategoryId.STANDARD_TOOLS, categoryId: ToolCategoryId.STANDARD_TOOLS,
subcategoryId: SubcategoryId.DOCUMENT_SECURITY, subcategoryId: SubcategoryId.DOCUMENT_SECURITY,
}, },
"change-permissions": { changePermissions: {
icon: <LocalIcon icon="lock-outline" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="lock-outline" width="1.5rem" height="1.5rem" />,
name: t("home.changePermissions.title", "Change Permissions"), name: t("home.changePermissions.title", "Change Permissions"),
component: ChangePermissions, component: ChangePermissions,
@ -266,7 +266,7 @@ export function useFlatToolRegistry(): ToolRegistry {
}, },
// Verification // Verification
"get-all-info-on-pdf": { getPdfInfo: {
icon: <LocalIcon icon="fact-check-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="fact-check-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.getPdfInfo.title", "Get ALL Info on PDF"), name: t("home.getPdfInfo.title", "Get ALL Info on PDF"),
component: null, component: null,
@ -274,7 +274,7 @@ export function useFlatToolRegistry(): ToolRegistry {
categoryId: ToolCategoryId.STANDARD_TOOLS, categoryId: ToolCategoryId.STANDARD_TOOLS,
subcategoryId: SubcategoryId.VERIFICATION, subcategoryId: SubcategoryId.VERIFICATION,
}, },
"validate-pdf-signature": { validateSignature: {
icon: <LocalIcon icon="verified-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="verified-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.validateSignature.title", "Validate PDF Signature"), name: t("home.validateSignature.title", "Validate PDF Signature"),
component: null, component: null,
@ -297,7 +297,7 @@ export function useFlatToolRegistry(): ToolRegistry {
categoryId: ToolCategoryId.STANDARD_TOOLS, categoryId: ToolCategoryId.STANDARD_TOOLS,
subcategoryId: SubcategoryId.DOCUMENT_REVIEW, subcategoryId: SubcategoryId.DOCUMENT_REVIEW,
}, },
"change-metadata": { changeMetadata: {
icon: <LocalIcon icon="assignment-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="assignment-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.changeMetadata.title", "Change Metadata"), name: t("home.changeMetadata.title", "Change Metadata"),
component: ChangeMetadata, component: ChangeMetadata,
@ -311,7 +311,7 @@ export function useFlatToolRegistry(): ToolRegistry {
}, },
// Page Formatting // Page Formatting
cropPdf: { crop: {
icon: <LocalIcon icon="crop-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="crop-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.crop.title", "Crop PDF"), name: t("home.crop.title", "Crop PDF"),
component: null, component: null,
@ -341,7 +341,7 @@ export function useFlatToolRegistry(): ToolRegistry {
operationConfig: splitOperationConfig, operationConfig: splitOperationConfig,
settingsComponent: SplitSettings, settingsComponent: SplitSettings,
}, },
"reorganize-pages": { reorganizePages: {
icon: <LocalIcon icon="move-down-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="move-down-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.reorganizePages.title", "Reorganize Pages"), name: t("home.reorganizePages.title", "Reorganize Pages"),
component: null, component: null,
@ -353,7 +353,7 @@ export function useFlatToolRegistry(): ToolRegistry {
categoryId: ToolCategoryId.STANDARD_TOOLS, categoryId: ToolCategoryId.STANDARD_TOOLS,
subcategoryId: SubcategoryId.PAGE_FORMATTING, subcategoryId: SubcategoryId.PAGE_FORMATTING,
}, },
"adjust-page-size-scale": { scalePages: {
icon: <LocalIcon icon="crop-free-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="crop-free-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.scalePages.title", "Adjust page size/scale"), name: t("home.scalePages.title", "Adjust page size/scale"),
component: AdjustPageScale, component: AdjustPageScale,
@ -374,7 +374,7 @@ export function useFlatToolRegistry(): ToolRegistry {
categoryId: ToolCategoryId.STANDARD_TOOLS, categoryId: ToolCategoryId.STANDARD_TOOLS,
subcategoryId: SubcategoryId.PAGE_FORMATTING, subcategoryId: SubcategoryId.PAGE_FORMATTING,
}, },
"multi-page-layout": { pageLayout: {
icon: <LocalIcon icon="dashboard-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="dashboard-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.pageLayout.title", "Multi-Page Layout"), name: t("home.pageLayout.title", "Multi-Page Layout"),
component: null, component: null,
@ -383,7 +383,7 @@ export function useFlatToolRegistry(): ToolRegistry {
categoryId: ToolCategoryId.STANDARD_TOOLS, categoryId: ToolCategoryId.STANDARD_TOOLS,
subcategoryId: SubcategoryId.PAGE_FORMATTING, subcategoryId: SubcategoryId.PAGE_FORMATTING,
}, },
"single-large-page": { pdfToSinglePage: {
icon: <LocalIcon icon="looks-one-outline-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="looks-one-outline-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.pdfToSinglePage.title", "PDF to Single Large Page"), name: t("home.pdfToSinglePage.title", "PDF to Single Large Page"),
component: SingleLargePage, component: SingleLargePage,
@ -396,7 +396,7 @@ export function useFlatToolRegistry(): ToolRegistry {
endpoints: ["pdf-to-single-page"], endpoints: ["pdf-to-single-page"],
operationConfig: singleLargePageOperationConfig, operationConfig: singleLargePageOperationConfig,
}, },
"add-attachments": { attachments: {
icon: <LocalIcon icon="attachment-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="attachment-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.attachments.title", "Add Attachments"), name: t("home.attachments.title", "Add Attachments"),
component: null, component: null,
@ -408,7 +408,7 @@ export function useFlatToolRegistry(): ToolRegistry {
// Extraction // Extraction
"extract-page": { extractPages: {
icon: <LocalIcon icon="upload-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="upload-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.extractPages.title", "Extract Pages"), name: t("home.extractPages.title", "Extract Pages"),
component: null, component: null,
@ -416,7 +416,7 @@ export function useFlatToolRegistry(): ToolRegistry {
categoryId: ToolCategoryId.STANDARD_TOOLS, categoryId: ToolCategoryId.STANDARD_TOOLS,
subcategoryId: SubcategoryId.EXTRACTION, subcategoryId: SubcategoryId.EXTRACTION,
}, },
"extract-images": { extractImages: {
icon: <LocalIcon icon="filter-alt" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="filter-alt" width="1.5rem" height="1.5rem" />,
name: t("home.extractImages.title", "Extract Images"), name: t("home.extractImages.title", "Extract Images"),
component: null, component: null,
@ -437,7 +437,7 @@ export function useFlatToolRegistry(): ToolRegistry {
maxFiles: 1, maxFiles: 1,
endpoints: ["remove-pages"], endpoints: ["remove-pages"],
}, },
"remove-blank-pages": { removeBlanks: {
icon: <LocalIcon icon="scan-delete-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="scan-delete-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.removeBlanks.title", "Remove Blank Pages"), name: t("home.removeBlanks.title", "Remove Blank Pages"),
component: RemoveBlanks, component: RemoveBlanks,
@ -447,7 +447,7 @@ export function useFlatToolRegistry(): ToolRegistry {
maxFiles: 1, maxFiles: 1,
endpoints: ["remove-blanks"], endpoints: ["remove-blanks"],
}, },
"remove-annotations": { removeAnnotations: {
icon: <LocalIcon icon="thread-unread-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="thread-unread-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.removeAnnotations.title", "Remove Annotations"), name: t("home.removeAnnotations.title", "Remove Annotations"),
component: null, component: null,
@ -455,15 +455,15 @@ export function useFlatToolRegistry(): ToolRegistry {
categoryId: ToolCategoryId.STANDARD_TOOLS, categoryId: ToolCategoryId.STANDARD_TOOLS,
subcategoryId: SubcategoryId.REMOVAL, subcategoryId: SubcategoryId.REMOVAL,
}, },
"remove-image": { removeImage: {
icon: <LocalIcon icon="remove-selection-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="remove-selection-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.removeImagePdf.title", "Remove Image"), name: t("home.removeImage.title", "Remove Image"),
component: null, component: null,
description: t("home.removeImagePdf.desc", "Remove images from PDF documents"), description: t("home.removeImage.desc", "Remove images from PDF documents"),
categoryId: ToolCategoryId.STANDARD_TOOLS, categoryId: ToolCategoryId.STANDARD_TOOLS,
subcategoryId: SubcategoryId.REMOVAL, subcategoryId: SubcategoryId.REMOVAL,
}, },
"remove-password": { removePassword: {
icon: <LocalIcon icon="lock-open-right-outline-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="lock-open-right-outline-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.removePassword.title", "Remove Password"), name: t("home.removePassword.title", "Remove Password"),
component: RemovePassword, component: RemovePassword,
@ -475,7 +475,7 @@ export function useFlatToolRegistry(): ToolRegistry {
operationConfig: removePasswordOperationConfig, operationConfig: removePasswordOperationConfig,
settingsComponent: RemovePasswordSettings, settingsComponent: RemovePasswordSettings,
}, },
"remove-certificate-sign": { removeCertSign: {
icon: <LocalIcon icon="remove-moderator-outline-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="remove-moderator-outline-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.removeCertSign.title", "Remove Certificate Sign"), name: t("home.removeCertSign.title", "Remove Certificate Sign"),
component: RemoveCertificateSign, component: RemoveCertificateSign,
@ -503,18 +503,18 @@ export function useFlatToolRegistry(): ToolRegistry {
supportedFormats: CONVERT_SUPPORTED_FORMATS, supportedFormats: CONVERT_SUPPORTED_FORMATS,
endpoints: ["handleData"], endpoints: ["handleData"],
}, },
"auto-rename-pdf-file": { autoRename: {
icon: <LocalIcon icon="match-word-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="match-word-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.auto-rename.title", "Auto Rename PDF File"), name: t("home.autoRename.title", "Auto Rename PDF File"),
component: AutoRename, component: AutoRename,
maxFiles: -1, maxFiles: -1,
endpoints: ["remove-certificate-sign"], endpoints: ["remove-certificate-sign"],
operationConfig: autoRenameOperationConfig, operationConfig: autoRenameOperationConfig,
description: t("home.auto-rename.desc", "Automatically rename PDF files based on their content"), description: t("home.autoRename.desc", "Automatically rename PDF files based on their content"),
categoryId: ToolCategoryId.ADVANCED_TOOLS, categoryId: ToolCategoryId.ADVANCED_TOOLS,
subcategoryId: SubcategoryId.AUTOMATION, subcategoryId: SubcategoryId.AUTOMATION,
}, },
"auto-split-pages": { autoSplitPDF: {
icon: <LocalIcon icon="split-scene-right-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="split-scene-right-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.autoSplitPDF.title", "Auto Split Pages"), name: t("home.autoSplitPDF.title", "Auto Split Pages"),
component: null, component: null,
@ -522,7 +522,7 @@ export function useFlatToolRegistry(): ToolRegistry {
categoryId: ToolCategoryId.ADVANCED_TOOLS, categoryId: ToolCategoryId.ADVANCED_TOOLS,
subcategoryId: SubcategoryId.AUTOMATION, subcategoryId: SubcategoryId.AUTOMATION,
}, },
"auto-split-by-size-count": { autoSizeSplitPDF: {
icon: <LocalIcon icon="content-cut-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="content-cut-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.autoSizeSplitPDF.title", "Auto Split by Size/Count"), name: t("home.autoSizeSplitPDF.title", "Auto Split by Size/Count"),
component: null, component: null,
@ -533,7 +533,7 @@ export function useFlatToolRegistry(): ToolRegistry {
// Advanced Formatting // Advanced Formatting
"adjust-contrast": { adjustContrast: {
icon: <LocalIcon icon="palette" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="palette" width="1.5rem" height="1.5rem" />,
name: t("home.adjustContrast.title", "Adjust Colors/Contrast"), name: t("home.adjustContrast.title", "Adjust Colors/Contrast"),
component: null, component: null,
@ -553,23 +553,23 @@ export function useFlatToolRegistry(): ToolRegistry {
operationConfig: repairOperationConfig, operationConfig: repairOperationConfig,
settingsComponent: RepairSettings, settingsComponent: RepairSettings,
}, },
"detect-split-scanned-photos": { scannerImageSplit: {
icon: <LocalIcon icon="scanner-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="scanner-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.ScannerImageSplit.title", "Detect & Split Scanned Photos"), name: t("home.scannerImageSplit.title", "Detect & Split Scanned Photos"),
component: null, component: null,
description: t("home.ScannerImageSplit.desc", "Detect and split scanned photos into separate pages"), description: t("home.scannerImageSplit.desc", "Detect and split scanned photos into separate pages"),
categoryId: ToolCategoryId.ADVANCED_TOOLS, categoryId: ToolCategoryId.ADVANCED_TOOLS,
subcategoryId: SubcategoryId.ADVANCED_FORMATTING, subcategoryId: SubcategoryId.ADVANCED_FORMATTING,
}, },
"overlay-pdfs": { overlayPdfs: {
icon: <LocalIcon icon="layers-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="layers-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.overlay-pdfs.title", "Overlay PDFs"), name: t("home.overlayPdfs.title", "Overlay PDFs"),
component: null, component: null,
description: t("home.overlay-pdfs.desc", "Overlay one PDF on top of another"), description: t("home.overlayPdfs.desc", "Overlay one PDF on top of another"),
categoryId: ToolCategoryId.ADVANCED_TOOLS, categoryId: ToolCategoryId.ADVANCED_TOOLS,
subcategoryId: SubcategoryId.ADVANCED_FORMATTING, subcategoryId: SubcategoryId.ADVANCED_FORMATTING,
}, },
"replace-and-invert-color": { replaceColorPdf: {
icon: <LocalIcon icon="format-color-fill-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="format-color-fill-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.replaceColorPdf.title", "Replace & Invert Color"), name: t("home.replaceColorPdf.title", "Replace & Invert Color"),
component: null, component: null,
@ -577,7 +577,7 @@ export function useFlatToolRegistry(): ToolRegistry {
categoryId: ToolCategoryId.ADVANCED_TOOLS, categoryId: ToolCategoryId.ADVANCED_TOOLS,
subcategoryId: SubcategoryId.ADVANCED_FORMATTING, subcategoryId: SubcategoryId.ADVANCED_FORMATTING,
}, },
"add-image": { addImage: {
icon: <LocalIcon icon="image-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="image-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.addImage.title", "Add Image"), name: t("home.addImage.title", "Add Image"),
component: null, component: null,
@ -585,7 +585,7 @@ export function useFlatToolRegistry(): ToolRegistry {
categoryId: ToolCategoryId.ADVANCED_TOOLS, categoryId: ToolCategoryId.ADVANCED_TOOLS,
subcategoryId: SubcategoryId.ADVANCED_FORMATTING, subcategoryId: SubcategoryId.ADVANCED_FORMATTING,
}, },
"edit-table-of-contents": { editTableOfContents: {
icon: <LocalIcon icon="bookmark-add-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="bookmark-add-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.editTableOfContents.title", "Edit Table of Contents"), name: t("home.editTableOfContents.title", "Edit Table of Contents"),
component: null, component: null,
@ -593,7 +593,7 @@ export function useFlatToolRegistry(): ToolRegistry {
categoryId: ToolCategoryId.ADVANCED_TOOLS, categoryId: ToolCategoryId.ADVANCED_TOOLS,
subcategoryId: SubcategoryId.ADVANCED_FORMATTING, subcategoryId: SubcategoryId.ADVANCED_FORMATTING,
}, },
"scanner-effect": { fakeScan: {
icon: <LocalIcon icon="scanner-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="scanner-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.fakeScan.title", "Scanner Effect"), name: t("home.fakeScan.title", "Scanner Effect"),
component: null, component: null,
@ -604,7 +604,7 @@ export function useFlatToolRegistry(): ToolRegistry {
// Developer Tools // Developer Tools
"show-javascript": { showJS: {
icon: <LocalIcon icon="javascript-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="javascript-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.showJS.title", "Show JavaScript"), name: t("home.showJS.title", "Show JavaScript"),
component: null, component: null,
@ -612,7 +612,7 @@ export function useFlatToolRegistry(): ToolRegistry {
categoryId: ToolCategoryId.ADVANCED_TOOLS, categoryId: ToolCategoryId.ADVANCED_TOOLS,
subcategoryId: SubcategoryId.DEVELOPER_TOOLS, subcategoryId: SubcategoryId.DEVELOPER_TOOLS,
}, },
"dev-api": { devApi: {
icon: <LocalIcon icon="open-in-new-rounded" width="1.5rem" height="1.5rem" style={{ color: "#2F7BF6" }} />, icon: <LocalIcon icon="open-in-new-rounded" width="1.5rem" height="1.5rem" style={{ color: "#2F7BF6" }} />,
name: t("home.devApi.title", "API"), name: t("home.devApi.title", "API"),
component: null, component: null,
@ -621,7 +621,7 @@ export function useFlatToolRegistry(): ToolRegistry {
subcategoryId: SubcategoryId.DEVELOPER_TOOLS, subcategoryId: SubcategoryId.DEVELOPER_TOOLS,
link: "https://stirlingpdf.io/swagger-ui/5.21.0/index.html", link: "https://stirlingpdf.io/swagger-ui/5.21.0/index.html",
}, },
"dev-folder-scanning": { devFolderScanning: {
icon: <LocalIcon icon="open-in-new-rounded" width="1.5rem" height="1.5rem" style={{ color: "#2F7BF6" }} />, icon: <LocalIcon icon="open-in-new-rounded" width="1.5rem" height="1.5rem" style={{ color: "#2F7BF6" }} />,
name: t("home.devFolderScanning.title", "Automated Folder Scanning"), name: t("home.devFolderScanning.title", "Automated Folder Scanning"),
component: null, component: null,
@ -630,7 +630,7 @@ export function useFlatToolRegistry(): ToolRegistry {
subcategoryId: SubcategoryId.DEVELOPER_TOOLS, subcategoryId: SubcategoryId.DEVELOPER_TOOLS,
link: "https://docs.stirlingpdf.com/Advanced%20Configuration/Folder%20Scanning/", link: "https://docs.stirlingpdf.com/Advanced%20Configuration/Folder%20Scanning/",
}, },
"dev-sso-guide": { devSsoGuide: {
icon: <LocalIcon icon="open-in-new-rounded" width="1.5rem" height="1.5rem" style={{ color: "#2F7BF6" }} />, icon: <LocalIcon icon="open-in-new-rounded" width="1.5rem" height="1.5rem" style={{ color: "#2F7BF6" }} />,
name: t("home.devSsoGuide.title", "SSO Guide"), name: t("home.devSsoGuide.title", "SSO Guide"),
component: null, component: null,
@ -639,7 +639,7 @@ export function useFlatToolRegistry(): ToolRegistry {
subcategoryId: SubcategoryId.DEVELOPER_TOOLS, subcategoryId: SubcategoryId.DEVELOPER_TOOLS,
link: "https://docs.stirlingpdf.com/Advanced%20Configuration/Single%20Sign-On%20Configuration", link: "https://docs.stirlingpdf.com/Advanced%20Configuration/Single%20Sign-On%20Configuration",
}, },
"dev-airgapped": { devAirgapped: {
icon: <LocalIcon icon="open-in-new-rounded" width="1.5rem" height="1.5rem" style={{ color: "#2F7BF6" }} />, icon: <LocalIcon icon="open-in-new-rounded" width="1.5rem" height="1.5rem" style={{ color: "#2F7BF6" }} />,
name: t("home.devAirgapped.title", "Air-gapped Setup"), name: t("home.devAirgapped.title", "Air-gapped Setup"),
component: null, component: null,
@ -698,7 +698,7 @@ export function useFlatToolRegistry(): ToolRegistry {
operationConfig: convertOperationConfig, operationConfig: convertOperationConfig,
settingsComponent: ConvertSettings, settingsComponent: ConvertSettings,
}, },
mergePdfs: { merge: {
icon: <LocalIcon icon="library-add-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="library-add-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.merge.title", "Merge"), name: t("home.merge.title", "Merge"),
component: Merge, component: Merge,
@ -710,7 +710,7 @@ export function useFlatToolRegistry(): ToolRegistry {
operationConfig: mergeOperationConfig, operationConfig: mergeOperationConfig,
settingsComponent: MergeSettings settingsComponent: MergeSettings
}, },
"multi-tool": { multiTool: {
icon: <LocalIcon icon="dashboard-customize-rounded" width="1.5rem" height="1.5rem" />, icon: <LocalIcon icon="dashboard-customize-rounded" width="1.5rem" height="1.5rem" />,
name: t("home.multiTool.title", "Multi-Tool"), name: t("home.multiTool.title", "Multi-Tool"),
component: null, component: null,

View File

@ -14,7 +14,7 @@ export const buildAdjustPageScaleFormData = (parameters: AdjustPageScaleParamete
export const adjustPageScaleOperationConfig = { export const adjustPageScaleOperationConfig = {
toolType: ToolType.singleFile, toolType: ToolType.singleFile,
buildFormData: buildAdjustPageScaleFormData, buildFormData: buildAdjustPageScaleFormData,
operationType: 'adjustPageScale', operationType: 'scalePages',
endpoint: '/api/v1/general/scale-pages', endpoint: '/api/v1/general/scale-pages',
defaultParameters, defaultParameters,
} as const; } as const;

View File

@ -113,7 +113,7 @@ describe('useChangePermissionsOperation', () => {
test.each([ test.each([
{ property: 'toolType' as const, expectedValue: ToolType.singleFile }, { property: 'toolType' as const, expectedValue: ToolType.singleFile },
{ property: 'endpoint' as const, expectedValue: '/api/v1/security/add-password' }, { property: 'endpoint' as const, expectedValue: '/api/v1/security/add-password' },
{ property: 'operationType' as const, expectedValue: 'change-permissions' } { property: 'operationType' as const, expectedValue: 'changePermissions' }
])('should configure $property correctly', ({ property, expectedValue }) => { ])('should configure $property correctly', ({ property, expectedValue }) => {
renderHook(() => useChangePermissionsOperation()); renderHook(() => useChangePermissionsOperation());

View File

@ -26,7 +26,7 @@ export const buildChangePermissionsFormData = (parameters: ChangePermissionsPara
export const changePermissionsOperationConfig = { export const changePermissionsOperationConfig = {
toolType: ToolType.singleFile, toolType: ToolType.singleFile,
buildFormData: buildChangePermissionsFormData, buildFormData: buildChangePermissionsFormData,
operationType: 'change-permissions', operationType: 'changePermissions',
endpoint: '/api/v1/security/add-password', // Change Permissions is a fake endpoint for the Add Password tool endpoint: '/api/v1/security/add-password', // Change Permissions is a fake endpoint for the Add Password tool
defaultParameters, defaultParameters,
} as const; } as const;

View File

@ -17,7 +17,7 @@ export const buildRemoveBlanksFormData = (parameters: RemoveBlanksParameters, fi
export const removeBlanksOperationConfig = { export const removeBlanksOperationConfig = {
toolType: ToolType.singleFile, toolType: ToolType.singleFile,
buildFormData: buildRemoveBlanksFormData, buildFormData: buildRemoveBlanksFormData,
operationType: 'remove-blanks', operationType: 'removeBlanks',
endpoint: '/api/v1/misc/remove-blanks', endpoint: '/api/v1/misc/remove-blanks',
defaultParameters, defaultParameters,
} as const satisfies ToolOperationConfig<RemoveBlanksParameters>; } as const satisfies ToolOperationConfig<RemoveBlanksParameters>;

View File

@ -14,7 +14,7 @@ export const buildRemoveCertificateSignFormData = (_parameters: RemoveCertificat
export const removeCertificateSignOperationConfig = { export const removeCertificateSignOperationConfig = {
toolType: ToolType.singleFile, toolType: ToolType.singleFile,
buildFormData: buildRemoveCertificateSignFormData, buildFormData: buildRemoveCertificateSignFormData,
operationType: 'remove-certificate-sign', operationType: 'removeCertSign',
endpoint: '/api/v1/security/remove-cert-sign', endpoint: '/api/v1/security/remove-cert-sign',
defaultParameters, defaultParameters,
} as const; } as const;

View File

@ -15,7 +15,7 @@ export const buildRemovePagesFormData = (parameters: RemovePagesParameters, file
export const removePagesOperationConfig = { export const removePagesOperationConfig = {
toolType: ToolType.singleFile, toolType: ToolType.singleFile,
buildFormData: buildRemovePagesFormData, buildFormData: buildRemovePagesFormData,
operationType: 'remove-pages', operationType: 'removePages',
endpoint: '/api/v1/general/remove-pages', endpoint: '/api/v1/general/remove-pages',
defaultParameters, defaultParameters,
} as const satisfies ToolOperationConfig<RemovePagesParameters>; } as const satisfies ToolOperationConfig<RemovePagesParameters>;

View File

@ -9,6 +9,8 @@ import { extractErrorMessage } from '../../../utils/toolErrorHandler';
import { StirlingFile, extractFiles, FileId, StirlingFileStub, createStirlingFile, createNewStirlingFileStub } from '../../../types/fileContext'; import { StirlingFile, extractFiles, FileId, StirlingFileStub, createStirlingFile, createNewStirlingFileStub } from '../../../types/fileContext';
import { ResponseHandler } from '../../../utils/toolResponseProcessor'; import { ResponseHandler } from '../../../utils/toolResponseProcessor';
import { createChildStub, generateProcessedFileMetadata } from '../../../contexts/file/fileActions'; import { createChildStub, generateProcessedFileMetadata } from '../../../contexts/file/fileActions';
import { ToolOperation } from '../../../types/file';
import { ToolId } from '../../../types/toolId';
// Re-export for backwards compatibility // Re-export for backwards compatibility
export type { ProcessingProgress, ResponseHandler }; export type { ProcessingProgress, ResponseHandler };
@ -29,7 +31,7 @@ export enum ToolType {
*/ */
interface BaseToolOperationConfig<TParams> { interface BaseToolOperationConfig<TParams> {
/** Operation identifier for tracking and logging */ /** Operation identifier for tracking and logging */
operationType: string; operationType: ToolId;
/** /**
* Prefix added to processed filenames (e.g., 'compressed_', 'split_'). * Prefix added to processed filenames (e.g., 'compressed_', 'split_').
@ -274,8 +276,8 @@ export const useToolOperation = <TParams>(
} }
// Create new tool operation // Create new tool operation
const newToolOperation = { const newToolOperation: ToolOperation = {
toolName: config.operationType, toolId: config.operationType,
timestamp: Date.now() timestamp: Date.now()
}; };

View File

@ -14,7 +14,7 @@ export const buildSingleLargePageFormData = (_parameters: SingleLargePageParamet
export const singleLargePageOperationConfig = { export const singleLargePageOperationConfig = {
toolType: ToolType.singleFile, toolType: ToolType.singleFile,
buildFormData: buildSingleLargePageFormData, buildFormData: buildSingleLargePageFormData,
operationType: 'single-large-page', operationType: 'pdfToSinglePage',
endpoint: '/api/v1/general/pdf-to-single-page', endpoint: '/api/v1/general/pdf-to-single-page',
defaultParameters, defaultParameters,
} as const; } as const;

View File

@ -71,7 +71,7 @@ export const getSplitEndpoint = (parameters: SplitParameters): string => {
export const splitOperationConfig = { export const splitOperationConfig = {
toolType: ToolType.singleFile, toolType: ToolType.singleFile,
buildFormData: buildSplitFormData, buildFormData: buildSplitFormData,
operationType: 'splitPdf', operationType: 'split',
endpoint: getSplitEndpoint, endpoint: getSplitEndpoint,
defaultParameters, defaultParameters,
} as const; } as const;

View File

@ -14,7 +14,7 @@ export const buildUnlockPdfFormsFormData = (_parameters: UnlockPdfFormsParameter
export const unlockPdfFormsOperationConfig = { export const unlockPdfFormsOperationConfig = {
toolType: ToolType.singleFile, toolType: ToolType.singleFile,
buildFormData: buildUnlockPdfFormsFormData, buildFormData: buildUnlockPdfFormsFormData,
operationType: 'unlock-pdf-forms', operationType: 'unlockPDFForms',
endpoint: '/api/v1/misc/unlock-pdf-forms', endpoint: '/api/v1/misc/unlock-pdf-forms',
defaultParameters, defaultParameters,
} as const; } as const;

View File

@ -3,6 +3,8 @@
* FileContext uses pure File objects with separate ID tracking * FileContext uses pure File objects with separate ID tracking
*/ */
import { ToolId } from "./toolId";
declare const tag: unique symbol; declare const tag: unique symbol;
export type FileId = string & { readonly [tag]: 'FileId' }; export type FileId = string & { readonly [tag]: 'FileId' };
@ -11,7 +13,7 @@ export type FileId = string & { readonly [tag]: 'FileId' };
* Note: Parameters removed for security - sensitive data like passwords should not be stored in history * Note: Parameters removed for security - sensitive data like passwords should not be stored in history
*/ */
export interface ToolOperation { export interface ToolOperation {
toolName: string; toolId: ToolId;
timestamp: number; timestamp: number;
} }
@ -32,9 +34,5 @@ export interface BaseFileMetadata {
originalFileId: string; // Root file ID for grouping versions originalFileId: string; // Root file ID for grouping versions
versionNumber: number; // Version number in chain versionNumber: number; // Version number in chain
parentFileId?: FileId; // Immediate parent file ID parentFileId?: FileId; // Immediate parent file ID
toolHistory?: Array<{ toolHistory?: ToolOperation[]; // Tool chain for history tracking
toolName: string;
timestamp: number;
}>; // Tool chain for history tracking
} }

View File

@ -1,19 +1,60 @@
// Define all possible tool IDs as source of truth // Define all possible tool IDs as source of truth
const TOOL_IDS = [ const TOOL_IDS = [
'certSign', 'sign', 'addPassword', 'remove-password', 'removePages', 'remove-blank-pages', 'remove-annotations', 'remove-image', 'certSign',
'change-permissions', 'addWatermark', 'sign',
'sanitize', 'auto-split-pages', 'auto-split-by-size-count', 'split', 'mergePdfs', 'addPassword',
'convert', 'ocr', 'add-image', 'rotate', 'removePassword',
'detect-split-scanned-photos', 'removePages',
'edit-table-of-contents', 'removeBlanks',
'scanner-effect', 'removeAnnotations',
'auto-rename-pdf-file', 'multi-page-layout', 'adjust-page-size-scale', 'adjust-contrast', 'cropPdf', 'single-large-page', 'multi-tool', 'removeImage',
'repair', 'compare', 'addPageNumbers', 'redact', 'changePermissions',
'flatten', 'remove-certificate-sign', 'watermark',
'unlock-pdf-forms', 'compress', 'extract-page', 'reorganize-pages', 'extract-images', 'sanitize',
'add-stamp', 'add-attachments', 'change-metadata', 'overlay-pdfs', 'autoSplitPDF',
'manage-certificates', 'get-all-info-on-pdf', 'validate-pdf-signature', 'read', 'automate', 'replace-and-invert-color', 'autoSizeSplitPDF',
'show-javascript', 'dev-api', 'dev-folder-scanning', 'dev-sso-guide', 'dev-airgapped' 'split',
'merge',
'convert',
'ocr',
'addImage',
'rotate',
'scannerImageSplit',
'editTableOfContents',
'fakeScan',
'autoRename',
'pageLayout',
'scalePages',
'adjustContrast',
'crop',
'pdfToSinglePage',
'multiTool',
'repair',
'compare',
'addPageNumbers',
'redact',
'flatten',
'removeCertSign',
'unlockPDFForms',
'compress',
'extractPages',
'reorganizePages',
'extractImages',
'addStamp',
'attachments',
'changeMetadata',
'overlayPdfs',
'manageCertificates',
'getPdfInfo',
'validateSignature',
'read',
'automate',
'replaceColorPdf',
'showJS',
'devApi',
'devFolderScanning',
'devSsoGuide',
'devAirgapped',
] as const; ] as const;
// Tool identity - what PDF operation we're performing (type-safe) // Tool identity - what PDF operation we're performing (type-safe)

View File

@ -4,7 +4,7 @@ import { ToolId } from '../types/toolId';
export const URL_TO_TOOL_MAP: Record<string, ToolId> = { export const URL_TO_TOOL_MAP: Record<string, ToolId> = {
'/split-pdfs': 'split', '/split-pdfs': 'split',
'/split': 'split', '/split': 'split',
'/merge-pdfs': 'mergePdfs', '/merge-pdfs': 'merge',
'/compress-pdf': 'compress', '/compress-pdf': 'compress',
'/convert': 'convert', '/convert': 'convert',
'/convert-pdf': 'convert', '/convert-pdf': 'convert',
@ -19,16 +19,16 @@ export const URL_TO_TOOL_MAP: Record<string, ToolId> = {
'/pdf-to-word': 'convert', '/pdf-to-word': 'convert',
'/pdf-to-xml': 'convert', '/pdf-to-xml': 'convert',
'/add-password': 'addPassword', '/add-password': 'addPassword',
'/change-permissions': 'change-permissions', '/change-permissions': 'changePermissions',
'/sanitize-pdf': 'sanitize', '/sanitize-pdf': 'sanitize',
'/ocr': 'ocr', '/ocr': 'ocr',
'/ocr-pdf': 'ocr', '/ocr-pdf': 'ocr',
'/add-watermark': 'addWatermark', '/add-watermark': 'watermark',
'/remove-password': 'remove-password', '/remove-password': 'removePassword',
'/single-large-page': 'single-large-page', '/single-large-page': 'pdfToSinglePage',
'/repair': 'repair', '/repair': 'repair',
'/rotate-pdf': 'rotate', '/rotate-pdf': 'rotate',
'/unlock-pdf-forms': 'unlock-pdf-forms', '/unlock-pdf-forms': 'unlockPDFForms',
'/remove-certificate-sign': 'remove-certificate-sign', '/remove-certificate-sign': 'removeCertSign',
'/remove-cert-sign': 'remove-certificate-sign' '/remove-cert-sign': 'removeCertSign',
}; };