mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-08-06 04:25:22 +00:00

# 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 <77850077+Frooodle@users.noreply.github.com>
102 lines
2.9 KiB
TypeScript
102 lines
2.9 KiB
TypeScript
import { useState, useCallback } from 'react';
|
|
import { getDocument } from 'pdfjs-dist';
|
|
import { PDFDocument, PDFPage } from '../types/pageEditor';
|
|
|
|
export function usePDFProcessor() {
|
|
const [loading, setLoading] = useState(false);
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
const generatePageThumbnail = useCallback(async (
|
|
file: File,
|
|
pageNumber: number,
|
|
scale: number = 0.5
|
|
): Promise<string> => {
|
|
try {
|
|
const arrayBuffer = await file.arrayBuffer();
|
|
const pdf = await getDocument({ data: arrayBuffer }).promise;
|
|
const page = await pdf.getPage(pageNumber);
|
|
|
|
const viewport = page.getViewport({ scale });
|
|
const canvas = document.createElement('canvas');
|
|
canvas.width = viewport.width;
|
|
canvas.height = viewport.height;
|
|
|
|
const context = canvas.getContext('2d');
|
|
if (!context) {
|
|
throw new Error('Could not get canvas context');
|
|
}
|
|
|
|
await page.render({ canvasContext: context, viewport }).promise;
|
|
const thumbnail = canvas.toDataURL();
|
|
|
|
// Clean up
|
|
pdf.destroy();
|
|
|
|
return thumbnail;
|
|
} catch (error) {
|
|
console.error('Failed to generate thumbnail:', error);
|
|
throw error;
|
|
}
|
|
}, []);
|
|
|
|
const processPDFFile = useCallback(async (file: File): Promise<PDFDocument> => {
|
|
setLoading(true);
|
|
setError(null);
|
|
|
|
try {
|
|
const arrayBuffer = await file.arrayBuffer();
|
|
const pdf = await getDocument({ data: arrayBuffer }).promise;
|
|
const totalPages = pdf.numPages;
|
|
|
|
const pages: PDFPage[] = [];
|
|
|
|
// Create pages without thumbnails initially - load them lazily
|
|
for (let i = 1; i <= totalPages; i++) {
|
|
pages.push({
|
|
id: `${file.name}-page-${i}`,
|
|
pageNumber: i,
|
|
thumbnail: null, // Will be loaded lazily
|
|
rotation: 0,
|
|
selected: false
|
|
});
|
|
}
|
|
|
|
// Generate thumbnails for first 10 pages immediately for better UX
|
|
const priorityPages = Math.min(10, totalPages);
|
|
for (let i = 1; i <= priorityPages; i++) {
|
|
try {
|
|
const thumbnail = await generatePageThumbnail(file, i);
|
|
pages[i - 1].thumbnail = thumbnail;
|
|
} catch (error) {
|
|
console.warn(`Failed to generate thumbnail for page ${i}:`, error);
|
|
}
|
|
}
|
|
|
|
// Clean up
|
|
pdf.destroy();
|
|
|
|
const document: PDFDocument = {
|
|
id: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
|
name: file.name,
|
|
file,
|
|
pages,
|
|
totalPages
|
|
};
|
|
|
|
return document;
|
|
} catch (error) {
|
|
const errorMessage = error instanceof Error ? error.message : 'Failed to process PDF';
|
|
setError(errorMessage);
|
|
throw error;
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}, [generatePageThumbnail]);
|
|
|
|
return {
|
|
processPDFFile,
|
|
generatePageThumbnail,
|
|
loading,
|
|
error
|
|
};
|
|
} |