import { useCallback, useEffect, useRef, useState } from 'react'; import type { SplitResult } from '../pdf/pdfTypes'; export interface PdfDownload { id: string; filename: string; url: string; } export interface SplitPdfDownload extends PdfDownload { pageIndex: number; } export interface PdfBlobResult { blob: Blob; filename: string; } function revokeDownload(download: PdfDownload | null): void { if (download) { URL.revokeObjectURL(download.url); } } function revokeDownloads(downloads: PdfDownload[]): void { downloads.forEach(revokeDownload); } function createDownload(id: string, filename: string, blob: Blob): PdfDownload { return { id, filename, url: URL.createObjectURL(blob), }; } export function usePdfGeneratedOutputs() { const [splitDownloads, setSplitDownloads] = useState([]); const [subsetDownload, setSubsetDownload] = useState( null ); const [exportDownload, setExportDownload] = useState( null ); const [splitZipDownload, setSplitZipDownload] = useState( null ); const splitDownloadsRef = useRef([]); const subsetDownloadRef = useRef(null); const exportDownloadRef = useRef(null); const splitZipDownloadRef = useRef(null); const replaceSplitResults = useCallback( (results: SplitResult[], zipResult?: PdfBlobResult) => { const nextDownloads: SplitPdfDownload[] = results.map((result) => ({ ...createDownload( `split-${result.pageIndex}-${result.filename}`, result.filename, result.blob ), pageIndex: result.pageIndex, })); const nextZipDownload = zipResult ? createDownload('split-zip', zipResult.filename, zipResult.blob) : null; revokeDownloads(splitDownloadsRef.current); revokeDownload(splitZipDownloadRef.current); splitDownloadsRef.current = nextDownloads; splitZipDownloadRef.current = nextZipDownload; setSplitDownloads(nextDownloads); setSplitZipDownload(nextZipDownload); }, [] ); const clearSplitResults = useCallback(() => { revokeDownloads(splitDownloadsRef.current); revokeDownload(splitZipDownloadRef.current); splitDownloadsRef.current = []; splitZipDownloadRef.current = null; setSplitDownloads([]); setSplitZipDownload(null); }, []); const replaceSubsetResult = useCallback((blob: Blob, filename: string) => { const nextDownload = createDownload('subset', filename, blob); revokeDownload(subsetDownloadRef.current); subsetDownloadRef.current = nextDownload; setSubsetDownload(nextDownload); }, []); const clearSubsetResult = useCallback(() => { revokeDownload(subsetDownloadRef.current); subsetDownloadRef.current = null; setSubsetDownload(null); }, []); const replaceExportResult = useCallback((blob: Blob, filename: string) => { const nextDownload = createDownload('export', filename, blob); revokeDownload(exportDownloadRef.current); exportDownloadRef.current = nextDownload; setExportDownload(nextDownload); }, []); const clearExportResult = useCallback(() => { revokeDownload(exportDownloadRef.current); exportDownloadRef.current = null; setExportDownload(null); }, []); const clearAllResults = useCallback(() => { revokeDownloads(splitDownloadsRef.current); revokeDownload(subsetDownloadRef.current); revokeDownload(exportDownloadRef.current); revokeDownload(splitZipDownloadRef.current); splitDownloadsRef.current = []; subsetDownloadRef.current = null; exportDownloadRef.current = null; splitZipDownloadRef.current = null; setSplitDownloads([]); setSubsetDownload(null); setExportDownload(null); setSplitZipDownload(null); }, []); useEffect(() => { return () => { revokeDownloads(splitDownloadsRef.current); revokeDownload(subsetDownloadRef.current); revokeDownload(exportDownloadRef.current); revokeDownload(splitZipDownloadRef.current); }; }, []); return { splitDownloads, subsetDownload, exportDownload, splitZipDownload, replaceSplitResults, clearSplitResults, replaceSubsetResult, clearSubsetResult, replaceExportResult, clearExportResult, clearAllResults, }; }