PdfViewer.tsx 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import React, {
  2. useEffect, useState, useRef, useCallback,
  3. } from 'react';
  4. import queryString from 'query-string';
  5. import config from '../config';
  6. import apiPath from '../constants/apiPath';
  7. import { initialPdfFile } from '../apis';
  8. import Viewer from '../components/Viewer';
  9. import { fetchPdf } from '../helpers/pdf';
  10. import { watchScroll } from '../helpers/utility';
  11. import { ProgressType, ScrollStateType } from '../constants/type';
  12. import useActions from '../actions';
  13. import useStore from '../store';
  14. const PdfViewer: React.FunctionComponent = () => {
  15. const containerRef = useRef<HTMLDivElement>(null);
  16. const pageRef = useRef(1);
  17. const viewportRef = useRef({ height: 0, width: 0 });
  18. const [initialized, setInitialize] = useState(false);
  19. const [{
  20. totalPage, currentPage, viewport, pdf, scale, rotation,
  21. }, dispatch] = useStore();
  22. const {
  23. setTotalPage, setCurrentPage, setPdf, setProgress, setViewport,
  24. } = useActions(dispatch);
  25. const setLoadingProgress = (totalSize: number) => (progress: ProgressType): void => {
  26. setProgress({
  27. total: totalSize,
  28. loaded: progress.loaded,
  29. });
  30. };
  31. const getViewport = async (pdfEle: any, s: number): Promise<any> => {
  32. const page = await pdfEle.getPage(1);
  33. const iViewport = page.getViewport({ scale: s });
  34. iViewport.width = Math.round(iViewport.width);
  35. iViewport.height = Math.round(iViewport.height);
  36. setViewport(iViewport);
  37. };
  38. const pdfGenerator = async (): Promise<any> => {
  39. const parsed = queryString.parse(window.location.search);
  40. const res = await initialPdfFile(parsed.token as string);
  41. if (res.data) {
  42. const iPdf = await fetchPdf(
  43. `${config.API_HOST}${apiPath.getOriginalPdfFile}?transaction_id=${res.data.transaction_id}`,
  44. setLoadingProgress(res.data.size),
  45. );
  46. const totalNum = iPdf.numPages;
  47. setTotalPage(totalNum);
  48. setPdf(iPdf);
  49. await getViewport(iPdf, 1);
  50. setInitialize(true);
  51. }
  52. };
  53. const scrollUpdate = useCallback((state: ScrollStateType) => {
  54. const iViewport = viewportRef.current;
  55. const page = Math.round((state.lastY + iViewport.height / 1.4) / (iViewport.height + 50));
  56. if (page !== pageRef.current) {
  57. setCurrentPage(page);
  58. }
  59. }, [dispatch]);
  60. useEffect(() => {
  61. pdfGenerator();
  62. }, []);
  63. useEffect(() => {
  64. if (containerRef.current) {
  65. watchScroll(containerRef.current, scrollUpdate);
  66. }
  67. }, [initialized]);
  68. useEffect(() => {
  69. pageRef.current = currentPage;
  70. viewportRef.current = viewport;
  71. }, [currentPage, viewport]);
  72. useEffect(() => {
  73. if (pdf) {
  74. getViewport(pdf, scale);
  75. }
  76. }, [scale]);
  77. return (
  78. initialized ? (
  79. <Viewer
  80. ref={containerRef}
  81. totalPage={totalPage}
  82. currentPage={currentPage}
  83. viewport={viewport}
  84. pdf={pdf}
  85. rotation={rotation}
  86. />
  87. ) : null
  88. );
  89. };
  90. export default PdfViewer;