index.tsx 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import React, { useEffect, useState, useRef } from 'react';
  2. import Icon from '../Icon';
  3. import Drawer from '../Drawer';
  4. import Thumbnail from '../Thumbnail';
  5. import { Wrapper, Head, Body, IconWrapper } from '../../global/sidebarStyled'
  6. import { ScrollStateType } from '../../constants/type';
  7. import { watchScroll, scrollIntoView } from '../../helpers/utility';
  8. import { ThumbnailsWrapper } from './styled';
  9. type Props = {
  10. isActive?: boolean;
  11. close: () => void;
  12. currentPage: number;
  13. totalPage: number;
  14. getPdfImage: (page: number) => Promise<string>;
  15. };
  16. const Thumbnails : React.FunctionComponent<Props> = ({
  17. isActive = false,
  18. close,
  19. currentPage,
  20. totalPage,
  21. getPdfImage,
  22. }) => {
  23. const containerRef = useRef<HTMLDivElement>(null);
  24. const [scrollIndex, setScrollIndex] = useState(currentPage);
  25. const [elements, setElement] = useState<React.ReactNode[]>([]);
  26. const scrollUpdate = (state: ScrollStateType) => {
  27. const height = 220;
  28. const index = Math.round((state.lastY + height) / height);
  29. setScrollIndex(index);
  30. };
  31. const createThumbnails = () => {
  32. const eleContent: React.ReactNode[] = [];
  33. for(let i = 1; i <= totalPage; i++) {
  34. const component = (
  35. <Thumbnail
  36. key={`thumbnail_${i}`}
  37. pageNum={i}
  38. getPdfImage={getPdfImage}
  39. renderingState={[1,2,3,4,5].includes(i) ? 'RENDERING' : 'LOADING'}
  40. />
  41. );
  42. eleContent.push(component);
  43. }
  44. setElement(eleContent);
  45. }
  46. const updateThumbnails = () => {
  47. const renderingIndexQueue = [scrollIndex - 1 ,scrollIndex, scrollIndex + 1, scrollIndex + 2, scrollIndex + 3];
  48. let index = scrollIndex - 5;
  49. const end = scrollIndex + 5;
  50. while (true) {
  51. if (elements[index]) {
  52. const pageNum = index + 1;
  53. elements[index] = (
  54. <Thumbnail
  55. key={`thumbnail_${pageNum}`}
  56. pageNum={pageNum}
  57. getPdfImage={getPdfImage}
  58. renderingState={renderingIndexQueue.includes(pageNum) ? 'RENDERING' : 'LOADING'}
  59. />
  60. )
  61. }
  62. index += 1;
  63. if (index >= end) break;
  64. }
  65. if (elements.length) {
  66. setElement([...elements]);
  67. }
  68. };
  69. useEffect(() => {
  70. if (containerRef.current) {
  71. watchScroll(containerRef.current, scrollUpdate);
  72. }
  73. }, [containerRef]);
  74. useEffect(() => {
  75. if (isActive && !elements.length) {
  76. createThumbnails();
  77. }
  78. }, [isActive]);
  79. useEffect(() => {
  80. updateThumbnails();
  81. }, [scrollIndex]);
  82. useEffect(() => {
  83. if (isActive && elements.length) {
  84. const ele : HTMLElement = document.getElementById(`thumbnail_${currentPage}`)!;
  85. scrollIntoView(ele);
  86. }
  87. }, [currentPage, isActive]);
  88. return (
  89. <Drawer anchor="right" open={isActive}>
  90. <Wrapper>
  91. <Head>
  92. <IconWrapper>
  93. <Icon glyph="right-back" onClick={close} />
  94. </IconWrapper>
  95. </Head>
  96. <Body ref={containerRef}>
  97. <ThumbnailsWrapper>
  98. {elements}
  99. </ThumbnailsWrapper>
  100. </Body>
  101. </Wrapper>
  102. </Drawer>
  103. );
  104. };
  105. export default Thumbnails;