Add support for long press to context menu on iOS (#1769)
* Initial support for touch context menu * Only deal with touch if it's available * Fix touch checking * Remove touch checking * Added comments * Combine onTouch with onPointer for mobile context menu support
This commit is contained in:
parent
8621ddb6a2
commit
cc52ea4ac2
@ -125,6 +125,7 @@ import {
|
||||
INITAL_SCENE_UPDATE_TIMEOUT,
|
||||
TAP_TWICE_TIMEOUT,
|
||||
SYNC_FULL_SCENE_INTERVAL_MS,
|
||||
TOUCH_CTX_MENU_TIMEOUT,
|
||||
} from "../time_constants";
|
||||
|
||||
import LayerUI from "./LayerUI";
|
||||
@ -172,6 +173,8 @@ let isHoldingSpace: boolean = false;
|
||||
let isPanning: boolean = false;
|
||||
let isDraggingScrollBar: boolean = false;
|
||||
let currentScrollBars: ScrollBars = { horizontal: null, vertical: null };
|
||||
let touchTimeout = 0;
|
||||
let touchMoving = false;
|
||||
|
||||
let lastPointerUp: ((event: any) => void) | null = null;
|
||||
const gesture: Gesture = {
|
||||
@ -256,6 +259,7 @@ class App extends React.Component<any, AppState> {
|
||||
onPointerMove={this.handleCanvasPointerMove}
|
||||
onPointerUp={this.removePointer}
|
||||
onPointerCancel={this.removePointer}
|
||||
onTouchMove={this.handleTouchMove}
|
||||
onDrop={this.handleCanvasOnDrop}
|
||||
>
|
||||
{t("labels.drawingCanvas")}
|
||||
@ -409,6 +413,8 @@ class App extends React.Component<any, AppState> {
|
||||
this.unmounted = true;
|
||||
this.removeSceneCallback!();
|
||||
this.removeEventListeners();
|
||||
|
||||
clearTimeout(touchTimeout);
|
||||
}
|
||||
|
||||
private onResize = withBatchedUpdates(() => {
|
||||
@ -818,6 +824,12 @@ class App extends React.Component<any, AppState> {
|
||||
};
|
||||
|
||||
removePointer = (event: React.PointerEvent<HTMLElement>) => {
|
||||
// remove touch handler for context menu on touch devices
|
||||
if (event.pointerType === "touch" && touchTimeout) {
|
||||
clearTimeout(touchTimeout);
|
||||
touchMoving = false;
|
||||
}
|
||||
|
||||
gesture.pointers.delete(event.pointerId);
|
||||
};
|
||||
|
||||
@ -1802,11 +1814,32 @@ class App extends React.Component<any, AppState> {
|
||||
}
|
||||
};
|
||||
|
||||
// set touch moving for mobile context menu
|
||||
private handleTouchMove = (event: React.TouchEvent<HTMLCanvasElement>) => {
|
||||
touchMoving = true;
|
||||
};
|
||||
|
||||
private handleCanvasPointerDown = (
|
||||
event: React.PointerEvent<HTMLCanvasElement>,
|
||||
) => {
|
||||
event.persist();
|
||||
|
||||
// deal with opening context menu on touch devices
|
||||
if (event.pointerType === "touch") {
|
||||
touchMoving = 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 (lastPointerUp !== null) {
|
||||
// Unfortunately, sometimes we don't get a pointerup after a pointerdown,
|
||||
// this can happen when a contextual menu or alert is triggered. In order to avoid
|
||||
@ -2847,9 +2880,18 @@ class App extends React.Component<any, AppState> {
|
||||
event: React.PointerEvent<HTMLCanvasElement>,
|
||||
) => {
|
||||
event.preventDefault();
|
||||
this.openContextMenu(event);
|
||||
};
|
||||
|
||||
private openContextMenu = ({
|
||||
clientX,
|
||||
clientY,
|
||||
}: {
|
||||
clientX: number;
|
||||
clientY: number;
|
||||
}) => {
|
||||
const { x, y } = viewportCoordsToSceneCoords(
|
||||
event,
|
||||
{ clientX, clientY },
|
||||
this.state,
|
||||
this.canvas,
|
||||
window.devicePixelRatio,
|
||||
@ -2888,8 +2930,8 @@ class App extends React.Component<any, AppState> {
|
||||
action: this.toggleGridMode,
|
||||
},
|
||||
],
|
||||
top: event.clientY,
|
||||
left: event.clientX,
|
||||
top: clientY,
|
||||
left: clientX,
|
||||
});
|
||||
return;
|
||||
}
|
||||
@ -2920,8 +2962,8 @@ class App extends React.Component<any, AppState> {
|
||||
(action) => !CANVAS_ONLY_ACTIONS.includes(action.name),
|
||||
),
|
||||
],
|
||||
top: event.clientY,
|
||||
left: event.clientX,
|
||||
top: clientY,
|
||||
left: clientX,
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -2,3 +2,4 @@
|
||||
export const TAP_TWICE_TIMEOUT = 300;
|
||||
export const INITAL_SCENE_UPDATE_TIMEOUT = 5000;
|
||||
export const SYNC_FULL_SCENE_INTERVAL_MS = 20000;
|
||||
export const TOUCH_CTX_MENU_TIMEOUT = 500;
|
||||
|
Loading…
x
Reference in New Issue
Block a user