|
|
|
|
@ -102,6 +102,7 @@ import {
@@ -102,6 +102,7 @@ import {
|
|
|
|
|
Emitter, |
|
|
|
|
isMobile, |
|
|
|
|
MINIMUM_ARROW_SIZE, |
|
|
|
|
DOUBLE_TAP_POSITION_THRESHOLD, |
|
|
|
|
} from "@excalidraw/common"; |
|
|
|
|
|
|
|
|
|
import { |
|
|
|
|
@ -531,6 +532,7 @@ export const useExcalidrawActionManager = () =>
@@ -531,6 +532,7 @@ export const useExcalidrawActionManager = () =>
|
|
|
|
|
|
|
|
|
|
let didTapTwice: boolean = false; |
|
|
|
|
let tappedTwiceTimer = 0; |
|
|
|
|
let firstTapPosition: { x: number; y: number } | null = null; |
|
|
|
|
let isHoldingSpace: boolean = false; |
|
|
|
|
let isPanning: boolean = false; |
|
|
|
|
let isDraggingScrollBar: boolean = false; |
|
|
|
|
@ -2989,6 +2991,7 @@ class App extends React.Component<AppProps, AppState> {
@@ -2989,6 +2991,7 @@ class App extends React.Component<AppProps, AppState> {
|
|
|
|
|
|
|
|
|
|
private static resetTapTwice() { |
|
|
|
|
didTapTwice = false; |
|
|
|
|
firstTapPosition = null; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private onTouchStart = (event: TouchEvent) => { |
|
|
|
|
@ -2999,6 +3002,13 @@ class App extends React.Component<AppProps, AppState> {
@@ -2999,6 +3002,13 @@ class App extends React.Component<AppProps, AppState> {
|
|
|
|
|
|
|
|
|
|
if (!didTapTwice) { |
|
|
|
|
didTapTwice = true; |
|
|
|
|
|
|
|
|
|
if (event.touches.length === 1) { |
|
|
|
|
firstTapPosition = { |
|
|
|
|
x: event.touches[0].clientX, |
|
|
|
|
y: event.touches[0].clientY, |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
clearTimeout(tappedTwiceTimer); |
|
|
|
|
tappedTwiceTimer = window.setTimeout( |
|
|
|
|
App.resetTapTwice, |
|
|
|
|
@ -3006,15 +3016,29 @@ class App extends React.Component<AppProps, AppState> {
@@ -3006,15 +3016,29 @@ class App extends React.Component<AppProps, AppState> {
|
|
|
|
|
); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
// insert text only if we tapped twice with a single finger
|
|
|
|
|
|
|
|
|
|
// insert text only if we tapped twice with a single finger at approximately the same position
|
|
|
|
|
// event.touches.length === 1 will also prevent inserting text when user's zooming
|
|
|
|
|
if (didTapTwice && event.touches.length === 1) { |
|
|
|
|
if (didTapTwice && event.touches.length === 1 && firstTapPosition) { |
|
|
|
|
const touch = event.touches[0]; |
|
|
|
|
// @ts-ignore
|
|
|
|
|
this.handleCanvasDoubleClick({ |
|
|
|
|
clientX: touch.clientX, |
|
|
|
|
clientY: touch.clientY, |
|
|
|
|
}); |
|
|
|
|
const distance = pointDistance( |
|
|
|
|
pointFrom(touch.clientX, touch.clientY), |
|
|
|
|
pointFrom(firstTapPosition.x, firstTapPosition.y), |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
// only create text if the second tap is within the threshold of the first tap
|
|
|
|
|
// this prevents accidental text creation during dragging/selection
|
|
|
|
|
if (distance <= DOUBLE_TAP_POSITION_THRESHOLD) { |
|
|
|
|
// end lasso trail and deselect elements just in case
|
|
|
|
|
this.lassoTrail.endPath(); |
|
|
|
|
this.deselectElements(); |
|
|
|
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
this.handleCanvasDoubleClick({ |
|
|
|
|
clientX: touch.clientX, |
|
|
|
|
clientY: touch.clientY, |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
didTapTwice = false; |
|
|
|
|
clearTimeout(tappedTwiceTimer); |
|
|
|
|
} |
|
|
|
|
|