import { Box, Typography } from '@mui/material'; import React, { useContext, useEffect, useState } from 'react'; import ToolContent from '@components/ToolContent'; import { ToolComponentProps } from '@tools/defineTool'; import ToolPdfInput from '@components/input/ToolPdfInput'; import ToolFileResult from '@components/result/ToolFileResult'; import { CardExampleType } from '@components/examples/ToolExamples'; import { PDFDocument } from 'pdf-lib'; import { CompressionLevel, InitialValuesType } from './types'; import { compressPdf } from './service'; import SimpleRadio from '@components/options/SimpleRadio'; import { CustomSnackBarContext } from '../../../../contexts/CustomSnackBarContext'; const initialValues: InitialValuesType = { compressionLevel: 'medium' }; const exampleCards: CardExampleType[] = [ { title: 'Low Compression', description: 'Slightly reduce file size with minimal quality loss', sampleText: '', sampleResult: '', sampleOptions: { compressionLevel: 'low' } }, { title: 'Medium Compression', description: 'Balance between file size and quality', sampleText: '', sampleResult: '', sampleOptions: { compressionLevel: 'medium' } }, { title: 'High Compression', description: 'Maximum file size reduction with some quality loss', sampleText: '', sampleResult: '', sampleOptions: { compressionLevel: 'high' } } ]; export default function CompressPdf({ title, longDescription }: ToolComponentProps) { const [input, setInput] = useState(null); const [result, setResult] = useState(null); const [resultSize, setResultSize] = useState(''); const [isProcessing, setIsProcessing] = useState(false); const [fileInfo, setFileInfo] = useState<{ size: string; pages: number; } | null>(null); const { showSnackBar } = useContext(CustomSnackBarContext); // Get the PDF info when a file is uploaded useEffect(() => { const getPdfInfo = async () => { if (!input) { setFileInfo(null); return; } try { const arrayBuffer = await input.arrayBuffer(); const pdf = await PDFDocument.load(arrayBuffer); const pages = pdf.getPageCount(); const size = formatFileSize(input.size); setFileInfo({ size, pages }); } catch (error) { console.error('Error getting PDF info:', error); setFileInfo(null); showSnackBar( 'Error reading PDF file. Please make sure it is a valid PDF.', 'error' ); } }; getPdfInfo(); }, [input]); const formatFileSize = (bytes: number): string => { if (bytes === 0) return '0 Bytes'; const k = 1024; const sizes = ['Bytes', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; }; const compute = async (values: InitialValuesType, input: File | null) => { if (!input) return; try { setIsProcessing(true); const compressedPdf = await compressPdf(input, values); setResult(compressedPdf); // Log compression results const compressionRatio = (compressedPdf.size / input.size) * 100; console.log(`Compression Ratio: ${compressionRatio.toFixed(2)}%`); setResultSize(formatFileSize(compressedPdf.size)); } catch (error) { console.error('Error compressing PDF:', error); showSnackBar( `Failed to compress PDF: ${ error instanceof Error ? error.message : String(error) }`, 'error' ); setResult(null); } finally { setIsProcessing(false); } }; const compressionOptions: { value: CompressionLevel; label: string; description: string; }[] = [ { value: 'low', label: 'Low Compression', description: 'Slightly reduce file size with minimal quality loss' }, { value: 'medium', label: 'Medium Compression', description: 'Balance between file size and quality' }, { value: 'high', label: 'High Compression', description: 'Maximum file size reduction with some quality loss' } ]; return ( } resultComponent={ } getGroups={({ values, updateField }) => [ { title: 'Compression Settings', component: ( Compression Level {compressionOptions.map((option) => ( { updateField('compressionLevel', option.value); }} /> ))} {fileInfo && ( File size: {fileInfo.size} Pages: {fileInfo.pages} {resultSize && ( Compressed file size: {resultSize} )} )} ) } ]} /> ); }