mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-08-26 14:19:24 +00:00
clean up
This commit is contained in:
parent
f181c18f4f
commit
7247edc029
@ -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, buildQuickKeySetFromMetadata } from './file/fileSelectors';
|
import { createFileSelectors } from './file/fileSelectors';
|
||||||
import { addFiles, consumeFiles, createFileActions } from './file/fileActions';
|
import { 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';
|
||||||
@ -76,7 +76,7 @@ function FileContextInner({
|
|||||||
const addRawFiles = useCallback(async (files: File[]): Promise<File[]> => {
|
const addRawFiles = useCallback(async (files: File[]): Promise<File[]> => {
|
||||||
const addedFilesWithIds = await addFiles('raw', { files }, stateRef, filesRef, dispatch, lifecycleManager);
|
const addedFilesWithIds = await addFiles('raw', { files }, stateRef, filesRef, dispatch, lifecycleManager);
|
||||||
|
|
||||||
// Persist to IndexedDB if enabled - pass existing thumbnail to prevent double generation
|
// 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 }) => {
|
||||||
try {
|
try {
|
||||||
|
@ -10,11 +10,10 @@ import { fileStorage, StoredFile } from '../services/fileStorage';
|
|||||||
import { FileId } from '../types/fileContext';
|
import { FileId } from '../types/fileContext';
|
||||||
import { FileMetadata } from '../types/file';
|
import { FileMetadata } from '../types/file';
|
||||||
import { generateThumbnailForFile } from '../utils/thumbnailUtils';
|
import { generateThumbnailForFile } from '../utils/thumbnailUtils';
|
||||||
import { pdfWorkerManager } from '../services/pdfWorkerManager';
|
|
||||||
|
|
||||||
interface IndexedDBContextValue {
|
interface IndexedDBContextValue {
|
||||||
// Core CRUD operations
|
// Core CRUD operations
|
||||||
saveFile: (file: File, fileId: FileId, thumbnail?: string) => Promise<FileMetadata>;
|
saveFile: (file: File, fileId: FileId, existingThumbnail?: string) => Promise<FileMetadata>;
|
||||||
loadFile: (fileId: FileId) => Promise<File | null>;
|
loadFile: (fileId: FileId) => Promise<File | null>;
|
||||||
loadMetadata: (fileId: FileId) => Promise<FileMetadata | null>;
|
loadMetadata: (fileId: FileId) => Promise<FileMetadata | null>;
|
||||||
deleteFile: (fileId: FileId) => Promise<void>;
|
deleteFile: (fileId: FileId) => Promise<void>;
|
||||||
@ -26,9 +25,6 @@ interface IndexedDBContextValue {
|
|||||||
|
|
||||||
// Utilities
|
// Utilities
|
||||||
getStorageStats: () => Promise<{ used: number; available: number; fileCount: number }>;
|
getStorageStats: () => Promise<{ used: number; available: number; fileCount: number }>;
|
||||||
|
|
||||||
// Draft operations
|
|
||||||
loadAllDraftMetadata: () => Promise<FileMetadata[]>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const IndexedDBContext = createContext<IndexedDBContextValue | null>(null);
|
const IndexedDBContext = createContext<IndexedDBContextValue | null>(null);
|
||||||
@ -60,44 +56,7 @@ export function IndexedDBProvider({ children }: IndexedDBProviderProps) {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const saveFile = useCallback(async (file: File, fileId: FileId, existingThumbnail?: string): Promise<FileMetadata> => {
|
const saveFile = useCallback(async (file: File, fileId: FileId, existingThumbnail?: string): Promise<FileMetadata> => {
|
||||||
// Check for duplicate at IndexedDB level before saving
|
// Use existing thumbnail or generate new one if none provided
|
||||||
const quickKey = `${file.name}|${file.size}|${file.lastModified}`;
|
|
||||||
const existingFiles = await fileStorage.getAllFileMetadata();
|
|
||||||
const duplicate = existingFiles.find(stored =>
|
|
||||||
`${stored.name}|${stored.size}|${stored.lastModified}` === quickKey
|
|
||||||
);
|
|
||||||
|
|
||||||
if (duplicate) {
|
|
||||||
if (DEBUG) console.log(`🔍 SAVE: Skipping IndexedDB duplicate - using existing record:`, duplicate.name);
|
|
||||||
// Return the existing file's metadata instead of saving duplicate
|
|
||||||
return {
|
|
||||||
id: duplicate.id,
|
|
||||||
name: duplicate.name,
|
|
||||||
type: duplicate.type,
|
|
||||||
size: duplicate.size,
|
|
||||||
lastModified: duplicate.lastModified,
|
|
||||||
thumbnail: duplicate.thumbnail
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEBUG: Check original file before saving
|
|
||||||
if (DEBUG && file.type === 'application/pdf') {
|
|
||||||
try {
|
|
||||||
const arrayBuffer = await file.arrayBuffer();
|
|
||||||
const pdf = await pdfWorkerManager.createDocument(arrayBuffer);
|
|
||||||
console.log(`🔍 BEFORE SAVE - Original file:`, {
|
|
||||||
name: file.name,
|
|
||||||
size: file.size,
|
|
||||||
arrayBufferSize: arrayBuffer.byteLength,
|
|
||||||
pages: pdf.numPages
|
|
||||||
});
|
|
||||||
pdfWorkerManager.destroyDocument(pdf);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`🔍 Error validating file before save:`, error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use existing thumbnail or generate new one
|
|
||||||
const thumbnail = existingThumbnail || await generateThumbnailForFile(file);
|
const thumbnail = existingThumbnail || await generateThumbnailForFile(file);
|
||||||
|
|
||||||
// Store in IndexedDB
|
// Store in IndexedDB
|
||||||
@ -127,12 +86,9 @@ export function IndexedDBProvider({ children }: IndexedDBProviderProps) {
|
|||||||
return cached.file;
|
return cached.file;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load from IndexedDB using the internal fileStorage (which wraps indexedDBManager)
|
// Load from IndexedDB
|
||||||
const storedFile = await fileStorage.getFile(fileId);
|
const storedFile = await fileStorage.getFile(fileId);
|
||||||
if (!storedFile) {
|
if (!storedFile) return null;
|
||||||
if (DEBUG) console.log(`📁 File not found in IndexedDB: ${fileId}`);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reconstruct File object
|
// Reconstruct File object
|
||||||
const file = new File([storedFile.data], storedFile.name, {
|
const file = new File([storedFile.data], storedFile.name, {
|
||||||
@ -140,27 +96,6 @@ export function IndexedDBProvider({ children }: IndexedDBProviderProps) {
|
|||||||
lastModified: storedFile.lastModified
|
lastModified: storedFile.lastModified
|
||||||
});
|
});
|
||||||
|
|
||||||
// DEBUG: Check if file reconstruction is working
|
|
||||||
if (DEBUG && file.type === 'application/pdf') {
|
|
||||||
console.log(`🔍 AFTER LOAD - Reconstructed file:`, {
|
|
||||||
name: file.name,
|
|
||||||
originalSize: storedFile.size,
|
|
||||||
reconstructedSize: file.size,
|
|
||||||
dataLength: storedFile.data.byteLength,
|
|
||||||
sizesMatch: storedFile.size === file.size
|
|
||||||
});
|
|
||||||
|
|
||||||
// Quick PDF validation
|
|
||||||
try {
|
|
||||||
const arrayBuffer = await file.arrayBuffer();
|
|
||||||
const pdf = await pdfWorkerManager.createDocument(arrayBuffer);
|
|
||||||
console.log(`🔍 AFTER LOAD - PDF validation: ${pdf.numPages} pages in reconstructed file`);
|
|
||||||
pdfWorkerManager.destroyDocument(pdf);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`🔍 AFTER LOAD - PDF reconstruction error:`, error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cache for future use with LRU eviction
|
// Cache for future use with LRU eviction
|
||||||
fileCache.current.set(fileId, { file, lastAccessed: Date.now() });
|
fileCache.current.set(fileId, { file, lastAccessed: Date.now() });
|
||||||
evictLRUEntries();
|
evictLRUEntries();
|
||||||
@ -239,40 +174,6 @@ export function IndexedDBProvider({ children }: IndexedDBProviderProps) {
|
|||||||
return await fileStorage.getStorageStats();
|
return await fileStorage.getStorageStats();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const loadAllDraftMetadata = useCallback(async (): Promise<FileMetadata[]> => {
|
|
||||||
try {
|
|
||||||
const { indexedDBManager, DATABASE_CONFIGS } = await import('../services/indexedDBManager');
|
|
||||||
const db = await indexedDBManager.openDatabase(DATABASE_CONFIGS.DRAFTS);
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const transaction = db.transaction(['drafts'], 'readonly');
|
|
||||||
const store = transaction.objectStore('drafts');
|
|
||||||
const request = store.getAll();
|
|
||||||
|
|
||||||
request.onsuccess = () => {
|
|
||||||
const drafts = request.result || [];
|
|
||||||
const draftMetadata: FileMetadata[] = drafts.map((draft: any) => ({
|
|
||||||
id: draft.id,
|
|
||||||
name: draft.name || `Draft ${draft.id}`,
|
|
||||||
type: 'application/pdf',
|
|
||||||
size: draft.size || 0,
|
|
||||||
lastModified: draft.timestamp || Date.now(),
|
|
||||||
thumbnail: draft.thumbnail,
|
|
||||||
isDraft: true
|
|
||||||
}));
|
|
||||||
resolve(draftMetadata);
|
|
||||||
};
|
|
||||||
|
|
||||||
request.onerror = () => reject(request.error);
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.warn('Failed to load draft metadata:', error);
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// No periodic cleanup needed - LRU eviction happens on-demand when cache fills
|
|
||||||
|
|
||||||
const value: IndexedDBContextValue = {
|
const value: IndexedDBContextValue = {
|
||||||
saveFile,
|
saveFile,
|
||||||
loadFile,
|
loadFile,
|
||||||
@ -281,8 +182,7 @@ export function IndexedDBProvider({ children }: IndexedDBProviderProps) {
|
|||||||
loadAllMetadata,
|
loadAllMetadata,
|
||||||
deleteMultiple,
|
deleteMultiple,
|
||||||
clearAll,
|
clearAll,
|
||||||
getStorageStats,
|
getStorageStats
|
||||||
loadAllDraftMetadata
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -217,7 +217,7 @@ export async function addFiles(
|
|||||||
try {
|
try {
|
||||||
if (DEBUG) console.log(`📄 addFiles(stored): Generating PDF metadata for stored file ${file.name}`);
|
if (DEBUG) console.log(`📄 addFiles(stored): Generating PDF metadata for stored file ${file.name}`);
|
||||||
|
|
||||||
// Use PDF worker manager directly for page count (avoids fileProcessingService conflicts)
|
// Get page count from PDF
|
||||||
const arrayBuffer = await file.arrayBuffer();
|
const arrayBuffer = await file.arrayBuffer();
|
||||||
const { pdfWorkerManager } = await import('../../services/pdfWorkerManager');
|
const { pdfWorkerManager } = await import('../../services/pdfWorkerManager');
|
||||||
const pdf = await pdfWorkerManager.createDocument(arrayBuffer);
|
const pdf = await pdfWorkerManager.createDocument(arrayBuffer);
|
||||||
@ -243,7 +243,6 @@ export async function addFiles(
|
|||||||
fileRecords.push(record);
|
fileRecords.push(record);
|
||||||
addedFiles.push({ file, id: fileId, thumbnail: metadata.thumbnail });
|
addedFiles.push({ file, id: fileId, thumbnail: metadata.thumbnail });
|
||||||
|
|
||||||
// Note: No background fileProcessingService call for stored files - we already processed them above
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user