index.tsx 3.0 KB

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