Add interactive signature buttons to PDF viewer
Introduced functionality to render interactive signature buttons on the PDF viewer. Added support for fetching and displaying signature data (`SignatureDto`) dynamically based on the current page. - Added `@using` directives in `EnvelopeViewer.razor` for required namespaces. - Introduced `_signatures` field to store signature data. - Updated `OnInitializedAsync` to fetch and process signatures. - Implemented `RenderSignatureButtonsAsync` to dynamically render buttons. - Added `[JSInvokable]` method `OnSignatureButtonClick` for button events. - Updated CSS to style `pdf-signature-layer` and `signature-button`. - Enhanced `pdf-viewer.js` with methods to render and clear buttons. - Ensured buttons respond to zoom and page navigation changes. - Added error handling and logging for signature rendering. These changes improve user interaction by enabling signing functionality directly on the PDF viewer.
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
@page "/envelope/{EnvelopeKey}"
|
||||
@using EnvelopeGenerator.ReceiverUI.Models
|
||||
@using EnvelopeGenerator.ReceiverUI.Models.Constants
|
||||
@using EnvelopeGenerator.ReceiverUI.Services
|
||||
@using Microsoft.Extensions.Options
|
||||
@using EnvelopeGenerator.ReceiverUI.Options
|
||||
@@ -155,6 +157,7 @@
|
||||
<div class="pdf-page-container">
|
||||
<canvas id="pdf-canvas" class="pdf-canvas"></canvas>
|
||||
<div id="pdf-text-layer" class="pdf-text-layer"></div>
|
||||
<div id="pdf-signature-layer" class="pdf-signature-layer"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -186,6 +189,7 @@ int _totalPages = 0;
|
||||
int _currentZoom = 150;
|
||||
bool _showThumbnails = true;
|
||||
DotNetObjectReference<EnvelopeViewer>? _dotNetRef;
|
||||
IReadOnlyList<SignatureDto> _signatures = [];
|
||||
|
||||
// Resizable splitter state
|
||||
int _thumbnailWidth = 260;
|
||||
@@ -195,7 +199,7 @@ int _resizeStartWidth = 0;
|
||||
const int MinThumbnailWidth = 150;
|
||||
const int MaxThumbnailWidth = 400;
|
||||
|
||||
protected override async Task OnInitializedAsync() {
|
||||
protected override async Task OnInitializedAsync() {
|
||||
if (string.IsNullOrWhiteSpace(EnvelopeKey)) {
|
||||
_errorMessage = "Envelope-Schlüssel fehlt.";
|
||||
_isLoading = false;
|
||||
@@ -213,8 +217,9 @@ protected override async Task OnInitializedAsync() {
|
||||
}
|
||||
|
||||
var signatures = await SignatureService.GetAsync(EnvelopeKey);
|
||||
_signatures = signatures.Convert(UnitOfLength.Point);
|
||||
|
||||
await JSRuntime.InvokeVoidAsync("console.log", signatures);
|
||||
await JSRuntime.InvokeVoidAsync("console.log", "Loaded signatures:", _signatures);
|
||||
|
||||
} catch (Exception ex) {
|
||||
_errorMessage = $"Fehler: {ex.Message}";
|
||||
@@ -269,11 +274,15 @@ protected override async Task OnInitializedAsync() {
|
||||
// Attach resize listeners
|
||||
await JSRuntime.InvokeVoidAsync("pdfViewer.attachResizeListeners", _dotNetRef);
|
||||
|
||||
|
||||
await InvokeAsync(StateHasChanged);
|
||||
|
||||
// Wait for DOM to be ready, then render thumbnails
|
||||
await Task.Delay(100);
|
||||
await RenderThumbnailsAsync();
|
||||
|
||||
// Render signature buttons
|
||||
await RenderSignatureButtonsAsync();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
_errorMessage = $"PDF.js Fehler: {ex.Message}";
|
||||
@@ -287,17 +296,23 @@ protected override async Task OnInitializedAsync() {
|
||||
{
|
||||
_currentZoom = (int)(scale * 100);
|
||||
await InvokeAsync(StateHasChanged);
|
||||
|
||||
// Re-render signature buttons when zoom changes
|
||||
await Task.Delay(100);
|
||||
await RenderSignatureButtonsAsync();
|
||||
}
|
||||
|
||||
async Task NextPage() {
|
||||
if (await JSRuntime.InvokeAsync<bool>("pdfViewer.nextPage")) {
|
||||
_currentPage = await JSRuntime.InvokeAsync<int>("pdfViewer.getCurrentPage");
|
||||
await RenderSignatureButtonsAsync();
|
||||
}
|
||||
}
|
||||
|
||||
async Task PreviousPage() {
|
||||
if (await JSRuntime.InvokeAsync<bool>("pdfViewer.previousPage")) {
|
||||
_currentPage = await JSRuntime.InvokeAsync<int>("pdfViewer.getCurrentPage");
|
||||
await RenderSignatureButtonsAsync();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,9 +370,25 @@ protected override async Task OnInitializedAsync() {
|
||||
async Task GoToPageFromThumbnail(int pageNum) {
|
||||
if (await JSRuntime.InvokeAsync<bool>("pdfViewer.goToPage", pageNum)) {
|
||||
_currentPage = pageNum;
|
||||
await RenderSignatureButtonsAsync();
|
||||
}
|
||||
}
|
||||
|
||||
async Task RenderSignatureButtonsAsync() {
|
||||
if (_signatures.Count == 0 || !_pdfLoaded) return;
|
||||
|
||||
try {
|
||||
await JSRuntime.InvokeVoidAsync("pdfViewer.renderSignatureButtons", _signatures, _currentPage, _dotNetRef);
|
||||
} catch (Exception ex) {
|
||||
System.Diagnostics.Debug.WriteLine($"Signature button rendering error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
[JSInvokable]
|
||||
public void OnSignatureButtonClick(int signatureId) {
|
||||
Console.WriteLine($"Signature #{signatureId} signed");
|
||||
}
|
||||
|
||||
async Task RenderThumbnailsAsync() {
|
||||
try {
|
||||
var delay = PdfViewerOptions.Value.ThumbnailRenderDelay;
|
||||
|
||||
Reference in New Issue
Block a user