Stirling-PDF/frontend/src/contexts/FileManagerContext.tsx

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

635 lines
22 KiB
TypeScript
Raw Normal View History

Feature/v2/file handling improvements (#4222) # Description of Changes A new universal file context rather than the splintered ones for the main views, tools and manager we had before (manager still has its own but its better integreated with the core context) File context has been split it into a handful of different files managing various file related issues separately to reduce the monolith - FileReducer.ts - State management fileActions.ts - File operations fileSelectors.ts - Data access patterns lifecycle.ts - Resource cleanup and memory management fileHooks.ts - React hooks interface contexts.ts - Context providers Improved thumbnail generation Improved indexxedb handling Stopped handling files as blobs were not necessary to improve performance A new library handling drag and drop https://github.com/atlassian/pragmatic-drag-and-drop (Out of scope yes but I broke the old one with the new filecontext and it needed doing so it was a might as well) A new library handling virtualisation on page editor @tanstack/react-virtual, as above. Quickly ripped out the last remnants of the old URL params stuff and replaced with the beginnings of what will later become the new URL navigation system (for now it just restores the tool name in url behavior) Fixed selected file not regestered when opening a tool Fixed png thumbnails Closes #(issue_number) --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --------- Co-authored-by: Reece Browne <you@example.com>
2025-08-21 17:30:26 +01:00
import React, { createContext, useContext, useState, useRef, useCallback, useEffect, useMemo } from 'react';
2025-09-10 10:03:35 +01:00
import { StoredFileMetadata, StoredFile } from '../services/fileStorage';
import { fileStorage } from '../services/fileStorage';
import { downloadFiles } from '../utils/downloadUtils';
import { FileId } from '../types/file';
2025-09-10 10:03:35 +01:00
import { groupFilesByOriginal } from '../utils/fileHistoryUtils';
// Type for the context value - now contains everything directly
interface FileManagerContextValue {
// State
activeSource: 'recent' | 'local' | 'drive';
selectedFileIds: FileId[];
searchTerm: string;
2025-09-10 10:03:35 +01:00
selectedFiles: StoredFileMetadata[];
filteredFiles: StoredFileMetadata[];
fileInputRef: React.RefObject<HTMLInputElement | null>;
selectedFilesSet: Set<string>;
2025-09-03 17:47:58 +01:00
expandedFileIds: Set<string>;
2025-09-10 10:03:35 +01:00
fileGroups: Map<string, StoredFileMetadata[]>;
2025-09-04 12:11:09 +01:00
// Handlers
onSourceChange: (source: 'recent' | 'local' | 'drive') => void;
onLocalFileClick: () => void;
2025-09-10 10:03:35 +01:00
onFileSelect: (file: StoredFileMetadata, index: number, shiftKey?: boolean) => void;
onFileRemove: (index: number) => void;
2025-09-10 10:03:35 +01:00
onFileDoubleClick: (file: StoredFileMetadata) => void;
onOpenFiles: () => void;
onSearchChange: (value: string) => void;
onFileInputChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
onSelectAll: () => void;
onDeleteSelected: () => void;
onDownloadSelected: () => void;
2025-09-10 10:03:35 +01:00
onDownloadSingle: (file: StoredFileMetadata) => void;
2025-09-03 17:47:58 +01:00
onToggleExpansion: (fileId: string) => void;
2025-09-10 10:03:35 +01:00
onAddToRecents: (file: StoredFileMetadata) => void;
2025-09-02 17:24:26 +01:00
onNewFilesSelect: (files: File[]) => void;
// External props
2025-09-10 10:03:35 +01:00
recentFiles: StoredFileMetadata[];
isFileSupported: (fileName: string) => boolean;
modalHeight: string;
}
// Create the context
const FileManagerContext = createContext<FileManagerContextValue | null>(null);
// Provider component props
interface FileManagerProviderProps {
children: React.ReactNode;
2025-09-10 10:03:35 +01:00
recentFiles: StoredFileMetadata[];
onFilesSelected: (files: StoredFileMetadata[]) => void; // For selecting stored files
Feature/v2/file handling improvements (#4222) # Description of Changes A new universal file context rather than the splintered ones for the main views, tools and manager we had before (manager still has its own but its better integreated with the core context) File context has been split it into a handful of different files managing various file related issues separately to reduce the monolith - FileReducer.ts - State management fileActions.ts - File operations fileSelectors.ts - Data access patterns lifecycle.ts - Resource cleanup and memory management fileHooks.ts - React hooks interface contexts.ts - Context providers Improved thumbnail generation Improved indexxedb handling Stopped handling files as blobs were not necessary to improve performance A new library handling drag and drop https://github.com/atlassian/pragmatic-drag-and-drop (Out of scope yes but I broke the old one with the new filecontext and it needed doing so it was a might as well) A new library handling virtualisation on page editor @tanstack/react-virtual, as above. Quickly ripped out the last remnants of the old URL params stuff and replaced with the beginnings of what will later become the new URL navigation system (for now it just restores the tool name in url behavior) Fixed selected file not regestered when opening a tool Fixed png thumbnails Closes #(issue_number) --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --------- Co-authored-by: Reece Browne <you@example.com>
2025-08-21 17:30:26 +01:00
onNewFilesSelect: (files: File[]) => void; // For uploading new local files
2025-09-10 10:03:35 +01:00
onStoredFilesSelect: (storedFiles: StoredFile[]) => void; // For adding stored files directly
onClose: () => void;
isFileSupported: (fileName: string) => boolean;
isOpen: boolean;
onFileRemove: (index: number) => void;
modalHeight: string;
refreshRecentFiles: () => Promise<void>;
}
export const FileManagerProvider: React.FC<FileManagerProviderProps> = ({
children,
recentFiles,
onFilesSelected,
Feature/v2/file handling improvements (#4222) # Description of Changes A new universal file context rather than the splintered ones for the main views, tools and manager we had before (manager still has its own but its better integreated with the core context) File context has been split it into a handful of different files managing various file related issues separately to reduce the monolith - FileReducer.ts - State management fileActions.ts - File operations fileSelectors.ts - Data access patterns lifecycle.ts - Resource cleanup and memory management fileHooks.ts - React hooks interface contexts.ts - Context providers Improved thumbnail generation Improved indexxedb handling Stopped handling files as blobs were not necessary to improve performance A new library handling drag and drop https://github.com/atlassian/pragmatic-drag-and-drop (Out of scope yes but I broke the old one with the new filecontext and it needed doing so it was a might as well) A new library handling virtualisation on page editor @tanstack/react-virtual, as above. Quickly ripped out the last remnants of the old URL params stuff and replaced with the beginnings of what will later become the new URL navigation system (for now it just restores the tool name in url behavior) Fixed selected file not regestered when opening a tool Fixed png thumbnails Closes #(issue_number) --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --------- Co-authored-by: Reece Browne <you@example.com>
2025-08-21 17:30:26 +01:00
onNewFilesSelect,
2025-09-10 10:03:35 +01:00
onStoredFilesSelect: onStoredFilesSelect,
onClose,
isFileSupported,
isOpen,
onFileRemove,
modalHeight,
refreshRecentFiles,
}) => {
const [activeSource, setActiveSource] = useState<'recent' | 'local' | 'drive'>('recent');
const [selectedFileIds, setSelectedFileIds] = useState<FileId[]>([]);
const [searchTerm, setSearchTerm] = useState('');
const [lastClickedIndex, setLastClickedIndex] = useState<number | null>(null);
2025-09-03 17:47:58 +01:00
const [expandedFileIds, setExpandedFileIds] = useState<Set<string>>(new Set());
2025-09-10 10:03:35 +01:00
const [loadedHistoryFiles, setLoadedHistoryFiles] = useState<Map<FileId, StoredFileMetadata[]>>(new Map()); // Cache for loaded history
const fileInputRef = useRef<HTMLInputElement>(null);
// Track blob URLs for cleanup
const createdBlobUrls = useRef<Set<string>>(new Set());
2025-09-04 12:11:09 +01:00
// Computed values (with null safety)
const selectedFilesSet = new Set(selectedFileIds);
2025-09-02 17:24:26 +01:00
// Group files by original file ID for version management
const fileGroups = useMemo(() => {
if (!recentFiles || recentFiles.length === 0) return new Map();
2025-09-10 10:03:35 +01:00
// Convert StoredFileMetadata to FileRecord-like objects for grouping utility
2025-09-02 17:24:26 +01:00
const recordsForGrouping = recentFiles.map(file => ({
...file,
originalFileId: file.originalFileId,
2025-09-10 10:03:35 +01:00
versionNumber: file.versionNumber || 1
2025-09-02 17:24:26 +01:00
}));
2025-09-10 10:03:35 +01:00
2025-09-02 17:24:26 +01:00
return groupFilesByOriginal(recordsForGrouping);
}, [recentFiles]);
2025-09-10 10:03:35 +01:00
// Get files to display with expansion logic
2025-09-02 17:24:26 +01:00
const displayFiles = useMemo(() => {
if (!recentFiles || recentFiles.length === 0) return [];
2025-09-10 10:03:35 +01:00
2025-09-03 17:47:58 +01:00
const expandedFiles = [];
2025-09-10 10:03:35 +01:00
2025-09-04 12:11:09 +01:00
// Since we now only load leaf files, iterate through recent files directly
for (const leafFile of recentFiles) {
// Add the leaf file (main file shown in list)
2025-09-03 17:47:58 +01:00
expandedFiles.push(leafFile);
2025-09-10 10:03:35 +01:00
2025-09-04 12:11:09 +01:00
// If expanded, add the loaded history files
if (expandedFileIds.has(leafFile.id)) {
const historyFiles = loadedHistoryFiles.get(leafFile.id) || [];
// Sort history files by version number (oldest first)
2025-09-10 10:03:35 +01:00
const sortedHistory = historyFiles.sort((a, b) => (a.versionNumber || 1) - (b.versionNumber || 1));
2025-09-04 12:11:09 +01:00
expandedFiles.push(...sortedHistory);
2025-09-03 17:47:58 +01:00
}
2025-09-02 17:24:26 +01:00
}
2025-09-10 10:03:35 +01:00
2025-09-03 17:47:58 +01:00
return expandedFiles;
2025-09-04 12:11:09 +01:00
}, [recentFiles, expandedFileIds, loadedHistoryFiles]);
2025-09-02 17:24:26 +01:00
const selectedFiles = selectedFileIds.length === 0 ? [] :
2025-09-02 17:24:26 +01:00
displayFiles.filter(file => selectedFilesSet.has(file.id));
2025-09-02 17:24:26 +01:00
const filteredFiles = !searchTerm ? displayFiles :
displayFiles.filter(file =>
file.name.toLowerCase().includes(searchTerm.toLowerCase())
);
const handleSourceChange = useCallback((source: 'recent' | 'local' | 'drive') => {
setActiveSource(source);
if (source !== 'recent') {
setSelectedFileIds([]);
setSearchTerm('');
setLastClickedIndex(null);
}
}, []);
const handleLocalFileClick = useCallback(() => {
fileInputRef.current?.click();
}, []);
2025-09-10 10:03:35 +01:00
const handleFileSelect = useCallback((file: StoredFileMetadata, currentIndex: number, shiftKey?: boolean) => {
Feature/v2/file handling improvements (#4222) # Description of Changes A new universal file context rather than the splintered ones for the main views, tools and manager we had before (manager still has its own but its better integreated with the core context) File context has been split it into a handful of different files managing various file related issues separately to reduce the monolith - FileReducer.ts - State management fileActions.ts - File operations fileSelectors.ts - Data access patterns lifecycle.ts - Resource cleanup and memory management fileHooks.ts - React hooks interface contexts.ts - Context providers Improved thumbnail generation Improved indexxedb handling Stopped handling files as blobs were not necessary to improve performance A new library handling drag and drop https://github.com/atlassian/pragmatic-drag-and-drop (Out of scope yes but I broke the old one with the new filecontext and it needed doing so it was a might as well) A new library handling virtualisation on page editor @tanstack/react-virtual, as above. Quickly ripped out the last remnants of the old URL params stuff and replaced with the beginnings of what will later become the new URL navigation system (for now it just restores the tool name in url behavior) Fixed selected file not regestered when opening a tool Fixed png thumbnails Closes #(issue_number) --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --------- Co-authored-by: Reece Browne <you@example.com>
2025-08-21 17:30:26 +01:00
const fileId = file.id;
if (!fileId) return;
if (shiftKey && lastClickedIndex !== null) {
// Range selection with shift-click
const startIndex = Math.min(lastClickedIndex, currentIndex);
const endIndex = Math.max(lastClickedIndex, currentIndex);
setSelectedFileIds(prev => {
const selectedSet = new Set(prev);
// Add all files in the range to selection
for (let i = startIndex; i <= endIndex; i++) {
Feature/v2/file handling improvements (#4222) # Description of Changes A new universal file context rather than the splintered ones for the main views, tools and manager we had before (manager still has its own but its better integreated with the core context) File context has been split it into a handful of different files managing various file related issues separately to reduce the monolith - FileReducer.ts - State management fileActions.ts - File operations fileSelectors.ts - Data access patterns lifecycle.ts - Resource cleanup and memory management fileHooks.ts - React hooks interface contexts.ts - Context providers Improved thumbnail generation Improved indexxedb handling Stopped handling files as blobs were not necessary to improve performance A new library handling drag and drop https://github.com/atlassian/pragmatic-drag-and-drop (Out of scope yes but I broke the old one with the new filecontext and it needed doing so it was a might as well) A new library handling virtualisation on page editor @tanstack/react-virtual, as above. Quickly ripped out the last remnants of the old URL params stuff and replaced with the beginnings of what will later become the new URL navigation system (for now it just restores the tool name in url behavior) Fixed selected file not regestered when opening a tool Fixed png thumbnails Closes #(issue_number) --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --------- Co-authored-by: Reece Browne <you@example.com>
2025-08-21 17:30:26 +01:00
const rangeFileId = filteredFiles[i]?.id;
if (rangeFileId) {
selectedSet.add(rangeFileId);
}
}
return Array.from(selectedSet);
});
} else {
// Normal click behavior - optimized with Set for O(1) lookup
setSelectedFileIds(prev => {
const selectedSet = new Set(prev);
if (selectedSet.has(fileId)) {
selectedSet.delete(fileId);
} else {
selectedSet.add(fileId);
}
return Array.from(selectedSet);
});
// Update last clicked index for future range selections
setLastClickedIndex(currentIndex);
}
}, [filteredFiles, lastClickedIndex]);
2025-09-10 10:03:35 +01:00
// Helper function to safely determine which files can be deleted
const getSafeFilesToDelete = useCallback((
leafFileIds: string[],
allStoredMetadata: Omit<import('../services/fileStorage').StoredFile, 'data'>[]
): string[] => {
const fileMap = new Map(allStoredMetadata.map(f => [f.id as string, f]));
const filesToDelete = new Set<string>();
const filesToPreserve = new Set<string>();
// First, identify all files in the lineages of the leaf files being deleted
for (const leafFileId of leafFileIds) {
const currentFile = fileMap.get(leafFileId);
if (!currentFile) continue;
// Always include the leaf file itself for deletion
filesToDelete.add(leafFileId);
// If this is a processed file with history, trace back through its lineage
if (currentFile.versionNumber && currentFile.versionNumber > 1) {
const originalFileId = currentFile.originalFileId || currentFile.id;
// Find all files in this history chain
const chainFiles = allStoredMetadata.filter(file =>
(file.originalFileId || file.id) === originalFileId
);
// Add all files in this lineage as candidates for deletion
chainFiles.forEach(file => filesToDelete.add(file.id));
}
}
// Now identify files that must be preserved because they're referenced by OTHER lineages
for (const file of allStoredMetadata) {
const fileOriginalId = file.originalFileId || file.id;
// If this file is a leaf node (not being deleted) and its lineage overlaps with files we want to delete
if (file.isLeaf !== false && !leafFileIds.includes(file.id)) {
// Find all files in this preserved lineage
const preservedChainFiles = allStoredMetadata.filter(chainFile =>
(chainFile.originalFileId || chainFile.id) === fileOriginalId
);
// Mark all files in this preserved lineage as must-preserve
preservedChainFiles.forEach(chainFile => filesToPreserve.add(chainFile.id));
}
}
// Final list: files to delete minus files that must be preserved
const safeToDelete = Array.from(filesToDelete).filter(fileId => !filesToPreserve.has(fileId));
console.log('Deletion analysis:', {
candidatesForDeletion: Array.from(filesToDelete),
mustPreserve: Array.from(filesToPreserve),
safeToDelete
});
return safeToDelete;
}, []);
2025-09-05 14:37:31 +01:00
const handleFileRemove = useCallback(async (index: number) => {
const fileToRemove = filteredFiles[index];
if (fileToRemove) {
2025-09-05 14:37:31 +01:00
const deletedFileId = fileToRemove.id;
2025-09-10 10:03:35 +01:00
// Get all stored files to analyze lineages
const allStoredMetadata = await fileStorage.getAllFileMetadata();
// Get safe files to delete (respecting shared lineages)
const filesToDelete = getSafeFilesToDelete([deletedFileId as string], allStoredMetadata);
console.log(`Safely deleting files for ${fileToRemove.name}:`, filesToDelete);
2025-09-05 14:37:31 +01:00
// Clear from selection immediately
2025-09-10 10:03:35 +01:00
setSelectedFileIds(prev => prev.filter(id => !filesToDelete.includes(id)));
2025-09-05 14:37:31 +01:00
// Clear from expanded state to prevent ghost entries
setExpandedFileIds(prev => {
const newExpanded = new Set(prev);
2025-09-10 10:03:35 +01:00
filesToDelete.forEach(id => newExpanded.delete(id));
2025-09-05 14:37:31 +01:00
return newExpanded;
});
2025-09-10 10:03:35 +01:00
// Clear from history cache - remove all files in the chain
2025-09-05 14:37:31 +01:00
setLoadedHistoryFiles(prev => {
const newCache = new Map(prev);
2025-09-10 10:03:35 +01:00
// Remove cache entries for all deleted files
filesToDelete.forEach(id => newCache.delete(id as FileId));
// Also remove deleted files from any other file's history cache
2025-09-05 14:37:31 +01:00
for (const [mainFileId, historyFiles] of newCache.entries()) {
2025-09-10 10:03:35 +01:00
const filteredHistory = historyFiles.filter(histFile => !filesToDelete.includes(histFile.id as string));
2025-09-05 14:37:31 +01:00
if (filteredHistory.length !== historyFiles.length) {
newCache.set(mainFileId, filteredHistory);
}
}
2025-09-10 10:03:35 +01:00
2025-09-05 14:37:31 +01:00
return newCache;
});
2025-09-10 10:03:35 +01:00
// Delete safe files from IndexedDB
try {
for (const fileId of filesToDelete) {
await fileStorage.deleteFile(fileId as FileId);
}
} catch (error) {
console.error('Failed to delete files from chain:', error);
}
// Call the parent's deletion logic for the main file only
2025-09-05 14:37:31 +01:00
await onFileRemove(index);
2025-09-10 10:03:35 +01:00
2025-09-05 14:37:31 +01:00
// Refresh to ensure consistent state
await refreshRecentFiles();
}
2025-09-10 10:03:35 +01:00
}, [filteredFiles, onFileRemove, refreshRecentFiles, getSafeFilesToDelete]);
2025-09-10 10:03:35 +01:00
const handleFileDoubleClick = useCallback((file: StoredFileMetadata) => {
if (isFileSupported(file.name)) {
onFilesSelected([file]);
onClose();
}
}, [isFileSupported, onFilesSelected, onClose]);
const handleOpenFiles = useCallback(() => {
if (selectedFiles.length > 0) {
onFilesSelected(selectedFiles);
onClose();
}
}, [selectedFiles, onFilesSelected, onClose]);
const handleSearchChange = useCallback((value: string) => {
setSearchTerm(value);
}, []);
const handleFileInputChange = useCallback(async (event: React.ChangeEvent<HTMLInputElement>) => {
const files = Array.from(event.target.files || []);
if (files.length > 0) {
try {
Feature/v2/file handling improvements (#4222) # Description of Changes A new universal file context rather than the splintered ones for the main views, tools and manager we had before (manager still has its own but its better integreated with the core context) File context has been split it into a handful of different files managing various file related issues separately to reduce the monolith - FileReducer.ts - State management fileActions.ts - File operations fileSelectors.ts - Data access patterns lifecycle.ts - Resource cleanup and memory management fileHooks.ts - React hooks interface contexts.ts - Context providers Improved thumbnail generation Improved indexxedb handling Stopped handling files as blobs were not necessary to improve performance A new library handling drag and drop https://github.com/atlassian/pragmatic-drag-and-drop (Out of scope yes but I broke the old one with the new filecontext and it needed doing so it was a might as well) A new library handling virtualisation on page editor @tanstack/react-virtual, as above. Quickly ripped out the last remnants of the old URL params stuff and replaced with the beginnings of what will later become the new URL navigation system (for now it just restores the tool name in url behavior) Fixed selected file not regestered when opening a tool Fixed png thumbnails Closes #(issue_number) --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --------- Co-authored-by: Reece Browne <you@example.com>
2025-08-21 17:30:26 +01:00
// For local file uploads, pass File objects directly to FileContext
onNewFilesSelect(files);
await refreshRecentFiles();
onClose();
} catch (error) {
console.error('Failed to process selected files:', error);
}
}
event.target.value = '';
Feature/v2/file handling improvements (#4222) # Description of Changes A new universal file context rather than the splintered ones for the main views, tools and manager we had before (manager still has its own but its better integreated with the core context) File context has been split it into a handful of different files managing various file related issues separately to reduce the monolith - FileReducer.ts - State management fileActions.ts - File operations fileSelectors.ts - Data access patterns lifecycle.ts - Resource cleanup and memory management fileHooks.ts - React hooks interface contexts.ts - Context providers Improved thumbnail generation Improved indexxedb handling Stopped handling files as blobs were not necessary to improve performance A new library handling drag and drop https://github.com/atlassian/pragmatic-drag-and-drop (Out of scope yes but I broke the old one with the new filecontext and it needed doing so it was a might as well) A new library handling virtualisation on page editor @tanstack/react-virtual, as above. Quickly ripped out the last remnants of the old URL params stuff and replaced with the beginnings of what will later become the new URL navigation system (for now it just restores the tool name in url behavior) Fixed selected file not regestered when opening a tool Fixed png thumbnails Closes #(issue_number) --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --------- Co-authored-by: Reece Browne <you@example.com>
2025-08-21 17:30:26 +01:00
}, [onNewFilesSelect, refreshRecentFiles, onClose]);
const handleSelectAll = useCallback(() => {
const allFilesSelected = filteredFiles.length > 0 && selectedFileIds.length === filteredFiles.length;
if (allFilesSelected) {
// Deselect all
setSelectedFileIds([]);
setLastClickedIndex(null);
} else {
// Select all filtered files
Feature/v2/file handling improvements (#4222) # Description of Changes A new universal file context rather than the splintered ones for the main views, tools and manager we had before (manager still has its own but its better integreated with the core context) File context has been split it into a handful of different files managing various file related issues separately to reduce the monolith - FileReducer.ts - State management fileActions.ts - File operations fileSelectors.ts - Data access patterns lifecycle.ts - Resource cleanup and memory management fileHooks.ts - React hooks interface contexts.ts - Context providers Improved thumbnail generation Improved indexxedb handling Stopped handling files as blobs were not necessary to improve performance A new library handling drag and drop https://github.com/atlassian/pragmatic-drag-and-drop (Out of scope yes but I broke the old one with the new filecontext and it needed doing so it was a might as well) A new library handling virtualisation on page editor @tanstack/react-virtual, as above. Quickly ripped out the last remnants of the old URL params stuff and replaced with the beginnings of what will later become the new URL navigation system (for now it just restores the tool name in url behavior) Fixed selected file not regestered when opening a tool Fixed png thumbnails Closes #(issue_number) --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --------- Co-authored-by: Reece Browne <you@example.com>
2025-08-21 17:30:26 +01:00
setSelectedFileIds(filteredFiles.map(file => file.id).filter(Boolean));
setLastClickedIndex(null);
}
}, [filteredFiles, selectedFileIds]);
const handleDeleteSelected = useCallback(async () => {
if (selectedFileIds.length === 0) return;
try {
2025-09-10 10:03:35 +01:00
// Get all stored files to analyze lineages
const allStoredMetadata = await fileStorage.getAllFileMetadata();
// Get safe files to delete (respecting shared lineages)
const filesToDelete = getSafeFilesToDelete(selectedFileIds, allStoredMetadata);
console.log(`Bulk safely deleting files and their history chains:`, filesToDelete);
2025-09-05 14:37:31 +01:00
// Update history cache synchronously
setLoadedHistoryFiles(prev => {
const newCache = new Map(prev);
2025-09-10 10:03:35 +01:00
// Remove cache entries for all deleted files
filesToDelete.forEach(id => newCache.delete(id as FileId));
// Also remove deleted files from any other file's history cache
for (const [mainFileId, historyFiles] of newCache.entries()) {
const filteredHistory = historyFiles.filter(histFile => !filesToDelete.includes(histFile.id as string));
if (filteredHistory.length !== historyFiles.length) {
newCache.set(mainFileId, filteredHistory);
2025-09-03 17:47:58 +01:00
}
}
2025-09-10 10:03:35 +01:00
2025-09-05 14:37:31 +01:00
return newCache;
});
2025-09-03 17:47:58 +01:00
2025-09-05 14:37:31 +01:00
// Also clear any expanded state for deleted files to prevent ghost entries
setExpandedFileIds(prev => {
const newExpanded = new Set(prev);
2025-09-10 10:03:35 +01:00
filesToDelete.forEach(id => newExpanded.delete(id));
2025-09-05 14:37:31 +01:00
return newExpanded;
});
2025-09-05 14:37:31 +01:00
// Clear selection immediately to prevent ghost selections
2025-09-10 10:03:35 +01:00
setSelectedFileIds(prev => prev.filter(id => !filesToDelete.includes(id)));
2025-09-05 14:37:31 +01:00
2025-09-10 10:03:35 +01:00
// Delete safe files from IndexedDB
for (const fileId of filesToDelete) {
await fileStorage.deleteFile(fileId as FileId);
2025-09-05 14:37:31 +01:00
}
2025-09-05 14:37:31 +01:00
// Refresh the file list to get updated data
await refreshRecentFiles();
} catch (error) {
console.error('Failed to delete selected files:', error);
}
2025-09-10 10:03:35 +01:00
}, [selectedFileIds, filteredFiles, refreshRecentFiles, getSafeFilesToDelete]);
const handleDownloadSelected = useCallback(async () => {
if (selectedFileIds.length === 0) return;
try {
// Get selected files
const selectedFilesToDownload = filteredFiles.filter(file =>
Feature/v2/file handling improvements (#4222) # Description of Changes A new universal file context rather than the splintered ones for the main views, tools and manager we had before (manager still has its own but its better integreated with the core context) File context has been split it into a handful of different files managing various file related issues separately to reduce the monolith - FileReducer.ts - State management fileActions.ts - File operations fileSelectors.ts - Data access patterns lifecycle.ts - Resource cleanup and memory management fileHooks.ts - React hooks interface contexts.ts - Context providers Improved thumbnail generation Improved indexxedb handling Stopped handling files as blobs were not necessary to improve performance A new library handling drag and drop https://github.com/atlassian/pragmatic-drag-and-drop (Out of scope yes but I broke the old one with the new filecontext and it needed doing so it was a might as well) A new library handling virtualisation on page editor @tanstack/react-virtual, as above. Quickly ripped out the last remnants of the old URL params stuff and replaced with the beginnings of what will later become the new URL navigation system (for now it just restores the tool name in url behavior) Fixed selected file not regestered when opening a tool Fixed png thumbnails Closes #(issue_number) --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --------- Co-authored-by: Reece Browne <you@example.com>
2025-08-21 17:30:26 +01:00
selectedFileIds.includes(file.id)
);
// Use generic download utility
await downloadFiles(selectedFilesToDownload, {
zipFilename: `selected-files-${new Date().toISOString().slice(0, 19).replace(/[:-]/g, '')}.zip`
});
} catch (error) {
console.error('Failed to download selected files:', error);
}
}, [selectedFileIds, filteredFiles]);
2025-09-10 10:03:35 +01:00
const handleDownloadSingle = useCallback(async (file: StoredFileMetadata) => {
try {
await downloadFiles([file]);
} catch (error) {
console.error('Failed to download file:', error);
}
}, []);
2025-09-04 12:11:09 +01:00
const handleToggleExpansion = useCallback(async (fileId: string) => {
const isCurrentlyExpanded = expandedFileIds.has(fileId);
2025-09-10 10:03:35 +01:00
2025-09-04 12:11:09 +01:00
// Update expansion state
2025-09-03 17:47:58 +01:00
setExpandedFileIds(prev => {
const newSet = new Set(prev);
if (newSet.has(fileId)) {
newSet.delete(fileId);
} else {
newSet.add(fileId);
}
return newSet;
});
2025-09-04 12:11:09 +01:00
// Load complete history chain if expanding
if (!isCurrentlyExpanded) {
const currentFileMetadata = recentFiles.find(f => f.id === fileId);
2025-09-10 10:03:35 +01:00
if (currentFileMetadata && (currentFileMetadata.versionNumber || 1) > 1) {
2025-09-04 12:11:09 +01:00
try {
2025-09-10 10:03:35 +01:00
// Get all stored file metadata for chain traversal
const allStoredMetadata = await fileStorage.getAllFileMetadata();
const fileMap = new Map(allStoredMetadata.map(f => [f.id, f]));
// Get the current file's IndexedDB data
const currentStoredFile = fileMap.get(fileId as FileId);
if (!currentStoredFile) {
console.warn(`No stored file found for ${fileId}`);
return;
2025-09-04 12:11:09 +01:00
}
2025-09-10 10:03:35 +01:00
// Build complete history chain using IndexedDB metadata
const historyFiles: StoredFileMetadata[] = [];
// Find the original file
const originalFileId = currentStoredFile.originalFileId || currentStoredFile.id;
// Collect all files in this history chain
const chainFiles = Array.from(fileMap.values()).filter(file =>
(file.originalFileId || file.id) === originalFileId && file.id !== fileId
);
// Sort by version number (oldest first for history display)
chainFiles.sort((a, b) => (a.versionNumber || 1) - (b.versionNumber || 1));
// Convert stored files to StoredFileMetadata format with proper history info
for (const storedFile of chainFiles) {
// Load the actual file to extract PDF metadata if available
const historyMetadata: StoredFileMetadata = {
id: storedFile.id,
name: storedFile.name,
type: storedFile.type,
size: storedFile.size,
lastModified: storedFile.lastModified,
thumbnail: storedFile.thumbnail,
versionNumber: storedFile.versionNumber,
isLeaf: storedFile.isLeaf,
// Use IndexedDB data directly - it's more reliable than re-parsing PDF
originalFileId: storedFile.originalFileId,
parentFileId: storedFile.parentFileId,
toolHistory: storedFile.toolHistory
};
historyFiles.push(historyMetadata);
}
// Cache the loaded history files
setLoadedHistoryFiles(prev => new Map(prev.set(fileId as FileId, historyFiles)));
2025-09-04 12:11:09 +01:00
} catch (error) {
console.warn(`Failed to load history chain for file ${fileId}:`, error);
}
}
} else {
// Clear loaded history when collapsing
setLoadedHistoryFiles(prev => {
const newMap = new Map(prev);
2025-09-05 14:37:31 +01:00
newMap.delete(fileId as FileId);
2025-09-04 12:11:09 +01:00
return newMap;
});
}
2025-09-10 10:03:35 +01:00
}, [expandedFileIds, recentFiles]);
2025-09-02 17:24:26 +01:00
2025-09-10 10:03:35 +01:00
const handleAddToRecents = useCallback(async (file: StoredFileMetadata) => {
2025-09-02 17:24:26 +01:00
try {
2025-09-10 10:03:35 +01:00
console.log('Adding to recents:', file.name, 'version:', file.versionNumber);
// Load file from storage and use addStoredFiles pattern
2025-09-02 17:24:26 +01:00
const storedFile = await fileStorage.getFile(file.id);
2025-09-10 10:03:35 +01:00
if (!storedFile) {
throw new Error(`File not found in storage: ${file.name}`);
2025-09-02 17:24:26 +01:00
}
2025-09-10 10:03:35 +01:00
// Use direct StoredFile approach - much more efficient
onStoredFilesSelect([storedFile]);
console.log('Successfully added to recents:', file.name, 'v' + file.versionNumber);
2025-09-02 17:24:26 +01:00
} catch (error) {
2025-09-10 10:03:35 +01:00
console.error('Failed to add to recents:', error);
2025-09-02 17:24:26 +01:00
}
2025-09-10 10:03:35 +01:00
}, [onStoredFilesSelect]);
// Cleanup blob URLs when component unmounts
useEffect(() => {
return () => {
// Clean up all created blob URLs
createdBlobUrls.current.forEach(url => {
URL.revokeObjectURL(url);
});
createdBlobUrls.current.clear();
};
}, []);
// Reset state when modal closes
useEffect(() => {
if (!isOpen) {
setActiveSource('recent');
setSelectedFileIds([]);
setSearchTerm('');
setLastClickedIndex(null);
}
}, [isOpen]);
Feature/v2/file handling improvements (#4222) # Description of Changes A new universal file context rather than the splintered ones for the main views, tools and manager we had before (manager still has its own but its better integreated with the core context) File context has been split it into a handful of different files managing various file related issues separately to reduce the monolith - FileReducer.ts - State management fileActions.ts - File operations fileSelectors.ts - Data access patterns lifecycle.ts - Resource cleanup and memory management fileHooks.ts - React hooks interface contexts.ts - Context providers Improved thumbnail generation Improved indexxedb handling Stopped handling files as blobs were not necessary to improve performance A new library handling drag and drop https://github.com/atlassian/pragmatic-drag-and-drop (Out of scope yes but I broke the old one with the new filecontext and it needed doing so it was a might as well) A new library handling virtualisation on page editor @tanstack/react-virtual, as above. Quickly ripped out the last remnants of the old URL params stuff and replaced with the beginnings of what will later become the new URL navigation system (for now it just restores the tool name in url behavior) Fixed selected file not regestered when opening a tool Fixed png thumbnails Closes #(issue_number) --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --------- Co-authored-by: Reece Browne <you@example.com>
2025-08-21 17:30:26 +01:00
const contextValue: FileManagerContextValue = useMemo(() => ({
// State
activeSource,
selectedFileIds,
searchTerm,
selectedFiles,
filteredFiles,
fileInputRef,
selectedFilesSet,
2025-09-03 17:47:58 +01:00
expandedFileIds,
2025-09-02 17:24:26 +01:00
fileGroups,
// Handlers
onSourceChange: handleSourceChange,
onLocalFileClick: handleLocalFileClick,
onFileSelect: handleFileSelect,
onFileRemove: handleFileRemove,
onFileDoubleClick: handleFileDoubleClick,
onOpenFiles: handleOpenFiles,
onSearchChange: handleSearchChange,
onFileInputChange: handleFileInputChange,
onSelectAll: handleSelectAll,
onDeleteSelected: handleDeleteSelected,
onDownloadSelected: handleDownloadSelected,
onDownloadSingle: handleDownloadSingle,
2025-09-03 17:47:58 +01:00
onToggleExpansion: handleToggleExpansion,
onAddToRecents: handleAddToRecents,
2025-09-02 17:24:26 +01:00
onNewFilesSelect,
// External props
recentFiles,
isFileSupported,
modalHeight,
Feature/v2/file handling improvements (#4222) # Description of Changes A new universal file context rather than the splintered ones for the main views, tools and manager we had before (manager still has its own but its better integreated with the core context) File context has been split it into a handful of different files managing various file related issues separately to reduce the monolith - FileReducer.ts - State management fileActions.ts - File operations fileSelectors.ts - Data access patterns lifecycle.ts - Resource cleanup and memory management fileHooks.ts - React hooks interface contexts.ts - Context providers Improved thumbnail generation Improved indexxedb handling Stopped handling files as blobs were not necessary to improve performance A new library handling drag and drop https://github.com/atlassian/pragmatic-drag-and-drop (Out of scope yes but I broke the old one with the new filecontext and it needed doing so it was a might as well) A new library handling virtualisation on page editor @tanstack/react-virtual, as above. Quickly ripped out the last remnants of the old URL params stuff and replaced with the beginnings of what will later become the new URL navigation system (for now it just restores the tool name in url behavior) Fixed selected file not regestered when opening a tool Fixed png thumbnails Closes #(issue_number) --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --------- Co-authored-by: Reece Browne <you@example.com>
2025-08-21 17:30:26 +01:00
}), [
activeSource,
selectedFileIds,
searchTerm,
selectedFiles,
filteredFiles,
fileInputRef,
2025-09-03 17:47:58 +01:00
expandedFileIds,
2025-09-02 17:24:26 +01:00
fileGroups,
Feature/v2/file handling improvements (#4222) # Description of Changes A new universal file context rather than the splintered ones for the main views, tools and manager we had before (manager still has its own but its better integreated with the core context) File context has been split it into a handful of different files managing various file related issues separately to reduce the monolith - FileReducer.ts - State management fileActions.ts - File operations fileSelectors.ts - Data access patterns lifecycle.ts - Resource cleanup and memory management fileHooks.ts - React hooks interface contexts.ts - Context providers Improved thumbnail generation Improved indexxedb handling Stopped handling files as blobs were not necessary to improve performance A new library handling drag and drop https://github.com/atlassian/pragmatic-drag-and-drop (Out of scope yes but I broke the old one with the new filecontext and it needed doing so it was a might as well) A new library handling virtualisation on page editor @tanstack/react-virtual, as above. Quickly ripped out the last remnants of the old URL params stuff and replaced with the beginnings of what will later become the new URL navigation system (for now it just restores the tool name in url behavior) Fixed selected file not regestered when opening a tool Fixed png thumbnails Closes #(issue_number) --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --------- Co-authored-by: Reece Browne <you@example.com>
2025-08-21 17:30:26 +01:00
handleSourceChange,
handleLocalFileClick,
handleFileSelect,
handleFileRemove,
handleFileDoubleClick,
handleOpenFiles,
handleSearchChange,
handleFileInputChange,
handleSelectAll,
handleDeleteSelected,
handleDownloadSelected,
2025-09-03 17:47:58 +01:00
handleToggleExpansion,
handleAddToRecents,
2025-09-02 17:24:26 +01:00
onNewFilesSelect,
Feature/v2/file handling improvements (#4222) # Description of Changes A new universal file context rather than the splintered ones for the main views, tools and manager we had before (manager still has its own but its better integreated with the core context) File context has been split it into a handful of different files managing various file related issues separately to reduce the monolith - FileReducer.ts - State management fileActions.ts - File operations fileSelectors.ts - Data access patterns lifecycle.ts - Resource cleanup and memory management fileHooks.ts - React hooks interface contexts.ts - Context providers Improved thumbnail generation Improved indexxedb handling Stopped handling files as blobs were not necessary to improve performance A new library handling drag and drop https://github.com/atlassian/pragmatic-drag-and-drop (Out of scope yes but I broke the old one with the new filecontext and it needed doing so it was a might as well) A new library handling virtualisation on page editor @tanstack/react-virtual, as above. Quickly ripped out the last remnants of the old URL params stuff and replaced with the beginnings of what will later become the new URL navigation system (for now it just restores the tool name in url behavior) Fixed selected file not regestered when opening a tool Fixed png thumbnails Closes #(issue_number) --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --------- Co-authored-by: Reece Browne <you@example.com>
2025-08-21 17:30:26 +01:00
recentFiles,
isFileSupported,
modalHeight,
]);
return (
<FileManagerContext.Provider value={contextValue}>
{children}
</FileManagerContext.Provider>
);
};
// Custom hook to use the context
export const useFileManagerContext = (): FileManagerContextValue => {
const context = useContext(FileManagerContext);
if (!context) {
throw new Error(
'useFileManagerContext must be used within a FileManagerProvider. ' +
'Make sure you wrap your component with <FileManagerProvider>.'
);
}
return context;
};
// Export the context for advanced use cases
export { FileManagerContext };