Fix action directive double tab iOS issues (#4639)

This commit is contained in:
Bram Kragten 2020-01-29 19:03:43 +01:00 committed by GitHub
parent 7ab9257f5e
commit dd8c568a2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,5 +1,7 @@
import { directive, PropertyPart } from "lit-html";
import "@material/mwc-ripple";
// tslint:disable-next-line
import { Ripple } from "@material/mwc-ripple";
import {
ActionHandlerOptions,
ActionHandlerDetail,
@ -26,22 +28,16 @@ declare global {
}
class ActionHandler extends HTMLElement implements ActionHandler {
public holdTime: number;
public ripple: any;
protected timer: number | undefined;
protected held: boolean;
protected cooldownStart: boolean;
protected cooldownEnd: boolean;
private dblClickTimeout: number | undefined;
public holdTime = 500;
public ripple: Ripple;
protected timer?: number;
protected held = false;
protected touch?: boolean;
private dblClickTimeout?: number;
constructor() {
super();
this.holdTime = 500;
this.ripple = document.createElement("mwc-ripple");
this.timer = undefined;
this.held = false;
this.cooldownStart = false;
this.cooldownEnd = false;
}
public connectedCallback() {
@ -96,10 +92,23 @@ class ActionHandler extends HTMLElement implements ActionHandler {
return false;
});
const clickStart = (ev: Event) => {
if (this.cooldownStart) {
const touchStart = (ev: TouchEvent) => {
if (this.touch === false) {
return;
}
this.touch = true;
start(ev);
};
const clickStart = (ev: MouseEvent) => {
if (this.touch === true) {
return;
}
this.touch = false;
start(ev);
};
const start = (ev: Event) => {
this.held = false;
let x;
let y;
@ -115,16 +124,34 @@ class ActionHandler extends HTMLElement implements ActionHandler {
this.startAnimation(x, y);
this.held = true;
}, this.holdTime);
this.cooldownStart = true;
window.setTimeout(() => (this.cooldownStart = false), 100);
};
const clickEnd = (ev: Event) => {
const touchEnd = (ev: TouchEvent) => {
if (this.touch === false) {
return;
}
end(ev);
};
const clickEnd = (ev: MouseEvent) => {
if (this.touch === true) {
return;
}
end(ev);
};
const handleEnter = (ev: KeyboardEvent) => {
if (this.touch === true || ev.keyCode !== 13) {
return;
}
this.touch = false;
end(ev);
};
const end = (ev: Event) => {
if (
this.cooldownEnd ||
(["touchend", "touchcancel"].includes(ev.type) &&
this.timer === undefined)
["touchend", "touchcancel"].includes(ev.type) &&
this.timer === undefined
) {
return;
}
@ -134,41 +161,33 @@ class ActionHandler extends HTMLElement implements ActionHandler {
if (this.held) {
fireEvent(element, "action", { action: "hold" });
} else if (options.hasDoubleClick) {
if ((ev as MouseEvent).detail === 1 || ev.type === "keyup") {
if (
(ev.type === "click" && (ev as MouseEvent).detail < 2) ||
!this.dblClickTimeout
) {
this.dblClickTimeout = window.setTimeout(() => {
this.dblClickTimeout = undefined;
fireEvent(element, "action", { action: "tap" });
}, 250);
} else {
clearTimeout(this.dblClickTimeout);
this.dblClickTimeout = undefined;
fireEvent(element, "action", { action: "double_tap" });
}
} else {
fireEvent(element, "action", { action: "tap" });
}
this.cooldownEnd = true;
window.setTimeout(() => (this.cooldownEnd = false), 100);
window.setTimeout(() => (this.touch = undefined), 100);
};
const handleEnter = (ev: Event) => {
if ((ev as KeyboardEvent).keyCode === 13) {
return clickEnd(ev);
}
};
element.addEventListener("touchstart", touchStart, { passive: true });
element.addEventListener("touchend", touchEnd);
element.addEventListener("touchcancel", touchEnd);
element.addEventListener("mousedown", clickStart, { passive: true });
element.addEventListener("click", clickEnd);
element.addEventListener("touchstart", clickStart, { passive: true });
element.addEventListener("touchend", clickEnd);
element.addEventListener("touchcancel", clickEnd);
element.addEventListener("keyup", handleEnter);
// iOS 13 sends a complete normal touchstart-touchend series of events followed by a mousedown-click series.
// That might be a bug, but until it's fixed, this should make action-handler work.
// If it's not a bug that is fixed, this might need updating with the next iOS version.
// Note that all events (both touch and mouse) must be listened for in order to work on computers with both mouse and touchscreen.
const isIOS13 = /iPhone OS 13_/.test(window.navigator.userAgent);
if (!isIOS13) {
element.addEventListener("mousedown", clickStart, { passive: true });
element.addEventListener("click", clickEnd);
}
}
private startAnimation(x: number, y: number) {