mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-09-03 17:52:30 +02:00
Automatically select added files (#4325)
# Description of Changes When adding files, the user probably wants to use them straight away in the next tool that they use, so automatically select any added files (in addition to whatever they previously had selected).
This commit is contained in:
parent
eecc410b77
commit
3b28b398d9
@ -25,7 +25,7 @@ import {
|
|||||||
// Import modular components
|
// Import modular components
|
||||||
import { fileContextReducer, initialFileContextState } from './file/FileReducer';
|
import { fileContextReducer, initialFileContextState } from './file/FileReducer';
|
||||||
import { createFileSelectors } from './file/fileSelectors';
|
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 { FileLifecycleManager } from './file/lifecycle';
|
||||||
import { FileStateContext, FileActionsContext } from './file/contexts';
|
import { FileStateContext, FileActionsContext } from './file/contexts';
|
||||||
import { IndexedDBProvider, useIndexedDB } from './IndexedDBContext';
|
import { IndexedDBProvider, useIndexedDB } from './IndexedDBContext';
|
||||||
@ -72,9 +72,21 @@ function FileContextInner({
|
|||||||
dispatch({ type: 'SET_UNSAVED_CHANGES', payload: { hasChanges } });
|
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
|
// File operations using unified addFiles helper with persistence
|
||||||
const addRawFiles = useCallback(async (files: File[], options?: { insertAfterPageId?: string }): Promise<File[]> => {
|
const addRawFiles = useCallback(async (files: File[], options?: { insertAfterPageId?: string; selectFiles?: boolean }): Promise<File[]> => {
|
||||||
const addedFilesWithIds = await addFiles('raw', { files, ...options }, stateRef, filesRef, dispatch, lifecycleManager);
|
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
|
// Persist to IndexedDB if enabled
|
||||||
if (indexedDB && enablePersistence && addedFilesWithIds.length > 0) {
|
if (indexedDB && enablePersistence && addedFilesWithIds.length > 0) {
|
||||||
await Promise.all(addedFilesWithIds.map(async ({ file, id, thumbnail }) => {
|
await Promise.all(addedFilesWithIds.map(async ({ file, id, thumbnail }) => {
|
||||||
@ -94,8 +106,14 @@ function FileContextInner({
|
|||||||
return result.map(({ file }) => file);
|
return result.map(({ file }) => file);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const addStoredFiles = useCallback(async (filesWithMetadata: Array<{ file: File; originalId: FileId; metadata: any }>): Promise<File[]> => {
|
const addStoredFiles = useCallback(async (filesWithMetadata: Array<{ file: File; originalId: FileId; metadata: any }>, options?: { selectFiles?: boolean }): Promise<File[]> => {
|
||||||
const result = await addFiles('stored', { filesWithMetadata }, stateRef, filesRef, dispatch, lifecycleManager);
|
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);
|
return result.map(({ file }) => file);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
@ -88,6 +88,12 @@ interface AddFileOptions {
|
|||||||
insertAfterPageId?: string;
|
insertAfterPageId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AddedFile {
|
||||||
|
file: File;
|
||||||
|
id: FileId;
|
||||||
|
thumbnail?: string;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unified file addition helper - replaces addFiles/addProcessedFiles/addStoredFiles
|
* Unified file addition helper - replaces addFiles/addProcessedFiles/addStoredFiles
|
||||||
*/
|
*/
|
||||||
@ -98,13 +104,13 @@ export async function addFiles(
|
|||||||
filesRef: React.MutableRefObject<Map<FileId, File>>,
|
filesRef: React.MutableRefObject<Map<FileId, File>>,
|
||||||
dispatch: React.Dispatch<FileContextAction>,
|
dispatch: React.Dispatch<FileContextAction>,
|
||||||
lifecycleManager: FileLifecycleManager
|
lifecycleManager: FileLifecycleManager
|
||||||
): Promise<Array<{ file: File; id: FileId; thumbnail?: string }>> {
|
): Promise<AddedFile[]> {
|
||||||
// Acquire mutex to prevent race conditions
|
// Acquire mutex to prevent race conditions
|
||||||
await addFilesMutex.lock();
|
await addFilesMutex.lock();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const fileRecords: FileRecord[] = [];
|
const fileRecords: FileRecord[] = [];
|
||||||
const addedFiles: Array<{ file: File; id: FileId; thumbnail?: string }> = [];
|
const addedFiles: AddedFile[] = [];
|
||||||
|
|
||||||
// Build quickKey lookup from existing files for deduplication
|
// Build quickKey lookup from existing files for deduplication
|
||||||
const existingQuickKeys = buildQuickKeySet(stateRef.current.files.byId);
|
const existingQuickKeys = buildQuickKeySet(stateRef.current.files.byId);
|
||||||
|
@ -9,12 +9,12 @@ export const useFileHandler = () => {
|
|||||||
|
|
||||||
const addToActiveFiles = useCallback(async (file: File) => {
|
const addToActiveFiles = useCallback(async (file: File) => {
|
||||||
// Let FileContext handle deduplication with quickKey logic
|
// Let FileContext handle deduplication with quickKey logic
|
||||||
await actions.addFiles([file]);
|
await actions.addFiles([file], { selectFiles: true });
|
||||||
}, [actions.addFiles]);
|
}, [actions.addFiles]);
|
||||||
|
|
||||||
const addMultipleFiles = useCallback(async (files: File[]) => {
|
const addMultipleFiles = useCallback(async (files: File[]) => {
|
||||||
// Let FileContext handle deduplication with quickKey logic
|
// Let FileContext handle deduplication with quickKey logic
|
||||||
await actions.addFiles(files);
|
await actions.addFiles(files, { selectFiles: true });
|
||||||
}, [actions.addFiles]);
|
}, [actions.addFiles]);
|
||||||
|
|
||||||
// Add stored files preserving their original IDs to prevent session duplicates
|
// Add stored files preserving their original IDs to prevent session duplicates
|
||||||
@ -25,7 +25,7 @@ export const useFileHandler = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (newFiles.length > 0) {
|
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)`);
|
console.log(`📁 Added ${newFiles.length} stored files (${filesWithMetadata.length - newFiles.length} skipped as duplicates)`);
|
||||||
|
@ -214,9 +214,9 @@ export type FileContextAction =
|
|||||||
|
|
||||||
export interface FileContextActions {
|
export interface FileContextActions {
|
||||||
// File management - lightweight actions only
|
// File management - lightweight actions only
|
||||||
addFiles: (files: File[], options?: { insertAfterPageId?: string }) => Promise<File[]>;
|
addFiles: (files: File[], options?: { insertAfterPageId?: string; selectFiles?: boolean }) => Promise<File[]>;
|
||||||
addProcessedFiles: (filesWithThumbnails: Array<{ file: File; thumbnail?: string; pageCount?: number }>) => Promise<File[]>;
|
addProcessedFiles: (filesWithThumbnails: Array<{ file: File; thumbnail?: string; pageCount?: number }>) => Promise<File[]>;
|
||||||
addStoredFiles: (filesWithMetadata: Array<{ file: File; originalId: FileId; metadata: FileMetadata }>) => Promise<File[]>;
|
addStoredFiles: (filesWithMetadata: Array<{ file: File; originalId: FileId; metadata: FileMetadata }>, options?: { selectFiles?: boolean }) => Promise<File[]>;
|
||||||
removeFiles: (fileIds: FileId[], deleteFromStorage?: boolean) => Promise<void>;
|
removeFiles: (fileIds: FileId[], deleteFromStorage?: boolean) => Promise<void>;
|
||||||
updateFileRecord: (id: FileId, updates: Partial<FileRecord>) => void;
|
updateFileRecord: (id: FileId, updates: Partial<FileRecord>) => void;
|
||||||
reorderFiles: (orderedFileIds: FileId[]) => void;
|
reorderFiles: (orderedFileIds: FileId[]) => void;
|
||||||
|
Loading…
Reference in New Issue
Block a user