Skip to content

Commit

Permalink
[MS] Improve PdfViewer pages error
Browse files Browse the repository at this point in the history
  • Loading branch information
NicoTuxx committed Jan 16, 2025
1 parent 214bab0 commit f70ebcc
Showing 1 changed file with 79 additions and 50 deletions.
129 changes: 79 additions & 50 deletions client/src/views/viewers/PdfViewer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import { FileControls, FileControlsButton, FileControlsPagination, FileControlsZ
import { MsSpinner, MsReportText, MsReportTheme, I18n } from 'megashark-lib';
import * as pdfjs from 'pdfjs-dist';
import { scan } from 'ionicons/icons';
import { needsMocks } from '@/parsec';

const props = defineProps<{
contentInfo: FileContentInfo;
Expand Down Expand Up @@ -108,52 +109,65 @@ async function loadPage(pageIndex: number): Promise<void> {

try {
const page = await pdf.value.getPage(pageIndex);
if (needsMocks() && pageIndex === 3) {
throw new Error('Failed to load page');
}

const canvasElement = canvas.value.at(pageIndex - 1);
if (!canvasElement) {
loading.value = false;
return;
}

const outputScale = window.devicePixelRatio || 1;
const viewport = page.getViewport({ scale: scale.value });
canvasElement.width = viewport.width * outputScale;
canvasElement.height = viewport.height * outputScale;
canvasElement.style.width = `${Math.floor(viewport.width)}px`;
canvasElement.style.height = `${Math.floor(viewport.height)}px`;

canvasElement.removeAttribute('data-rendered');
drawBlankCanvas(canvasElement, viewport);
} catch (e: any) {
const canvasElement = canvas.value.at(pageIndex - 1);
if (!canvasElement) {
loading.value = false;
return;
}
canvasElement.width = 300;
canvasElement.height = 60;
canvasElement.style.width = '300px';
canvasElement.style.height = '60px';
canvasElement.classList.add('error');
const context = canvasElement.getContext('2d', { willReadFrequently: true });
if (context) {
const errorMessage = I18n.translate('fileViewers.pdf.loadPageError');
context.font = '14px "Albert Sans"';
drawErrorCanvas(canvasElement);
window.electronAPI.log('error', `Failed to load PDF page: ${e}`);
} finally {
loading.value = false;
}
}

// Calculate the width and height of the text
const textMetrics = context.measureText(errorMessage);
const textWidth = textMetrics.width;
const textHeight = 14; // Approximate height based on font size
function drawBlankCanvas(canvasElement: HTMLCanvasElement, viewport: pdfjs.PageViewport): void {
const outputScale = window.devicePixelRatio || 1;
canvasElement.width = viewport.width * outputScale;
canvasElement.height = viewport.height * outputScale;
canvasElement.style.width = `${Math.floor(viewport.width)}px`;
canvasElement.style.height = `${Math.floor(viewport.height)}px`;

canvasElement.removeAttribute('data-rendered');
canvasElement.removeAttribute('data-failed');
canvasElement.classList.remove('error');
}

// Calculate the position to center the text
const x = (canvasElement.width - textWidth) / 2;
const y = (canvasElement.height + textHeight) / 2;
function drawErrorCanvas(canvasElement: HTMLCanvasElement): void {
canvasElement.width = 300;
canvasElement.height = 60;
canvasElement.style.width = '300px';
canvasElement.style.height = '60px';
canvasElement.removeAttribute('data-rendered');
canvasElement.setAttribute('data-failed', '');
canvasElement.classList.add('error');

// Draw the text
context.fillText(errorMessage, x, y);
}
window.electronAPI.log('error', `Failed to open PDF page: ${e}`);
} finally {
loading.value = false;
const context = canvasElement.getContext('2d', { willReadFrequently: true });
if (context) {
const errorMessage = I18n.translate('fileViewers.pdf.loadPageError');
context.font = '14px "Albert Sans"';

// Calculate the width and height of the text
const textMetrics = context.measureText(errorMessage);
const textWidth = textMetrics.width;
const textHeight = 14; // Approximate height based on font size

// Calculate the position to center the text
const x = (canvasElement.width - textWidth) / 2;
const y = (canvasElement.height + textHeight) / 2;

// Draw the text
context.fillText(errorMessage, x, y);
}
}

Expand All @@ -168,29 +182,44 @@ async function loadPages(): Promise<void> {
}

async function renderPage(pageNumber: number): Promise<void> {
const page = await pdf.value!.getPage(pageNumber);
if (!page || isRendering.value) {
return;
}

const canvasElement = canvas.value.at(pageNumber - 1);
if (!canvasElement || isCanvasRendered(canvasElement)) {
if (isRendering.value) {
return;
}

isRendering.value = true;

const outputScale = window.devicePixelRatio || 1;
const context = canvasElement.getContext('2d', { willReadFrequently: true });
const renderContext = {
canvasContext: context!,
transform: outputScale !== 1 ? [outputScale, 0, 0, outputScale, 0, 0] : undefined,
viewport: page.getViewport({ scale: scale.value }),
};

await page.render(renderContext).promise;
isRendering.value = false;
canvasElement.setAttribute('data-rendered', '');
try {
const page = await pdf.value!.getPage(pageNumber);
const canvasElement = canvas.value.at(pageNumber - 1);
if (!page || !canvasElement || isCanvasRendered(canvasElement)) {
return;
}

const viewport = page.getViewport({ scale: scale.value });
if (canvasElement.getAttribute('data-failed') !== null) {
drawBlankCanvas(canvasElement, viewport);
}

const outputScale = window.devicePixelRatio || 1;
const context = canvasElement.getContext('2d', { willReadFrequently: true });
const renderContext = {
canvasContext: context!,
transform: outputScale !== 1 ? [outputScale, 0, 0, outputScale, 0, 0] : undefined,
viewport: viewport,
};

await page.render(renderContext).promise;
canvasElement.setAttribute('data-rendered', '');
} catch (e: any) {
const canvasElement = canvas.value.at(pageNumber - 1);
if (!canvasElement) {
return;
}
drawErrorCanvas(canvasElement);
window.electronAPI.log('error', `Failed to render PDF page: ${e}`);
} finally {
isRendering.value = false;
}
}

async function onZoomLevelChange(value: number): Promise<void> {
Expand Down

0 comments on commit f70ebcc

Please sign in to comment.