Skip to content

Commit

Permalink
Rewrite PageSVG to React Hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
wojtekmaj committed Mar 8, 2023
1 parent ad27c6d commit 753614c
Showing 1 changed file with 75 additions and 69 deletions.
144 changes: 75 additions & 69 deletions src/Page/PageSVG.jsx
Original file line number Diff line number Diff line change
@@ -1,76 +1,83 @@
import React, { PureComponent } from 'react';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import PropTypes from 'prop-types';
import makeCancellable from 'make-cancellable-promise';
import warning from 'tiny-warning';
import * as pdfjs from 'pdfjs-dist/build/pdf';

import PageContext from '../PageContext';

import { isCancelException, makePageCallback } from '../shared/utils';
import { cancelRunningTask, isCancelException, makePageCallback } from '../shared/utils';

import { isPage, isRotate } from '../shared/propTypes';

export class PageSVGInternal extends PureComponent {
state = {
svg: null,
};

componentDidMount() {
this.renderSVG();
}
export function PageSVGInternal({
onRenderSuccess: onRenderSuccessProps,
onRenderError: onRenderErrorProps,
page,
rotate: rotateProps,
scale,
}) {
const [svg, setSvg] = useState(null);

/**
* Called when a page is rendered successfully.
* Called when a page is rendered successfully
*/
onRenderSuccess = () => {
this.renderer = null;

const { onRenderSuccess, page, scale } = this.props;

if (onRenderSuccess) onRenderSuccess(makePageCallback(page, scale));
};
const onRenderSuccess = useCallback(() => {
if (onRenderSuccessProps) {
onRenderSuccessProps(makePageCallback(page, scale));
}
}, [onRenderSuccessProps, page, scale]);

/**
* Called when a page fails to render.
* Called when a page fails to render
*/
onRenderError = (error) => {
if (isCancelException(error)) {
return;
}

warning(false, error);

const { onRenderError } = this.props;

if (onRenderError) onRenderError(error);
};

get viewport() {
const { page, rotate, scale } = this.props;
const onRenderError = useCallback(
(error) => {
if (isCancelException(error)) {
return;
}

warning(false, error);

if (onRenderErrorProps) {
onRenderErrorProps(error);
}
},
[onRenderErrorProps],
);

return page.getViewport({ scale, rotation: rotate });
}
const viewport = useMemo(
() => page.getViewport({ scale, rotation: rotateProps }),
[page, rotateProps, scale],
);

renderSVG = () => {
const { page } = this.props;
function renderSVG() {
if (svg) {
return;
}

this.renderer = page.getOperatorList();
const cancellable = makeCancellable(page.getOperatorList());
const runningTask = cancellable.promise;

return this.renderer
cancellable.promise
.then((operatorList) => {
const svgGfx = new pdfjs.SVGGraphics(page.commonObjs, page.objs);
this.renderer = svgGfx
.getSVG(operatorList, this.viewport)
.then((svg) => {
this.setState({ svg }, this.onRenderSuccess);
svgGfx
.getSVG(operatorList, viewport)
.then((nextSvg) => {
setSvg(nextSvg);
onRenderSuccess();
})
.catch(this.onRenderError);
.catch(onRenderError);
})
.catch(this.onRenderError);
};
.catch(onRenderError);

return () => cancelRunningTask(runningTask);
}

drawPageOnContainer = (element) => {
const { svg } = this.state;
useEffect(renderSVG, [onRenderError, onRenderSuccess, page, svg, viewport]);

function drawPageOnContainer(element) {
if (!element || !svg) {
return;
}
Expand All @@ -80,30 +87,29 @@ export class PageSVGInternal extends PureComponent {
element.appendChild(svg);
}

const { width, height } = this.viewport;
const { width, height } = viewport;

svg.setAttribute('width', width);
svg.setAttribute('height', height);
};

render() {
const { width, height } = this.viewport;

return (
<div
className="react-pdf__Page__svg"
// Note: This cannot be shortened, as we need this function to be called with each render.
ref={(ref) => this.drawPageOnContainer(ref)}
style={{
display: 'block',
backgroundColor: 'white',
overflow: 'hidden',
width,
height,
userSelect: 'none',
}}
/>
);
}

const { width, height } = viewport;

return (
<div
className="react-pdf__Page__svg"
// Note: This cannot be shortened, as we need this function to be called with each render.
ref={(ref) => drawPageOnContainer(ref)}
style={{
display: 'block',
backgroundColor: 'white',
overflow: 'hidden',
width,
height,
userSelect: 'none',
}}
/>
);
}

PageSVGInternal.propTypes = {
Expand Down

0 comments on commit 753614c

Please sign in to comment.