refactor(mobile): drawing mouse to pointer events, field colors and actions feedback, touch action
This commit is contained in:
parent
757012399a
commit
b20ffe6e87
@ -9,7 +9,6 @@ import {
|
||||
} from '@mui/material'
|
||||
import styles from './style.module.scss'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import * as PDFJS from 'pdfjs-dist'
|
||||
import { ProfileMetadata, User, UserRole } from '../../types'
|
||||
import { MouseState, PdfPage, DrawnField, DrawTool } from '../../types/drawing'
|
||||
import { truncate } from 'lodash'
|
||||
@ -22,10 +21,10 @@ import { useScale } from '../../hooks/useScale'
|
||||
import { AvatarIconButton } from '../UserAvatarIconButton'
|
||||
import { LoadingSpinner } from '../LoadingSpinner'
|
||||
|
||||
PDFJS.GlobalWorkerOptions.workerSrc = new URL(
|
||||
'pdfjs-dist/build/pdf.worker.min.mjs',
|
||||
import.meta.url
|
||||
).toString()
|
||||
const DEFAULT_START_SIZE = {
|
||||
width: 140,
|
||||
height: 40
|
||||
} as const
|
||||
|
||||
interface Props {
|
||||
selectedFiles: File[]
|
||||
@ -46,6 +45,8 @@ export const DrawPDFFields = (props: Props) => {
|
||||
clicked: false
|
||||
})
|
||||
|
||||
const [activeDrawField, setActiveDrawField] = useState<number>()
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedFiles) {
|
||||
/**
|
||||
@ -77,10 +78,12 @@ export const DrawPDFFields = (props: Props) => {
|
||||
* Drawing events
|
||||
*/
|
||||
useEffect(() => {
|
||||
window.addEventListener('mouseup', onMouseUp)
|
||||
window.addEventListener('pointerup', handlePointerUp)
|
||||
window.addEventListener('pointercancel', handlePointerUp)
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('mouseup', onMouseUp)
|
||||
window.removeEventListener('pointerup', handlePointerUp)
|
||||
window.removeEventListener('pointercancel', handlePointerUp)
|
||||
}
|
||||
}, [])
|
||||
|
||||
@ -96,10 +99,7 @@ export const DrawPDFFields = (props: Props) => {
|
||||
* @param event Mouse event
|
||||
* @param page PdfPage where press happened
|
||||
*/
|
||||
const onMouseDown = (
|
||||
event: React.MouseEvent<HTMLDivElement>,
|
||||
page: PdfPage
|
||||
) => {
|
||||
const handlePointerDown = (event: React.PointerEvent, page: PdfPage) => {
|
||||
// Proceed only if left click
|
||||
if (event.button !== 0) return
|
||||
|
||||
@ -112,8 +112,8 @@ export const DrawPDFFields = (props: Props) => {
|
||||
const newField: DrawnField = {
|
||||
left: to(page.width, mouseX),
|
||||
top: to(page.width, mouseY),
|
||||
width: 0,
|
||||
height: 0,
|
||||
width: event.pointerType === 'mouse' ? 0 : DEFAULT_START_SIZE.width,
|
||||
height: event.pointerType === 'mouse' ? 0 : DEFAULT_START_SIZE.height,
|
||||
counterpart: '',
|
||||
type: selectedTool.identifier
|
||||
}
|
||||
@ -132,7 +132,7 @@ export const DrawPDFFields = (props: Props) => {
|
||||
* Drawing is finished, resets all the variables used to draw
|
||||
* @param event Mouse event
|
||||
*/
|
||||
const onMouseUp = () => {
|
||||
const handlePointerUp = () => {
|
||||
setMouseState((prev) => {
|
||||
return {
|
||||
...prev,
|
||||
@ -144,16 +144,13 @@ export const DrawPDFFields = (props: Props) => {
|
||||
}
|
||||
|
||||
/**
|
||||
* After {@link onMouseDown} create an drawing element, this function gets called on every pixel moved
|
||||
* After {@link handlePointerDown} create an drawing element, this function gets called on every pixel moved
|
||||
* which alters the newly created drawing element, resizing it while mouse move
|
||||
* @param event Mouse event
|
||||
* @param page PdfPage where moving is happening
|
||||
*/
|
||||
const onMouseMove = (
|
||||
event: React.MouseEvent<HTMLDivElement>,
|
||||
page: PdfPage
|
||||
) => {
|
||||
if (mouseState.clicked && selectedTool) {
|
||||
const handlePointerMove = (event: React.PointerEvent, page: PdfPage) => {
|
||||
if (mouseState.clicked && selectedTool && event.pointerType === 'mouse') {
|
||||
const lastElementIndex = page.drawnFields.length - 1
|
||||
|
||||
const lastDrawnField = page.drawnFields[lastElementIndex]
|
||||
@ -187,9 +184,12 @@ export const DrawPDFFields = (props: Props) => {
|
||||
* mouseY - offsetY
|
||||
*
|
||||
* @param event Mouse event
|
||||
* @param drawnField Which we are moving
|
||||
* @param drawnFieldIndex Which we are moving
|
||||
*/
|
||||
const onDrawnFieldMouseDown = (event: React.MouseEvent<HTMLDivElement>) => {
|
||||
const handleDrawnFieldPointerDown = (
|
||||
event: React.PointerEvent,
|
||||
drawnFieldIndex: number
|
||||
) => {
|
||||
event.stopPropagation()
|
||||
|
||||
// Proceed only if left click
|
||||
@ -197,6 +197,7 @@ export const DrawPDFFields = (props: Props) => {
|
||||
|
||||
const drawingRectangleCoords = getMouseCoordinates(event)
|
||||
|
||||
setActiveDrawField(drawnFieldIndex)
|
||||
setMouseState({
|
||||
dragging: true,
|
||||
clicked: false,
|
||||
@ -212,8 +213,8 @@ export const DrawPDFFields = (props: Props) => {
|
||||
* @param event Mouse event
|
||||
* @param drawnField which we are moving
|
||||
*/
|
||||
const onDrawnFieldMouseMove = (
|
||||
event: React.MouseEvent<HTMLDivElement>,
|
||||
const handleDrawnFieldPointerMove = (
|
||||
event: React.PointerEvent,
|
||||
drawnField: DrawnField,
|
||||
pageWidth: number
|
||||
) => {
|
||||
@ -228,8 +229,8 @@ export const DrawPDFFields = (props: Props) => {
|
||||
let left = to(pageWidth, mouseX - coordsOffset.mouseX)
|
||||
let top = to(pageWidth, mouseY - coordsOffset.mouseY)
|
||||
|
||||
const rightLimit = to(pageWidth, rect.width) - drawnField.width - 3
|
||||
const bottomLimit = to(pageWidth, rect.height) - drawnField.height - 3
|
||||
const rightLimit = to(pageWidth, rect.width) - drawnField.width
|
||||
const bottomLimit = to(pageWidth, rect.height) - drawnField.height
|
||||
|
||||
if (left < 0) left = 0
|
||||
if (top < 0) top = 0
|
||||
@ -247,16 +248,17 @@ export const DrawPDFFields = (props: Props) => {
|
||||
/**
|
||||
* Fired when clicked on the resize handle, sets the state for a resize action
|
||||
* @param event Mouse event
|
||||
* @param drawnField which we are resizing
|
||||
* @param drawnFieldIndex which we are resizing
|
||||
*/
|
||||
const onResizeHandleMouseDown = (
|
||||
event: React.MouseEvent<HTMLSpanElement>
|
||||
const handleResizePointerDown = (
|
||||
event: React.PointerEvent,
|
||||
drawnFieldIndex: number
|
||||
) => {
|
||||
// Proceed only if left click
|
||||
if (event.button !== 0) return
|
||||
|
||||
event.stopPropagation()
|
||||
|
||||
setActiveDrawField(drawnFieldIndex)
|
||||
setMouseState({
|
||||
resizing: true
|
||||
})
|
||||
@ -267,8 +269,8 @@ export const DrawPDFFields = (props: Props) => {
|
||||
* @param event Mouse event
|
||||
* @param drawnField which we are resizing
|
||||
*/
|
||||
const onResizeHandleMouseMove = (
|
||||
event: React.MouseEvent<HTMLSpanElement>,
|
||||
const handleResizePointerMove = (
|
||||
event: React.PointerEvent,
|
||||
drawnField: DrawnField,
|
||||
pageWidth: number
|
||||
) => {
|
||||
@ -298,8 +300,8 @@ export const DrawPDFFields = (props: Props) => {
|
||||
* @param pdfPageIndex pdf page index
|
||||
* @param drawnFileIndex drawn file index
|
||||
*/
|
||||
const onRemoveHandleMouseDown = (
|
||||
event: React.MouseEvent<HTMLSpanElement>,
|
||||
const handleRemovePointerDown = (
|
||||
event: React.PointerEvent,
|
||||
pdfFileIndex: number,
|
||||
pdfPageIndex: number,
|
||||
drawnFileIndex: number
|
||||
@ -317,20 +319,18 @@ export const DrawPDFFields = (props: Props) => {
|
||||
* so select can work properly
|
||||
* @param event Mouse event
|
||||
*/
|
||||
const onUserSelectHandleMouseDown = (
|
||||
event: React.MouseEvent<HTMLDivElement>
|
||||
) => {
|
||||
const handleUserSelectPointerDown = (event: React.PointerEvent) => {
|
||||
event.stopPropagation()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the mouse coordinates relative to a element in the `event` param
|
||||
* @param event MouseEvent
|
||||
* @param event PointerEvent
|
||||
* @param customTarget mouse coordinates relative to this element, if not provided
|
||||
* event.target will be used
|
||||
*/
|
||||
const getMouseCoordinates = (
|
||||
event: React.MouseEvent<HTMLElement>,
|
||||
event: React.PointerEvent,
|
||||
customTarget?: HTMLElement | null
|
||||
) => {
|
||||
const target = customTarget ? customTarget : event.currentTarget
|
||||
@ -346,7 +346,6 @@ export const DrawPDFFields = (props: Props) => {
|
||||
rect
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the pdf pages and drawing elements
|
||||
*/
|
||||
@ -363,11 +362,11 @@ export const DrawPDFFields = (props: Props) => {
|
||||
className={`image-wrapper ${styles.pdfImageWrapper} ${selectedTool ? styles.drawing : ''}`}
|
||||
>
|
||||
<img
|
||||
onMouseMove={(event) => {
|
||||
onMouseMove(event, page)
|
||||
onPointerMove={(event) => {
|
||||
handlePointerMove(event, page)
|
||||
}}
|
||||
onMouseDown={(event) => {
|
||||
onMouseDown(event, page)
|
||||
onPointerDown={(event) => {
|
||||
handlePointerDown(event, page)
|
||||
}}
|
||||
draggable="false"
|
||||
src={page.image}
|
||||
@ -378,29 +377,52 @@ export const DrawPDFFields = (props: Props) => {
|
||||
return (
|
||||
<div
|
||||
key={drawnFieldIndex}
|
||||
onMouseDown={onDrawnFieldMouseDown}
|
||||
onMouseMove={(event) => {
|
||||
onDrawnFieldMouseMove(event, drawnField, page.width)
|
||||
onPointerDown={(event) =>
|
||||
handleDrawnFieldPointerDown(event, drawnFieldIndex)
|
||||
}
|
||||
onPointerMove={(event) => {
|
||||
handleDrawnFieldPointerMove(event, drawnField, page.width)
|
||||
}}
|
||||
className={styles.drawingRectangle}
|
||||
style={{
|
||||
backgroundColor: drawnField.counterpart
|
||||
? `#${npubToHex(drawnField.counterpart)?.substring(0, 6)}4b`
|
||||
: undefined,
|
||||
borderColor: drawnField.counterpart
|
||||
? `#${npubToHex(drawnField.counterpart)?.substring(0, 6)}`
|
||||
: undefined,
|
||||
left: inPx(from(page.width, drawnField.left)),
|
||||
top: inPx(from(page.width, drawnField.top)),
|
||||
width: inPx(from(page.width, drawnField.width)),
|
||||
height: inPx(from(page.width, drawnField.height)),
|
||||
pointerEvents: mouseState.clicked ? 'none' : 'all'
|
||||
pointerEvents: mouseState.clicked ? 'none' : 'all',
|
||||
touchAction: 'none',
|
||||
opacity:
|
||||
mouseState.dragging &&
|
||||
activeDrawField === drawnFieldIndex
|
||||
? 0.8
|
||||
: undefined
|
||||
}}
|
||||
>
|
||||
<span
|
||||
onMouseDown={onResizeHandleMouseDown}
|
||||
onMouseMove={(event) => {
|
||||
onResizeHandleMouseMove(event, drawnField, page.width)
|
||||
onPointerDown={(event) =>
|
||||
handleResizePointerDown(event, drawnFieldIndex)
|
||||
}
|
||||
onPointerMove={(event) => {
|
||||
handleResizePointerMove(event, drawnField, page.width)
|
||||
}}
|
||||
className={styles.resizeHandle}
|
||||
style={{
|
||||
background:
|
||||
mouseState.resizing &&
|
||||
activeDrawField === drawnFieldIndex
|
||||
? 'var(--primary-main)'
|
||||
: undefined
|
||||
}}
|
||||
></span>
|
||||
<span
|
||||
onMouseDown={(event) => {
|
||||
onRemoveHandleMouseDown(
|
||||
onPointerDown={(event) => {
|
||||
handleRemovePointerDown(
|
||||
event,
|
||||
fileIndex,
|
||||
pageIndex,
|
||||
@ -412,7 +434,7 @@ export const DrawPDFFields = (props: Props) => {
|
||||
<Close fontSize="small" />
|
||||
</span>
|
||||
<div
|
||||
onMouseDown={onUserSelectHandleMouseDown}
|
||||
onPointerDown={handleUserSelectPointerDown}
|
||||
className={styles.userSelect}
|
||||
>
|
||||
<FormControl fullWidth size="small">
|
||||
|
Loading…
Reference in New Issue
Block a user