Add PDF printing functionality to editor components
Enabled PDF printing in `SenderPdfImageEditor` and `SenderPdfImageEditorToolbar`. Added `CanPrintPdf` property to determine print availability and a new `OnPrintPdfAsync` method for handling print logic via JavaScript interop. Updated the toolbar with a "Print" button that triggers the print functionality. Implemented the `printDataUrlPdf` function in `envelope-editor.js` to handle printing from a data URL. This function creates an iframe, loads the PDF, and invokes the browser's print functionality with proper cleanup of resources.
This commit is contained in:
@@ -25,7 +25,9 @@
|
|||||||
ZoomIn="OnZoomInAsync"
|
ZoomIn="OnZoomInAsync"
|
||||||
SetZoomPercent="OnSetZoomPercentAsync"
|
SetZoomPercent="OnSetZoomPercentAsync"
|
||||||
CanDownloadPdf="@CanDownloadPdf"
|
CanDownloadPdf="@CanDownloadPdf"
|
||||||
DownloadPdf="OnDownloadPdfAsync" />
|
CanPrintPdf="@CanPrintPdf"
|
||||||
|
DownloadPdf="OnDownloadPdfAsync"
|
||||||
|
PrintPdf="OnPrintPdfAsync" />
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,6 +152,7 @@
|
|||||||
private const int MaxZoomPercent = 300;
|
private const int MaxZoomPercent = 300;
|
||||||
private const int ZoomStepPercent = 5;
|
private const int ZoomStepPercent = 5;
|
||||||
private bool CanDownloadPdf => !string.IsNullOrWhiteSpace(PdfDataUrl);
|
private bool CanDownloadPdf => !string.IsNullOrWhiteSpace(PdfDataUrl);
|
||||||
|
private bool CanPrintPdf => !string.IsNullOrWhiteSpace(PdfDataUrl);
|
||||||
|
|
||||||
private static string GetFieldStyle(SenderPdfFieldOverlay field, double pageWidthPt, double pageHeightPt)
|
private static string GetFieldStyle(SenderPdfFieldOverlay field, double pageWidthPt, double pageHeightPt)
|
||||||
{
|
{
|
||||||
@@ -397,6 +400,17 @@
|
|||||||
"application/pdf");
|
"application/pdf");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task OnPrintPdfAsync()
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(PdfDataUrl))
|
||||||
|
return;
|
||||||
|
|
||||||
|
await JSRuntime.InvokeVoidAsync(
|
||||||
|
"envelopeEditor.printDataUrlPdf",
|
||||||
|
PdfDataUrl,
|
||||||
|
"application/pdf");
|
||||||
|
}
|
||||||
|
|
||||||
private void OnEditorMouseUp(MouseEventArgs args)
|
private void OnEditorMouseUp(MouseEventArgs args)
|
||||||
{
|
{
|
||||||
_draggedFieldIndex = null;
|
_draggedFieldIndex = null;
|
||||||
|
|||||||
@@ -86,7 +86,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="sender-image-toolbar__group sender-image-toolbar__group--actions" role="group" aria-label="Document actions">
|
<div class="sender-image-toolbar__group sender-image-toolbar__group--actions" role="group" aria-label="Document actions">
|
||||||
<button type="button" class="sender-image-toolbar__icon-btn" title="Print" disabled>
|
<button type="button" class="sender-image-toolbar__icon-btn" title="Print" disabled="@(!CanPrintPdf)" @onclick="PrintPdfAsync">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
||||||
<path d="M7 9V4H17V9" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
<path d="M7 9V4H17V9" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
||||||
<rect x="5" y="9" width="14" height="8" rx="2" stroke="currentColor" stroke-width="2" />
|
<rect x="5" y="9" width="14" height="8" rx="2" stroke="currentColor" stroke-width="2" />
|
||||||
@@ -150,9 +150,15 @@
|
|||||||
[Parameter]
|
[Parameter]
|
||||||
public bool CanDownloadPdf { get; set; }
|
public bool CanDownloadPdf { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public bool CanPrintPdf { get; set; }
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public EventCallback DownloadPdf { get; set; }
|
public EventCallback DownloadPdf { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public EventCallback PrintPdf { get; set; }
|
||||||
|
|
||||||
private int CurrentPageDisplay => CurrentPage > 0 ? CurrentPage : 0;
|
private int CurrentPageDisplay => CurrentPage > 0 ? CurrentPage : 0;
|
||||||
private int TotalPagesDisplay => TotalPages > 0 ? TotalPages : 0;
|
private int TotalPagesDisplay => TotalPages > 0 ? TotalPages : 0;
|
||||||
private int ZoomPercentDisplay => ZoomPercent > 0 ? ZoomPercent : 100;
|
private int ZoomPercentDisplay => ZoomPercent > 0 ? ZoomPercent : 100;
|
||||||
@@ -238,4 +244,10 @@
|
|||||||
if (DownloadPdf.HasDelegate)
|
if (DownloadPdf.HasDelegate)
|
||||||
await DownloadPdf.InvokeAsync();
|
await DownloadPdf.InvokeAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task PrintPdfAsync()
|
||||||
|
{
|
||||||
|
if (PrintPdf.HasDelegate)
|
||||||
|
await PrintPdf.InvokeAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -243,5 +243,82 @@ window.envelopeEditor = {
|
|||||||
host.appendChild(link);
|
host.appendChild(link);
|
||||||
link.click();
|
link.click();
|
||||||
host.removeChild(link);
|
host.removeChild(link);
|
||||||
|
},
|
||||||
|
|
||||||
|
printDataUrlPdf: async function (dataUrl, mimeType) {
|
||||||
|
if (!dataUrl || typeof dataUrl !== 'string') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let objectUrl = null;
|
||||||
|
let printSrc = dataUrl;
|
||||||
|
|
||||||
|
if (dataUrl.startsWith('data:')) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(dataUrl);
|
||||||
|
const blob = await response.blob();
|
||||||
|
objectUrl = URL.createObjectURL(blob);
|
||||||
|
printSrc = objectUrl;
|
||||||
|
} catch {
|
||||||
|
printSrc = dataUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const frame = document.createElement('iframe');
|
||||||
|
frame.style.position = 'fixed';
|
||||||
|
frame.style.right = '0';
|
||||||
|
frame.style.bottom = '0';
|
||||||
|
frame.style.width = '0';
|
||||||
|
frame.style.height = '0';
|
||||||
|
frame.style.border = '0';
|
||||||
|
frame.setAttribute('aria-hidden', 'true');
|
||||||
|
|
||||||
|
const host = document.body || document.documentElement;
|
||||||
|
host.appendChild(frame);
|
||||||
|
|
||||||
|
let cleaned = false;
|
||||||
|
const cleanup = function () {
|
||||||
|
if (cleaned) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleaned = true;
|
||||||
|
|
||||||
|
if (frame.parentNode) {
|
||||||
|
frame.parentNode.removeChild(frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (objectUrl) {
|
||||||
|
URL.revokeObjectURL(objectUrl);
|
||||||
|
objectUrl = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
frame.onload = function () {
|
||||||
|
try {
|
||||||
|
const frameWindow = frame.contentWindow;
|
||||||
|
if (!frameWindow) {
|
||||||
|
cleanup();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
frameWindow.addEventListener('afterprint', function () {
|
||||||
|
window.setTimeout(cleanup, 250);
|
||||||
|
}, { once: true });
|
||||||
|
|
||||||
|
window.addEventListener('focus', function () {
|
||||||
|
window.setTimeout(cleanup, 1500);
|
||||||
|
}, { once: true });
|
||||||
|
|
||||||
|
frameWindow.focus();
|
||||||
|
frameWindow.print();
|
||||||
|
} catch {
|
||||||
|
cleanup();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
frame.src = printSrc;
|
||||||
|
|
||||||
|
window.setTimeout(cleanup, 120000);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user