diff --git a/frontend/src/contexts/FileContext.tsx b/frontend/src/contexts/FileContext.tsx index 05fdc9a9a..0698310b4 100644 --- a/frontend/src/contexts/FileContext.tsx +++ b/frontend/src/contexts/FileContext.tsx @@ -25,7 +25,7 @@ import { // Import modular components import { fileContextReducer, initialFileContextState } from './file/FileReducer'; import { createFileSelectors } from './file/fileSelectors'; -import { addFiles, consumeFiles, createFileActions } from './file/fileActions'; +import { AddedFile, addFiles, consumeFiles, createFileActions } from './file/fileActions'; import { FileLifecycleManager } from './file/lifecycle'; import { FileStateContext, FileActionsContext } from './file/contexts'; import { IndexedDBProvider, useIndexedDB } from './IndexedDBContext'; @@ -72,9 +72,21 @@ function FileContextInner({ dispatch({ type: 'SET_UNSAVED_CHANGES', payload: { hasChanges } }); }, []); + const selectFiles = (addedFilesWithIds: AddedFile[]) => { + const currentSelection = stateRef.current.ui.selectedFileIds; + const newFileIds = addedFilesWithIds.map(({ id }) => id); + dispatch({ type: 'SET_SELECTED_FILES', payload: { fileIds: [...currentSelection, ...newFileIds] } }); + } + // File operations using unified addFiles helper with persistence - const addRawFiles = useCallback(async (files: File[], options?: { insertAfterPageId?: string }): Promise => { + const addRawFiles = useCallback(async (files: File[], options?: { insertAfterPageId?: string; selectFiles?: boolean }): Promise => { const addedFilesWithIds = await addFiles('raw', { files, ...options }, stateRef, filesRef, dispatch, lifecycleManager); + + // Auto-select the newly added files if requested + if (options?.selectFiles && addedFilesWithIds.length > 0) { + selectFiles(addedFilesWithIds); + } + // Persist to IndexedDB if enabled if (indexedDB && enablePersistence && addedFilesWithIds.length > 0) { await Promise.all(addedFilesWithIds.map(async ({ file, id, thumbnail }) => { @@ -94,8 +106,14 @@ function FileContextInner({ return result.map(({ file }) => file); }, []); - const addStoredFiles = useCallback(async (filesWithMetadata: Array<{ file: File; originalId: FileId; metadata: any }>): Promise => { + const addStoredFiles = useCallback(async (filesWithMetadata: Array<{ file: File; originalId: FileId; metadata: any }>, options?: { selectFiles?: boolean }): Promise => { const result = await addFiles('stored', { filesWithMetadata }, stateRef, filesRef, dispatch, lifecycleManager); + + // Auto-select the newly added files if requested + if (options?.selectFiles && result.length > 0) { + selectFiles(result); + } + return result.map(({ file }) => file); }, []); diff --git a/frontend/src/contexts/file/fileActions.ts b/frontend/src/contexts/file/fileActions.ts index d0c565783..8d91f8855 100644 --- a/frontend/src/contexts/file/fileActions.ts +++ b/frontend/src/contexts/file/fileActions.ts @@ -88,6 +88,12 @@ interface AddFileOptions { insertAfterPageId?: string; } +export interface AddedFile { + file: File; + id: FileId; + thumbnail?: string; +} + /** * Unified file addition helper - replaces addFiles/addProcessedFiles/addStoredFiles */ @@ -98,13 +104,13 @@ export async function addFiles( filesRef: React.MutableRefObject>, dispatch: React.Dispatch, lifecycleManager: FileLifecycleManager -): Promise> { +): Promise { // Acquire mutex to prevent race conditions await addFilesMutex.lock(); try { const fileRecords: FileRecord[] = []; - const addedFiles: Array<{ file: File; id: FileId; thumbnail?: string }> = []; + const addedFiles: AddedFile[] = []; // Build quickKey lookup from existing files for deduplication const existingQuickKeys = buildQuickKeySet(stateRef.current.files.byId); diff --git a/frontend/src/hooks/useFileHandler.ts b/frontend/src/hooks/useFileHandler.ts index 475affa6f..8c2a4e2a1 100644 --- a/frontend/src/hooks/useFileHandler.ts +++ b/frontend/src/hooks/useFileHandler.ts @@ -9,12 +9,12 @@ export const useFileHandler = () => { const addToActiveFiles = useCallback(async (file: File) => { // Let FileContext handle deduplication with quickKey logic - await actions.addFiles([file]); + await actions.addFiles([file], { selectFiles: true }); }, [actions.addFiles]); const addMultipleFiles = useCallback(async (files: File[]) => { // Let FileContext handle deduplication with quickKey logic - await actions.addFiles(files); + await actions.addFiles(files, { selectFiles: true }); }, [actions.addFiles]); // Add stored files preserving their original IDs to prevent session duplicates @@ -25,7 +25,7 @@ export const useFileHandler = () => { }); if (newFiles.length > 0) { - await actions.addStoredFiles(newFiles); + await actions.addStoredFiles(newFiles, { selectFiles: true }); } console.log(`📁 Added ${newFiles.length} stored files (${filesWithMetadata.length - newFiles.length} skipped as duplicates)`); diff --git a/frontend/src/types/fileContext.ts b/frontend/src/types/fileContext.ts index 644b3dbfe..d9bd8751e 100644 --- a/frontend/src/types/fileContext.ts +++ b/frontend/src/types/fileContext.ts @@ -214,9 +214,9 @@ export type FileContextAction = export interface FileContextActions { // File management - lightweight actions only - addFiles: (files: File[], options?: { insertAfterPageId?: string }) => Promise; + addFiles: (files: File[], options?: { insertAfterPageId?: string; selectFiles?: boolean }) => Promise; addProcessedFiles: (filesWithThumbnails: Array<{ file: File; thumbnail?: string; pageCount?: number }>) => Promise; - addStoredFiles: (filesWithMetadata: Array<{ file: File; originalId: FileId; metadata: FileMetadata }>) => Promise; + addStoredFiles: (filesWithMetadata: Array<{ file: File; originalId: FileId; metadata: FileMetadata }>, options?: { selectFiles?: boolean }) => Promise; removeFiles: (fileIds: FileId[], deleteFromStorage?: boolean) => Promise; updateFileRecord: (id: FileId, updates: Partial) => void; reorderFiles: (orderedFileIds: FileId[]) => void;