fix(dees-pdf-viewer): use in-memory PDF data for download and print; add robust print wrapper, cleanup and error handling
This commit is contained in:
@@ -1,5 +1,13 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2026-01-29 - 3.41.3 - fix(dees-pdf-viewer)
|
||||||
|
use in-memory PDF data for download and print; add robust print wrapper, cleanup and error handling
|
||||||
|
|
||||||
|
- Download and Print now use pdfDocument.getData() to create Blob URLs so in-memory PDFs (pdf.js) can be saved/printed.
|
||||||
|
- Print flow now opens an HTML wrapper with an iframe to allow onafterprint handling, auto-close, popup-fallback and timed cleanup of Blob URLs.
|
||||||
|
- Added try/catch logging, URL.revokeObjectURL calls and safety timeouts to avoid resource leaks.
|
||||||
|
- Removed context menu items that relied on the raw PDF URL (Open in New Tab, Copy PDF URL); Download/Print actions now await the async handlers.
|
||||||
|
|
||||||
## 2026-01-28 - 3.41.2 - fix(dees-pdf-viewer)
|
## 2026-01-28 - 3.41.2 - fix(dees-pdf-viewer)
|
||||||
account for devicePixelRatio when setting canvas dimensions and scale 2D context to render crisp PDF pages and thumbnails on high-DPI displays
|
account for devicePixelRatio when setting canvas dimensions and scale 2D context to render crisp PDF pages and thumbnails on high-DPI displays
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@design.estate/dees-catalog',
|
name: '@design.estate/dees-catalog',
|
||||||
version: '3.41.2',
|
version: '3.41.3',
|
||||||
description: 'A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.'
|
description: 'A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -935,15 +935,98 @@ export class DeesPdfViewer extends DeesElement {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private downloadPdf() {
|
private async downloadPdf() {
|
||||||
|
if (!this.pdfDocument) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Get raw PDF data from the loaded document
|
||||||
|
const data = await this.pdfDocument.getData();
|
||||||
|
const blob = new Blob([data.buffer], { type: 'application/pdf' });
|
||||||
|
const blobUrl = URL.createObjectURL(blob);
|
||||||
|
|
||||||
const link = document.createElement('a');
|
const link = document.createElement('a');
|
||||||
link.href = this.pdfUrl;
|
link.href = blobUrl;
|
||||||
link.download = this.pdfUrl.split('/').pop() || 'document.pdf';
|
link.download = this.pdfUrl ? this.pdfUrl.split('/').pop() || 'document.pdf' : 'document.pdf';
|
||||||
link.click();
|
link.click();
|
||||||
|
|
||||||
|
// Clean up blob URL after short delay
|
||||||
|
setTimeout(() => URL.revokeObjectURL(blobUrl), 1000);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error downloading PDF:', error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private printPdf() {
|
private async printPdf() {
|
||||||
window.open(this.pdfUrl, '_blank')?.print();
|
if (!this.pdfDocument) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Get raw PDF data from the loaded document
|
||||||
|
const data = await this.pdfDocument.getData();
|
||||||
|
const blob = new Blob([data.buffer], { type: 'application/pdf' });
|
||||||
|
const pdfUrl = URL.createObjectURL(blob);
|
||||||
|
|
||||||
|
// Create an HTML wrapper page that embeds the PDF and handles print/close
|
||||||
|
// This gives us control over the afterprint event (direct PDF URLs don't support it)
|
||||||
|
const htmlContent = `
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Print PDF</title>
|
||||||
|
<style>
|
||||||
|
* { margin: 0; padding: 0; }
|
||||||
|
html, body { width: 100%; height: 100%; overflow: hidden; }
|
||||||
|
iframe { width: 100%; height: 100%; border: none; }
|
||||||
|
@media print {
|
||||||
|
html, body, iframe { width: 100%; height: 100%; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<iframe src="${pdfUrl}" type="application/pdf"></iframe>
|
||||||
|
<script>
|
||||||
|
window.onload = function() {
|
||||||
|
setTimeout(function() {
|
||||||
|
window.focus();
|
||||||
|
window.print();
|
||||||
|
}, 500);
|
||||||
|
};
|
||||||
|
window.onafterprint = function() {
|
||||||
|
window.close();
|
||||||
|
};
|
||||||
|
// Safety close after 2 minutes
|
||||||
|
setTimeout(function() { window.close(); }, 120000);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`;
|
||||||
|
const htmlBlob = new Blob([htmlContent], { type: 'text/html' });
|
||||||
|
const htmlUrl = URL.createObjectURL(htmlBlob);
|
||||||
|
|
||||||
|
const printWindow = window.open(htmlUrl, '_blank', 'width=800,height=600');
|
||||||
|
if (printWindow) {
|
||||||
|
// Cleanup blob URLs when window closes
|
||||||
|
const checkClosed = setInterval(() => {
|
||||||
|
if (printWindow.closed) {
|
||||||
|
clearInterval(checkClosed);
|
||||||
|
URL.revokeObjectURL(pdfUrl);
|
||||||
|
URL.revokeObjectURL(htmlUrl);
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
// Safety cleanup after 2 minutes
|
||||||
|
setTimeout(() => {
|
||||||
|
clearInterval(checkClosed);
|
||||||
|
URL.revokeObjectURL(pdfUrl);
|
||||||
|
URL.revokeObjectURL(htmlUrl);
|
||||||
|
}, 120000);
|
||||||
|
} else {
|
||||||
|
// Popup blocked - fall back to direct navigation
|
||||||
|
window.open(pdfUrl, '_blank');
|
||||||
|
setTimeout(() => URL.revokeObjectURL(pdfUrl), 60000);
|
||||||
|
URL.revokeObjectURL(htmlUrl);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error printing PDF:', error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -967,33 +1050,18 @@ export class DeesPdfViewer extends DeesElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
items.push(
|
items.push(
|
||||||
{
|
|
||||||
name: 'Open PDF in New Tab',
|
|
||||||
iconName: 'lucide:ExternalLink',
|
|
||||||
action: async () => {
|
|
||||||
window.open(this.pdfUrl, '_blank');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ divider: true },
|
|
||||||
{
|
|
||||||
name: 'Copy PDF URL',
|
|
||||||
iconName: 'lucide:Link',
|
|
||||||
action: async () => {
|
|
||||||
await navigator.clipboard.writeText(this.pdfUrl);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'Download PDF',
|
name: 'Download PDF',
|
||||||
iconName: 'lucide:Download',
|
iconName: 'lucide:Download',
|
||||||
action: async () => {
|
action: async () => {
|
||||||
this.downloadPdf();
|
await this.downloadPdf();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Print PDF',
|
name: 'Print PDF',
|
||||||
iconName: 'lucide:Printer',
|
iconName: 'lucide:Printer',
|
||||||
action: async () => {
|
action: async () => {
|
||||||
this.printPdf();
|
await this.printPdf();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user