mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-08-27 06:39:24 +00:00
228 lines
6.9 KiB
TypeScript
228 lines
6.9 KiB
TypeScript
![]() |
/**
|
||
|
* New performant file hooks - Clean API without legacy compatibility
|
||
|
*/
|
||
|
|
||
|
import { useContext, useMemo } from 'react';
|
||
|
import {
|
||
|
FileStateContext,
|
||
|
FileActionsContext,
|
||
|
FileContextStateValue,
|
||
|
FileContextActionsValue
|
||
|
} from './contexts';
|
||
|
import { FileId, FileRecord } from '../../types/fileContext';
|
||
|
|
||
|
/**
|
||
|
* Hook for accessing file state (will re-render on any state change)
|
||
|
* Use individual selector hooks below for better performance
|
||
|
*/
|
||
|
export function useFileState(): FileContextStateValue {
|
||
|
const context = useContext(FileStateContext);
|
||
|
if (!context) {
|
||
|
throw new Error('useFileState must be used within a FileContextProvider');
|
||
|
}
|
||
|
return context;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Hook for accessing file actions (stable - won't cause re-renders)
|
||
|
*/
|
||
|
export function useFileActions(): FileContextActionsValue {
|
||
|
const context = useContext(FileActionsContext);
|
||
|
if (!context) {
|
||
|
throw new Error('useFileActions must be used within a FileContextProvider');
|
||
|
}
|
||
|
return context;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Hook for current/primary file (first in list)
|
||
|
*/
|
||
|
export function useCurrentFile(): { file?: File; record?: FileRecord } {
|
||
|
const { state, selectors } = useFileState();
|
||
|
|
||
|
const primaryFileId = state.files.ids[0];
|
||
|
return useMemo(() => ({
|
||
|
file: primaryFileId ? selectors.getFile(primaryFileId) : undefined,
|
||
|
record: primaryFileId ? selectors.getFileRecord(primaryFileId) : undefined
|
||
|
}), [primaryFileId, selectors]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Hook for file selection state and actions
|
||
|
*/
|
||
|
export function useFileSelection() {
|
||
|
const { state } = useFileState();
|
||
|
const { actions } = useFileActions();
|
||
|
|
||
|
return useMemo(() => ({
|
||
|
selectedFileIds: state.ui.selectedFileIds,
|
||
|
selectedPageNumbers: state.ui.selectedPageNumbers,
|
||
|
setSelectedFiles: actions.setSelectedFiles,
|
||
|
setSelectedPages: actions.setSelectedPages,
|
||
|
clearSelections: actions.clearSelections
|
||
|
}), [
|
||
|
state.ui.selectedFileIds,
|
||
|
state.ui.selectedPageNumbers,
|
||
|
actions.setSelectedFiles,
|
||
|
actions.setSelectedPages,
|
||
|
actions.clearSelections
|
||
|
]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Hook for file management operations
|
||
|
*/
|
||
|
export function useFileManagement() {
|
||
|
const { actions } = useFileActions();
|
||
|
|
||
|
return useMemo(() => ({
|
||
|
addFiles: actions.addFiles,
|
||
|
removeFiles: actions.removeFiles,
|
||
|
clearAllFiles: actions.clearAllFiles,
|
||
|
updateFileRecord: actions.updateFileRecord
|
||
|
}), [actions]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Hook for UI state
|
||
|
*/
|
||
|
export function useFileUI() {
|
||
|
const { state } = useFileState();
|
||
|
const { actions } = useFileActions();
|
||
|
|
||
|
return useMemo(() => ({
|
||
|
isProcessing: state.ui.isProcessing,
|
||
|
processingProgress: state.ui.processingProgress,
|
||
|
hasUnsavedChanges: state.ui.hasUnsavedChanges,
|
||
|
setProcessing: actions.setProcessing,
|
||
|
setUnsavedChanges: actions.setHasUnsavedChanges
|
||
|
}), [state.ui, actions]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Hook for specific file by ID (optimized for individual file access)
|
||
|
*/
|
||
|
export function useFileRecord(fileId: FileId): { file?: File; record?: FileRecord } {
|
||
|
const { selectors } = useFileState();
|
||
|
|
||
|
return useMemo(() => ({
|
||
|
file: selectors.getFile(fileId),
|
||
|
record: selectors.getFileRecord(fileId)
|
||
|
}), [fileId, selectors]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Hook for all files (use sparingly - causes re-renders on file list changes)
|
||
|
*/
|
||
|
export function useAllFiles(): { files: File[]; records: FileRecord[]; fileIds: FileId[] } {
|
||
|
const { state, selectors } = useFileState();
|
||
|
|
||
|
return useMemo(() => ({
|
||
|
files: selectors.getFiles(),
|
||
|
records: selectors.getFileRecords(),
|
||
|
fileIds: state.files.ids
|
||
|
}), [state.files.ids, selectors]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Hook for selected files (optimized for selection-based UI)
|
||
|
*/
|
||
|
export function useSelectedFiles(): { files: File[]; records: FileRecord[]; fileIds: FileId[] } {
|
||
|
const { state, selectors } = useFileState();
|
||
|
|
||
|
return useMemo(() => ({
|
||
|
files: selectors.getSelectedFiles(),
|
||
|
records: selectors.getSelectedFileRecords(),
|
||
|
fileIds: state.ui.selectedFileIds
|
||
|
}), [state.ui.selectedFileIds, selectors]);
|
||
|
}
|
||
|
|
||
|
// Navigation management removed - moved to NavigationContext
|
||
|
|
||
|
/**
|
||
|
* Primary API hook for file context operations
|
||
|
* Used by tools for core file context functionality
|
||
|
*/
|
||
|
export function useFileContext() {
|
||
|
const { actions } = useFileActions();
|
||
|
|
||
|
return useMemo(() => ({
|
||
|
trackBlobUrl: actions.trackBlobUrl,
|
||
|
trackPdfDocument: actions.trackPdfDocument,
|
||
|
scheduleCleanup: actions.scheduleCleanup,
|
||
|
setUnsavedChanges: actions.setHasUnsavedChanges
|
||
|
}), [actions]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Primary API hook for tool file selection workflow
|
||
|
* Used by tools for managing file selection and tool-specific operations
|
||
|
*/
|
||
|
export function useToolFileSelection() {
|
||
|
const { state, selectors } = useFileState();
|
||
|
const { actions } = useFileActions();
|
||
|
|
||
|
// Memoize selected files to avoid recreating arrays
|
||
|
const selectedFiles = useMemo(() => {
|
||
|
return selectors.getSelectedFiles();
|
||
|
}, [state.ui.selectedFileIds, selectors]);
|
||
|
|
||
|
return useMemo(() => ({
|
||
|
selectedFiles,
|
||
|
selectedFileIds: state.ui.selectedFileIds,
|
||
|
selectedPageNumbers: state.ui.selectedPageNumbers,
|
||
|
setSelectedFiles: actions.setSelectedFiles,
|
||
|
setSelectedPages: actions.setSelectedPages,
|
||
|
clearSelections: actions.clearSelections,
|
||
|
// Tool workflow properties
|
||
|
maxFiles: 10, // Default value for tools
|
||
|
isToolMode: true,
|
||
|
setMaxFiles: (maxFiles: number) => { /* Tool-specific - can be implemented if needed */ },
|
||
|
setIsToolMode: (isToolMode: boolean) => { /* Tool-specific - can be implemented if needed */ }
|
||
|
}), [
|
||
|
selectedFiles,
|
||
|
state.ui.selectedFileIds,
|
||
|
state.ui.selectedPageNumbers,
|
||
|
actions.setSelectedFiles,
|
||
|
actions.setSelectedPages,
|
||
|
actions.clearSelections
|
||
|
]);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Hook for processed files (compatibility with old FileContext)
|
||
|
* Provides access to files with their processed metadata
|
||
|
*/
|
||
|
export function useProcessedFiles() {
|
||
|
const { state, selectors } = useFileState();
|
||
|
|
||
|
// Create a Map-like interface for backward compatibility
|
||
|
const compatibilityMap = useMemo(() => ({
|
||
|
size: state.files.ids.length,
|
||
|
get: (file: File) => {
|
||
|
// Find file record by matching File object properties
|
||
|
const record = Object.values(state.files.byId).find(r =>
|
||
|
r.name === file.name && r.size === file.size && r.lastModified === file.lastModified
|
||
|
);
|
||
|
return record?.processedFile || null;
|
||
|
},
|
||
|
has: (file: File) => {
|
||
|
// Find file record by matching File object properties
|
||
|
const record = Object.values(state.files.byId).find(r =>
|
||
|
r.name === file.name && r.size === file.size && r.lastModified === file.lastModified
|
||
|
);
|
||
|
return !!record?.processedFile;
|
||
|
},
|
||
|
set: () => {
|
||
|
console.warn('processedFiles.set is deprecated - use FileRecord updates instead');
|
||
|
}
|
||
|
}), [state.files.byId, state.files.ids.length]);
|
||
|
|
||
|
return useMemo(() => ({
|
||
|
processedFiles: compatibilityMap,
|
||
|
getProcessedFile: (file: File) => compatibilityMap.get(file),
|
||
|
updateProcessedFile: () => {
|
||
|
console.warn('updateProcessedFile is deprecated - processed files are now stored in FileRecord');
|
||
|
}
|
||
|
}), [compatibilityMap]);
|
||
|
}
|