fix: tighten distance for double tap text creation (#9889)

This commit is contained in:
Ryan Di
2025-08-23 02:12:51 +10:00
committed by GitHub
parent 531f3e5524
commit 3085f4af81
2 changed files with 33 additions and 7 deletions

View File

@@ -522,3 +522,5 @@ export enum UserIdleState {
* the start and end points) * the start and end points)
*/ */
export const LINE_POLYGON_POINT_MERGE_DISTANCE = 20; export const LINE_POLYGON_POINT_MERGE_DISTANCE = 20;
export const DOUBLE_TAP_POSITION_THRESHOLD = 35;

View File

@@ -102,6 +102,7 @@ import {
Emitter, Emitter,
isMobile, isMobile,
MINIMUM_ARROW_SIZE, MINIMUM_ARROW_SIZE,
DOUBLE_TAP_POSITION_THRESHOLD,
} from "@excalidraw/common"; } from "@excalidraw/common";
import { import {
@@ -531,6 +532,7 @@ export const useExcalidrawActionManager = () =>
let didTapTwice: boolean = false; let didTapTwice: boolean = false;
let tappedTwiceTimer = 0; let tappedTwiceTimer = 0;
let firstTapPosition: { x: number; y: number } | null = null;
let isHoldingSpace: boolean = false; let isHoldingSpace: boolean = false;
let isPanning: boolean = false; let isPanning: boolean = false;
let isDraggingScrollBar: boolean = false; let isDraggingScrollBar: boolean = false;
@@ -2989,6 +2991,7 @@ class App extends React.Component<AppProps, AppState> {
private static resetTapTwice() { private static resetTapTwice() {
didTapTwice = false; didTapTwice = false;
firstTapPosition = null;
} }
private onTouchStart = (event: TouchEvent) => { private onTouchStart = (event: TouchEvent) => {
@@ -2999,6 +3002,13 @@ class App extends React.Component<AppProps, AppState> {
if (!didTapTwice) { if (!didTapTwice) {
didTapTwice = true; didTapTwice = true;
if (event.touches.length === 1) {
firstTapPosition = {
x: event.touches[0].clientX,
y: event.touches[0].clientY,
};
}
clearTimeout(tappedTwiceTimer); clearTimeout(tappedTwiceTimer);
tappedTwiceTimer = window.setTimeout( tappedTwiceTimer = window.setTimeout(
App.resetTapTwice, App.resetTapTwice,
@@ -3006,15 +3016,29 @@ class App extends React.Component<AppProps, AppState> {
); );
return; 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 // 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]; const touch = event.touches[0];
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 // @ts-ignore
this.handleCanvasDoubleClick({ this.handleCanvasDoubleClick({
clientX: touch.clientX, clientX: touch.clientX,
clientY: touch.clientY, clientY: touch.clientY,
}); });
}
didTapTwice = false; didTapTwice = false;
clearTimeout(tappedTwiceTimer); clearTimeout(tappedTwiceTimer);
} }