import React, { useState, useEffect, useCallback } from 'react'; import { v4 as uuidv4 } from 'uuid'; import { ANNOTATION_TYPE } from '../constants'; import Icon from '../components/Icon'; import Button from '../components/Button'; import ExpansionPanel from '../components/ExpansionPanel'; import InkOption from '../components/InkOption'; import { getAbsoluteCoordinate, parsePositionForBackend, } from '../helpers/position'; import { parseAnnotationObject, appendUserIdAndDate, } from '../helpers/annotation'; import { switchPdfViewerScrollState } from '../helpers/pdf'; import useCursorPosition from '../hooks/useCursorPosition'; import useActions from '../actions'; import useStore from '../store'; type Props = { title: string; isActive: boolean; onClick: () => void; }; const FreehandTool: React.FC = ({ title, isActive, onClick }: Props) => { const [cursorPosition, setRef] = useCursorPosition(30); const [uuid, setUuid] = useState(''); const [data, setData] = useState({ type: 'pen', opacity: 100, color: '#FF0000', width: 3, }); const [{ viewport, scale, annotations }, dispatch] = useStore(); const { addAnnots, updateAnnots } = useActions(dispatch); const setDataState = (obj: OptionPropsType): void => { setData((prev) => ({ ...prev, ...obj, })); }; const handleMouseDown = useCallback( (event: MouseEvent | TouchEvent): void => { const pageEle = (event.target as HTMLElement).parentNode as HTMLElement; switchPdfViewerScrollState('hidden'); if (pageEle.hasAttribute('data-page-num')) { setRef(pageEle); const pageNum = pageEle.getAttribute('data-page-num') || 0; const coordinate = getAbsoluteCoordinate(pageEle, event); const id = uuidv4(); setUuid(id); const annotData = { id, obj_type: ANNOTATION_TYPE.ink, obj_attr: { page: pageNum as number, bdcolor: data.color, bdwidth: data.width, position: [[coordinate]], transparency: data.opacity, }, }; const freehand = appendUserIdAndDate( parseAnnotationObject(annotData, viewport.height, scale), ); addAnnots([freehand]); } }, [data, viewport, scale], ); const handleMouseUp = useCallback((): void => { switchPdfViewerScrollState('scroll'); const index = annotations.length - 1; if (annotations[index]) { const position = annotations[index].obj_attr.position as PointType[][]; if (!position[0]) return; if (position[0].length === 1 && annotations[index].id === uuid) { const point = position[0][0]; annotations[index].obj_attr.position = [ [ { x: point.x - 5, y: point.y - 5 }, { x: point.x + 5, y: point.y + 5 }, ], ]; annotations[index] = appendUserIdAndDate(annotations[index]); updateAnnots([...annotations]); } setRef(null); setUuid(''); } }, [annotations, uuid]); useEffect(() => { const index = annotations.length - 1; if ( annotations[index] && annotations[index].id === uuid && cursorPosition.x && cursorPosition.y ) { const type = annotations[index].obj_type; const position = annotations[index].obj_attr.position as PointType[][]; const coordinates = parsePositionForBackend( type, { x: cursorPosition.x, y: cursorPosition.y }, viewport.height, scale, ) as PointType; const lastPosition = position[0].slice(-1)[0]; if ( coordinates.x !== lastPosition.x && coordinates.y !== lastPosition.y ) { position[0].push(coordinates); annotations[index].obj_attr.position = position; annotations[index] = appendUserIdAndDate(annotations[index]); updateAnnots([...annotations]); } } }, [annotations, cursorPosition, uuid]); const subscribeEvent = (): void => { const pdfViewer = document.getElementById('pdf_viewer') as HTMLDivElement; pdfViewer.addEventListener('mousedown', handleMouseDown); pdfViewer.addEventListener('mouseup', handleMouseUp); pdfViewer.addEventListener('touchstart', handleMouseDown); pdfViewer.addEventListener('touchend', handleMouseUp); }; const unsubscribeEvent = (): void => { const pdfViewer = document.getElementById('pdf_viewer') as HTMLDivElement; pdfViewer.removeEventListener('mousedown', handleMouseDown); pdfViewer.removeEventListener('mouseup', handleMouseUp); pdfViewer.removeEventListener('touchstart', handleMouseDown); pdfViewer.removeEventListener('touchend', handleMouseUp); }; useEffect(() => { const pdfViewer = document.getElementById('pdf_viewer') as HTMLDivElement; if (isActive && pdfViewer) { subscribeEvent(); } return (): void => { if (pdfViewer) { unsubscribeEvent(); } }; }, [isActive, handleMouseDown, handleMouseUp]); const Label = ( ); return ( ); }; export default FreehandTool;