mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-23 09:16:38 +00:00
Fix action directive double tab iOS issues (#4639)
This commit is contained in:
parent
7ab9257f5e
commit
dd8c568a2c
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user