Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion src/PDFPreviewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,14 @@ type Props = {
ErrorComponent?: ReactNode;
shouldShowErrorComponent?: boolean;
onLoadError?: () => void;
/** Called once every page has been measured and the pages are ready to display */
onLoadSuccess?: () => void;
containerStyle?: CSSProperties;
contentContainerStyle?: CSSProperties;
rotation?: RotationDegrees;
options?: DocumentProps['options'];
/** 1-indexed page to scroll to. The previewer scrolls whenever it changes, including once the document loads. */
page?: number;
};

type OnPasswordCallback = (password: string | null) => void;
Expand All @@ -51,8 +55,10 @@ function PDFPreviewer({
contentContainerStyle,
shouldShowErrorComponent = true,
onLoadError,
onLoadSuccess,
rotation = 0,
options = DEFAULT_DOCUMENT_OPTIONS,
page,
}: Props): JSX.Element {
const [pageViewports, setPageViewports] = useState<PageViewport[]>([]);
const [numPages, setNumPages] = useState(0);
Expand All @@ -64,6 +70,12 @@ function PDFPreviewer({
const onPasswordCallbackRef = useRef<OnPasswordCallback | null>(null);
const listRef = useRef<List>(null);

// Measuring every page can take seconds, so call the latest callback rather than the one from when loading began
const onLoadSuccessRef = useRef(onLoadSuccess);
useLayoutEffect(() => {
onLoadSuccessRef.current = onLoadSuccess;
}, [onLoadSuccess]);

/**
* Calculate the devicePixelRatio the page should be rendered with
* Each platform has a different default devicePixelRatio and different canvas limits, we need to verify that
Expand Down Expand Up @@ -143,14 +155,15 @@ function PDFPreviewer({
times(pdf.numPages, (index: number) => {
const pageNumber = index + 1;

return pdf.getPage(pageNumber).then((page) => page.getViewport({scale: 1}));
return pdf.getPage(pageNumber).then((pdfPage) => pdfPage.getViewport({scale: 1}));
}),
).then(
(viewports: PageViewport[]) => {
setPageViewports(viewports);
setNumPages(pdf.numPages);
setShouldRequestPassword(false);
setIsPasswordInvalid(false);
onLoadSuccessRef.current?.();
},
() => {},
);
Expand Down Expand Up @@ -226,6 +239,16 @@ function PDFPreviewer({
listRef.current?.scrollTo(0);
}, [rotation]);

/**
* Keep the requested page aligned to the top. Re-runs after load and resizes because page offsets change then.
*/
useLayoutEffect(() => {
if (!page || pageViewports.length === 0) {
return;
}
listRef.current?.scrollToItem(page - 1, 'start');
}, [page, pageViewports.length, containerWidth, containerHeight, rotation]);

useLayoutEffect(() => {
if (!containerRef.current) {
return undefined;
Expand Down
Loading