| import { | |
| useGetChunkHighlights, | |
| useGetDocumentUrl, | |
| } from '@/hooks/document-hooks'; | |
| import { IChunk } from '@/interfaces/database/knowledge'; | |
| import { Skeleton } from 'antd'; | |
| import { useEffect, useRef, useState } from 'react'; | |
| import { | |
| AreaHighlight, | |
| Highlight, | |
| IHighlight, | |
| PdfHighlighter, | |
| PdfLoader, | |
| Popup, | |
| } from 'react-pdf-highlighter'; | |
| import FileError from '@/pages/document-viewer/file-error'; | |
| import { useCatchDocumentError } from './hooks'; | |
| import styles from './index.less'; | |
| interface IProps { | |
| chunk: IChunk; | |
| documentId: string; | |
| visible: boolean; | |
| } | |
| const HighlightPopup = ({ | |
| comment, | |
| }: { | |
| comment: { text: string; emoji: string }; | |
| }) => | |
| comment.text ? ( | |
| <div className="Highlight__popup"> | |
| {comment.emoji} {comment.text} | |
| </div> | |
| ) : null; | |
| const DocumentPreviewer = ({ chunk, documentId, visible }: IProps) => { | |
| const getDocumentUrl = useGetDocumentUrl(documentId); | |
| const { highlights: state, setWidthAndHeight } = useGetChunkHighlights(chunk); | |
| const ref = useRef<(highlight: IHighlight) => void>(() => {}); | |
| const [loaded, setLoaded] = useState(false); | |
| const url = getDocumentUrl(); | |
| const error = useCatchDocumentError(url); | |
| const resetHash = () => {}; | |
| useEffect(() => { | |
| setLoaded(visible); | |
| }, [visible]); | |
| useEffect(() => { | |
| if (state.length > 0 && loaded) { | |
| setLoaded(false); | |
| ref.current(state[0]); | |
| } | |
| }, [state, loaded]); | |
| return ( | |
| <div className={styles.documentContainer}> | |
| <PdfLoader | |
| url={url} | |
| beforeLoad={<Skeleton active />} | |
| workerSrc="/pdfjs-dist/pdf.worker.min.js" | |
| errorMessage={<FileError>{error}</FileError>} | |
| > | |
| {(pdfDocument) => { | |
| pdfDocument.getPage(1).then((page) => { | |
| const viewport = page.getViewport({ scale: 1 }); | |
| const width = viewport.width; | |
| const height = viewport.height; | |
| setWidthAndHeight(width, height); | |
| }); | |
| return ( | |
| <PdfHighlighter | |
| pdfDocument={pdfDocument} | |
| enableAreaSelection={(event) => event.altKey} | |
| onScrollChange={resetHash} | |
| scrollRef={(scrollTo) => { | |
| ref.current = scrollTo; | |
| setLoaded(true); | |
| }} | |
| onSelectionFinished={() => null} | |
| highlightTransform={( | |
| highlight, | |
| index, | |
| setTip, | |
| hideTip, | |
| viewportToScaled, | |
| screenshot, | |
| isScrolledTo, | |
| ) => { | |
| const isTextHighlight = !Boolean( | |
| highlight.content && highlight.content.image, | |
| ); | |
| const component = isTextHighlight ? ( | |
| <Highlight | |
| isScrolledTo={isScrolledTo} | |
| position={highlight.position} | |
| comment={highlight.comment} | |
| /> | |
| ) : ( | |
| <AreaHighlight | |
| isScrolledTo={isScrolledTo} | |
| highlight={highlight} | |
| onChange={() => {}} | |
| /> | |
| ); | |
| return ( | |
| <Popup | |
| popupContent={<HighlightPopup {...highlight} />} | |
| onMouseOver={(popupContent) => | |
| setTip(highlight, () => popupContent) | |
| } | |
| onMouseOut={hideTip} | |
| key={index} | |
| > | |
| {component} | |
| </Popup> | |
| ); | |
| }} | |
| highlights={state} | |
| /> | |
| ); | |
| }} | |
| </PdfLoader> | |
| </div> | |
| ); | |
| }; | |
| export default DocumentPreviewer; | |