From 507ad1dc6197a3887c3ec9c051afc8daaf288050 Mon Sep 17 00:00:00 2001 From: Reece Browne <74901996+reecebrowne@users.noreply.github.com> Date: Fri, 8 Aug 2025 16:01:56 +0100 Subject: [PATCH] Feature/v2/shared tool hooks (#4134) # 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) ### 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. --------- Co-authored-by: Reece Browne --- CLAUDE.md | 80 ++- .../components/tools/split/SplitSettings.tsx | 17 +- .../tools/compress/useCompressOperation.ts | 287 ++--------- .../tools/convert/useConvertOperation.ts | 464 ++++-------------- .../src/hooks/tools/ocr/useOCROperation.ts | 443 ++++------------- .../src/hooks/tools/shared/useToolApiCalls.ts | 86 ++++ .../hooks/tools/shared/useToolOperation.ts | 264 ++++++++++ .../hooks/tools/shared/useToolResources.ts | 114 +++++ .../src/hooks/tools/shared/useToolState.ts | 137 ++++++ .../hooks/tools/split/useSplitOperation.ts | 302 +++--------- .../hooks/tools/split/useSplitParameters.ts | 15 +- .../services/enhancedPDFProcessingService.ts | 5 +- .../tests/convert/ConvertIntegration.test.tsx | 2 +- frontend/src/tools/Split.tsx | 7 +- frontend/src/types/processing.ts | 1 - frontend/src/utils/toolErrorHandler.ts | 33 ++ frontend/src/utils/toolOperationTracker.ts | 28 ++ frontend/src/utils/toolResponseProcessor.ts | 25 + 18 files changed, 1068 insertions(+), 1242 deletions(-) create mode 100644 frontend/src/hooks/tools/shared/useToolApiCalls.ts create mode 100644 frontend/src/hooks/tools/shared/useToolOperation.ts create mode 100644 frontend/src/hooks/tools/shared/useToolResources.ts create mode 100644 frontend/src/hooks/tools/shared/useToolState.ts create mode 100644 frontend/src/utils/toolErrorHandler.ts create mode 100644 frontend/src/utils/toolOperationTracker.ts create mode 100644 frontend/src/utils/toolResponseProcessor.ts diff --git a/CLAUDE.md b/CLAUDE.md index 8bdd7c235..be4e92201 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -59,12 +59,73 @@ Frontend designed for **stateful document processing**: Without cleanup: browser crashes with memory leaks. #### Tool Development -- **Pattern**: Follow `src/tools/Split.tsx` as reference implementation -- **File Access**: Tools receive `selectedFiles` prop (computed from activeFiles based on user selection) -- **File Selection**: Users select files in FileEditor (tool mode) → stored as IDs → computed to File objects for tools -- **Integration**: All files are part of FileContext ecosystem - automatic memory management and operation tracking -- **Parameters**: Tool parameter handling patterns still being standardized -- **Preview Integration**: Tools can implement preview functionality (see Split tool's thumbnail preview) + +**Architecture**: Modular hook-based system with clear separation of concerns: + +- **useToolOperation** (`frontend/src/hooks/tools/shared/useToolOperation.ts`): Main orchestrator hook + - Coordinates all tool operations with consistent interface + - Integrates with FileContext for operation tracking + - Handles validation, error handling, and UI state management + +- **Supporting Hooks**: + - **useToolState**: UI state management (loading, progress, error, files) + - **useToolApiCalls**: HTTP requests and file processing + - **useToolResources**: Blob URLs, thumbnails, ZIP downloads + +- **Utilities**: + - **toolErrorHandler**: Standardized error extraction and i18n support + - **toolResponseProcessor**: API response handling (single/zip/custom) + - **toolOperationTracker**: FileContext integration utilities + +**Three Tool Patterns**: + +**Pattern 1: Single-File Tools** (Individual processing) +- Backend processes one file per API call +- Set `multiFileEndpoint: false` +- Examples: Compress, Rotate +```typescript +return useToolOperation({ + operationType: 'compress', + endpoint: '/api/v1/misc/compress-pdf', + buildFormData: (params, file: File) => { /* single file */ }, + multiFileEndpoint: false, + filePrefix: 'compressed_' +}); +``` + +**Pattern 2: Multi-File Tools** (Batch processing) +- Backend accepts `MultipartFile[]` arrays in single API call +- Set `multiFileEndpoint: true` +- Examples: Split, Merge, Overlay +```typescript +return useToolOperation({ + operationType: 'split', + endpoint: '/api/v1/general/split-pages', + buildFormData: (params, files: File[]) => { /* all files */ }, + multiFileEndpoint: true, + filePrefix: 'split_' +}); +``` + +**Pattern 3: Complex Tools** (Custom processing) +- Tools with complex routing logic or non-standard processing +- Provide `customProcessor` for full control +- Examples: Convert, OCR +```typescript +return useToolOperation({ + operationType: 'convert', + customProcessor: async (params, files) => { /* custom logic */ }, + filePrefix: 'converted_' +}); +``` + +**Benefits**: +- **No Timeouts**: Operations run until completion (supports 100GB+ files) +- **Consistent**: All tools follow same pattern and interface +- **Maintainable**: Single responsibility hooks, easy to test and modify +- **i18n Ready**: Built-in internationalization support +- **Type Safe**: Full TypeScript support with generic interfaces +- **Memory Safe**: Automatic resource cleanup and blob URL management ## Architecture Overview @@ -126,7 +187,10 @@ Without cleanup: browser crashes with memory leaks. - **Core Status**: React SPA architecture complete with multi-tool workflow support - **State Management**: FileContext handles all file operations and tool navigation - **File Processing**: Production-ready with memory management for large PDF workflows (up to 100GB+) -- **Tool Integration**: Standardized tool interface - see `src/tools/Split.tsx` as reference +- **Tool Integration**: Modular hook architecture with `useToolOperation` orchestrator + - Individual hooks: `useToolState`, `useToolApiCalls`, `useToolResources` + - Utilities: `toolErrorHandler`, `toolResponseProcessor`, `toolOperationTracker` + - Pattern: Each tool creates focused operation hook, UI consumes state/actions - **Preview System**: Tool results can be previewed without polluting file context (Split tool example) - **Performance**: Web Worker thumbnails, IndexedDB persistence, background processing @@ -141,7 +205,7 @@ Without cleanup: browser crashes with memory leaks. - **Security**: When `DOCKER_ENABLE_SECURITY=false`, security-related classes are excluded from compilation - **FileContext**: All file operations MUST go through FileContext - never bypass with direct File handling - **Memory Management**: Manual cleanup required for PDF.js documents and blob URLs - don't remove cleanup code -- **Tool Development**: New tools should follow Split tool pattern (`src/tools/Split.tsx`) +- **Tool Development**: New tools should follow `useToolOperation` hook pattern (see `useCompressOperation.ts`) - **Performance Target**: Must handle PDFs up to 100GB+ without browser crashes - **Preview System**: Tools can preview results without polluting main file context (see Split tool implementation) diff --git a/frontend/src/components/tools/split/SplitSettings.tsx b/frontend/src/components/tools/split/SplitSettings.tsx index 50ca49f20..95e972eaf 100644 --- a/frontend/src/components/tools/split/SplitSettings.tsx +++ b/frontend/src/components/tools/split/SplitSettings.tsx @@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next'; import { SPLIT_MODES, SPLIT_TYPES, type SplitMode, type SplitType } from '../../../constants/splitConstants'; export interface SplitParameters { + mode: SplitMode | ''; pages: string; hDiv: string; vDiv: string; @@ -15,16 +16,12 @@ export interface SplitParameters { } export interface SplitSettingsProps { - mode: SplitMode | ''; - onModeChange: (mode: SplitMode | '') => void; parameters: SplitParameters; onParameterChange: (parameter: keyof SplitParameters, value: string | boolean) => void; disabled?: boolean; } const SplitSettings = ({ - mode, - onModeChange, parameters, onParameterChange, disabled = false @@ -125,8 +122,8 @@ const SplitSettings = ({