// PDF.js Viewer for Blazor WASM window.pdfViewer = { pdfDoc: null, pageNum: 1, pageRendering: false, pageNumPending: null, scale: 1.5, canvas: null, ctx: null, totalPages: 0, async initialize(canvasId, pdfDataUrl) { try { console.log('PDF.js initialization started for canvas:', canvasId); // Wait for PDF.js to load if (typeof window.pdfjsLib === 'undefined') { console.error('PDF.js library not loaded, waiting...'); await this.waitForPdfJs(); } const pdfjsLib = window.pdfjsLib; pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js'; this.canvas = document.getElementById(canvasId); if (!this.canvas) { console.error('Canvas element not found:', canvasId); return false; } console.log('Canvas element found, loading PDF...'); this.ctx = this.canvas.getContext('2d'); // Load PDF from data URL const uint8Array = this.base64ToUint8Array(pdfDataUrl); console.log('PDF data converted to Uint8Array, size:', uint8Array.length); const loadingTask = pdfjsLib.getDocument({ data: uint8Array }); this.pdfDoc = await loadingTask.promise; this.totalPages = this.pdfDoc.numPages; console.log('PDF loaded successfully, total pages:', this.totalPages); // Render first page await this.renderPage(this.pageNum); return true; } catch (error) { console.error('Error initializing PDF viewer:', error); return false; } }, async waitForPdfJs() { for (let i = 0; i < 50; i++) { if (typeof window.pdfjsLib !== 'undefined') { console.log('PDF.js loaded after', i * 100, 'ms'); return; } await new Promise(resolve => setTimeout(resolve, 100)); } throw new Error('PDF.js failed to load after 5 seconds'); }, base64ToUint8Array(base64) { // Remove data URL prefix if present const base64String = base64.includes(',') ? base64.split(',')[1] : base64; const raw = atob(base64String); const uint8Array = new Uint8Array(raw.length); for (let i = 0; i < raw.length; i++) { uint8Array[i] = raw.charCodeAt(i); } return uint8Array; }, async renderPage(num) { this.pageRendering = true; try { const page = await this.pdfDoc.getPage(num); const viewport = page.getViewport({ scale: this.scale }); console.log('Rendering page:', num, 'Viewport:', viewport.width, 'x', viewport.height); this.canvas.height = viewport.height; this.canvas.width = viewport.width; const renderContext = { canvasContext: this.ctx, viewport: viewport }; await page.render(renderContext).promise; console.log('Page rendered successfully'); this.pageRendering = false; if (this.pageNumPending !== null) { this.renderPage(this.pageNumPending); this.pageNumPending = null; } } catch (error) { console.error('Error rendering page:', error); this.pageRendering = false; } }, queueRenderPage(num) { if (this.pageRendering) { this.pageNumPending = num; } else { this.renderPage(num); } }, nextPage() { if (this.pageNum >= this.totalPages) { return false; } this.pageNum++; this.queueRenderPage(this.pageNum); return true; }, previousPage() { if (this.pageNum <= 1) { return false; } this.pageNum--; this.queueRenderPage(this.pageNum); return true; }, goToPage(num) { if (num < 1 || num > this.totalPages) { return false; } this.pageNum = num; this.queueRenderPage(this.pageNum); return true; }, zoomIn() { this.scale += 0.25; this.queueRenderPage(this.pageNum); }, zoomOut() { if (this.scale > 0.5) { this.scale -= 0.25; this.queueRenderPage(this.pageNum); } }, getCurrentPage() { return this.pageNum; }, getTotalPages() { return this.totalPages; }, getScale() { return this.scale; } };