From 8a2a14ce74634d44071fa3b682c0965b289aef0c Mon Sep 17 00:00:00 2001 From: Dmitry S Date: Tue, 9 Feb 2021 10:05:47 -0500 Subject: [PATCH] (core) Fix double-tap on Android failing to select tapped cell; ensure gestures don't get interpreted as double-tap Summary: This solves the issue of double-tapping cells when NOT in mobile mode, which is caused by delayed simulation of click events. (In mobile mode, modern browsers don't add a delay either way.) Also avoid unintended opening of the editor by checking that the double-tap is on the same cell. Test Plan: Tested manually on iPhone and Chrome emulator. Reviewers: paulfitz Reviewed By: paulfitz Differential Revision: https://phab.getgrist.com/D2727 --- app/client/lib/dblclick.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/app/client/lib/dblclick.ts b/app/client/lib/dblclick.ts index 2911194e..f3d3bc25 100644 --- a/app/client/lib/dblclick.ts +++ b/app/client/lib/dblclick.ts @@ -20,16 +20,25 @@ const DOUBLE_TAP_INTERVAL_MS = 500; * - https://github.com/w3c/pointerevents/issues/171 */ export function onDblClickMatchElem(elem: EventTarget, selector: string, callback: EventCB): void { + // According to https://developer.mozilla.org/en-US/docs/Web/CSS/touch-action, this "removes the + // need for browsers to delay the generation of click events when the user taps the screen". + // Without it, the delay (e.g. on mobile Chrome) prevents cursor from moving on double-tap. + dom.styleElem(elem as HTMLElement, 'touch-action', 'manipulation'); dom.onMatchElem(elem, selector, 'dblclick', (ev, _elem) => { callback(ev, _elem); }); let lastTapTime = 0; + let lastTapElem: EventTarget|null = null; dom.onMatchElem(elem, selector, 'touchend', (ev, _elem) => { const currentTime = Date.now(); const tapLength = currentTime - lastTapTime; + const sameElem = (_elem === lastTapElem); lastTapTime = currentTime; - if (tapLength < DOUBLE_TAP_INTERVAL_MS && tapLength > 0) { + lastTapElem = _elem; + // Only consider a gesture a double-tap if it's on the same cell. Otherwise, two-finger + // gestures, such as zooming, may trigger this too. + if (sameElem && tapLength < DOUBLE_TAP_INTERVAL_MS && tapLength > 0) { ev.preventDefault(); callback(ev, _elem); }