mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-09-18 09:29:24 +00:00
bulk deleted
This commit is contained in:
parent
410a6b8e9d
commit
2b60f56ddc
@ -230,63 +230,79 @@ export const FileManagerProvider: React.FC<FileManagerProviderProps> = ({
|
|||||||
return safeToDelete;
|
return safeToDelete;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// Shared internal delete logic
|
||||||
|
const performFileDelete = useCallback(async (fileToRemove: StirlingFileStub, fileIndex: number) => {
|
||||||
|
const deletedFileId = fileToRemove.id;
|
||||||
|
|
||||||
|
// Get all stored files to analyze lineages
|
||||||
|
const allStoredStubs = await fileStorage.getAllStirlingFileStubs();
|
||||||
|
|
||||||
|
// Get safe files to delete (respecting shared lineages)
|
||||||
|
const filesToDelete = getSafeFilesToDelete([deletedFileId as string], allStoredStubs);
|
||||||
|
|
||||||
|
console.log(`Safely deleting files for ${fileToRemove.name}:`, filesToDelete);
|
||||||
|
|
||||||
|
// Clear from selection immediately
|
||||||
|
setSelectedFileIds(prev => prev.filter(id => !filesToDelete.includes(id)));
|
||||||
|
|
||||||
|
// Clear from expanded state to prevent ghost entries
|
||||||
|
setExpandedFileIds(prev => {
|
||||||
|
const newExpanded = new Set(prev);
|
||||||
|
filesToDelete.forEach(id => newExpanded.delete(id));
|
||||||
|
return newExpanded;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Clear from history cache - remove all files in the chain
|
||||||
|
setLoadedHistoryFiles(prev => {
|
||||||
|
const newCache = new Map(prev);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newCache;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Delete safe files from IndexedDB
|
||||||
|
try {
|
||||||
|
for (const fileId of filesToDelete) {
|
||||||
|
await fileStorage.deleteStirlingFile(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
|
||||||
|
onFileRemove(fileIndex);
|
||||||
|
|
||||||
|
// Refresh to ensure consistent state
|
||||||
|
await refreshRecentFiles();
|
||||||
|
}, [getSafeFilesToDelete, setSelectedFileIds, setExpandedFileIds, setLoadedHistoryFiles, onFileRemove, refreshRecentFiles]);
|
||||||
|
|
||||||
const handleFileRemove = useCallback(async (index: number) => {
|
const handleFileRemove = useCallback(async (index: number) => {
|
||||||
const fileToRemove = filteredFiles[index];
|
const fileToRemove = filteredFiles[index];
|
||||||
if (fileToRemove) {
|
if (fileToRemove) {
|
||||||
const deletedFileId = fileToRemove.id;
|
await performFileDelete(fileToRemove, index);
|
||||||
|
|
||||||
// Get all stored files to analyze lineages
|
|
||||||
const allStoredStubs = await fileStorage.getAllStirlingFileStubs();
|
|
||||||
|
|
||||||
// Get safe files to delete (respecting shared lineages)
|
|
||||||
const filesToDelete = getSafeFilesToDelete([deletedFileId as string], allStoredStubs);
|
|
||||||
|
|
||||||
console.log(`Safely deleting files for ${fileToRemove.name}:`, filesToDelete);
|
|
||||||
|
|
||||||
// Clear from selection immediately
|
|
||||||
setSelectedFileIds(prev => prev.filter(id => !filesToDelete.includes(id)));
|
|
||||||
|
|
||||||
// Clear from expanded state to prevent ghost entries
|
|
||||||
setExpandedFileIds(prev => {
|
|
||||||
const newExpanded = new Set(prev);
|
|
||||||
filesToDelete.forEach(id => newExpanded.delete(id));
|
|
||||||
return newExpanded;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Clear from history cache - remove all files in the chain
|
|
||||||
setLoadedHistoryFiles(prev => {
|
|
||||||
const newCache = new Map(prev);
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newCache;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Delete safe files from IndexedDB
|
|
||||||
try {
|
|
||||||
for (const fileId of filesToDelete) {
|
|
||||||
await fileStorage.deleteStirlingFile(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
|
|
||||||
onFileRemove(index);
|
|
||||||
|
|
||||||
// Refresh to ensure consistent state
|
|
||||||
await refreshRecentFiles();
|
|
||||||
}
|
}
|
||||||
}, [filteredFiles, onFileRemove, refreshRecentFiles, getSafeFilesToDelete]);
|
}, [filteredFiles, performFileDelete]);
|
||||||
|
|
||||||
|
// Handle deletion by fileId (more robust than index-based)
|
||||||
|
const handleFileRemoveById = useCallback(async (fileId: FileId) => {
|
||||||
|
// Find the file and its index in filteredFiles
|
||||||
|
const fileIndex = filteredFiles.findIndex(file => file.id === fileId);
|
||||||
|
const fileToRemove = filteredFiles[fileIndex];
|
||||||
|
|
||||||
|
if (fileToRemove && fileIndex !== -1) {
|
||||||
|
await performFileDelete(fileToRemove, fileIndex);
|
||||||
|
}
|
||||||
|
}, [filteredFiles, performFileDelete]);
|
||||||
|
|
||||||
// Handle deletion of specific history files (not index-based)
|
// Handle deletion of specific history files (not index-based)
|
||||||
const handleHistoryFileRemove = useCallback(async (fileToRemove: StirlingFileStub) => {
|
const handleHistoryFileRemove = useCallback(async (fileToRemove: StirlingFileStub) => {
|
||||||
@ -378,53 +394,14 @@ export const FileManagerProvider: React.FC<FileManagerProviderProps> = ({
|
|||||||
if (selectedFileIds.length === 0) return;
|
if (selectedFileIds.length === 0) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Get all stored files to analyze lineages
|
// Delete each selected file using the proven single delete logic
|
||||||
const allStoredStubs = await fileStorage.getAllStirlingFileStubs();
|
for (const fileId of selectedFileIds) {
|
||||||
|
await handleFileRemoveById(fileId);
|
||||||
// Get safe files to delete (respecting shared lineages)
|
|
||||||
const filesToDelete = getSafeFilesToDelete(selectedFileIds, allStoredStubs);
|
|
||||||
|
|
||||||
console.log(`Bulk safely deleting files and their history chains:`, filesToDelete);
|
|
||||||
|
|
||||||
// Update history cache synchronously
|
|
||||||
setLoadedHistoryFiles(prev => {
|
|
||||||
const newCache = new Map(prev);
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newCache;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Also clear any expanded state for deleted files to prevent ghost entries
|
|
||||||
setExpandedFileIds(prev => {
|
|
||||||
const newExpanded = new Set(prev);
|
|
||||||
filesToDelete.forEach(id => newExpanded.delete(id));
|
|
||||||
return newExpanded;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Clear selection immediately to prevent ghost selections
|
|
||||||
setSelectedFileIds(prev => prev.filter(id => !filesToDelete.includes(id)));
|
|
||||||
|
|
||||||
// Delete safe files from IndexedDB
|
|
||||||
for (const fileId of filesToDelete) {
|
|
||||||
await fileStorage.deleteStirlingFile(fileId as FileId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refresh the file list to get updated data
|
|
||||||
await refreshRecentFiles();
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to delete selected files:', error);
|
console.error('Failed to delete selected files:', error);
|
||||||
}
|
}
|
||||||
}, [selectedFileIds, filteredFiles, refreshRecentFiles, getSafeFilesToDelete]);
|
}, [selectedFileIds, handleFileRemoveById]);
|
||||||
|
|
||||||
|
|
||||||
const handleDownloadSelected = useCallback(async () => {
|
const handleDownloadSelected = useCallback(async () => {
|
||||||
@ -612,6 +589,8 @@ export const FileManagerProvider: React.FC<FileManagerProviderProps> = ({
|
|||||||
handleLocalFileClick,
|
handleLocalFileClick,
|
||||||
handleFileSelect,
|
handleFileSelect,
|
||||||
handleFileRemove,
|
handleFileRemove,
|
||||||
|
handleFileRemoveById,
|
||||||
|
performFileDelete,
|
||||||
handleFileDoubleClick,
|
handleFileDoubleClick,
|
||||||
handleOpenFiles,
|
handleOpenFiles,
|
||||||
handleSearchChange,
|
handleSearchChange,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user