diff --git a/EnvelopeGenerator.ReceiverUIBlazor/Pages/Index.razor b/EnvelopeGenerator.ReceiverUIBlazor/Pages/Index.razor
index 74516821..83d66884 100644
--- a/EnvelopeGenerator.ReceiverUIBlazor/Pages/Index.razor
+++ b/EnvelopeGenerator.ReceiverUIBlazor/Pages/Index.razor
@@ -12,6 +12,11 @@
+@if (!string.IsNullOrWhiteSpace(ErrorMessage))
+{
+
@ErrorMessage
+}
+
@if (!HasPdf)
{
Drop or select a PDF to start.
@@ -96,6 +101,7 @@
private double StartLeft;
private double StartTop;
private string TextValue = "Text";
+ private string? ErrorMessage;
private bool HasPdf => !string.IsNullOrWhiteSpace(PdfBase64);
private int DisplayPage => PageIndex + 1;
@@ -117,22 +123,41 @@
private async Task HandleFileSelected(InputFileChangeEventArgs e)
{
- if (e.FileCount == 0)
+ ErrorMessage = null;
+
+ try
{
- return;
+ if (e.FileCount == 0)
+ {
+ return;
+ }
+
+ var file = e.File;
+ await using var stream = file.OpenReadStream(maxAllowedSize: 20 * 1024 * 1024);
+ using var ms = new MemoryStream();
+ await stream.CopyToAsync(ms);
+ PdfBase64 = Convert.ToBase64String(ms.ToArray());
+
+ // Show the canvas before we start rendering
+ await InvokeAsync(StateHasChanged);
+ await Task.Yield();
+
+ // Make sure pdf.js is ready
+ await JS.InvokeVoidAsync("pdfInterop.ensureReady");
+
+ var result = await JS.InvokeAsync("pdfInterop.loadPdf", PdfBase64);
+ PageCount = result.Pages;
+ PageIndex = 0;
+
+ await RenderPage();
+ }
+ catch (Exception ex)
+ {
+ ErrorMessage = $"Fehler beim Laden der PDF: {ex.Message}";
+ PdfBase64 = null;
+ PageCount = 0;
+ PageIndex = 0;
}
-
- var file = e.File;
- await using var stream = file.OpenReadStream(maxAllowedSize: 20 * 1024 * 1024);
- using var ms = new MemoryStream();
- await stream.CopyToAsync(ms);
- PdfBase64 = Convert.ToBase64String(ms.ToArray());
-
- var result = await JS.InvokeAsync("pdfInterop.loadPdf", PdfBase64);
- PageCount = result.Pages;
- PageIndex = 0;
-
- await RenderPage();
}
private async Task RenderPage()
@@ -142,10 +167,17 @@
return;
}
- var viewport = await JS.InvokeAsync("pdfInterop.renderPage", PageIndex, "pdf-canvas", ViewportWidthPx);
- ViewportWidthPx = viewport.Width;
- ViewportHeightPx = viewport.Height;
- StateHasChanged();
+ try
+ {
+ var viewport = await JS.InvokeAsync("pdfInterop.renderPage", PageIndex, "pdf-canvas", ViewportWidthPx);
+ ViewportWidthPx = viewport.Width;
+ ViewportHeightPx = viewport.Height;
+ StateHasChanged();
+ }
+ catch (Exception ex)
+ {
+ ErrorMessage = $"Fehler beim Rendern: {ex.Message}";
+ }
}
private void Reset()
diff --git a/EnvelopeGenerator.ReceiverUIBlazor/wwwroot/css/app.css b/EnvelopeGenerator.ReceiverUIBlazor/wwwroot/css/app.css
index 669a1de3..1386cc4d 100644
--- a/EnvelopeGenerator.ReceiverUIBlazor/wwwroot/css/app.css
+++ b/EnvelopeGenerator.ReceiverUIBlazor/wwwroot/css/app.css
@@ -76,6 +76,15 @@ h1 {
color: rgba(226, 232, 240, 0.8);
}
+.error-banner {
+ margin-top: 8px;
+ padding: 10px 12px;
+ border-radius: 8px;
+ background: rgba(239, 68, 68, 0.12);
+ border: 1px solid rgba(239, 68, 68, 0.3);
+ color: #fecdd3;
+}
+
.document-shell {
position: relative;
margin-top: 12px;
diff --git a/EnvelopeGenerator.ReceiverUIBlazor/wwwroot/index.html b/EnvelopeGenerator.ReceiverUIBlazor/wwwroot/index.html
index 3831da21..b58847a9 100644
--- a/EnvelopeGenerator.ReceiverUIBlazor/wwwroot/index.html
+++ b/EnvelopeGenerator.ReceiverUIBlazor/wwwroot/index.html
@@ -6,9 +6,10 @@
Receiver UI (Blazor)
-
-
-
+
+
+
+
diff --git a/EnvelopeGenerator.ReceiverUIBlazor/wwwroot/js/pdfInterop.js b/EnvelopeGenerator.ReceiverUIBlazor/wwwroot/js/pdfInterop.js
index 62c2bde5..cb5b4f4b 100644
--- a/EnvelopeGenerator.ReceiverUIBlazor/wwwroot/js/pdfInterop.js
+++ b/EnvelopeGenerator.ReceiverUIBlazor/wwwroot/js/pdfInterop.js
@@ -1,8 +1,13 @@
(function () {
+ // Stick to pdf.js 3.11 UMD + classic worker for compatibility.
+ const PDF_JS_SRC = "https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js";
+ const WORKER_SRC = "https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js";
+
const state = {
pdfDoc: null,
pdfBytes: null,
lastViewport: null,
+ pdfJsReady: null,
};
function base64ToUint8(base64) {
@@ -32,17 +37,73 @@
const pointerPads = new Map();
- window.pdfInterop = {
- ensureReady: () => {
- if (pdfjsLib && pdfjsLib.GlobalWorkerOptions) {
- // worker is already loaded via CDN include
+ function loadScriptOnce(url) {
+ return new Promise((resolve, reject) => {
+ // If already present, resolve immediately
+ const existing = Array.from(document.getElementsByTagName('script')).find(s => s.src === url);
+ if (existing && existing.dataset.loaded === "true") {
+ resolve();
return;
}
+
+ const script = existing || document.createElement('script');
+ script.src = url;
+ script.defer = true;
+ script.onload = () => {
+ script.dataset.loaded = "true";
+ resolve();
+ };
+ script.onerror = (e) => reject(new Error(`Script load failed: ${url}`));
+
+ if (!existing) {
+ document.head.appendChild(script);
+ }
+ });
+ }
+
+ async function ensurePdfJsLoaded() {
+ if (typeof pdfjsLib !== "undefined") {
+ return;
+ }
+
+ if (!state.pdfJsReady) {
+ state.pdfJsReady = loadScriptOnce(PDF_JS_SRC);
+ }
+
+ await state.pdfJsReady;
+
+ if (typeof pdfjsLib === "undefined") {
+ throw new Error("pdfjsLib could not be loaded");
+ }
+ }
+
+ window.pdfInterop = {
+ ensureReady: async () => {
+ // Ensure pdf.js is present and the worker path is set explicitly.
+ await ensurePdfJsLoaded();
+ if (pdfjsLib && pdfjsLib.GlobalWorkerOptions) {
+ if (pdfjsLib.GlobalWorkerOptions.workerSrc !== WORKER_SRC) {
+ pdfjsLib.GlobalWorkerOptions.workerSrc = WORKER_SRC;
+ }
+ } else {
+ throw new Error("pdf.js not available after load");
+ }
},
loadPdf: async (base64) => {
- return await reloadFromBase64(base64);
+ await ensurePdfJsLoaded();
+ try {
+ const result = await reloadFromBase64(base64);
+ if (!result || !result.pages) {
+ throw new Error("PDF has keine Seiten erkannt");
+ }
+ return result;
+ } catch (err) {
+ console.error("pdfInterop.loadPdf failed", err);
+ throw err;
+ }
},
renderPage: async (pageIndex, canvasId, targetWidth) => {
+ await ensurePdfJsLoaded();
if (!state.pdfDoc) {
throw new Error('PDF not loaded');
}
@@ -51,8 +112,14 @@
const scale = targetWidth / rawViewport.width;
const viewport = page.getViewport({ scale });
- const canvas = document.getElementById(canvasId);
+ let canvas = document.getElementById(canvasId);
if (!canvas) {
+ // give the UI a tiny delay to render the canvas into the DOM
+ await new Promise(r => setTimeout(r, 40));
+ canvas = document.getElementById(canvasId);
+ }
+ if (!canvas) {
+ console.error("renderPage: canvas not found", canvasId);
throw new Error('Canvas not found');
}
const ctx = canvas.getContext('2d');