Don't open context menu when multi-touch (#2455)

This was very annoying when you would zoom on mobile and the context menu would appear.

The problem was the following:
- You put a finger in, it creates a timeout
- You put a second finger in, it creates another timeout
- 300ms elapsed, which is not that much
- The context menu opens
- Now you move your fingers, which works, but the context menu is still open

The fix is to invalidate the context menu if a second finger is added even if the first one hasn't moved.
This commit is contained in:
Christopher Chedeau 2020-12-05 15:06:50 -08:00 committed by GitHub
parent e617ccc252
commit 545b214558
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 24 additions and 14 deletions

View File

@ -186,7 +186,7 @@ let isPanning: boolean = false;
let isDraggingScrollBar: boolean = false;
let currentScrollBars: ScrollBars = { horizontal: null, vertical: null };
let touchTimeout = 0;
let touchMoving = false;
let invalidateContextMenu = false;
let lastPointerUp: ((event: any) => void) | null = null;
const gesture: Gesture = {
@ -645,6 +645,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
this.removeEventListeners();
this.scene.destroy();
clearTimeout(touchTimeout);
touchTimeout = 0;
}
private onResize = withBatchedUpdates(() => {
@ -1097,7 +1098,8 @@ class App extends React.Component<ExcalidrawProps, AppState> {
// remove touch handler for context menu on touch devices
if (event.pointerType === "touch" && touchTimeout) {
clearTimeout(touchTimeout);
touchMoving = false;
touchTimeout = 0;
invalidateContextMenu = false;
}
gesture.pointers.delete(event.pointerId);
@ -1924,7 +1926,7 @@ class App extends React.Component<ExcalidrawProps, AppState> {
// set touch moving for mobile context menu
private handleTouchMove = (event: React.TouchEvent<HTMLCanvasElement>) => {
touchMoving = true;
invalidateContextMenu = true;
};
private handleCanvasPointerDown = (
@ -2029,18 +2031,26 @@ class App extends React.Component<ExcalidrawProps, AppState> {
): void => {
// deal with opening context menu on touch devices
if (event.pointerType === "touch") {
touchMoving = false;
invalidateContextMenu = false;
// open the context menu with the first touch's clientX and clientY
// if the touch is not moving
touchTimeout = window.setTimeout(() => {
if (!touchMoving) {
this.openContextMenu({
clientX: event.clientX,
clientY: event.clientY,
});
}
}, TOUCH_CTX_MENU_TIMEOUT);
if (touchTimeout) {
// If there's already a touchTimeout, this means that there's another
// touch down and we are doing another touch, so we shouldn't open the
// context menu.
invalidateContextMenu = true;
} else {
// open the context menu with the first touch's clientX and clientY
// if the touch is not moving
touchTimeout = window.setTimeout(() => {
touchTimeout = 0;
if (!invalidateContextMenu) {
this.openContextMenu({
clientX: event.clientX,
clientY: event.clientY,
});
}
}, TOUCH_CTX_MENU_TIMEOUT);
}
}
};