2025-07-16 17:53:50 +01:00
|
|
|
import React, { useState, useCallback, useRef, useEffect } from 'react';
|
|
|
|
import {
|
|
|
|
Button, Text, Center, Box, Notification, TextInput, LoadingOverlay, Modal, Alert, Container,
|
|
|
|
Stack, Group
|
|
|
|
} from '@mantine/core';
|
|
|
|
import { Dropzone } from '@mantine/dropzone';
|
|
|
|
import { useTranslation } from 'react-i18next';
|
|
|
|
import UploadFileIcon from '@mui/icons-material/UploadFile';
|
2025-08-10 21:08:32 +01:00
|
|
|
import { useFileContext, useToolFileSelection, useProcessedFiles, useFileState, useFileManagement } from '../../contexts/FileContext';
|
|
|
|
import { FileOperation, createStableFileId } from '../../types/fileContext';
|
2025-07-16 17:53:50 +01:00
|
|
|
import { fileStorage } from '../../services/fileStorage';
|
|
|
|
import { generateThumbnailForFile } from '../../utils/thumbnailUtils';
|
|
|
|
import { zipFileService } from '../../services/zipFileService';
|
2025-08-01 16:08:04 +01:00
|
|
|
import { detectFileExtension } from '../../utils/fileUtils';
|
2025-07-16 17:53:50 +01:00
|
|
|
import styles from '../pageEditor/PageEditor.module.css';
|
|
|
|
import FileThumbnail from '../pageEditor/FileThumbnail';
|
|
|
|
import DragDropGrid from '../pageEditor/DragDropGrid';
|
|
|
|
import FilePickerModal from '../shared/FilePickerModal';
|
|
|
|
import SkeletonLoader from '../shared/SkeletonLoader';
|
|
|
|
|
|
|
|
interface FileItem {
|
|
|
|
id: string;
|
|
|
|
name: string;
|
|
|
|
pageCount: number;
|
|
|
|
thumbnail: string;
|
|
|
|
size: number;
|
|
|
|
file: File;
|
|
|
|
splitBefore?: boolean;
|
|
|
|
}
|
|
|
|
|
|
|
|
interface FileEditorProps {
|
|
|
|
onOpenPageEditor?: (file: File) => void;
|
|
|
|
onMergeFiles?: (files: File[]) => void;
|
|
|
|
toolMode?: boolean;
|
|
|
|
showUpload?: boolean;
|
|
|
|
showBulkActions?: boolean;
|
2025-08-01 16:08:04 +01:00
|
|
|
supportedExtensions?: string[];
|
2025-07-16 17:53:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
const FileEditor = ({
|
|
|
|
onOpenPageEditor,
|
|
|
|
onMergeFiles,
|
|
|
|
toolMode = false,
|
|
|
|
showUpload = true,
|
2025-08-01 16:08:04 +01:00
|
|
|
showBulkActions = true,
|
|
|
|
supportedExtensions = ["pdf"]
|
2025-07-16 17:53:50 +01:00
|
|
|
}: FileEditorProps) => {
|
|
|
|
const { t } = useTranslation();
|
|
|
|
|
2025-08-01 16:08:04 +01:00
|
|
|
// Utility function to check if a file extension is supported
|
|
|
|
const isFileSupported = useCallback((fileName: string): boolean => {
|
|
|
|
const extension = detectFileExtension(fileName);
|
|
|
|
return extension ? supportedExtensions.includes(extension) : false;
|
|
|
|
}, [supportedExtensions]);
|
|
|
|
|
2025-08-10 21:08:32 +01:00
|
|
|
// Use optimized FileContext hooks
|
|
|
|
const { state } = useFileState();
|
|
|
|
const { addFiles, removeFiles } = useFileManagement();
|
|
|
|
const processedFiles = useProcessedFiles(); // Now gets real processed files
|
|
|
|
|
|
|
|
// Extract needed values from state
|
|
|
|
const activeFiles = state.files.ids.map(id => state.files.byId[id]?.file).filter(Boolean);
|
|
|
|
const selectedFileIds = state.ui.selectedFileIds;
|
|
|
|
const isProcessing = state.ui.isProcessing;
|
|
|
|
|
|
|
|
// Legacy compatibility for existing code
|
|
|
|
const setContextSelectedFiles = (fileIds: string[]) => {
|
|
|
|
// This function is used for FileEditor's own selection, not tool selection
|
|
|
|
console.log('FileEditor setContextSelectedFiles called with:', fileIds);
|
|
|
|
};
|
|
|
|
|
|
|
|
const setCurrentView = (mode: any) => {
|
|
|
|
// Will be handled by parent component actions
|
|
|
|
console.log('FileEditor setCurrentView called with:', mode);
|
|
|
|
};
|
|
|
|
|
2025-08-11 16:40:38 +01:00
|
|
|
// Get file selection context
|
|
|
|
const {
|
|
|
|
selectedFiles: toolSelectedFiles,
|
|
|
|
setSelectedFiles: setToolSelectedFiles,
|
|
|
|
maxFiles,
|
|
|
|
isToolMode
|
|
|
|
} = useFileSelection();
|
2025-08-10 21:08:32 +01:00
|
|
|
// Get tool file selection context (replaces FileSelectionContext)
|
Feature/v2/multiselect (#4024)
# Description of Changes
This pull request introduces significant updates to the file selection
logic, tool rendering, and file context management in the frontend
codebase. The changes aim to improve modularity, enhance
maintainability, and streamline the handling of file-related operations.
Key updates include the introduction of a new `FileSelectionContext`,
refactoring of file selection logic, and updates to tool management and
rendering.
### File Selection Context and Logic Refactor:
* Added a new `FileSelectionContext` to centralize file selection state
and provide utility hooks for managing selected files, selection limits,
and tool mode. (`frontend/src/contexts/FileSelectionContext.tsx`,
[frontend/src/contexts/FileSelectionContext.tsxR1-R77](diffhunk://#diff-bda35f1aaa5eafa0a0dc48e0b1270d862f6da360ba1241234e891f0ca8907327R1-R77))
* Replaced local file selection logic in `FileEditor` with context-based
logic, improving consistency and reducing duplication.
(`frontend/src/components/fileEditor/FileEditor.tsx`,
[[1]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R63-R70)
[[2]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R404-R438)
### Tool Management and Rendering:
* Refactored `ToolRenderer` to use a `Suspense` fallback for lazy-loaded
tools, improving user experience during tool loading.
(`frontend/src/components/tools/ToolRenderer.tsx`,
[frontend/src/components/tools/ToolRenderer.tsxL32-L64](diffhunk://#diff-2083701113aa92cd1f5ce1b4b52cc233858e31ed7bcf39c5bfb1bcc34e99b6a9L32-L64))
* Simplified `ToolPicker` by reusing the `ToolRegistry` type, reducing
redundancy. (`frontend/src/components/tools/ToolPicker.tsx`,
[frontend/src/components/tools/ToolPicker.tsxL4-R4](diffhunk://#diff-e47deca9132018344c159925f1264794acdd57f4b65e582eb9b2a4ea69ec126dL4-R4))
### File Context Enhancements:
* Introduced a utility function `getFileId` for consistent file ID
extraction, replacing repetitive inline logic.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcR25)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL101-R102)
* Updated `FileContextProvider` to use more specific types for PDF
documents, enhancing type safety.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL350-R351)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL384-R385)
### Compression Tool Enhancements:
* Added blob URL cleanup logic to the compression hook to prevent memory
leaks. (`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsR58-L66](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673R58-L66))
* Adjusted file ID generation in the compression operation to handle
multiple files more effectively.
(`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsL90-R102](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673L90-R102))
---
## 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.
2025-07-25 09:37:52 +01:00
|
|
|
const {
|
|
|
|
selectedFiles: toolSelectedFiles,
|
|
|
|
setSelectedFiles: setToolSelectedFiles,
|
|
|
|
maxFiles,
|
|
|
|
isToolMode
|
2025-08-10 21:08:32 +01:00
|
|
|
} = useToolFileSelection();
|
Feature/v2/multiselect (#4024)
# Description of Changes
This pull request introduces significant updates to the file selection
logic, tool rendering, and file context management in the frontend
codebase. The changes aim to improve modularity, enhance
maintainability, and streamline the handling of file-related operations.
Key updates include the introduction of a new `FileSelectionContext`,
refactoring of file selection logic, and updates to tool management and
rendering.
### File Selection Context and Logic Refactor:
* Added a new `FileSelectionContext` to centralize file selection state
and provide utility hooks for managing selected files, selection limits,
and tool mode. (`frontend/src/contexts/FileSelectionContext.tsx`,
[frontend/src/contexts/FileSelectionContext.tsxR1-R77](diffhunk://#diff-bda35f1aaa5eafa0a0dc48e0b1270d862f6da360ba1241234e891f0ca8907327R1-R77))
* Replaced local file selection logic in `FileEditor` with context-based
logic, improving consistency and reducing duplication.
(`frontend/src/components/fileEditor/FileEditor.tsx`,
[[1]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R63-R70)
[[2]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R404-R438)
### Tool Management and Rendering:
* Refactored `ToolRenderer` to use a `Suspense` fallback for lazy-loaded
tools, improving user experience during tool loading.
(`frontend/src/components/tools/ToolRenderer.tsx`,
[frontend/src/components/tools/ToolRenderer.tsxL32-L64](diffhunk://#diff-2083701113aa92cd1f5ce1b4b52cc233858e31ed7bcf39c5bfb1bcc34e99b6a9L32-L64))
* Simplified `ToolPicker` by reusing the `ToolRegistry` type, reducing
redundancy. (`frontend/src/components/tools/ToolPicker.tsx`,
[frontend/src/components/tools/ToolPicker.tsxL4-R4](diffhunk://#diff-e47deca9132018344c159925f1264794acdd57f4b65e582eb9b2a4ea69ec126dL4-R4))
### File Context Enhancements:
* Introduced a utility function `getFileId` for consistent file ID
extraction, replacing repetitive inline logic.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcR25)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL101-R102)
* Updated `FileContextProvider` to use more specific types for PDF
documents, enhancing type safety.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL350-R351)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL384-R385)
### Compression Tool Enhancements:
* Added blob URL cleanup logic to the compression hook to prevent memory
leaks. (`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsR58-L66](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673R58-L66))
* Adjusted file ID generation in the compression operation to handle
multiple files more effectively.
(`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsL90-R102](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673L90-R102))
---
## 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.
2025-07-25 09:37:52 +01:00
|
|
|
|
2025-07-16 17:53:50 +01:00
|
|
|
const [files, setFiles] = useState<FileItem[]>([]);
|
|
|
|
const [status, setStatus] = useState<string | null>(null);
|
|
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
const [localLoading, setLocalLoading] = useState(false);
|
|
|
|
const [selectionMode, setSelectionMode] = useState(toolMode);
|
2025-08-11 16:40:38 +01:00
|
|
|
|
2025-07-16 17:53:50 +01:00
|
|
|
// Enable selection mode automatically in tool mode
|
|
|
|
React.useEffect(() => {
|
|
|
|
if (toolMode) {
|
|
|
|
setSelectionMode(true);
|
|
|
|
}
|
|
|
|
}, [toolMode]);
|
|
|
|
const [draggedFile, setDraggedFile] = useState<string | null>(null);
|
|
|
|
const [dropTarget, setDropTarget] = useState<string | null>(null);
|
|
|
|
const [multiFileDrag, setMultiFileDrag] = useState<{fileIds: string[], count: number} | null>(null);
|
|
|
|
const [dragPosition, setDragPosition] = useState<{x: number, y: number} | null>(null);
|
|
|
|
const [isAnimating, setIsAnimating] = useState(false);
|
|
|
|
const [showFilePickerModal, setShowFilePickerModal] = useState(false);
|
|
|
|
const [conversionProgress, setConversionProgress] = useState(0);
|
|
|
|
const [zipExtractionProgress, setZipExtractionProgress] = useState<{
|
|
|
|
isExtracting: boolean;
|
|
|
|
currentFile: string;
|
|
|
|
progress: number;
|
|
|
|
extractedCount: number;
|
|
|
|
totalFiles: number;
|
|
|
|
}>({
|
|
|
|
isExtracting: false,
|
|
|
|
currentFile: '',
|
|
|
|
progress: 0,
|
|
|
|
extractedCount: 0,
|
|
|
|
totalFiles: 0
|
|
|
|
});
|
|
|
|
const fileRefs = useRef<Map<string, HTMLDivElement>>(new Map());
|
|
|
|
const lastActiveFilesRef = useRef<string[]>([]);
|
|
|
|
const lastProcessedFilesRef = useRef<number>(0);
|
|
|
|
|
Feature/v2/multiselect (#4024)
# Description of Changes
This pull request introduces significant updates to the file selection
logic, tool rendering, and file context management in the frontend
codebase. The changes aim to improve modularity, enhance
maintainability, and streamline the handling of file-related operations.
Key updates include the introduction of a new `FileSelectionContext`,
refactoring of file selection logic, and updates to tool management and
rendering.
### File Selection Context and Logic Refactor:
* Added a new `FileSelectionContext` to centralize file selection state
and provide utility hooks for managing selected files, selection limits,
and tool mode. (`frontend/src/contexts/FileSelectionContext.tsx`,
[frontend/src/contexts/FileSelectionContext.tsxR1-R77](diffhunk://#diff-bda35f1aaa5eafa0a0dc48e0b1270d862f6da360ba1241234e891f0ca8907327R1-R77))
* Replaced local file selection logic in `FileEditor` with context-based
logic, improving consistency and reducing duplication.
(`frontend/src/components/fileEditor/FileEditor.tsx`,
[[1]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R63-R70)
[[2]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R404-R438)
### Tool Management and Rendering:
* Refactored `ToolRenderer` to use a `Suspense` fallback for lazy-loaded
tools, improving user experience during tool loading.
(`frontend/src/components/tools/ToolRenderer.tsx`,
[frontend/src/components/tools/ToolRenderer.tsxL32-L64](diffhunk://#diff-2083701113aa92cd1f5ce1b4b52cc233858e31ed7bcf39c5bfb1bcc34e99b6a9L32-L64))
* Simplified `ToolPicker` by reusing the `ToolRegistry` type, reducing
redundancy. (`frontend/src/components/tools/ToolPicker.tsx`,
[frontend/src/components/tools/ToolPicker.tsxL4-R4](diffhunk://#diff-e47deca9132018344c159925f1264794acdd57f4b65e582eb9b2a4ea69ec126dL4-R4))
### File Context Enhancements:
* Introduced a utility function `getFileId` for consistent file ID
extraction, replacing repetitive inline logic.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcR25)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL101-R102)
* Updated `FileContextProvider` to use more specific types for PDF
documents, enhancing type safety.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL350-R351)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL384-R385)
### Compression Tool Enhancements:
* Added blob URL cleanup logic to the compression hook to prevent memory
leaks. (`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsR58-L66](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673R58-L66))
* Adjusted file ID generation in the compression operation to handle
multiple files more effectively.
(`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsL90-R102](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673L90-R102))
---
## 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.
2025-07-25 09:37:52 +01:00
|
|
|
// Get selected file IDs from context (defensive programming)
|
|
|
|
const contextSelectedIds = Array.isArray(selectedFileIds) ? selectedFileIds : [];
|
2025-08-11 16:40:38 +01:00
|
|
|
|
Feature/v2/multiselect (#4024)
# Description of Changes
This pull request introduces significant updates to the file selection
logic, tool rendering, and file context management in the frontend
codebase. The changes aim to improve modularity, enhance
maintainability, and streamline the handling of file-related operations.
Key updates include the introduction of a new `FileSelectionContext`,
refactoring of file selection logic, and updates to tool management and
rendering.
### File Selection Context and Logic Refactor:
* Added a new `FileSelectionContext` to centralize file selection state
and provide utility hooks for managing selected files, selection limits,
and tool mode. (`frontend/src/contexts/FileSelectionContext.tsx`,
[frontend/src/contexts/FileSelectionContext.tsxR1-R77](diffhunk://#diff-bda35f1aaa5eafa0a0dc48e0b1270d862f6da360ba1241234e891f0ca8907327R1-R77))
* Replaced local file selection logic in `FileEditor` with context-based
logic, improving consistency and reducing duplication.
(`frontend/src/components/fileEditor/FileEditor.tsx`,
[[1]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R63-R70)
[[2]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R404-R438)
### Tool Management and Rendering:
* Refactored `ToolRenderer` to use a `Suspense` fallback for lazy-loaded
tools, improving user experience during tool loading.
(`frontend/src/components/tools/ToolRenderer.tsx`,
[frontend/src/components/tools/ToolRenderer.tsxL32-L64](diffhunk://#diff-2083701113aa92cd1f5ce1b4b52cc233858e31ed7bcf39c5bfb1bcc34e99b6a9L32-L64))
* Simplified `ToolPicker` by reusing the `ToolRegistry` type, reducing
redundancy. (`frontend/src/components/tools/ToolPicker.tsx`,
[frontend/src/components/tools/ToolPicker.tsxL4-R4](diffhunk://#diff-e47deca9132018344c159925f1264794acdd57f4b65e582eb9b2a4ea69ec126dL4-R4))
### File Context Enhancements:
* Introduced a utility function `getFileId` for consistent file ID
extraction, replacing repetitive inline logic.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcR25)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL101-R102)
* Updated `FileContextProvider` to use more specific types for PDF
documents, enhancing type safety.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL350-R351)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL384-R385)
### Compression Tool Enhancements:
* Added blob URL cleanup logic to the compression hook to prevent memory
leaks. (`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsR58-L66](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673R58-L66))
* Adjusted file ID generation in the compression operation to handle
multiple files more effectively.
(`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsL90-R102](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673L90-R102))
---
## 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.
2025-07-25 09:37:52 +01:00
|
|
|
// Map context selections to local file IDs for UI display
|
|
|
|
const localSelectedIds = files
|
2025-07-16 17:53:50 +01:00
|
|
|
.filter(file => {
|
2025-08-10 21:08:32 +01:00
|
|
|
const contextFileId = createStableFileId(file.file);
|
|
|
|
return contextSelectedIds.includes(contextFileId);
|
2025-07-16 17:53:50 +01:00
|
|
|
})
|
|
|
|
.map(file => file.id);
|
|
|
|
|
|
|
|
// Convert shared files to FileEditor format
|
|
|
|
const convertToFileItem = useCallback(async (sharedFile: any): Promise<FileItem> => {
|
|
|
|
// Generate thumbnail if not already available
|
|
|
|
const thumbnail = sharedFile.thumbnail || await generateThumbnailForFile(sharedFile.file || sharedFile);
|
|
|
|
|
|
|
|
return {
|
|
|
|
id: sharedFile.id || `file-${Date.now()}-${Math.random()}`,
|
|
|
|
name: (sharedFile.file?.name || sharedFile.name || 'unknown'),
|
2025-08-10 21:08:32 +01:00
|
|
|
pageCount: sharedFile.pageCount || 1, // Default to 1 page if unknown
|
2025-07-16 17:53:50 +01:00
|
|
|
thumbnail,
|
|
|
|
size: sharedFile.file?.size || sharedFile.size || 0,
|
|
|
|
file: sharedFile.file || sharedFile,
|
|
|
|
};
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
// Convert activeFiles to FileItem format using context (async to avoid blocking)
|
|
|
|
useEffect(() => {
|
|
|
|
// Check if the actual content has changed, not just references
|
|
|
|
const currentActiveFileNames = activeFiles.map(f => f.name);
|
|
|
|
const currentProcessedFilesSize = processedFiles.size;
|
2025-08-11 16:40:38 +01:00
|
|
|
|
2025-07-16 17:53:50 +01:00
|
|
|
const activeFilesChanged = JSON.stringify(currentActiveFileNames) !== JSON.stringify(lastActiveFilesRef.current);
|
|
|
|
const processedFilesChanged = currentProcessedFilesSize !== lastProcessedFilesRef.current;
|
2025-08-11 16:40:38 +01:00
|
|
|
|
2025-07-16 17:53:50 +01:00
|
|
|
if (!activeFilesChanged && !processedFilesChanged) {
|
|
|
|
return;
|
|
|
|
}
|
2025-08-11 16:40:38 +01:00
|
|
|
|
2025-07-16 17:53:50 +01:00
|
|
|
// Update refs
|
|
|
|
lastActiveFilesRef.current = currentActiveFileNames;
|
|
|
|
lastProcessedFilesRef.current = currentProcessedFilesSize;
|
2025-08-11 16:40:38 +01:00
|
|
|
|
2025-07-16 17:53:50 +01:00
|
|
|
const convertActiveFiles = async () => {
|
2025-08-11 16:40:38 +01:00
|
|
|
|
2025-07-16 17:53:50 +01:00
|
|
|
if (activeFiles.length > 0) {
|
|
|
|
setLocalLoading(true);
|
|
|
|
try {
|
|
|
|
// Process files in chunks to avoid blocking UI
|
|
|
|
const convertedFiles: FileItem[] = [];
|
2025-08-11 16:40:38 +01:00
|
|
|
|
2025-07-16 17:53:50 +01:00
|
|
|
for (let i = 0; i < activeFiles.length; i++) {
|
|
|
|
const file = activeFiles[i];
|
2025-08-11 16:40:38 +01:00
|
|
|
|
2025-07-16 17:53:50 +01:00
|
|
|
// Try to get thumbnail from processed file first
|
|
|
|
const processedFile = processedFiles.get(file);
|
|
|
|
let thumbnail = processedFile?.pages?.[0]?.thumbnail;
|
2025-08-11 16:40:38 +01:00
|
|
|
|
2025-07-16 17:53:50 +01:00
|
|
|
// If no thumbnail from processed file, try to generate one
|
|
|
|
if (!thumbnail) {
|
|
|
|
try {
|
|
|
|
thumbnail = await generateThumbnailForFile(file);
|
|
|
|
} catch (error) {
|
|
|
|
console.warn(`Failed to generate thumbnail for ${file.name}:`, error);
|
|
|
|
thumbnail = undefined; // Use placeholder
|
|
|
|
}
|
|
|
|
}
|
2025-08-11 16:40:38 +01:00
|
|
|
|
2025-07-16 17:53:50 +01:00
|
|
|
|
2025-08-10 21:08:32 +01:00
|
|
|
// Get actual page count from processed file
|
|
|
|
let pageCount = 1; // Default for non-PDFs
|
|
|
|
if (processedFile) {
|
|
|
|
pageCount = processedFile.pages?.length || processedFile.totalPages || 1;
|
|
|
|
} else if (file.type === 'application/pdf') {
|
|
|
|
// For PDFs without processed data, try to get a quick page count estimate
|
|
|
|
// If processing is taking too long, show a reasonable default
|
|
|
|
try {
|
|
|
|
// Quick and dirty page count using PDF structure analysis
|
|
|
|
const arrayBuffer = await file.arrayBuffer();
|
|
|
|
const text = new TextDecoder('latin1').decode(arrayBuffer);
|
|
|
|
const pageMatches = text.match(/\/Type\s*\/Page[^s]/g);
|
|
|
|
pageCount = pageMatches ? pageMatches.length : 1;
|
|
|
|
console.log(`📄 Quick page count for ${file.name}: ${pageCount} pages (estimated)`);
|
|
|
|
} catch (error) {
|
|
|
|
console.warn(`Failed to estimate page count for ${file.name}:`, error);
|
|
|
|
pageCount = 1; // Safe fallback
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-07-16 17:53:50 +01:00
|
|
|
const convertedFile = {
|
2025-08-10 21:08:32 +01:00
|
|
|
id: createStableFileId(file), // Use same ID function as context
|
2025-07-16 17:53:50 +01:00
|
|
|
name: file.name,
|
2025-08-11 16:40:38 +01:00
|
|
|
pageCount: processedFile?.totalPages || Math.floor(Math.random() * 20) + 1,
|
|
|
|
thumbnail: thumbnail || '',
|
2025-08-10 21:08:32 +01:00
|
|
|
pageCount: pageCount,
|
2025-07-16 17:53:50 +01:00
|
|
|
thumbnail,
|
|
|
|
size: file.size,
|
|
|
|
file,
|
|
|
|
};
|
2025-08-11 16:40:38 +01:00
|
|
|
|
2025-07-16 17:53:50 +01:00
|
|
|
convertedFiles.push(convertedFile);
|
2025-08-11 16:40:38 +01:00
|
|
|
|
2025-07-16 17:53:50 +01:00
|
|
|
// Update progress
|
|
|
|
setConversionProgress(((i + 1) / activeFiles.length) * 100);
|
2025-08-11 16:40:38 +01:00
|
|
|
|
2025-07-16 17:53:50 +01:00
|
|
|
// Yield to main thread between files
|
|
|
|
if (i < activeFiles.length - 1) {
|
|
|
|
await new Promise(resolve => requestAnimationFrame(resolve));
|
|
|
|
}
|
|
|
|
}
|
2025-08-11 16:40:38 +01:00
|
|
|
|
|
|
|
|
2025-07-16 17:53:50 +01:00
|
|
|
setFiles(convertedFiles);
|
|
|
|
} catch (err) {
|
|
|
|
console.error('Error converting active files:', err);
|
|
|
|
} finally {
|
|
|
|
setLocalLoading(false);
|
|
|
|
setConversionProgress(0);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
setFiles([]);
|
|
|
|
setLocalLoading(false);
|
|
|
|
setConversionProgress(0);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
convertActiveFiles();
|
|
|
|
}, [activeFiles, processedFiles]);
|
|
|
|
|
|
|
|
|
|
|
|
// Process uploaded files using context
|
|
|
|
const handleFileUpload = useCallback(async (uploadedFiles: File[]) => {
|
|
|
|
setError(null);
|
|
|
|
|
|
|
|
try {
|
|
|
|
const allExtractedFiles: File[] = [];
|
|
|
|
const errors: string[] = [];
|
|
|
|
|
|
|
|
for (const file of uploadedFiles) {
|
|
|
|
if (file.type === 'application/pdf') {
|
|
|
|
// Handle PDF files normally
|
|
|
|
allExtractedFiles.push(file);
|
|
|
|
} else if (file.type === 'application/zip' || file.type === 'application/x-zip-compressed' || file.name.toLowerCase().endsWith('.zip')) {
|
2025-08-01 16:08:04 +01:00
|
|
|
// Handle ZIP files - only expand if they contain PDFs
|
2025-07-16 17:53:50 +01:00
|
|
|
try {
|
|
|
|
// Validate ZIP file first
|
|
|
|
const validation = await zipFileService.validateZipFile(file);
|
2025-08-11 16:40:38 +01:00
|
|
|
|
2025-08-01 16:08:04 +01:00
|
|
|
if (validation.isValid && validation.containsPDFs) {
|
|
|
|
// ZIP contains PDFs - extract them
|
2025-07-16 17:53:50 +01:00
|
|
|
setZipExtractionProgress({
|
|
|
|
isExtracting: true,
|
2025-08-01 16:08:04 +01:00
|
|
|
currentFile: file.name,
|
|
|
|
progress: 0,
|
|
|
|
extractedCount: 0,
|
|
|
|
totalFiles: validation.fileCount
|
2025-07-16 17:53:50 +01:00
|
|
|
});
|
|
|
|
|
2025-08-01 16:08:04 +01:00
|
|
|
const extractionResult = await zipFileService.extractPdfFiles(file, (progress) => {
|
|
|
|
setZipExtractionProgress({
|
|
|
|
isExtracting: true,
|
|
|
|
currentFile: progress.currentFile,
|
|
|
|
progress: progress.progress,
|
|
|
|
extractedCount: progress.extractedCount,
|
|
|
|
totalFiles: progress.totalFiles
|
|
|
|
});
|
|
|
|
});
|
2025-07-16 17:53:50 +01:00
|
|
|
|
2025-08-01 16:08:04 +01:00
|
|
|
// Reset extraction progress
|
|
|
|
setZipExtractionProgress({
|
|
|
|
isExtracting: false,
|
|
|
|
currentFile: '',
|
|
|
|
progress: 0,
|
|
|
|
extractedCount: 0,
|
|
|
|
totalFiles: 0
|
|
|
|
});
|
|
|
|
|
|
|
|
if (extractionResult.success) {
|
|
|
|
allExtractedFiles.push(...extractionResult.extractedFiles);
|
2025-08-11 16:40:38 +01:00
|
|
|
|
2025-08-01 16:08:04 +01:00
|
|
|
// Record ZIP extraction operation
|
|
|
|
const operationId = `zip-extract-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
|
|
const operation: FileOperation = {
|
2025-07-16 17:53:50 +01:00
|
|
|
id: operationId,
|
|
|
|
type: 'convert',
|
|
|
|
timestamp: Date.now(),
|
|
|
|
fileIds: extractionResult.extractedFiles.map(f => f.name),
|
|
|
|
status: 'pending',
|
|
|
|
metadata: {
|
|
|
|
originalFileName: file.name,
|
|
|
|
outputFileNames: extractionResult.extractedFiles.map(f => f.name),
|
|
|
|
fileSize: file.size,
|
|
|
|
parameters: {
|
|
|
|
extractionType: 'zip',
|
|
|
|
extractedCount: extractionResult.extractedCount,
|
|
|
|
totalFiles: extractionResult.totalFiles
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2025-08-11 16:40:38 +01:00
|
|
|
|
|
|
|
recordOperation(file.name, operation);
|
|
|
|
markOperationApplied(file.name, operationId);
|
|
|
|
|
2025-07-16 17:53:50 +01:00
|
|
|
|
2025-08-10 21:08:32 +01:00
|
|
|
// Legacy operation tracking removed
|
2025-07-16 17:53:50 +01:00
|
|
|
|
|
|
|
if (extractionResult.errors.length > 0) {
|
|
|
|
errors.push(...extractionResult.errors);
|
|
|
|
}
|
2025-08-01 16:08:04 +01:00
|
|
|
} else {
|
|
|
|
errors.push(`Failed to extract ZIP file "${file.name}": ${extractionResult.errors.join(', ')}`);
|
|
|
|
}
|
2025-07-16 17:53:50 +01:00
|
|
|
} else {
|
2025-08-01 16:08:04 +01:00
|
|
|
// ZIP doesn't contain PDFs or is invalid - treat as regular file
|
|
|
|
console.log(`Adding ZIP file as regular file: ${file.name} (no PDFs found)`);
|
|
|
|
allExtractedFiles.push(file);
|
2025-07-16 17:53:50 +01:00
|
|
|
}
|
|
|
|
} catch (zipError) {
|
|
|
|
errors.push(`Failed to process ZIP file "${file.name}": ${zipError instanceof Error ? zipError.message : 'Unknown error'}`);
|
|
|
|
setZipExtractionProgress({
|
|
|
|
isExtracting: false,
|
|
|
|
currentFile: '',
|
|
|
|
progress: 0,
|
|
|
|
extractedCount: 0,
|
|
|
|
totalFiles: 0
|
|
|
|
});
|
|
|
|
}
|
|
|
|
} else {
|
2025-08-01 16:08:04 +01:00
|
|
|
console.log(`Adding none PDF file: ${file.name} (${file.type})`);
|
|
|
|
allExtractedFiles.push(file);
|
2025-07-16 17:53:50 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show any errors
|
|
|
|
if (errors.length > 0) {
|
|
|
|
setError(errors.join('\n'));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Process all extracted files
|
|
|
|
if (allExtractedFiles.length > 0) {
|
|
|
|
// Record upload operations for PDF files
|
|
|
|
for (const file of allExtractedFiles) {
|
|
|
|
const operationId = `upload-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
|
|
const operation: FileOperation = {
|
|
|
|
id: operationId,
|
|
|
|
type: 'upload',
|
|
|
|
timestamp: Date.now(),
|
|
|
|
fileIds: [file.name],
|
|
|
|
status: 'pending',
|
|
|
|
metadata: {
|
|
|
|
originalFileName: file.name,
|
|
|
|
fileSize: file.size,
|
|
|
|
parameters: {
|
|
|
|
uploadMethod: 'drag-drop'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2025-08-11 16:40:38 +01:00
|
|
|
|
|
|
|
recordOperation(file.name, operation);
|
|
|
|
markOperationApplied(file.name, operationId);
|
2025-07-16 17:53:50 +01:00
|
|
|
|
2025-08-10 21:08:32 +01:00
|
|
|
// Legacy operation tracking removed
|
2025-07-16 17:53:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Add files to context (they will be processed automatically)
|
|
|
|
await addFiles(allExtractedFiles);
|
|
|
|
setStatus(`Added ${allExtractedFiles.length} files`);
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
const errorMessage = err instanceof Error ? err.message : 'Failed to process files';
|
|
|
|
setError(errorMessage);
|
|
|
|
console.error('File processing error:', err);
|
2025-08-11 16:40:38 +01:00
|
|
|
|
2025-07-16 17:53:50 +01:00
|
|
|
// Reset extraction progress on error
|
|
|
|
setZipExtractionProgress({
|
|
|
|
isExtracting: false,
|
|
|
|
currentFile: '',
|
|
|
|
progress: 0,
|
|
|
|
extractedCount: 0,
|
|
|
|
totalFiles: 0
|
|
|
|
});
|
|
|
|
}
|
2025-08-10 21:08:32 +01:00
|
|
|
}, [addFiles]);
|
2025-07-16 17:53:50 +01:00
|
|
|
|
|
|
|
const selectAll = useCallback(() => {
|
|
|
|
setContextSelectedFiles(files.map(f => (f.file as any).id || f.name));
|
|
|
|
}, [files, setContextSelectedFiles]);
|
|
|
|
|
|
|
|
const deselectAll = useCallback(() => setContextSelectedFiles([]), [setContextSelectedFiles]);
|
|
|
|
|
|
|
|
const closeAllFiles = useCallback(() => {
|
|
|
|
if (activeFiles.length === 0) return;
|
2025-08-11 16:40:38 +01:00
|
|
|
|
2025-07-16 17:53:50 +01:00
|
|
|
// Record close all operation for each file
|
|
|
|
activeFiles.forEach(file => {
|
|
|
|
const operationId = `close-all-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
|
|
const operation: FileOperation = {
|
|
|
|
id: operationId,
|
|
|
|
type: 'remove',
|
|
|
|
timestamp: Date.now(),
|
|
|
|
fileIds: [file.name],
|
|
|
|
status: 'pending',
|
|
|
|
metadata: {
|
|
|
|
originalFileName: file.name,
|
|
|
|
fileSize: file.size,
|
|
|
|
parameters: {
|
|
|
|
action: 'close_all',
|
|
|
|
reason: 'user_request'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2025-08-11 16:40:38 +01:00
|
|
|
|
|
|
|
recordOperation(file.name, operation);
|
|
|
|
markOperationApplied(file.name, operationId);
|
2025-07-16 17:53:50 +01:00
|
|
|
|
2025-08-10 21:08:32 +01:00
|
|
|
// Legacy operation tracking removed
|
2025-07-16 17:53:50 +01:00
|
|
|
});
|
2025-08-11 16:40:38 +01:00
|
|
|
|
2025-07-16 17:53:50 +01:00
|
|
|
// Remove all files from context but keep in storage
|
|
|
|
removeFiles(activeFiles.map(f => (f as any).id || f.name), false);
|
2025-08-11 16:40:38 +01:00
|
|
|
|
2025-07-16 17:53:50 +01:00
|
|
|
// Clear selections
|
|
|
|
setContextSelectedFiles([]);
|
2025-08-10 21:08:32 +01:00
|
|
|
}, [activeFiles, removeFiles, setContextSelectedFiles]);
|
2025-07-16 17:53:50 +01:00
|
|
|
|
|
|
|
const toggleFile = useCallback((fileId: string) => {
|
|
|
|
const targetFile = files.find(f => f.id === fileId);
|
|
|
|
if (!targetFile) return;
|
2025-08-11 16:40:38 +01:00
|
|
|
|
|
|
|
const contextFileId = (targetFile.file as any).id || targetFile.name;
|
2025-07-16 17:53:50 +01:00
|
|
|
|
2025-08-10 21:08:32 +01:00
|
|
|
const contextFileId = createStableFileId(targetFile.file);
|
Feature/v2/multiselect (#4024)
# Description of Changes
This pull request introduces significant updates to the file selection
logic, tool rendering, and file context management in the frontend
codebase. The changes aim to improve modularity, enhance
maintainability, and streamline the handling of file-related operations.
Key updates include the introduction of a new `FileSelectionContext`,
refactoring of file selection logic, and updates to tool management and
rendering.
### File Selection Context and Logic Refactor:
* Added a new `FileSelectionContext` to centralize file selection state
and provide utility hooks for managing selected files, selection limits,
and tool mode. (`frontend/src/contexts/FileSelectionContext.tsx`,
[frontend/src/contexts/FileSelectionContext.tsxR1-R77](diffhunk://#diff-bda35f1aaa5eafa0a0dc48e0b1270d862f6da360ba1241234e891f0ca8907327R1-R77))
* Replaced local file selection logic in `FileEditor` with context-based
logic, improving consistency and reducing duplication.
(`frontend/src/components/fileEditor/FileEditor.tsx`,
[[1]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R63-R70)
[[2]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R404-R438)
### Tool Management and Rendering:
* Refactored `ToolRenderer` to use a `Suspense` fallback for lazy-loaded
tools, improving user experience during tool loading.
(`frontend/src/components/tools/ToolRenderer.tsx`,
[frontend/src/components/tools/ToolRenderer.tsxL32-L64](diffhunk://#diff-2083701113aa92cd1f5ce1b4b52cc233858e31ed7bcf39c5bfb1bcc34e99b6a9L32-L64))
* Simplified `ToolPicker` by reusing the `ToolRegistry` type, reducing
redundancy. (`frontend/src/components/tools/ToolPicker.tsx`,
[frontend/src/components/tools/ToolPicker.tsxL4-R4](diffhunk://#diff-e47deca9132018344c159925f1264794acdd57f4b65e582eb9b2a4ea69ec126dL4-R4))
### File Context Enhancements:
* Introduced a utility function `getFileId` for consistent file ID
extraction, replacing repetitive inline logic.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcR25)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL101-R102)
* Updated `FileContextProvider` to use more specific types for PDF
documents, enhancing type safety.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL350-R351)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL384-R385)
### Compression Tool Enhancements:
* Added blob URL cleanup logic to the compression hook to prevent memory
leaks. (`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsR58-L66](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673R58-L66))
* Adjusted file ID generation in the compression operation to handle
multiple files more effectively.
(`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsL90-R102](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673L90-R102))
---
## 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.
2025-07-25 09:37:52 +01:00
|
|
|
const isSelected = contextSelectedIds.includes(contextFileId);
|
2025-08-11 16:40:38 +01:00
|
|
|
|
Feature/v2/multiselect (#4024)
# Description of Changes
This pull request introduces significant updates to the file selection
logic, tool rendering, and file context management in the frontend
codebase. The changes aim to improve modularity, enhance
maintainability, and streamline the handling of file-related operations.
Key updates include the introduction of a new `FileSelectionContext`,
refactoring of file selection logic, and updates to tool management and
rendering.
### File Selection Context and Logic Refactor:
* Added a new `FileSelectionContext` to centralize file selection state
and provide utility hooks for managing selected files, selection limits,
and tool mode. (`frontend/src/contexts/FileSelectionContext.tsx`,
[frontend/src/contexts/FileSelectionContext.tsxR1-R77](diffhunk://#diff-bda35f1aaa5eafa0a0dc48e0b1270d862f6da360ba1241234e891f0ca8907327R1-R77))
* Replaced local file selection logic in `FileEditor` with context-based
logic, improving consistency and reducing duplication.
(`frontend/src/components/fileEditor/FileEditor.tsx`,
[[1]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R63-R70)
[[2]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R404-R438)
### Tool Management and Rendering:
* Refactored `ToolRenderer` to use a `Suspense` fallback for lazy-loaded
tools, improving user experience during tool loading.
(`frontend/src/components/tools/ToolRenderer.tsx`,
[frontend/src/components/tools/ToolRenderer.tsxL32-L64](diffhunk://#diff-2083701113aa92cd1f5ce1b4b52cc233858e31ed7bcf39c5bfb1bcc34e99b6a9L32-L64))
* Simplified `ToolPicker` by reusing the `ToolRegistry` type, reducing
redundancy. (`frontend/src/components/tools/ToolPicker.tsx`,
[frontend/src/components/tools/ToolPicker.tsxL4-R4](diffhunk://#diff-e47deca9132018344c159925f1264794acdd57f4b65e582eb9b2a4ea69ec126dL4-R4))
### File Context Enhancements:
* Introduced a utility function `getFileId` for consistent file ID
extraction, replacing repetitive inline logic.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcR25)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL101-R102)
* Updated `FileContextProvider` to use more specific types for PDF
documents, enhancing type safety.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL350-R351)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL384-R385)
### Compression Tool Enhancements:
* Added blob URL cleanup logic to the compression hook to prevent memory
leaks. (`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsR58-L66](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673R58-L66))
* Adjusted file ID generation in the compression operation to handle
multiple files more effectively.
(`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsL90-R102](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673L90-R102))
---
## 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.
2025-07-25 09:37:52 +01:00
|
|
|
let newSelection: string[];
|
2025-08-11 16:40:38 +01:00
|
|
|
|
Feature/v2/multiselect (#4024)
# Description of Changes
This pull request introduces significant updates to the file selection
logic, tool rendering, and file context management in the frontend
codebase. The changes aim to improve modularity, enhance
maintainability, and streamline the handling of file-related operations.
Key updates include the introduction of a new `FileSelectionContext`,
refactoring of file selection logic, and updates to tool management and
rendering.
### File Selection Context and Logic Refactor:
* Added a new `FileSelectionContext` to centralize file selection state
and provide utility hooks for managing selected files, selection limits,
and tool mode. (`frontend/src/contexts/FileSelectionContext.tsx`,
[frontend/src/contexts/FileSelectionContext.tsxR1-R77](diffhunk://#diff-bda35f1aaa5eafa0a0dc48e0b1270d862f6da360ba1241234e891f0ca8907327R1-R77))
* Replaced local file selection logic in `FileEditor` with context-based
logic, improving consistency and reducing duplication.
(`frontend/src/components/fileEditor/FileEditor.tsx`,
[[1]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R63-R70)
[[2]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R404-R438)
### Tool Management and Rendering:
* Refactored `ToolRenderer` to use a `Suspense` fallback for lazy-loaded
tools, improving user experience during tool loading.
(`frontend/src/components/tools/ToolRenderer.tsx`,
[frontend/src/components/tools/ToolRenderer.tsxL32-L64](diffhunk://#diff-2083701113aa92cd1f5ce1b4b52cc233858e31ed7bcf39c5bfb1bcc34e99b6a9L32-L64))
* Simplified `ToolPicker` by reusing the `ToolRegistry` type, reducing
redundancy. (`frontend/src/components/tools/ToolPicker.tsx`,
[frontend/src/components/tools/ToolPicker.tsxL4-R4](diffhunk://#diff-e47deca9132018344c159925f1264794acdd57f4b65e582eb9b2a4ea69ec126dL4-R4))
### File Context Enhancements:
* Introduced a utility function `getFileId` for consistent file ID
extraction, replacing repetitive inline logic.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcR25)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL101-R102)
* Updated `FileContextProvider` to use more specific types for PDF
documents, enhancing type safety.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL350-R351)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL384-R385)
### Compression Tool Enhancements:
* Added blob URL cleanup logic to the compression hook to prevent memory
leaks. (`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsR58-L66](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673R58-L66))
* Adjusted file ID generation in the compression operation to handle
multiple files more effectively.
(`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsL90-R102](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673L90-R102))
---
## 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.
2025-07-25 09:37:52 +01:00
|
|
|
if (isSelected) {
|
|
|
|
// Remove file from selection
|
|
|
|
newSelection = contextSelectedIds.filter(id => id !== contextFileId);
|
|
|
|
} else {
|
|
|
|
// Add file to selection
|
|
|
|
if (maxFiles === 1) {
|
|
|
|
newSelection = [contextFileId];
|
2025-07-16 17:53:50 +01:00
|
|
|
} else {
|
Feature/v2/multiselect (#4024)
# Description of Changes
This pull request introduces significant updates to the file selection
logic, tool rendering, and file context management in the frontend
codebase. The changes aim to improve modularity, enhance
maintainability, and streamline the handling of file-related operations.
Key updates include the introduction of a new `FileSelectionContext`,
refactoring of file selection logic, and updates to tool management and
rendering.
### File Selection Context and Logic Refactor:
* Added a new `FileSelectionContext` to centralize file selection state
and provide utility hooks for managing selected files, selection limits,
and tool mode. (`frontend/src/contexts/FileSelectionContext.tsx`,
[frontend/src/contexts/FileSelectionContext.tsxR1-R77](diffhunk://#diff-bda35f1aaa5eafa0a0dc48e0b1270d862f6da360ba1241234e891f0ca8907327R1-R77))
* Replaced local file selection logic in `FileEditor` with context-based
logic, improving consistency and reducing duplication.
(`frontend/src/components/fileEditor/FileEditor.tsx`,
[[1]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R63-R70)
[[2]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R404-R438)
### Tool Management and Rendering:
* Refactored `ToolRenderer` to use a `Suspense` fallback for lazy-loaded
tools, improving user experience during tool loading.
(`frontend/src/components/tools/ToolRenderer.tsx`,
[frontend/src/components/tools/ToolRenderer.tsxL32-L64](diffhunk://#diff-2083701113aa92cd1f5ce1b4b52cc233858e31ed7bcf39c5bfb1bcc34e99b6a9L32-L64))
* Simplified `ToolPicker` by reusing the `ToolRegistry` type, reducing
redundancy. (`frontend/src/components/tools/ToolPicker.tsx`,
[frontend/src/components/tools/ToolPicker.tsxL4-R4](diffhunk://#diff-e47deca9132018344c159925f1264794acdd57f4b65e582eb9b2a4ea69ec126dL4-R4))
### File Context Enhancements:
* Introduced a utility function `getFileId` for consistent file ID
extraction, replacing repetitive inline logic.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcR25)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL101-R102)
* Updated `FileContextProvider` to use more specific types for PDF
documents, enhancing type safety.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL350-R351)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL384-R385)
### Compression Tool Enhancements:
* Added blob URL cleanup logic to the compression hook to prevent memory
leaks. (`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsR58-L66](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673R58-L66))
* Adjusted file ID generation in the compression operation to handle
multiple files more effectively.
(`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsL90-R102](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673L90-R102))
---
## 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.
2025-07-25 09:37:52 +01:00
|
|
|
// Check if we've hit the selection limit
|
|
|
|
if (maxFiles > 1 && contextSelectedIds.length >= maxFiles) {
|
|
|
|
setStatus(`Maximum ${maxFiles} files can be selected`);
|
|
|
|
return;
|
2025-07-16 17:53:50 +01:00
|
|
|
}
|
Feature/v2/multiselect (#4024)
# Description of Changes
This pull request introduces significant updates to the file selection
logic, tool rendering, and file context management in the frontend
codebase. The changes aim to improve modularity, enhance
maintainability, and streamline the handling of file-related operations.
Key updates include the introduction of a new `FileSelectionContext`,
refactoring of file selection logic, and updates to tool management and
rendering.
### File Selection Context and Logic Refactor:
* Added a new `FileSelectionContext` to centralize file selection state
and provide utility hooks for managing selected files, selection limits,
and tool mode. (`frontend/src/contexts/FileSelectionContext.tsx`,
[frontend/src/contexts/FileSelectionContext.tsxR1-R77](diffhunk://#diff-bda35f1aaa5eafa0a0dc48e0b1270d862f6da360ba1241234e891f0ca8907327R1-R77))
* Replaced local file selection logic in `FileEditor` with context-based
logic, improving consistency and reducing duplication.
(`frontend/src/components/fileEditor/FileEditor.tsx`,
[[1]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R63-R70)
[[2]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R404-R438)
### Tool Management and Rendering:
* Refactored `ToolRenderer` to use a `Suspense` fallback for lazy-loaded
tools, improving user experience during tool loading.
(`frontend/src/components/tools/ToolRenderer.tsx`,
[frontend/src/components/tools/ToolRenderer.tsxL32-L64](diffhunk://#diff-2083701113aa92cd1f5ce1b4b52cc233858e31ed7bcf39c5bfb1bcc34e99b6a9L32-L64))
* Simplified `ToolPicker` by reusing the `ToolRegistry` type, reducing
redundancy. (`frontend/src/components/tools/ToolPicker.tsx`,
[frontend/src/components/tools/ToolPicker.tsxL4-R4](diffhunk://#diff-e47deca9132018344c159925f1264794acdd57f4b65e582eb9b2a4ea69ec126dL4-R4))
### File Context Enhancements:
* Introduced a utility function `getFileId` for consistent file ID
extraction, replacing repetitive inline logic.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcR25)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL101-R102)
* Updated `FileContextProvider` to use more specific types for PDF
documents, enhancing type safety.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL350-R351)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL384-R385)
### Compression Tool Enhancements:
* Added blob URL cleanup logic to the compression hook to prevent memory
leaks. (`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsR58-L66](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673R58-L66))
* Adjusted file ID generation in the compression operation to handle
multiple files more effectively.
(`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsL90-R102](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673L90-R102))
---
## 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.
2025-07-25 09:37:52 +01:00
|
|
|
newSelection = [...contextSelectedIds, contextFileId];
|
2025-07-16 17:53:50 +01:00
|
|
|
}
|
|
|
|
}
|
2025-08-11 16:40:38 +01:00
|
|
|
|
Feature/v2/multiselect (#4024)
# Description of Changes
This pull request introduces significant updates to the file selection
logic, tool rendering, and file context management in the frontend
codebase. The changes aim to improve modularity, enhance
maintainability, and streamline the handling of file-related operations.
Key updates include the introduction of a new `FileSelectionContext`,
refactoring of file selection logic, and updates to tool management and
rendering.
### File Selection Context and Logic Refactor:
* Added a new `FileSelectionContext` to centralize file selection state
and provide utility hooks for managing selected files, selection limits,
and tool mode. (`frontend/src/contexts/FileSelectionContext.tsx`,
[frontend/src/contexts/FileSelectionContext.tsxR1-R77](diffhunk://#diff-bda35f1aaa5eafa0a0dc48e0b1270d862f6da360ba1241234e891f0ca8907327R1-R77))
* Replaced local file selection logic in `FileEditor` with context-based
logic, improving consistency and reducing duplication.
(`frontend/src/components/fileEditor/FileEditor.tsx`,
[[1]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R63-R70)
[[2]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R404-R438)
### Tool Management and Rendering:
* Refactored `ToolRenderer` to use a `Suspense` fallback for lazy-loaded
tools, improving user experience during tool loading.
(`frontend/src/components/tools/ToolRenderer.tsx`,
[frontend/src/components/tools/ToolRenderer.tsxL32-L64](diffhunk://#diff-2083701113aa92cd1f5ce1b4b52cc233858e31ed7bcf39c5bfb1bcc34e99b6a9L32-L64))
* Simplified `ToolPicker` by reusing the `ToolRegistry` type, reducing
redundancy. (`frontend/src/components/tools/ToolPicker.tsx`,
[frontend/src/components/tools/ToolPicker.tsxL4-R4](diffhunk://#diff-e47deca9132018344c159925f1264794acdd57f4b65e582eb9b2a4ea69ec126dL4-R4))
### File Context Enhancements:
* Introduced a utility function `getFileId` for consistent file ID
extraction, replacing repetitive inline logic.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcR25)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL101-R102)
* Updated `FileContextProvider` to use more specific types for PDF
documents, enhancing type safety.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL350-R351)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL384-R385)
### Compression Tool Enhancements:
* Added blob URL cleanup logic to the compression hook to prevent memory
leaks. (`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsR58-L66](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673R58-L66))
* Adjusted file ID generation in the compression operation to handle
multiple files more effectively.
(`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsL90-R102](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673L90-R102))
---
## 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.
2025-07-25 09:37:52 +01:00
|
|
|
// Update context
|
|
|
|
setContextSelectedFiles(newSelection);
|
2025-08-11 16:40:38 +01:00
|
|
|
|
Feature/v2/multiselect (#4024)
# Description of Changes
This pull request introduces significant updates to the file selection
logic, tool rendering, and file context management in the frontend
codebase. The changes aim to improve modularity, enhance
maintainability, and streamline the handling of file-related operations.
Key updates include the introduction of a new `FileSelectionContext`,
refactoring of file selection logic, and updates to tool management and
rendering.
### File Selection Context and Logic Refactor:
* Added a new `FileSelectionContext` to centralize file selection state
and provide utility hooks for managing selected files, selection limits,
and tool mode. (`frontend/src/contexts/FileSelectionContext.tsx`,
[frontend/src/contexts/FileSelectionContext.tsxR1-R77](diffhunk://#diff-bda35f1aaa5eafa0a0dc48e0b1270d862f6da360ba1241234e891f0ca8907327R1-R77))
* Replaced local file selection logic in `FileEditor` with context-based
logic, improving consistency and reducing duplication.
(`frontend/src/components/fileEditor/FileEditor.tsx`,
[[1]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R63-R70)
[[2]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R404-R438)
### Tool Management and Rendering:
* Refactored `ToolRenderer` to use a `Suspense` fallback for lazy-loaded
tools, improving user experience during tool loading.
(`frontend/src/components/tools/ToolRenderer.tsx`,
[frontend/src/components/tools/ToolRenderer.tsxL32-L64](diffhunk://#diff-2083701113aa92cd1f5ce1b4b52cc233858e31ed7bcf39c5bfb1bcc34e99b6a9L32-L64))
* Simplified `ToolPicker` by reusing the `ToolRegistry` type, reducing
redundancy. (`frontend/src/components/tools/ToolPicker.tsx`,
[frontend/src/components/tools/ToolPicker.tsxL4-R4](diffhunk://#diff-e47deca9132018344c159925f1264794acdd57f4b65e582eb9b2a4ea69ec126dL4-R4))
### File Context Enhancements:
* Introduced a utility function `getFileId` for consistent file ID
extraction, replacing repetitive inline logic.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcR25)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL101-R102)
* Updated `FileContextProvider` to use more specific types for PDF
documents, enhancing type safety.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL350-R351)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL384-R385)
### Compression Tool Enhancements:
* Added blob URL cleanup logic to the compression hook to prevent memory
leaks. (`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsR58-L66](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673R58-L66))
* Adjusted file ID generation in the compression operation to handle
multiple files more effectively.
(`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsL90-R102](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673L90-R102))
---
## 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.
2025-07-25 09:37:52 +01:00
|
|
|
// Update tool selection context if in tool mode
|
|
|
|
if (isToolMode || toolMode) {
|
|
|
|
const selectedFiles = files
|
|
|
|
.filter(f => {
|
2025-08-10 21:08:32 +01:00
|
|
|
const fId = createStableFileId(f.file);
|
Feature/v2/multiselect (#4024)
# Description of Changes
This pull request introduces significant updates to the file selection
logic, tool rendering, and file context management in the frontend
codebase. The changes aim to improve modularity, enhance
maintainability, and streamline the handling of file-related operations.
Key updates include the introduction of a new `FileSelectionContext`,
refactoring of file selection logic, and updates to tool management and
rendering.
### File Selection Context and Logic Refactor:
* Added a new `FileSelectionContext` to centralize file selection state
and provide utility hooks for managing selected files, selection limits,
and tool mode. (`frontend/src/contexts/FileSelectionContext.tsx`,
[frontend/src/contexts/FileSelectionContext.tsxR1-R77](diffhunk://#diff-bda35f1aaa5eafa0a0dc48e0b1270d862f6da360ba1241234e891f0ca8907327R1-R77))
* Replaced local file selection logic in `FileEditor` with context-based
logic, improving consistency and reducing duplication.
(`frontend/src/components/fileEditor/FileEditor.tsx`,
[[1]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R63-R70)
[[2]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R404-R438)
### Tool Management and Rendering:
* Refactored `ToolRenderer` to use a `Suspense` fallback for lazy-loaded
tools, improving user experience during tool loading.
(`frontend/src/components/tools/ToolRenderer.tsx`,
[frontend/src/components/tools/ToolRenderer.tsxL32-L64](diffhunk://#diff-2083701113aa92cd1f5ce1b4b52cc233858e31ed7bcf39c5bfb1bcc34e99b6a9L32-L64))
* Simplified `ToolPicker` by reusing the `ToolRegistry` type, reducing
redundancy. (`frontend/src/components/tools/ToolPicker.tsx`,
[frontend/src/components/tools/ToolPicker.tsxL4-R4](diffhunk://#diff-e47deca9132018344c159925f1264794acdd57f4b65e582eb9b2a4ea69ec126dL4-R4))
### File Context Enhancements:
* Introduced a utility function `getFileId` for consistent file ID
extraction, replacing repetitive inline logic.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcR25)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL101-R102)
* Updated `FileContextProvider` to use more specific types for PDF
documents, enhancing type safety.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL350-R351)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL384-R385)
### Compression Tool Enhancements:
* Added blob URL cleanup logic to the compression hook to prevent memory
leaks. (`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsR58-L66](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673R58-L66))
* Adjusted file ID generation in the compression operation to handle
multiple files more effectively.
(`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsL90-R102](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673L90-R102))
---
## 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.
2025-07-25 09:37:52 +01:00
|
|
|
return newSelection.includes(fId);
|
|
|
|
})
|
|
|
|
.map(f => f.file);
|
|
|
|
setToolSelectedFiles(selectedFiles);
|
|
|
|
}
|
|
|
|
}, [files, setContextSelectedFiles, maxFiles, contextSelectedIds, setStatus, isToolMode, toolMode, setToolSelectedFiles]);
|
2025-07-16 17:53:50 +01:00
|
|
|
|
|
|
|
const toggleSelectionMode = useCallback(() => {
|
|
|
|
setSelectionMode(prev => {
|
|
|
|
const newMode = !prev;
|
|
|
|
if (!newMode) {
|
|
|
|
setContextSelectedFiles([]);
|
|
|
|
}
|
|
|
|
return newMode;
|
|
|
|
});
|
|
|
|
}, [setContextSelectedFiles]);
|
|
|
|
|
|
|
|
|
|
|
|
// Drag and drop handlers
|
|
|
|
const handleDragStart = useCallback((fileId: string) => {
|
|
|
|
setDraggedFile(fileId);
|
|
|
|
|
Feature/v2/multiselect (#4024)
# Description of Changes
This pull request introduces significant updates to the file selection
logic, tool rendering, and file context management in the frontend
codebase. The changes aim to improve modularity, enhance
maintainability, and streamline the handling of file-related operations.
Key updates include the introduction of a new `FileSelectionContext`,
refactoring of file selection logic, and updates to tool management and
rendering.
### File Selection Context and Logic Refactor:
* Added a new `FileSelectionContext` to centralize file selection state
and provide utility hooks for managing selected files, selection limits,
and tool mode. (`frontend/src/contexts/FileSelectionContext.tsx`,
[frontend/src/contexts/FileSelectionContext.tsxR1-R77](diffhunk://#diff-bda35f1aaa5eafa0a0dc48e0b1270d862f6da360ba1241234e891f0ca8907327R1-R77))
* Replaced local file selection logic in `FileEditor` with context-based
logic, improving consistency and reducing duplication.
(`frontend/src/components/fileEditor/FileEditor.tsx`,
[[1]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R63-R70)
[[2]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R404-R438)
### Tool Management and Rendering:
* Refactored `ToolRenderer` to use a `Suspense` fallback for lazy-loaded
tools, improving user experience during tool loading.
(`frontend/src/components/tools/ToolRenderer.tsx`,
[frontend/src/components/tools/ToolRenderer.tsxL32-L64](diffhunk://#diff-2083701113aa92cd1f5ce1b4b52cc233858e31ed7bcf39c5bfb1bcc34e99b6a9L32-L64))
* Simplified `ToolPicker` by reusing the `ToolRegistry` type, reducing
redundancy. (`frontend/src/components/tools/ToolPicker.tsx`,
[frontend/src/components/tools/ToolPicker.tsxL4-R4](diffhunk://#diff-e47deca9132018344c159925f1264794acdd57f4b65e582eb9b2a4ea69ec126dL4-R4))
### File Context Enhancements:
* Introduced a utility function `getFileId` for consistent file ID
extraction, replacing repetitive inline logic.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcR25)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL101-R102)
* Updated `FileContextProvider` to use more specific types for PDF
documents, enhancing type safety.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL350-R351)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL384-R385)
### Compression Tool Enhancements:
* Added blob URL cleanup logic to the compression hook to prevent memory
leaks. (`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsR58-L66](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673R58-L66))
* Adjusted file ID generation in the compression operation to handle
multiple files more effectively.
(`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsL90-R102](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673L90-R102))
---
## 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.
2025-07-25 09:37:52 +01:00
|
|
|
if (selectionMode && localSelectedIds.includes(fileId) && localSelectedIds.length > 1) {
|
2025-07-16 17:53:50 +01:00
|
|
|
setMultiFileDrag({
|
Feature/v2/multiselect (#4024)
# Description of Changes
This pull request introduces significant updates to the file selection
logic, tool rendering, and file context management in the frontend
codebase. The changes aim to improve modularity, enhance
maintainability, and streamline the handling of file-related operations.
Key updates include the introduction of a new `FileSelectionContext`,
refactoring of file selection logic, and updates to tool management and
rendering.
### File Selection Context and Logic Refactor:
* Added a new `FileSelectionContext` to centralize file selection state
and provide utility hooks for managing selected files, selection limits,
and tool mode. (`frontend/src/contexts/FileSelectionContext.tsx`,
[frontend/src/contexts/FileSelectionContext.tsxR1-R77](diffhunk://#diff-bda35f1aaa5eafa0a0dc48e0b1270d862f6da360ba1241234e891f0ca8907327R1-R77))
* Replaced local file selection logic in `FileEditor` with context-based
logic, improving consistency and reducing duplication.
(`frontend/src/components/fileEditor/FileEditor.tsx`,
[[1]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R63-R70)
[[2]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R404-R438)
### Tool Management and Rendering:
* Refactored `ToolRenderer` to use a `Suspense` fallback for lazy-loaded
tools, improving user experience during tool loading.
(`frontend/src/components/tools/ToolRenderer.tsx`,
[frontend/src/components/tools/ToolRenderer.tsxL32-L64](diffhunk://#diff-2083701113aa92cd1f5ce1b4b52cc233858e31ed7bcf39c5bfb1bcc34e99b6a9L32-L64))
* Simplified `ToolPicker` by reusing the `ToolRegistry` type, reducing
redundancy. (`frontend/src/components/tools/ToolPicker.tsx`,
[frontend/src/components/tools/ToolPicker.tsxL4-R4](diffhunk://#diff-e47deca9132018344c159925f1264794acdd57f4b65e582eb9b2a4ea69ec126dL4-R4))
### File Context Enhancements:
* Introduced a utility function `getFileId` for consistent file ID
extraction, replacing repetitive inline logic.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcR25)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL101-R102)
* Updated `FileContextProvider` to use more specific types for PDF
documents, enhancing type safety.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL350-R351)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL384-R385)
### Compression Tool Enhancements:
* Added blob URL cleanup logic to the compression hook to prevent memory
leaks. (`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsR58-L66](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673R58-L66))
* Adjusted file ID generation in the compression operation to handle
multiple files more effectively.
(`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsL90-R102](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673L90-R102))
---
## 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.
2025-07-25 09:37:52 +01:00
|
|
|
fileIds: localSelectedIds,
|
|
|
|
count: localSelectedIds.length
|
2025-07-16 17:53:50 +01:00
|
|
|
});
|
|
|
|
} else {
|
|
|
|
setMultiFileDrag(null);
|
|
|
|
}
|
Feature/v2/multiselect (#4024)
# Description of Changes
This pull request introduces significant updates to the file selection
logic, tool rendering, and file context management in the frontend
codebase. The changes aim to improve modularity, enhance
maintainability, and streamline the handling of file-related operations.
Key updates include the introduction of a new `FileSelectionContext`,
refactoring of file selection logic, and updates to tool management and
rendering.
### File Selection Context and Logic Refactor:
* Added a new `FileSelectionContext` to centralize file selection state
and provide utility hooks for managing selected files, selection limits,
and tool mode. (`frontend/src/contexts/FileSelectionContext.tsx`,
[frontend/src/contexts/FileSelectionContext.tsxR1-R77](diffhunk://#diff-bda35f1aaa5eafa0a0dc48e0b1270d862f6da360ba1241234e891f0ca8907327R1-R77))
* Replaced local file selection logic in `FileEditor` with context-based
logic, improving consistency and reducing duplication.
(`frontend/src/components/fileEditor/FileEditor.tsx`,
[[1]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R63-R70)
[[2]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R404-R438)
### Tool Management and Rendering:
* Refactored `ToolRenderer` to use a `Suspense` fallback for lazy-loaded
tools, improving user experience during tool loading.
(`frontend/src/components/tools/ToolRenderer.tsx`,
[frontend/src/components/tools/ToolRenderer.tsxL32-L64](diffhunk://#diff-2083701113aa92cd1f5ce1b4b52cc233858e31ed7bcf39c5bfb1bcc34e99b6a9L32-L64))
* Simplified `ToolPicker` by reusing the `ToolRegistry` type, reducing
redundancy. (`frontend/src/components/tools/ToolPicker.tsx`,
[frontend/src/components/tools/ToolPicker.tsxL4-R4](diffhunk://#diff-e47deca9132018344c159925f1264794acdd57f4b65e582eb9b2a4ea69ec126dL4-R4))
### File Context Enhancements:
* Introduced a utility function `getFileId` for consistent file ID
extraction, replacing repetitive inline logic.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcR25)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL101-R102)
* Updated `FileContextProvider` to use more specific types for PDF
documents, enhancing type safety.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL350-R351)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL384-R385)
### Compression Tool Enhancements:
* Added blob URL cleanup logic to the compression hook to prevent memory
leaks. (`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsR58-L66](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673R58-L66))
* Adjusted file ID generation in the compression operation to handle
multiple files more effectively.
(`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsL90-R102](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673L90-R102))
---
## 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.
2025-07-25 09:37:52 +01:00
|
|
|
}, [selectionMode, localSelectedIds]);
|
2025-07-16 17:53:50 +01:00
|
|
|
|
|
|
|
const handleDragEnd = useCallback(() => {
|
|
|
|
setDraggedFile(null);
|
|
|
|
setDropTarget(null);
|
|
|
|
setMultiFileDrag(null);
|
|
|
|
setDragPosition(null);
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
const handleDragOver = useCallback((e: React.DragEvent) => {
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
|
|
if (!draggedFile) return;
|
|
|
|
|
|
|
|
if (multiFileDrag) {
|
|
|
|
setDragPosition({ x: e.clientX, y: e.clientY });
|
|
|
|
}
|
|
|
|
|
|
|
|
const elementUnderCursor = document.elementFromPoint(e.clientX, e.clientY);
|
|
|
|
if (!elementUnderCursor) return;
|
|
|
|
|
|
|
|
const fileContainer = elementUnderCursor.closest('[data-file-id]');
|
|
|
|
if (fileContainer) {
|
|
|
|
const fileId = fileContainer.getAttribute('data-file-id');
|
|
|
|
if (fileId && fileId !== draggedFile) {
|
|
|
|
setDropTarget(fileId);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const endZone = elementUnderCursor.closest('[data-drop-zone="end"]');
|
|
|
|
if (endZone) {
|
|
|
|
setDropTarget('end');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
setDropTarget(null);
|
|
|
|
}, [draggedFile, multiFileDrag]);
|
|
|
|
|
|
|
|
const handleDragEnter = useCallback((fileId: string) => {
|
|
|
|
if (draggedFile && fileId !== draggedFile) {
|
|
|
|
setDropTarget(fileId);
|
|
|
|
}
|
|
|
|
}, [draggedFile]);
|
|
|
|
|
|
|
|
const handleDragLeave = useCallback(() => {
|
|
|
|
// Let dragover handle this
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
const handleDrop = useCallback((e: React.DragEvent, targetFileId: string | 'end') => {
|
|
|
|
e.preventDefault();
|
|
|
|
if (!draggedFile || draggedFile === targetFileId) return;
|
|
|
|
|
|
|
|
let targetIndex: number;
|
|
|
|
if (targetFileId === 'end') {
|
|
|
|
targetIndex = files.length;
|
|
|
|
} else {
|
|
|
|
targetIndex = files.findIndex(f => f.id === targetFileId);
|
|
|
|
if (targetIndex === -1) return;
|
|
|
|
}
|
|
|
|
|
Feature/v2/multiselect (#4024)
# Description of Changes
This pull request introduces significant updates to the file selection
logic, tool rendering, and file context management in the frontend
codebase. The changes aim to improve modularity, enhance
maintainability, and streamline the handling of file-related operations.
Key updates include the introduction of a new `FileSelectionContext`,
refactoring of file selection logic, and updates to tool management and
rendering.
### File Selection Context and Logic Refactor:
* Added a new `FileSelectionContext` to centralize file selection state
and provide utility hooks for managing selected files, selection limits,
and tool mode. (`frontend/src/contexts/FileSelectionContext.tsx`,
[frontend/src/contexts/FileSelectionContext.tsxR1-R77](diffhunk://#diff-bda35f1aaa5eafa0a0dc48e0b1270d862f6da360ba1241234e891f0ca8907327R1-R77))
* Replaced local file selection logic in `FileEditor` with context-based
logic, improving consistency and reducing duplication.
(`frontend/src/components/fileEditor/FileEditor.tsx`,
[[1]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R63-R70)
[[2]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R404-R438)
### Tool Management and Rendering:
* Refactored `ToolRenderer` to use a `Suspense` fallback for lazy-loaded
tools, improving user experience during tool loading.
(`frontend/src/components/tools/ToolRenderer.tsx`,
[frontend/src/components/tools/ToolRenderer.tsxL32-L64](diffhunk://#diff-2083701113aa92cd1f5ce1b4b52cc233858e31ed7bcf39c5bfb1bcc34e99b6a9L32-L64))
* Simplified `ToolPicker` by reusing the `ToolRegistry` type, reducing
redundancy. (`frontend/src/components/tools/ToolPicker.tsx`,
[frontend/src/components/tools/ToolPicker.tsxL4-R4](diffhunk://#diff-e47deca9132018344c159925f1264794acdd57f4b65e582eb9b2a4ea69ec126dL4-R4))
### File Context Enhancements:
* Introduced a utility function `getFileId` for consistent file ID
extraction, replacing repetitive inline logic.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcR25)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL101-R102)
* Updated `FileContextProvider` to use more specific types for PDF
documents, enhancing type safety.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL350-R351)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL384-R385)
### Compression Tool Enhancements:
* Added blob URL cleanup logic to the compression hook to prevent memory
leaks. (`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsR58-L66](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673R58-L66))
* Adjusted file ID generation in the compression operation to handle
multiple files more effectively.
(`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsL90-R102](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673L90-R102))
---
## 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.
2025-07-25 09:37:52 +01:00
|
|
|
const filesToMove = selectionMode && localSelectedIds.includes(draggedFile)
|
|
|
|
? localSelectedIds
|
2025-07-16 17:53:50 +01:00
|
|
|
: [draggedFile];
|
|
|
|
|
|
|
|
// Update the local files state and sync with activeFiles
|
|
|
|
setFiles(prev => {
|
|
|
|
const newFiles = [...prev];
|
|
|
|
const movedFiles = filesToMove.map(id => newFiles.find(f => f.id === id)!).filter(Boolean);
|
|
|
|
|
|
|
|
// Remove moved files
|
|
|
|
filesToMove.forEach(id => {
|
|
|
|
const index = newFiles.findIndex(f => f.id === id);
|
|
|
|
if (index !== -1) newFiles.splice(index, 1);
|
|
|
|
});
|
|
|
|
|
|
|
|
// Insert at target position
|
|
|
|
newFiles.splice(targetIndex, 0, ...movedFiles);
|
|
|
|
|
|
|
|
// TODO: Update context with reordered files (need to implement file reordering in context)
|
|
|
|
// For now, just return the reordered local state
|
|
|
|
return newFiles;
|
|
|
|
});
|
|
|
|
|
|
|
|
const moveCount = multiFileDrag ? multiFileDrag.count : 1;
|
|
|
|
setStatus(`${moveCount > 1 ? `${moveCount} files` : 'File'} reordered`);
|
|
|
|
|
Feature/v2/multiselect (#4024)
# Description of Changes
This pull request introduces significant updates to the file selection
logic, tool rendering, and file context management in the frontend
codebase. The changes aim to improve modularity, enhance
maintainability, and streamline the handling of file-related operations.
Key updates include the introduction of a new `FileSelectionContext`,
refactoring of file selection logic, and updates to tool management and
rendering.
### File Selection Context and Logic Refactor:
* Added a new `FileSelectionContext` to centralize file selection state
and provide utility hooks for managing selected files, selection limits,
and tool mode. (`frontend/src/contexts/FileSelectionContext.tsx`,
[frontend/src/contexts/FileSelectionContext.tsxR1-R77](diffhunk://#diff-bda35f1aaa5eafa0a0dc48e0b1270d862f6da360ba1241234e891f0ca8907327R1-R77))
* Replaced local file selection logic in `FileEditor` with context-based
logic, improving consistency and reducing duplication.
(`frontend/src/components/fileEditor/FileEditor.tsx`,
[[1]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R63-R70)
[[2]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R404-R438)
### Tool Management and Rendering:
* Refactored `ToolRenderer` to use a `Suspense` fallback for lazy-loaded
tools, improving user experience during tool loading.
(`frontend/src/components/tools/ToolRenderer.tsx`,
[frontend/src/components/tools/ToolRenderer.tsxL32-L64](diffhunk://#diff-2083701113aa92cd1f5ce1b4b52cc233858e31ed7bcf39c5bfb1bcc34e99b6a9L32-L64))
* Simplified `ToolPicker` by reusing the `ToolRegistry` type, reducing
redundancy. (`frontend/src/components/tools/ToolPicker.tsx`,
[frontend/src/components/tools/ToolPicker.tsxL4-R4](diffhunk://#diff-e47deca9132018344c159925f1264794acdd57f4b65e582eb9b2a4ea69ec126dL4-R4))
### File Context Enhancements:
* Introduced a utility function `getFileId` for consistent file ID
extraction, replacing repetitive inline logic.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcR25)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL101-R102)
* Updated `FileContextProvider` to use more specific types for PDF
documents, enhancing type safety.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL350-R351)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL384-R385)
### Compression Tool Enhancements:
* Added blob URL cleanup logic to the compression hook to prevent memory
leaks. (`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsR58-L66](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673R58-L66))
* Adjusted file ID generation in the compression operation to handle
multiple files more effectively.
(`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsL90-R102](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673L90-R102))
---
## 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.
2025-07-25 09:37:52 +01:00
|
|
|
}, [draggedFile, files, selectionMode, localSelectedIds, multiFileDrag]);
|
2025-07-16 17:53:50 +01:00
|
|
|
|
|
|
|
const handleEndZoneDragEnter = useCallback(() => {
|
|
|
|
if (draggedFile) {
|
|
|
|
setDropTarget('end');
|
|
|
|
}
|
|
|
|
}, [draggedFile]);
|
|
|
|
|
|
|
|
// File operations using context
|
|
|
|
const handleDeleteFile = useCallback((fileId: string) => {
|
|
|
|
console.log('handleDeleteFile called with fileId:', fileId);
|
|
|
|
const file = files.find(f => f.id === fileId);
|
|
|
|
console.log('Found file:', file);
|
2025-08-11 16:40:38 +01:00
|
|
|
|
2025-07-16 17:53:50 +01:00
|
|
|
if (file) {
|
|
|
|
console.log('Attempting to remove file:', file.name);
|
|
|
|
console.log('Actual file object:', file.file);
|
|
|
|
console.log('Actual file.file.name:', file.file.name);
|
2025-08-11 16:40:38 +01:00
|
|
|
|
2025-07-16 17:53:50 +01:00
|
|
|
// Record close operation
|
|
|
|
const fileName = file.file.name;
|
|
|
|
const fileId = (file.file as any).id || fileName;
|
|
|
|
const operationId = `close-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
|
|
const operation: FileOperation = {
|
|
|
|
id: operationId,
|
|
|
|
type: 'remove',
|
|
|
|
timestamp: Date.now(),
|
|
|
|
fileIds: [fileName],
|
|
|
|
status: 'pending',
|
|
|
|
metadata: {
|
|
|
|
originalFileName: fileName,
|
|
|
|
fileSize: file.size,
|
|
|
|
parameters: {
|
|
|
|
action: 'close',
|
|
|
|
reason: 'user_request'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2025-08-11 16:40:38 +01:00
|
|
|
|
|
|
|
recordOperation(fileName, operation);
|
|
|
|
|
2025-07-16 17:53:50 +01:00
|
|
|
|
2025-08-10 21:08:32 +01:00
|
|
|
// Legacy operation tracking removed
|
2025-07-16 17:53:50 +01:00
|
|
|
|
|
|
|
// Remove file from context but keep in storage (close, don't delete)
|
|
|
|
console.log('Calling removeFiles with:', [fileId]);
|
|
|
|
removeFiles([fileId], false);
|
2025-08-11 16:40:38 +01:00
|
|
|
|
2025-07-16 17:53:50 +01:00
|
|
|
// Remove from context selections
|
2025-08-11 16:40:38 +01:00
|
|
|
const newSelection = contextSelectedIds.filter(id => id !== fileId);
|
|
|
|
setContextSelectedFiles(newSelection);
|
|
|
|
// Mark operation as applied
|
|
|
|
markOperationApplied(fileName, operationId);
|
2025-07-16 17:53:50 +01:00
|
|
|
setContextSelectedFiles(prev => {
|
|
|
|
const safePrev = Array.isArray(prev) ? prev : [];
|
|
|
|
return safePrev.filter(id => id !== fileId);
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
console.log('File not found for fileId:', fileId);
|
|
|
|
}
|
2025-08-10 21:08:32 +01:00
|
|
|
}, [files, removeFiles, setContextSelectedFiles]);
|
2025-07-16 17:53:50 +01:00
|
|
|
|
|
|
|
const handleViewFile = useCallback((fileId: string) => {
|
|
|
|
const file = files.find(f => f.id === fileId);
|
|
|
|
if (file) {
|
2025-08-10 21:08:32 +01:00
|
|
|
// Set the file as selected in context and switch to viewer for preview
|
|
|
|
const contextFileId = createStableFileId(file.file);
|
2025-07-16 17:53:50 +01:00
|
|
|
setContextSelectedFiles([contextFileId]);
|
2025-08-10 21:08:32 +01:00
|
|
|
setCurrentView('viewer');
|
2025-07-16 17:53:50 +01:00
|
|
|
}
|
2025-08-10 21:08:32 +01:00
|
|
|
}, [files, setContextSelectedFiles, setCurrentView]);
|
2025-07-16 17:53:50 +01:00
|
|
|
|
|
|
|
const handleMergeFromHere = useCallback((fileId: string) => {
|
|
|
|
const startIndex = files.findIndex(f => f.id === fileId);
|
|
|
|
if (startIndex === -1) return;
|
|
|
|
|
|
|
|
const filesToMerge = files.slice(startIndex).map(f => f.file);
|
|
|
|
if (onMergeFiles) {
|
|
|
|
onMergeFiles(filesToMerge);
|
|
|
|
}
|
|
|
|
}, [files, onMergeFiles]);
|
|
|
|
|
|
|
|
const handleSplitFile = useCallback((fileId: string) => {
|
|
|
|
const file = files.find(f => f.id === fileId);
|
|
|
|
if (file && onOpenPageEditor) {
|
|
|
|
onOpenPageEditor(file.file);
|
|
|
|
}
|
|
|
|
}, [files, onOpenPageEditor]);
|
|
|
|
|
|
|
|
const handleLoadFromStorage = useCallback(async (selectedFiles: any[]) => {
|
|
|
|
if (selectedFiles.length === 0) return;
|
|
|
|
|
|
|
|
setLocalLoading(true);
|
|
|
|
try {
|
|
|
|
const convertedFiles = await Promise.all(
|
|
|
|
selectedFiles.map(convertToFileItem)
|
|
|
|
);
|
|
|
|
setFiles(prev => [...prev, ...convertedFiles]);
|
|
|
|
setStatus(`Loaded ${selectedFiles.length} files from storage`);
|
|
|
|
} catch (err) {
|
|
|
|
console.error('Error loading files from storage:', err);
|
|
|
|
setError('Failed to load some files from storage');
|
|
|
|
} finally {
|
|
|
|
setLocalLoading(false);
|
|
|
|
}
|
|
|
|
}, [convertToFileItem]);
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
2025-08-04 15:01:36 +01:00
|
|
|
<Dropzone
|
|
|
|
onDrop={handleFileUpload}
|
|
|
|
accept={["*/*"]}
|
|
|
|
multiple={true}
|
|
|
|
maxSize={2 * 1024 * 1024 * 1024}
|
2025-08-11 16:40:38 +01:00
|
|
|
style={{
|
2025-08-04 15:01:36 +01:00
|
|
|
height: '100vh',
|
|
|
|
border: 'none',
|
|
|
|
borderRadius: 0,
|
|
|
|
backgroundColor: 'transparent'
|
|
|
|
}}
|
|
|
|
activateOnClick={false}
|
|
|
|
activateOnDrag={true}
|
|
|
|
>
|
|
|
|
<Box pos="relative" h="100vh" style={{ overflow: 'auto' }}>
|
|
|
|
<LoadingOverlay visible={false} />
|
|
|
|
|
|
|
|
<Box p="md" pt="xl">
|
|
|
|
<Group mb="md">
|
|
|
|
{showBulkActions && !toolMode && (
|
|
|
|
<>
|
|
|
|
<Button onClick={selectAll} variant="light">Select All</Button>
|
|
|
|
<Button onClick={deselectAll} variant="light">Deselect All</Button>
|
|
|
|
<Button onClick={closeAllFiles} variant="light" color="orange">
|
|
|
|
Close All
|
2025-07-16 17:53:50 +01:00
|
|
|
</Button>
|
2025-08-04 15:01:36 +01:00
|
|
|
</>
|
|
|
|
)}
|
|
|
|
</Group>
|
2025-07-16 17:53:50 +01:00
|
|
|
|
|
|
|
|
|
|
|
{files.length === 0 && !localLoading && !zipExtractionProgress.isExtracting ? (
|
|
|
|
<Center h="60vh">
|
|
|
|
<Stack align="center" gap="md">
|
|
|
|
<Text size="lg" c="dimmed">📁</Text>
|
|
|
|
<Text c="dimmed">No files loaded</Text>
|
|
|
|
<Text size="sm" c="dimmed">Upload PDF files, ZIP archives, or load from storage to get started</Text>
|
|
|
|
</Stack>
|
|
|
|
</Center>
|
|
|
|
) : files.length === 0 && (localLoading || zipExtractionProgress.isExtracting) ? (
|
|
|
|
<Box>
|
|
|
|
<SkeletonLoader type="controls" />
|
2025-08-11 16:40:38 +01:00
|
|
|
|
2025-07-16 17:53:50 +01:00
|
|
|
{/* ZIP Extraction Progress */}
|
|
|
|
{zipExtractionProgress.isExtracting && (
|
|
|
|
<Box mb="md" p="sm" style={{ backgroundColor: 'var(--mantine-color-orange-0)', borderRadius: 8 }}>
|
|
|
|
<Group justify="space-between" mb="xs">
|
|
|
|
<Text size="sm" fw={500}>Extracting ZIP archive...</Text>
|
|
|
|
<Text size="sm" c="dimmed">{Math.round(zipExtractionProgress.progress)}%</Text>
|
|
|
|
</Group>
|
|
|
|
<Text size="xs" c="dimmed" mb="xs">
|
|
|
|
{zipExtractionProgress.currentFile || 'Processing files...'}
|
|
|
|
</Text>
|
|
|
|
<Text size="xs" c="dimmed" mb="xs">
|
|
|
|
{zipExtractionProgress.extractedCount} of {zipExtractionProgress.totalFiles} files extracted
|
|
|
|
</Text>
|
2025-08-11 16:40:38 +01:00
|
|
|
<div style={{
|
|
|
|
width: '100%',
|
|
|
|
height: '4px',
|
|
|
|
backgroundColor: 'var(--mantine-color-gray-2)',
|
2025-07-16 17:53:50 +01:00
|
|
|
borderRadius: '2px',
|
|
|
|
overflow: 'hidden'
|
|
|
|
}}>
|
|
|
|
<div style={{
|
|
|
|
width: `${Math.round(zipExtractionProgress.progress)}%`,
|
|
|
|
height: '100%',
|
|
|
|
backgroundColor: 'var(--mantine-color-orange-6)',
|
|
|
|
transition: 'width 0.3s ease'
|
|
|
|
}} />
|
|
|
|
</div>
|
|
|
|
</Box>
|
|
|
|
)}
|
2025-08-11 16:40:38 +01:00
|
|
|
|
2025-07-16 17:53:50 +01:00
|
|
|
{/* Processing indicator */}
|
|
|
|
{localLoading && (
|
|
|
|
<Box mb="md" p="sm" style={{ backgroundColor: 'var(--mantine-color-blue-0)', borderRadius: 8 }}>
|
|
|
|
<Group justify="space-between" mb="xs">
|
|
|
|
<Text size="sm" fw={500}>Loading files...</Text>
|
|
|
|
<Text size="sm" c="dimmed">{Math.round(conversionProgress)}%</Text>
|
|
|
|
</Group>
|
2025-08-11 16:40:38 +01:00
|
|
|
<div style={{
|
|
|
|
width: '100%',
|
|
|
|
height: '4px',
|
|
|
|
backgroundColor: 'var(--mantine-color-gray-2)',
|
2025-07-16 17:53:50 +01:00
|
|
|
borderRadius: '2px',
|
|
|
|
overflow: 'hidden'
|
|
|
|
}}>
|
|
|
|
<div style={{
|
|
|
|
width: `${Math.round(conversionProgress)}%`,
|
|
|
|
height: '100%',
|
|
|
|
backgroundColor: 'var(--mantine-color-blue-6)',
|
|
|
|
transition: 'width 0.3s ease'
|
|
|
|
}} />
|
|
|
|
</div>
|
|
|
|
</Box>
|
|
|
|
)}
|
2025-08-11 16:40:38 +01:00
|
|
|
|
2025-07-16 17:53:50 +01:00
|
|
|
<SkeletonLoader type="fileGrid" count={6} />
|
|
|
|
</Box>
|
|
|
|
) : (
|
|
|
|
<DragDropGrid
|
|
|
|
items={files}
|
2025-08-11 16:40:38 +01:00
|
|
|
selectedItems={localSelectedIds as any /* FIX ME */}
|
2025-07-16 17:53:50 +01:00
|
|
|
selectionMode={selectionMode}
|
|
|
|
isAnimating={isAnimating}
|
2025-08-11 16:40:38 +01:00
|
|
|
onDragStart={handleDragStart as any /* FIX ME */}
|
|
|
|
onDragEnd={handleDragEnd}
|
|
|
|
onDragOver={handleDragOver}
|
|
|
|
onDragEnter={handleDragEnter as any /* FIX ME */}
|
|
|
|
onDragLeave={handleDragLeave}
|
|
|
|
onDrop={handleDrop as any /* FIX ME */}
|
|
|
|
onEndZoneDragEnter={handleEndZoneDragEnter}
|
|
|
|
draggedItem={draggedFile as any /* FIX ME */}
|
|
|
|
dropTarget={dropTarget as any /* FIX ME */}
|
|
|
|
multiItemDrag={multiFileDrag as any /* FIX ME */}
|
|
|
|
dragPosition={dragPosition}
|
|
|
|
renderItem={(file, index, refs) => (
|
2025-07-16 17:53:50 +01:00
|
|
|
<FileThumbnail
|
|
|
|
file={file}
|
|
|
|
index={index}
|
|
|
|
totalFiles={files.length}
|
Feature/v2/multiselect (#4024)
# Description of Changes
This pull request introduces significant updates to the file selection
logic, tool rendering, and file context management in the frontend
codebase. The changes aim to improve modularity, enhance
maintainability, and streamline the handling of file-related operations.
Key updates include the introduction of a new `FileSelectionContext`,
refactoring of file selection logic, and updates to tool management and
rendering.
### File Selection Context and Logic Refactor:
* Added a new `FileSelectionContext` to centralize file selection state
and provide utility hooks for managing selected files, selection limits,
and tool mode. (`frontend/src/contexts/FileSelectionContext.tsx`,
[frontend/src/contexts/FileSelectionContext.tsxR1-R77](diffhunk://#diff-bda35f1aaa5eafa0a0dc48e0b1270d862f6da360ba1241234e891f0ca8907327R1-R77))
* Replaced local file selection logic in `FileEditor` with context-based
logic, improving consistency and reducing duplication.
(`frontend/src/components/fileEditor/FileEditor.tsx`,
[[1]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R63-R70)
[[2]](diffhunk://#diff-481d0a2d8a1714d34d21181db63a020b08dfccfbfa80bf47ac9af382dff25310R404-R438)
### Tool Management and Rendering:
* Refactored `ToolRenderer` to use a `Suspense` fallback for lazy-loaded
tools, improving user experience during tool loading.
(`frontend/src/components/tools/ToolRenderer.tsx`,
[frontend/src/components/tools/ToolRenderer.tsxL32-L64](diffhunk://#diff-2083701113aa92cd1f5ce1b4b52cc233858e31ed7bcf39c5bfb1bcc34e99b6a9L32-L64))
* Simplified `ToolPicker` by reusing the `ToolRegistry` type, reducing
redundancy. (`frontend/src/components/tools/ToolPicker.tsx`,
[frontend/src/components/tools/ToolPicker.tsxL4-R4](diffhunk://#diff-e47deca9132018344c159925f1264794acdd57f4b65e582eb9b2a4ea69ec126dL4-R4))
### File Context Enhancements:
* Introduced a utility function `getFileId` for consistent file ID
extraction, replacing repetitive inline logic.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcR25)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL101-R102)
* Updated `FileContextProvider` to use more specific types for PDF
documents, enhancing type safety.
(`frontend/src/contexts/FileContext.tsx`,
[[1]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL350-R351)
[[2]](diffhunk://#diff-95b3d103fa434f81fdae55f2ea14eda705f0def45a0f2c5754f81de6f2fd93bcL384-R385)
### Compression Tool Enhancements:
* Added blob URL cleanup logic to the compression hook to prevent memory
leaks. (`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsR58-L66](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673R58-L66))
* Adjusted file ID generation in the compression operation to handle
multiple files more effectively.
(`frontend/src/hooks/tools/compress/useCompressOperation.ts`,
[frontend/src/hooks/tools/compress/useCompressOperation.tsL90-R102](diffhunk://#diff-d7815fea0e89989511ae1786f7031cba492b9f2db39b7ade92d9736d1bd4b673L90-R102))
---
## 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.
2025-07-25 09:37:52 +01:00
|
|
|
selectedFiles={localSelectedIds}
|
2025-07-16 17:53:50 +01:00
|
|
|
selectionMode={selectionMode}
|
|
|
|
draggedFile={draggedFile}
|
|
|
|
dropTarget={dropTarget}
|
|
|
|
isAnimating={isAnimating}
|
|
|
|
fileRefs={refs}
|
|
|
|
onDragStart={handleDragStart}
|
|
|
|
onDragEnd={handleDragEnd}
|
|
|
|
onDragOver={handleDragOver}
|
|
|
|
onDragEnter={handleDragEnter}
|
|
|
|
onDragLeave={handleDragLeave}
|
|
|
|
onDrop={handleDrop}
|
|
|
|
onToggleFile={toggleFile}
|
|
|
|
onDeleteFile={handleDeleteFile}
|
|
|
|
onViewFile={handleViewFile}
|
|
|
|
onSetStatus={setStatus}
|
|
|
|
toolMode={toolMode}
|
2025-08-01 16:08:04 +01:00
|
|
|
isSupported={isFileSupported(file.name)}
|
2025-07-16 17:53:50 +01:00
|
|
|
/>
|
|
|
|
)}
|
|
|
|
renderSplitMarker={(file, index) => (
|
|
|
|
<div
|
|
|
|
style={{
|
|
|
|
width: '2px',
|
|
|
|
height: '24rem',
|
|
|
|
borderLeft: '2px dashed #3b82f6',
|
|
|
|
backgroundColor: 'transparent',
|
|
|
|
marginLeft: '-0.75rem',
|
|
|
|
marginRight: '-0.75rem',
|
|
|
|
flexShrink: 0
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</Box>
|
|
|
|
|
|
|
|
{/* File Picker Modal */}
|
|
|
|
<FilePickerModal
|
|
|
|
opened={showFilePickerModal}
|
|
|
|
onClose={() => setShowFilePickerModal(false)}
|
|
|
|
storedFiles={[]} // FileEditor doesn't have access to stored files, needs to be passed from parent
|
|
|
|
onSelectFiles={handleLoadFromStorage}
|
|
|
|
/>
|
|
|
|
|
|
|
|
{status && (
|
|
|
|
<Notification
|
|
|
|
color="blue"
|
|
|
|
mt="md"
|
|
|
|
onClose={() => setStatus(null)}
|
|
|
|
style={{ position: 'fixed', bottom: 20, right: 20, zIndex: 1000 }}
|
|
|
|
>
|
|
|
|
{status}
|
|
|
|
</Notification>
|
|
|
|
)}
|
|
|
|
|
|
|
|
{error && (
|
|
|
|
<Notification
|
|
|
|
color="red"
|
|
|
|
mt="md"
|
|
|
|
onClose={() => setError(null)}
|
|
|
|
style={{ position: 'fixed', bottom: 80, right: 20, zIndex: 1000 }}
|
|
|
|
>
|
|
|
|
{error}
|
|
|
|
</Notification>
|
|
|
|
)}
|
2025-08-04 15:01:36 +01:00
|
|
|
</Box>
|
|
|
|
</Dropzone>
|
2025-07-16 17:53:50 +01:00
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export default FileEditor;
|