mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-15 02:54:06 +02:00
Stirling 2.0 (#3928)
# Description of Changes <!-- File context for managing files between tools and views Optimisation for large files Updated Split to work with new file system and match Matts stepped design closer --> --- ## Checklist ### General - [ ] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [ ] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [ ] I have performed a self-review of my own code - [ ] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --------- Co-authored-by: Anthony Stirling <[email protected]>
This commit is contained in:
co-authored by
Anthony Stirling
parent
584e2ecee7
commit
922bbc9076
@@ -0,0 +1,178 @@
|
||||
/**
|
||||
* Types for global file context management across views and tools
|
||||
*/
|
||||
|
||||
import { ProcessedFile } from './processing';
|
||||
import { PDFDocument, PDFPage, PageOperation } from './pageEditor';
|
||||
|
||||
export type ModeType = 'viewer' | 'pageEditor' | 'fileEditor' | 'merge' | 'split' | 'compress';
|
||||
|
||||
// Legacy types for backward compatibility during transition
|
||||
export type ViewType = 'viewer' | 'pageEditor' | 'fileEditor';
|
||||
export type ToolType = 'merge' | 'split' | 'compress' | null;
|
||||
|
||||
export interface FileOperation {
|
||||
id: string;
|
||||
type: 'merge' | 'split' | 'compress' | 'add' | 'remove' | 'replace' | 'convert' | 'upload';
|
||||
timestamp: number;
|
||||
fileIds: string[];
|
||||
status: 'pending' | 'applied' | 'failed';
|
||||
data?: any;
|
||||
metadata?: {
|
||||
originalFileName?: string;
|
||||
outputFileNames?: string[];
|
||||
parameters?: Record<string, any>;
|
||||
fileSize?: number;
|
||||
pageCount?: number;
|
||||
error?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface FileOperationHistory {
|
||||
fileId: string;
|
||||
fileName: string;
|
||||
operations: (FileOperation | PageOperation)[];
|
||||
createdAt: number;
|
||||
lastModified: number;
|
||||
}
|
||||
|
||||
export interface ViewerConfig {
|
||||
zoom: number;
|
||||
currentPage: number;
|
||||
viewMode: 'single' | 'continuous' | 'facing';
|
||||
sidebarOpen: boolean;
|
||||
}
|
||||
|
||||
export interface FileEditHistory {
|
||||
fileId: string;
|
||||
pageOperations: PageOperation[];
|
||||
lastModified: number;
|
||||
}
|
||||
|
||||
export interface FileContextState {
|
||||
// Core file management
|
||||
activeFiles: File[];
|
||||
processedFiles: Map<File, ProcessedFile>;
|
||||
|
||||
// Current navigation state
|
||||
currentMode: ModeType;
|
||||
// Legacy fields for backward compatibility
|
||||
currentView: ViewType;
|
||||
currentTool: ToolType;
|
||||
|
||||
// Edit history and state
|
||||
fileEditHistory: Map<string, FileEditHistory>;
|
||||
globalFileOperations: FileOperation[];
|
||||
// New comprehensive operation history
|
||||
fileOperationHistory: Map<string, FileOperationHistory>;
|
||||
|
||||
// UI state that persists across views
|
||||
selectedFileIds: string[];
|
||||
selectedPageNumbers: number[];
|
||||
viewerConfig: ViewerConfig;
|
||||
|
||||
// Processing state
|
||||
isProcessing: boolean;
|
||||
processingProgress: number;
|
||||
|
||||
// Export state
|
||||
lastExportConfig?: {
|
||||
filename: string;
|
||||
selectedOnly: boolean;
|
||||
splitDocuments: boolean;
|
||||
};
|
||||
|
||||
// Navigation guard system
|
||||
hasUnsavedChanges: boolean;
|
||||
pendingNavigation: (() => void) | null;
|
||||
showNavigationWarning: boolean;
|
||||
}
|
||||
|
||||
export interface FileContextActions {
|
||||
// File management
|
||||
addFiles: (files: File[]) => Promise<void>;
|
||||
removeFiles: (fileIds: string[], deleteFromStorage?: boolean) => void;
|
||||
replaceFile: (oldFileId: string, newFile: File) => Promise<void>;
|
||||
clearAllFiles: () => void;
|
||||
|
||||
// Navigation
|
||||
setCurrentMode: (mode: ModeType) => void;
|
||||
// Legacy navigation functions for backward compatibility
|
||||
setCurrentView: (view: ViewType) => void;
|
||||
setCurrentTool: (tool: ToolType) => void;
|
||||
|
||||
// Selection management
|
||||
setSelectedFiles: (fileIds: string[]) => void;
|
||||
setSelectedPages: (pageNumbers: number[]) => void;
|
||||
updateProcessedFile: (file: File, processedFile: ProcessedFile) => void;
|
||||
clearSelections: () => void;
|
||||
|
||||
// Edit operations
|
||||
applyPageOperations: (fileId: string, operations: PageOperation[]) => void;
|
||||
applyFileOperation: (operation: FileOperation) => void;
|
||||
undoLastOperation: (fileId?: string) => void;
|
||||
|
||||
// Operation history management
|
||||
recordOperation: (fileId: string, operation: FileOperation | PageOperation) => void;
|
||||
markOperationApplied: (fileId: string, operationId: string) => void;
|
||||
markOperationFailed: (fileId: string, operationId: string, error: string) => void;
|
||||
getFileHistory: (fileId: string) => FileOperationHistory | undefined;
|
||||
getAppliedOperations: (fileId: string) => (FileOperation | PageOperation)[];
|
||||
clearFileHistory: (fileId: string) => void;
|
||||
|
||||
// Viewer state
|
||||
updateViewerConfig: (config: Partial<ViewerConfig>) => void;
|
||||
|
||||
// Export configuration
|
||||
setExportConfig: (config: FileContextState['lastExportConfig']) => void;
|
||||
|
||||
|
||||
// Utility
|
||||
getFileById: (fileId: string) => File | undefined;
|
||||
getProcessedFileById: (fileId: string) => ProcessedFile | undefined;
|
||||
getCurrentFile: () => File | undefined;
|
||||
getCurrentProcessedFile: () => ProcessedFile | undefined;
|
||||
|
||||
// Context persistence
|
||||
saveContext: () => Promise<void>;
|
||||
loadContext: () => Promise<void>;
|
||||
resetContext: () => void;
|
||||
|
||||
// Navigation guard system
|
||||
setHasUnsavedChanges: (hasChanges: boolean) => void;
|
||||
requestNavigation: (navigationFn: () => void) => boolean;
|
||||
confirmNavigation: () => void;
|
||||
cancelNavigation: () => void;
|
||||
|
||||
// Memory management
|
||||
trackBlobUrl: (url: string) => void;
|
||||
trackPdfDocument: (fileId: string, pdfDoc: any) => void;
|
||||
cleanupFile: (fileId: string) => Promise<void>;
|
||||
scheduleCleanup: (fileId: string, delay?: number) => void;
|
||||
}
|
||||
|
||||
export interface FileContextValue extends FileContextState, FileContextActions {}
|
||||
|
||||
export interface FileContextProviderProps {
|
||||
children: React.ReactNode;
|
||||
enableUrlSync?: boolean;
|
||||
enablePersistence?: boolean;
|
||||
maxCacheSize?: number;
|
||||
}
|
||||
|
||||
// Helper types for component props
|
||||
export interface WithFileContext {
|
||||
fileContext: FileContextValue;
|
||||
}
|
||||
|
||||
// URL parameter types for deep linking
|
||||
export interface FileContextUrlParams {
|
||||
mode?: ModeType;
|
||||
// Legacy parameters for backward compatibility
|
||||
view?: ViewType;
|
||||
tool?: ToolType;
|
||||
fileIds?: string[];
|
||||
pageIds?: string[];
|
||||
zoom?: number;
|
||||
page?: number;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
export interface PDFPage {
|
||||
id: string;
|
||||
pageNumber: number;
|
||||
thumbnail: string;
|
||||
thumbnail: string | null;
|
||||
rotation: number;
|
||||
selected: boolean;
|
||||
splitBefore?: boolean;
|
||||
@@ -16,12 +16,23 @@ export interface PDFDocument {
|
||||
}
|
||||
|
||||
export interface PageOperation {
|
||||
type: 'rotate' | 'delete' | 'move' | 'split' | 'insert';
|
||||
id: string;
|
||||
type: 'rotate' | 'delete' | 'move' | 'split' | 'insert' | 'reorder';
|
||||
pageIds: string[];
|
||||
timestamp: number;
|
||||
status: 'pending' | 'applied' | 'failed';
|
||||
data?: any;
|
||||
metadata?: {
|
||||
rotation?: number;
|
||||
fromPosition?: number;
|
||||
toPosition?: number;
|
||||
splitType?: string;
|
||||
insertAfterPage?: number;
|
||||
error?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface UndoRedoState {
|
||||
operations: PageOperation[];
|
||||
currentIndex: number;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
export interface ProcessingError {
|
||||
type: 'network' | 'parsing' | 'memory' | 'corruption' | 'timeout' | 'cancelled';
|
||||
message: string;
|
||||
recoverable: boolean;
|
||||
retryCount: number;
|
||||
maxRetries: number;
|
||||
originalError?: Error;
|
||||
}
|
||||
|
||||
export interface ProcessingState {
|
||||
fileKey: string;
|
||||
fileName: string;
|
||||
status: 'pending' | 'processing' | 'completed' | 'error' | 'cancelled';
|
||||
progress: number; // 0-100
|
||||
strategy: ProcessingStrategy;
|
||||
error?: ProcessingError;
|
||||
startedAt: number;
|
||||
completedAt?: number;
|
||||
estimatedTimeRemaining?: number;
|
||||
currentPage?: number;
|
||||
cancellationToken?: AbortController;
|
||||
}
|
||||
|
||||
export interface ProcessedFile {
|
||||
id: string;
|
||||
pages: PDFPage[];
|
||||
totalPages: number;
|
||||
metadata: {
|
||||
title: string;
|
||||
createdAt: string;
|
||||
modifiedAt: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface PDFPage {
|
||||
id: string;
|
||||
pageNumber: number;
|
||||
thumbnail: string | null;
|
||||
rotation: number;
|
||||
selected: boolean;
|
||||
splitBefore?: boolean;
|
||||
}
|
||||
|
||||
export interface CacheConfig {
|
||||
maxFiles: number;
|
||||
maxSizeBytes: number;
|
||||
ttlMs: number;
|
||||
}
|
||||
|
||||
export interface CacheEntry {
|
||||
data: ProcessedFile;
|
||||
size: number;
|
||||
lastAccessed: number;
|
||||
createdAt: number;
|
||||
}
|
||||
|
||||
export interface CacheStats {
|
||||
entries: number;
|
||||
totalSizeBytes: number;
|
||||
maxSizeBytes: number;
|
||||
}
|
||||
|
||||
export type ProcessingStrategy = 'immediate_full' | 'progressive_chunked' | 'metadata_only' | 'priority_pages';
|
||||
|
||||
export interface ProcessingConfig {
|
||||
strategy: ProcessingStrategy;
|
||||
chunkSize: number; // Pages per chunk
|
||||
thumbnailQuality: 'low' | 'medium' | 'high';
|
||||
priorityPageCount: number; // Number of priority pages to process first
|
||||
useWebWorker: boolean;
|
||||
maxRetries: number;
|
||||
timeoutMs: number;
|
||||
}
|
||||
|
||||
export interface FileAnalysis {
|
||||
fileSize: number;
|
||||
estimatedPageCount?: number;
|
||||
isEncrypted: boolean;
|
||||
isCorrupted: boolean;
|
||||
recommendedStrategy: ProcessingStrategy;
|
||||
estimatedProcessingTime: number; // milliseconds
|
||||
}
|
||||
|
||||
export interface ProcessingMetrics {
|
||||
totalFiles: number;
|
||||
completedFiles: number;
|
||||
failedFiles: number;
|
||||
averageProcessingTime: number;
|
||||
cacheHitRate: number;
|
||||
memoryUsage: number;
|
||||
}
|
||||
Reference in New Issue
Block a user