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

View File

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