action-handler (#4115)
* action-handler * comments * address comments * finish conversion * move haptics * address comments * lint * keyup * double enter * address comments * keyuppull/4171/head
parent
9b3891f778
commit
274c2016c0
|
@ -161,8 +161,8 @@ if (!window.cardTools) {
|
|||
};
|
||||
|
||||
cardTools.longpress = (element) => {
|
||||
customElements.whenDefined("long-press").then(() => {
|
||||
const longpress = document.body.querySelector("long-press");
|
||||
customElements.whenDefined("action-handler").then(() => {
|
||||
const longpress = document.body.querySelector("action-handler");
|
||||
longpress.bind(element);
|
||||
});
|
||||
return element;
|
||||
|
|
|
@ -2,7 +2,8 @@ import { html, LitElement, TemplateResult } from "lit-element";
|
|||
import "@material/mwc-button";
|
||||
|
||||
import "../../../src/components/ha-card";
|
||||
import { longPress } from "../../../src/panels/lovelace/common/directives/long-press-directive";
|
||||
import { actionHandler } from "../../../src/panels/lovelace/common/directives/action-handler-directive";
|
||||
import { ActionHandlerEvent } from "../../../src/data/lovelace";
|
||||
|
||||
export class DemoUtilLongPress extends LitElement {
|
||||
protected render(): TemplateResult | void {
|
||||
|
@ -12,9 +13,8 @@ export class DemoUtilLongPress extends LitElement {
|
|||
() => html`
|
||||
<ha-card>
|
||||
<mwc-button
|
||||
@ha-click="${this._handleClick}"
|
||||
@ha-hold="${this._handleHold}"
|
||||
.longPress="${longPress()}"
|
||||
@action=${this._handleAction}
|
||||
.actionHandler=${actionHandler({})}
|
||||
>
|
||||
(long) press me!
|
||||
</mwc-button>
|
||||
|
@ -28,12 +28,8 @@ export class DemoUtilLongPress extends LitElement {
|
|||
`;
|
||||
}
|
||||
|
||||
private _handleClick(ev: Event) {
|
||||
this._addValue(ev, "tap");
|
||||
}
|
||||
|
||||
private _handleHold(ev: Event) {
|
||||
this._addValue(ev, "hold");
|
||||
private _handleAction(ev: ActionHandlerEvent) {
|
||||
this._addValue(ev, ev.detail.action!);
|
||||
}
|
||||
|
||||
private _addValue(ev: Event, value: string) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { HomeAssistant } from "../types";
|
||||
import { Connection, getCollection } from "home-assistant-js-websocket";
|
||||
import { HASSDomEvent } from "../common/dom/fire_event";
|
||||
|
||||
export interface LovelaceConfig {
|
||||
title?: string;
|
||||
|
@ -127,6 +128,13 @@ export interface WindowWithLovelaceProm extends Window {
|
|||
llConfProm?: Promise<LovelaceConfig>;
|
||||
}
|
||||
|
||||
export interface LongPressOptions {
|
||||
export interface ActionHandlerOptions {
|
||||
hasHold?: boolean;
|
||||
hasDoubleClick?: boolean;
|
||||
}
|
||||
|
||||
export interface ActionHandlerDetail {
|
||||
action: string;
|
||||
}
|
||||
|
||||
export type ActionHandlerEvent = HASSDomEvent<ActionHandlerDetail>;
|
||||
|
|
|
@ -12,9 +12,10 @@ import "../components/hui-warning-element";
|
|||
import { LovelaceBadge } from "../types";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { StateLabelBadgeConfig } from "./types";
|
||||
import { longPress } from "../common/directives/long-press-directive";
|
||||
import { hasDoubleClick } from "../common/has-double-click";
|
||||
import { handleClick } from "../common/handle-click";
|
||||
import { actionHandler } from "../common/directives/action-handler-directive";
|
||||
import { hasAction } from "../common/has-action";
|
||||
import { ActionHandlerEvent } from "../../../data/lovelace";
|
||||
import { handleAction } from "../common/handle-action";
|
||||
|
||||
@customElement("hui-state-label-badge")
|
||||
export class HuiStateLabelBadge extends LitElement implements LovelaceBadge {
|
||||
|
@ -39,26 +40,17 @@ export class HuiStateLabelBadge extends LitElement implements LovelaceBadge {
|
|||
.name=${this._config.name}
|
||||
.icon=${this._config.icon}
|
||||
.image=${this._config.image}
|
||||
@ha-click=${this._handleClick}
|
||||
@ha-hold=${this._handleHold}
|
||||
@ha-dblclick=${this._handleDblClick}
|
||||
.longPress=${longPress({
|
||||
hasDoubleClick: hasDoubleClick(this._config!.double_tap_action),
|
||||
@action=${this._handleAction}
|
||||
.actionHandler=${actionHandler({
|
||||
hasHold: hasAction(this._config!.hold_action),
|
||||
hasDoubleClick: hasAction(this._config!.double_tap_action),
|
||||
})}
|
||||
></ha-state-label-badge>
|
||||
`;
|
||||
}
|
||||
|
||||
private _handleClick() {
|
||||
handleClick(this, this.hass!, this._config!, false, false);
|
||||
}
|
||||
|
||||
private _handleHold() {
|
||||
handleClick(this, this.hass!, this._config!, true, false);
|
||||
}
|
||||
|
||||
private _handleDblClick() {
|
||||
handleClick(this, this.hass!, this._config!, false, true);
|
||||
private _handleAction(ev: ActionHandlerEvent) {
|
||||
handleAction(this, this.hass!, this._config!, ev.detail.action!);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,11 +24,12 @@ import { computeDomain } from "../../../common/entity/compute_domain";
|
|||
|
||||
import { HomeAssistant, LightEntity } from "../../../types";
|
||||
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||
import { longPress } from "../common/directives/long-press-directive";
|
||||
import { handleClick } from "../common/handle-click";
|
||||
import { DOMAINS_TOGGLE } from "../../../common/const";
|
||||
import { EntityButtonCardConfig } from "./types";
|
||||
import { hasDoubleClick } from "../common/has-double-click";
|
||||
import { actionHandler } from "../common/directives/action-handler-directive";
|
||||
import { hasAction } from "../common/has-action";
|
||||
import { handleAction } from "../common/handle-action";
|
||||
import { ActionHandlerEvent } from "../../../data/lovelace";
|
||||
|
||||
@customElement("hui-entity-button-card")
|
||||
class HuiEntityButtonCard extends LitElement implements LovelaceCard {
|
||||
|
@ -126,11 +127,10 @@ class HuiEntityButtonCard extends LitElement implements LovelaceCard {
|
|||
|
||||
return html`
|
||||
<ha-card
|
||||
@ha-click=${this._handleClick}
|
||||
@ha-hold=${this._handleHold}
|
||||
@ha-dblclick=${this._handleDblClick}
|
||||
.longPress=${longPress({
|
||||
hasDoubleClick: hasDoubleClick(this._config!.double_tap_action),
|
||||
@action=${this._handleAction}
|
||||
.actionHandler=${actionHandler({
|
||||
hasHold: hasAction(this._config!.hold_action),
|
||||
hasDoubleClick: hasAction(this._config!.double_tap_action),
|
||||
})}
|
||||
>
|
||||
${this._config.show_icon
|
||||
|
@ -232,16 +232,8 @@ class HuiEntityButtonCard extends LitElement implements LovelaceCard {
|
|||
return `hsl(${hue}, 100%, ${100 - sat / 2}%)`;
|
||||
}
|
||||
|
||||
private _handleClick() {
|
||||
handleClick(this, this.hass!, this._config!, false, false);
|
||||
}
|
||||
|
||||
private _handleHold() {
|
||||
handleClick(this, this.hass!, this._config!, true, false);
|
||||
}
|
||||
|
||||
private _handleDblClick() {
|
||||
handleClick(this, this.hass!, this._config!, false, true);
|
||||
private _handleAction(ev: ActionHandlerEvent) {
|
||||
handleAction(this, this.hass!, this._config!, ev.detail.action!);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,11 +22,12 @@ import "../components/hui-warning-element";
|
|||
import { computeStateDisplay } from "../../../common/entity/compute_state_display";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||
import { longPress } from "../common/directives/long-press-directive";
|
||||
import { processConfigEntities } from "../common/process-config-entities";
|
||||
import { handleClick } from "../common/handle-click";
|
||||
import { GlanceCardConfig, GlanceConfigEntity } from "./types";
|
||||
import { hasDoubleClick } from "../common/has-double-click";
|
||||
import { actionHandler } from "../common/directives/action-handler-directive";
|
||||
import { hasAction } from "../common/has-action";
|
||||
import { ActionHandlerEvent } from "../../../data/lovelace";
|
||||
import { handleAction } from "../common/handle-action";
|
||||
|
||||
@customElement("hui-glance-card")
|
||||
export class HuiGlanceCard extends LitElement implements LovelaceCard {
|
||||
|
@ -199,11 +200,10 @@ export class HuiGlanceCard extends LitElement implements LovelaceCard {
|
|||
<div
|
||||
class="entity"
|
||||
.config="${entityConf}"
|
||||
@ha-click=${this._handleClick}
|
||||
@ha-hold=${this._handleHold}
|
||||
@ha-dblclick=${this._handleDblClick}
|
||||
.longPress=${longPress({
|
||||
hasDoubleClick: hasDoubleClick(entityConf.double_tap_action),
|
||||
@action=${this._handleAction}
|
||||
.actionHandler=${actionHandler({
|
||||
hasHold: hasAction(entityConf.hold_action),
|
||||
hasDoubleClick: hasAction(entityConf.double_tap_action),
|
||||
})}
|
||||
>
|
||||
${this._config!.show_name !== false
|
||||
|
@ -245,19 +245,9 @@ export class HuiGlanceCard extends LitElement implements LovelaceCard {
|
|||
`;
|
||||
}
|
||||
|
||||
private _handleClick(ev: MouseEvent): void {
|
||||
private _handleAction(ev: ActionHandlerEvent) {
|
||||
const config = (ev.currentTarget as any).config as GlanceConfigEntity;
|
||||
handleClick(this, this.hass!, config, false, false);
|
||||
}
|
||||
|
||||
private _handleHold(ev: MouseEvent): void {
|
||||
const config = (ev.currentTarget as any).config as GlanceConfigEntity;
|
||||
handleClick(this, this.hass!, config, true, false);
|
||||
}
|
||||
|
||||
private _handleDblClick(ev: MouseEvent): void {
|
||||
const config = (ev.currentTarget as any).config as GlanceConfigEntity;
|
||||
handleClick(this, this.hass!, config, false, true);
|
||||
handleAction(this, this.hass!, config, ev.detail.action!);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,11 +14,12 @@ import "../../../components/ha-card";
|
|||
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { classMap } from "lit-html/directives/class-map";
|
||||
import { handleClick } from "../common/handle-click";
|
||||
import { longPress } from "../common/directives/long-press-directive";
|
||||
import { PictureCardConfig } from "./types";
|
||||
import { hasDoubleClick } from "../common/has-double-click";
|
||||
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
||||
import { actionHandler } from "../common/directives/action-handler-directive";
|
||||
import { hasAction } from "../common/has-action";
|
||||
import { ActionHandlerEvent } from "../../../data/lovelace";
|
||||
import { handleAction } from "../common/handle-action";
|
||||
|
||||
@customElement("hui-picture-card")
|
||||
export class HuiPictureCard extends LitElement implements LovelaceCard {
|
||||
|
@ -78,11 +79,10 @@ export class HuiPictureCard extends LitElement implements LovelaceCard {
|
|||
|
||||
return html`
|
||||
<ha-card
|
||||
@ha-click=${this._handleClick}
|
||||
@ha-hold=${this._handleHold}
|
||||
@ha-dblclick=${this._handleDblClick}
|
||||
.longPress=${longPress({
|
||||
hasDoubleClick: hasDoubleClick(this._config!.double_tap_action),
|
||||
@action=${this._handleAction}
|
||||
.actionHandler=${actionHandler({
|
||||
hasHold: hasAction(this._config!.hold_action),
|
||||
hasDoubleClick: hasAction(this._config!.double_tap_action),
|
||||
})}
|
||||
class="${classMap({
|
||||
clickable: Boolean(
|
||||
|
@ -112,16 +112,8 @@ export class HuiPictureCard extends LitElement implements LovelaceCard {
|
|||
`;
|
||||
}
|
||||
|
||||
private _handleClick() {
|
||||
handleClick(this, this.hass!, this._config!, false, false);
|
||||
}
|
||||
|
||||
private _handleHold() {
|
||||
handleClick(this, this.hass!, this._config!, true, false);
|
||||
}
|
||||
|
||||
private _handleDblClick() {
|
||||
handleClick(this, this.hass!, this._config!, false, true);
|
||||
private _handleAction(ev: ActionHandlerEvent) {
|
||||
handleAction(this, this.hass!, this._config!, ev.detail.action!);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,15 +18,16 @@ import { computeDomain } from "../../../common/entity/compute_domain";
|
|||
import { computeStateName } from "../../../common/entity/compute_state_name";
|
||||
|
||||
import { computeStateDisplay } from "../../../common/entity/compute_state_display";
|
||||
import { longPress } from "../common/directives/long-press-directive";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||
import { handleClick } from "../common/handle-click";
|
||||
import { UNAVAILABLE } from "../../../data/entity";
|
||||
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||
import { PictureEntityCardConfig } from "./types";
|
||||
import { hasDoubleClick } from "../common/has-double-click";
|
||||
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
||||
import { actionHandler } from "../common/directives/action-handler-directive";
|
||||
import { hasAction } from "../common/has-action";
|
||||
import { ActionHandlerEvent } from "../../../data/lovelace";
|
||||
import { handleAction } from "../common/handle-action";
|
||||
|
||||
@customElement("hui-picture-entity-card")
|
||||
class HuiPictureEntityCard extends LitElement implements LovelaceCard {
|
||||
|
@ -146,11 +147,10 @@ class HuiPictureEntityCard extends LitElement implements LovelaceCard {
|
|||
.cameraView=${this._config.camera_view}
|
||||
.entity=${this._config.entity}
|
||||
.aspectRatio=${this._config.aspect_ratio}
|
||||
@ha-click=${this._handleClick}
|
||||
@ha-hold=${this._handleHold}
|
||||
@ha-dblclick=${this._handleDblClick}
|
||||
.longPress=${longPress({
|
||||
hasDoubleClick: hasDoubleClick(this._config!.double_tap_action),
|
||||
@action=${this._handleAction}
|
||||
.actionHandler=${actionHandler({
|
||||
hasHold: hasAction(this._config!.hold_action),
|
||||
hasDoubleClick: hasAction(this._config!.double_tap_action),
|
||||
})}
|
||||
class=${classMap({
|
||||
clickable: stateObj.state !== UNAVAILABLE,
|
||||
|
@ -202,16 +202,8 @@ class HuiPictureEntityCard extends LitElement implements LovelaceCard {
|
|||
`;
|
||||
}
|
||||
|
||||
private _handleClick() {
|
||||
handleClick(this, this.hass!, this._config!, false, false);
|
||||
}
|
||||
|
||||
private _handleHold() {
|
||||
handleClick(this, this.hass!, this._config!, true, false);
|
||||
}
|
||||
|
||||
private _handleDblClick() {
|
||||
handleClick(this, this.hass!, this._config!, false, true);
|
||||
private _handleAction(ev: ActionHandlerEvent) {
|
||||
handleAction(this, this.hass!, this._config!, ev.detail.action!);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,13 +22,14 @@ import { computeStateDisplay } from "../../../common/entity/compute_state_displa
|
|||
import { DOMAINS_TOGGLE } from "../../../common/const";
|
||||
import { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { longPress } from "../common/directives/long-press-directive";
|
||||
import { processConfigEntities } from "../common/process-config-entities";
|
||||
import { handleClick } from "../common/handle-click";
|
||||
import { hasDoubleClick } from "../common/has-double-click";
|
||||
import { PictureGlanceCardConfig, PictureGlanceEntityConfig } from "./types";
|
||||
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
||||
import { actionHandler } from "../common/directives/action-handler-directive";
|
||||
import { hasAction } from "../common/has-action";
|
||||
import { ActionHandlerEvent } from "../../../data/lovelace";
|
||||
import { handleAction } from "../common/handle-action";
|
||||
|
||||
const STATES_OFF = new Set(["closed", "locked", "not_home", "off"]);
|
||||
|
||||
|
@ -160,11 +161,10 @@ class HuiPictureGlanceCard extends LitElement implements LovelaceCard {
|
|||
this._config.camera_image
|
||||
),
|
||||
})}
|
||||
@ha-click=${this._handleClick}
|
||||
@ha-hold=${this._handleHold}
|
||||
@ha-dblclick=${this._handleDblClick}
|
||||
.longPress=${longPress({
|
||||
hasDoubleClick: hasDoubleClick(this._config!.double_tap_action),
|
||||
@action=${this._handleAction}
|
||||
.actionHandler=${actionHandler({
|
||||
hasHold: hasAction(this._config!.hold_action),
|
||||
hasDoubleClick: hasAction(this._config!.double_tap_action),
|
||||
})}
|
||||
.config=${this._config}
|
||||
.hass=${this.hass}
|
||||
|
@ -223,11 +223,10 @@ class HuiPictureGlanceCard extends LitElement implements LovelaceCard {
|
|||
return html`
|
||||
<div class="wrapper">
|
||||
<ha-icon
|
||||
@ha-click=${this._handleClick}
|
||||
@ha-hold=${this._handleHold}
|
||||
@ha-dblclick=${this._handleDblClick}
|
||||
.longPress=${longPress({
|
||||
hasDoubleClick: hasDoubleClick(entityConf.double_tap_action),
|
||||
@action=${this._handleAction}
|
||||
.actionHandler=${actionHandler({
|
||||
hasHold: hasAction(entityConf.hold_action),
|
||||
hasDoubleClick: hasAction(entityConf.double_tap_action),
|
||||
})}
|
||||
.config=${entityConf}
|
||||
class="${classMap({
|
||||
|
@ -259,19 +258,9 @@ class HuiPictureGlanceCard extends LitElement implements LovelaceCard {
|
|||
`;
|
||||
}
|
||||
|
||||
private _handleClick(ev: MouseEvent): void {
|
||||
private _handleAction(ev: ActionHandlerEvent) {
|
||||
const config = (ev.currentTarget as any).config as any;
|
||||
handleClick(this, this.hass!, config, false, false);
|
||||
}
|
||||
|
||||
private _handleHold(ev: MouseEvent): void {
|
||||
const config = (ev.currentTarget as any).config as any;
|
||||
handleClick(this, this.hass!, config, true, false);
|
||||
}
|
||||
|
||||
private _handleDblClick(ev: MouseEvent): void {
|
||||
const config = (ev.currentTarget as any).config as any;
|
||||
handleClick(this, this.hass!, config, false, true);
|
||||
handleAction(this, this.hass!, config, ev.detail.action!);
|
||||
}
|
||||
|
||||
static get styles(): CSSResult {
|
||||
|
|
|
@ -1,21 +1,31 @@
|
|||
import { directive, PropertyPart } from "lit-html";
|
||||
import "@material/mwc-ripple";
|
||||
import { LongPressOptions } from "../../../../data/lovelace";
|
||||
import {
|
||||
ActionHandlerOptions,
|
||||
ActionHandlerDetail,
|
||||
} from "../../../../data/lovelace";
|
||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
|
||||
const isTouch =
|
||||
"ontouchstart" in window ||
|
||||
navigator.maxTouchPoints > 0 ||
|
||||
navigator.msMaxTouchPoints > 0;
|
||||
|
||||
interface LongPress extends HTMLElement {
|
||||
interface ActionHandler extends HTMLElement {
|
||||
holdTime: number;
|
||||
bind(element: Element, options): void;
|
||||
}
|
||||
interface LongPressElement extends Element {
|
||||
longPress?: boolean;
|
||||
interface ActionHandlerElement extends HTMLElement {
|
||||
actionHandler?: boolean;
|
||||
}
|
||||
|
||||
class LongPress extends HTMLElement implements LongPress {
|
||||
declare global {
|
||||
interface HASSDomEvents {
|
||||
action: ActionHandlerDetail;
|
||||
}
|
||||
}
|
||||
|
||||
class ActionHandler extends HTMLElement implements ActionHandler {
|
||||
public holdTime: number;
|
||||
public ripple: any;
|
||||
protected timer: number | undefined;
|
||||
|
@ -67,11 +77,11 @@ class LongPress extends HTMLElement implements LongPress {
|
|||
});
|
||||
}
|
||||
|
||||
public bind(element: LongPressElement, options) {
|
||||
if (element.longPress) {
|
||||
public bind(element: ActionHandlerElement, options) {
|
||||
if (element.actionHandler) {
|
||||
return;
|
||||
}
|
||||
element.longPress = true;
|
||||
element.actionHandler = true;
|
||||
|
||||
element.addEventListener("contextmenu", (ev: Event) => {
|
||||
const e = ev || window.event;
|
||||
|
@ -100,10 +110,13 @@ class LongPress extends HTMLElement implements LongPress {
|
|||
x = (ev as MouseEvent).pageX;
|
||||
y = (ev as MouseEvent).pageY;
|
||||
}
|
||||
this.timer = window.setTimeout(() => {
|
||||
this.startAnimation(x, y);
|
||||
this.held = true;
|
||||
}, this.holdTime);
|
||||
|
||||
if (options.hasHold) {
|
||||
this.timer = window.setTimeout(() => {
|
||||
this.startAnimation(x, y);
|
||||
this.held = true;
|
||||
}, this.holdTime);
|
||||
}
|
||||
|
||||
this.cooldownStart = true;
|
||||
window.setTimeout(() => (this.cooldownStart = false), 100);
|
||||
|
@ -121,18 +134,18 @@ class LongPress extends HTMLElement implements LongPress {
|
|||
this.stopAnimation();
|
||||
this.timer = undefined;
|
||||
if (this.held) {
|
||||
element.dispatchEvent(new Event("ha-hold"));
|
||||
fireEvent(element, "action", { action: "hold" });
|
||||
} else if (options.hasDoubleClick) {
|
||||
if ((ev as MouseEvent).detail === 1 || ev.type === "keyup") {
|
||||
this.dblClickTimeout = window.setTimeout(() => {
|
||||
element.dispatchEvent(new Event("ha-click"));
|
||||
fireEvent(element, "action", { action: "tap" });
|
||||
}, 250);
|
||||
} else {
|
||||
clearTimeout(this.dblClickTimeout);
|
||||
element.dispatchEvent(new Event("ha-dblclick"));
|
||||
fireEvent(element, "action", { action: "double_tap" });
|
||||
}
|
||||
} else {
|
||||
element.dispatchEvent(new Event("ha-click"));
|
||||
fireEvent(element, "action", { action: "tap" });
|
||||
}
|
||||
this.cooldownEnd = true;
|
||||
window.setTimeout(() => (this.cooldownEnd = false), 100);
|
||||
|
@ -150,7 +163,7 @@ class LongPress extends HTMLElement implements LongPress {
|
|||
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 long-press work.
|
||||
// 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 = window.navigator.userAgent.match(/iPhone OS 13_/);
|
||||
|
@ -178,33 +191,33 @@ class LongPress extends HTMLElement implements LongPress {
|
|||
}
|
||||
}
|
||||
|
||||
customElements.define("long-press", LongPress);
|
||||
customElements.define("action-handler", ActionHandler);
|
||||
|
||||
const getLongPress = (): LongPress => {
|
||||
const geActionHandler = (): ActionHandler => {
|
||||
const body = document.body;
|
||||
if (body.querySelector("long-press")) {
|
||||
return body.querySelector("long-press") as LongPress;
|
||||
if (body.querySelector("action-handler")) {
|
||||
return body.querySelector("action-handler") as ActionHandler;
|
||||
}
|
||||
|
||||
const longpress = document.createElement("long-press");
|
||||
body.appendChild(longpress);
|
||||
const actionhandler = document.createElement("action-handler");
|
||||
body.appendChild(actionhandler);
|
||||
|
||||
return longpress as LongPress;
|
||||
return actionhandler as ActionHandler;
|
||||
};
|
||||
|
||||
export const longPressBind = (
|
||||
element: LongPressElement,
|
||||
options: LongPressOptions
|
||||
export const actionHandlerBind = (
|
||||
element: ActionHandlerElement,
|
||||
options: ActionHandlerOptions
|
||||
) => {
|
||||
const longpress: LongPress = getLongPress();
|
||||
if (!longpress) {
|
||||
const actionhandler: ActionHandler = geActionHandler();
|
||||
if (!actionhandler) {
|
||||
return;
|
||||
}
|
||||
longpress.bind(element, options);
|
||||
actionhandler.bind(element, options);
|
||||
};
|
||||
|
||||
export const longPress = directive(
|
||||
(options: LongPressOptions = {}) => (part: PropertyPart) => {
|
||||
longPressBind(part.committer.element, options);
|
||||
export const actionHandler = directive(
|
||||
(options: ActionHandlerOptions = {}) => (part: PropertyPart) => {
|
||||
actionHandlerBind(part.committer.element as ActionHandlerElement, options);
|
||||
}
|
||||
);
|
|
@ -1,11 +1,11 @@
|
|||
import { HomeAssistant } from "../../../types";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import { navigate } from "../../../common/navigate";
|
||||
import { toggleEntity } from "../../../../src/panels/lovelace/common/entity/toggle-entity";
|
||||
import { toggleEntity } from "./entity/toggle-entity";
|
||||
import { ActionConfig } from "../../../data/lovelace";
|
||||
import { forwardHaptic } from "../../../data/haptics";
|
||||
|
||||
export const handleClick = (
|
||||
export const handleAction = (
|
||||
node: HTMLElement,
|
||||
hass: HomeAssistant,
|
||||
config: {
|
||||
|
@ -15,16 +15,15 @@ export const handleClick = (
|
|||
tap_action?: ActionConfig;
|
||||
double_tap_action?: ActionConfig;
|
||||
},
|
||||
hold: boolean,
|
||||
dblClick: boolean
|
||||
action: string
|
||||
): void => {
|
||||
let actionConfig: ActionConfig | undefined;
|
||||
|
||||
if (dblClick && config.double_tap_action) {
|
||||
if (action === "double_tap" && config.double_tap_action) {
|
||||
actionConfig = config.double_tap_action;
|
||||
} else if (hold && config.hold_action) {
|
||||
} else if (action === "hold" && config.hold_action) {
|
||||
actionConfig = config.hold_action;
|
||||
} else if (!hold && config.tap_action) {
|
||||
} else if (action === "tap" && config.tap_action) {
|
||||
actionConfig = config.tap_action;
|
||||
}
|
||||
|
||||
|
@ -41,6 +40,8 @@ export const handleClick = (
|
|||
(e) => e.user === hass!.user!.id
|
||||
))
|
||||
) {
|
||||
forwardHaptic("warning");
|
||||
|
||||
if (
|
||||
!confirm(
|
||||
actionConfig.confirmation.text ||
|
|
@ -1,6 +1,5 @@
|
|||
import { ActionConfig } from "../../../data/lovelace";
|
||||
|
||||
// Check if config or Entity changed
|
||||
export function hasDoubleClick(config?: ActionConfig): boolean {
|
||||
export function hasAction(config?: ActionConfig): boolean {
|
||||
return config !== undefined && config.action !== "none";
|
||||
}
|
|
@ -17,13 +17,14 @@ import "../components/hui-warning";
|
|||
import { HomeAssistant } from "../../../types";
|
||||
import { computeRTL } from "../../../common/util/compute_rtl";
|
||||
import { toggleAttribute } from "../../../common/dom/toggle_attribute";
|
||||
import { longPress } from "../common/directives/long-press-directive";
|
||||
import { hasDoubleClick } from "../common/has-double-click";
|
||||
import { handleClick } from "../common/handle-click";
|
||||
import { DOMAINS_HIDE_MORE_INFO } from "../../../common/const";
|
||||
import { computeDomain } from "../../../common/entity/compute_domain";
|
||||
import { classMap } from "lit-html/directives/class-map";
|
||||
import { EntitiesCardEntityConfig } from "../cards/types";
|
||||
import { actionHandler } from "../common/directives/action-handler-directive";
|
||||
import { hasAction } from "../common/has-action";
|
||||
import { ActionHandlerEvent } from "../../../data/lovelace";
|
||||
import { handleAction } from "../common/handle-action";
|
||||
|
||||
class HuiGenericEntityRow extends LitElement {
|
||||
@property() public hass?: HomeAssistant;
|
||||
|
@ -66,11 +67,10 @@ class HuiGenericEntityRow extends LitElement {
|
|||
.stateObj=${stateObj}
|
||||
.overrideIcon=${this.config.icon}
|
||||
.overrideImage=${this.config.image}
|
||||
@ha-click=${this._handleClick}
|
||||
@ha-hold=${this._handleHold}
|
||||
@ha-dblclick=${this._handleDblClick}
|
||||
.longPress=${longPress({
|
||||
hasDoubleClick: hasDoubleClick(this.config.double_tap_action),
|
||||
@action=${this._handleAction}
|
||||
.actionHandler=${actionHandler({
|
||||
hasHold: hasAction(this.config!.hold_action),
|
||||
hasDoubleClick: hasAction(this.config!.double_tap_action),
|
||||
})}
|
||||
tabindex="0"
|
||||
></state-badge>
|
||||
|
@ -84,11 +84,10 @@ class HuiGenericEntityRow extends LitElement {
|
|||
!this.showSecondary || this.config.secondary_info
|
||||
),
|
||||
})}
|
||||
@ha-click=${this._handleClick}
|
||||
@ha-hold=${this._handleHold}
|
||||
@ha-dblclick=${this._handleDblClick}
|
||||
.longPress=${longPress({
|
||||
hasDoubleClick: hasDoubleClick(this.config.double_tap_action),
|
||||
@action=${this._handleAction}
|
||||
.actionHandler=${actionHandler({
|
||||
hasHold: hasAction(this.config!.hold_action),
|
||||
hasDoubleClick: hasAction(this.config!.double_tap_action),
|
||||
})}
|
||||
>
|
||||
${this.config.name || computeStateName(stateObj)}
|
||||
|
@ -122,16 +121,8 @@ class HuiGenericEntityRow extends LitElement {
|
|||
}
|
||||
}
|
||||
|
||||
private _handleClick(): void {
|
||||
handleClick(this, this.hass!, this.config!, false, false);
|
||||
}
|
||||
|
||||
private _handleHold(): void {
|
||||
handleClick(this, this.hass!, this.config!, true, false);
|
||||
}
|
||||
|
||||
private _handleDblClick(): void {
|
||||
handleClick(this, this.hass!, this.config!, false, true);
|
||||
private _handleAction(ev: ActionHandlerEvent) {
|
||||
handleAction(this, this.hass!, this.config!, ev.detail.action!);
|
||||
}
|
||||
|
||||
static get styles(): CSSResult {
|
||||
|
|
|
@ -11,11 +11,12 @@ import {
|
|||
import "../../../components/ha-icon";
|
||||
|
||||
import { computeTooltip } from "../common/compute-tooltip";
|
||||
import { handleClick } from "../common/handle-click";
|
||||
import { longPress } from "../common/directives/long-press-directive";
|
||||
import { LovelaceElement, IconElementConfig } from "./types";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { hasDoubleClick } from "../common/has-double-click";
|
||||
import { actionHandler } from "../common/directives/action-handler-directive";
|
||||
import { hasAction } from "../common/has-action";
|
||||
import { ActionHandlerEvent } from "../../../data/lovelace";
|
||||
import { handleAction } from "../common/handle-action";
|
||||
|
||||
@customElement("hui-icon-element")
|
||||
export class HuiIconElement extends LitElement implements LovelaceElement {
|
||||
|
@ -39,26 +40,17 @@ export class HuiIconElement extends LitElement implements LovelaceElement {
|
|||
<ha-icon
|
||||
.icon="${this._config.icon}"
|
||||
.title="${computeTooltip(this.hass, this._config)}"
|
||||
@ha-click=${this._handleClick}
|
||||
@ha-hold=${this._handleHold}
|
||||
@ha-dblclick=${this._handleDblClick}
|
||||
.longPress=${longPress({
|
||||
hasDoubleClick: hasDoubleClick(this._config!.double_tap_action),
|
||||
@action=${this._handleAction}
|
||||
.actionHandler=${actionHandler({
|
||||
hasHold: hasAction(this._config!.hold_action),
|
||||
hasDoubleClick: hasAction(this._config!.double_tap_action),
|
||||
})}
|
||||
></ha-icon>
|
||||
`;
|
||||
}
|
||||
|
||||
private _handleClick(): void {
|
||||
handleClick(this, this.hass!, this._config!, false, false);
|
||||
}
|
||||
|
||||
private _handleHold(): void {
|
||||
handleClick(this, this.hass!, this._config!, true, false);
|
||||
}
|
||||
|
||||
private _handleDblClick() {
|
||||
handleClick(this, this.hass!, this._config!, false, true);
|
||||
private _handleAction(ev: ActionHandlerEvent) {
|
||||
handleAction(this, this.hass!, this._config!, ev.detail.action!);
|
||||
}
|
||||
|
||||
static get styles(): CSSResult {
|
||||
|
|
|
@ -11,11 +11,12 @@ import {
|
|||
import "../components/hui-image";
|
||||
|
||||
import { computeTooltip } from "../common/compute-tooltip";
|
||||
import { handleClick } from "../common/handle-click";
|
||||
import { longPress } from "../common/directives/long-press-directive";
|
||||
import { LovelaceElement, ImageElementConfig } from "./types";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { hasDoubleClick } from "../common/has-double-click";
|
||||
import { actionHandler } from "../common/directives/action-handler-directive";
|
||||
import { hasAction } from "../common/has-action";
|
||||
import { ActionHandlerEvent } from "../../../data/lovelace";
|
||||
import { handleAction } from "../common/handle-action";
|
||||
|
||||
@customElement("hui-image-element")
|
||||
export class HuiImageElement extends LitElement implements LovelaceElement {
|
||||
|
@ -50,11 +51,10 @@ export class HuiImageElement extends LitElement implements LovelaceElement {
|
|||
.stateFilter="${this._config.state_filter}"
|
||||
.title="${computeTooltip(this.hass, this._config)}"
|
||||
.aspectRatio="${this._config.aspect_ratio}"
|
||||
@ha-click=${this._handleClick}
|
||||
@ha-hold=${this._handleHold}
|
||||
@ha-dblclick=${this._handleDblClick}
|
||||
.longPress=${longPress({
|
||||
hasDoubleClick: hasDoubleClick(this._config!.double_tap_action),
|
||||
@action=${this._handleAction}
|
||||
.actionHandler=${actionHandler({
|
||||
hasHold: hasAction(this._config!.hold_action),
|
||||
hasDoubleClick: hasAction(this._config!.double_tap_action),
|
||||
})}
|
||||
></hui-image>
|
||||
`;
|
||||
|
@ -73,16 +73,8 @@ export class HuiImageElement extends LitElement implements LovelaceElement {
|
|||
`;
|
||||
}
|
||||
|
||||
private _handleClick(): void {
|
||||
handleClick(this, this.hass!, this._config!, false, false);
|
||||
}
|
||||
|
||||
private _handleHold(): void {
|
||||
handleClick(this, this.hass!, this._config!, true, false);
|
||||
}
|
||||
|
||||
private _handleDblClick() {
|
||||
handleClick(this, this.hass!, this._config!, false, true);
|
||||
private _handleAction(ev: ActionHandlerEvent) {
|
||||
handleAction(this, this.hass!, this._config!, ev.detail.action!);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,9 +14,10 @@ import { computeStateName } from "../../../common/entity/compute_state_name";
|
|||
import { LovelaceElement, StateBadgeElementConfig } from "./types";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||
import { longPress } from "../common/directives/long-press-directive";
|
||||
import { hasDoubleClick } from "../common/has-double-click";
|
||||
import { handleClick } from "../common/handle-click";
|
||||
import { actionHandler } from "../common/directives/action-handler-directive";
|
||||
import { hasAction } from "../common/has-action";
|
||||
import { ActionHandlerEvent } from "../../../data/lovelace";
|
||||
import { handleAction } from "../common/handle-action";
|
||||
|
||||
@customElement("hui-state-badge-element")
|
||||
export class HuiStateBadgeElement extends LitElement
|
||||
|
@ -64,26 +65,17 @@ export class HuiStateBadgeElement extends LitElement
|
|||
: this._config.title === null
|
||||
? ""
|
||||
: this._config.title}"
|
||||
@ha-click=${this._handleClick}
|
||||
@ha-hold=${this._handleHold}
|
||||
@ha-dblclick=${this._handleDblClick}
|
||||
.longPress=${longPress({
|
||||
hasDoubleClick: hasDoubleClick(this._config!.double_tap_action),
|
||||
@action=${this._handleAction}
|
||||
.actionHandler=${actionHandler({
|
||||
hasHold: hasAction(this._config!.hold_action),
|
||||
hasDoubleClick: hasAction(this._config!.double_tap_action),
|
||||
})}
|
||||
></ha-state-label-badge>
|
||||
`;
|
||||
}
|
||||
|
||||
private _handleClick() {
|
||||
handleClick(this, this.hass!, this._config!, false, false);
|
||||
}
|
||||
|
||||
private _handleHold() {
|
||||
handleClick(this, this.hass!, this._config!, true, false);
|
||||
}
|
||||
|
||||
private _handleDblClick() {
|
||||
handleClick(this, this.hass!, this._config!, false, true);
|
||||
private _handleAction(ev: ActionHandlerEvent) {
|
||||
handleAction(this, this.hass!, this._config!, ev.detail.action!);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,12 +13,13 @@ import "../../../components/entity/state-badge";
|
|||
import "../components/hui-warning-element";
|
||||
|
||||
import { computeTooltip } from "../common/compute-tooltip";
|
||||
import { handleClick } from "../common/handle-click";
|
||||
import { longPress } from "../common/directives/long-press-directive";
|
||||
import { LovelaceElement, StateIconElementConfig } from "./types";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||
import { hasDoubleClick } from "../common/has-double-click";
|
||||
import { actionHandler } from "../common/directives/action-handler-directive";
|
||||
import { hasAction } from "../common/has-action";
|
||||
import { ActionHandlerEvent } from "../../../data/lovelace";
|
||||
import { handleAction } from "../common/handle-action";
|
||||
|
||||
@customElement("hui-state-icon-element")
|
||||
export class HuiStateIconElement extends LitElement implements LovelaceElement {
|
||||
|
@ -60,11 +61,10 @@ export class HuiStateIconElement extends LitElement implements LovelaceElement {
|
|||
<state-badge
|
||||
.stateObj="${stateObj}"
|
||||
.title="${computeTooltip(this.hass, this._config)}"
|
||||
@ha-click=${this._handleClick}
|
||||
@ha-hold=${this._handleHold}
|
||||
@ha-dblclick=${this._handleDblClick}
|
||||
.longPress=${longPress({
|
||||
hasDoubleClick: hasDoubleClick(this._config!.double_tap_action),
|
||||
@action=${this._handleAction}
|
||||
.actionHandler=${actionHandler({
|
||||
hasHold: hasAction(this._config!.hold_action),
|
||||
hasDoubleClick: hasAction(this._config!.double_tap_action),
|
||||
})}
|
||||
.overrideIcon=${this._config.icon}
|
||||
></state-badge>
|
||||
|
@ -79,16 +79,8 @@ export class HuiStateIconElement extends LitElement implements LovelaceElement {
|
|||
`;
|
||||
}
|
||||
|
||||
private _handleClick(): void {
|
||||
handleClick(this, this.hass!, this._config!, false, false);
|
||||
}
|
||||
|
||||
private _handleHold(): void {
|
||||
handleClick(this, this.hass!, this._config!, true, false);
|
||||
}
|
||||
|
||||
private _handleDblClick() {
|
||||
handleClick(this, this.hass!, this._config!, false, true);
|
||||
private _handleAction(ev: ActionHandlerEvent) {
|
||||
handleAction(this, this.hass!, this._config!, ev.detail.action!);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,12 +13,13 @@ import "../components/hui-warning-element";
|
|||
|
||||
import { computeStateDisplay } from "../../../common/entity/compute_state_display";
|
||||
import { computeTooltip } from "../common/compute-tooltip";
|
||||
import { handleClick } from "../common/handle-click";
|
||||
import { longPress } from "../common/directives/long-press-directive";
|
||||
import { LovelaceElement, StateLabelElementConfig } from "./types";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||
import { hasDoubleClick } from "../common/has-double-click";
|
||||
import { actionHandler } from "../common/directives/action-handler-directive";
|
||||
import { hasAction } from "../common/has-action";
|
||||
import { ActionHandlerEvent } from "../../../data/lovelace";
|
||||
import { handleAction } from "../common/handle-action";
|
||||
|
||||
@customElement("hui-state-label-element")
|
||||
class HuiStateLabelElement extends LitElement implements LovelaceElement {
|
||||
|
@ -59,11 +60,10 @@ class HuiStateLabelElement extends LitElement implements LovelaceElement {
|
|||
return html`
|
||||
<div
|
||||
.title="${computeTooltip(this.hass, this._config)}"
|
||||
@ha-click=${this._handleClick}
|
||||
@ha-hold=${this._handleHold}
|
||||
@ha-dblclick=${this._handleDblClick}
|
||||
.longPress=${longPress({
|
||||
hasDoubleClick: hasDoubleClick(this._config!.double_tap_action),
|
||||
@action=${this._handleAction}
|
||||
.actionHandler=${actionHandler({
|
||||
hasHold: hasAction(this._config!.hold_action),
|
||||
hasDoubleClick: hasAction(this._config!.double_tap_action),
|
||||
})}
|
||||
>
|
||||
${this._config.prefix}${stateObj
|
||||
|
@ -77,16 +77,8 @@ class HuiStateLabelElement extends LitElement implements LovelaceElement {
|
|||
`;
|
||||
}
|
||||
|
||||
private _handleClick(): void {
|
||||
handleClick(this, this.hass!, this._config!, false, false);
|
||||
}
|
||||
|
||||
private _handleHold(): void {
|
||||
handleClick(this, this.hass!, this._config!, true, false);
|
||||
}
|
||||
|
||||
private _handleDblClick() {
|
||||
handleClick(this, this.hass!, this._config!, false, true);
|
||||
private _handleAction(ev: ActionHandlerEvent) {
|
||||
handleAction(this, this.hass!, this._config!, ev.detail.action!);
|
||||
}
|
||||
|
||||
static get styles(): CSSResult {
|
||||
|
|
|
@ -23,13 +23,14 @@ import { setInputSelectOption } from "../../../data/input-select";
|
|||
import { hasConfigOrEntityChanged } from "../common/has-changed";
|
||||
import { forwardHaptic } from "../../../data/haptics";
|
||||
import { stopPropagation } from "../../../common/dom/stop_propagation";
|
||||
import { longPress } from "../common/directives/long-press-directive";
|
||||
import { hasDoubleClick } from "../common/has-double-click";
|
||||
import { handleClick } from "../common/handle-click";
|
||||
import { classMap } from "lit-html/directives/class-map";
|
||||
import { DOMAINS_HIDE_MORE_INFO } from "../../../common/const";
|
||||
import { computeDomain } from "../../../common/entity/compute_domain";
|
||||
import { EntitiesCardEntityConfig } from "../cards/types";
|
||||
import { actionHandler } from "../common/directives/action-handler-directive";
|
||||
import { hasAction } from "../common/has-action";
|
||||
import { ActionHandlerEvent } from "../../../data/lovelace";
|
||||
import { handleAction } from "../common/handle-action";
|
||||
|
||||
@customElement("hui-input-select-entity-row")
|
||||
class HuiInputSelectEntityRow extends LitElement implements EntityRow {
|
||||
|
@ -81,11 +82,10 @@ class HuiInputSelectEntityRow extends LitElement implements EntityRow {
|
|||
class=${classMap({
|
||||
pointer,
|
||||
})}
|
||||
@ha-click=${this._handleClick}
|
||||
@ha-hold=${this._handleHold}
|
||||
@ha-dblclick=${this._handleDblClick}
|
||||
.longPress=${longPress({
|
||||
hasDoubleClick: hasDoubleClick(this._config.double_tap_action),
|
||||
@action=${this._handleAction}
|
||||
.actionHandler=${actionHandler({
|
||||
hasHold: hasAction(this._config!.hold_action),
|
||||
hasDoubleClick: hasAction(this._config!.double_tap_action),
|
||||
})}
|
||||
tabindex="0"
|
||||
></state-badge>
|
||||
|
@ -127,16 +127,8 @@ class HuiInputSelectEntityRow extends LitElement implements EntityRow {
|
|||
)!.selected = stateObj.attributes.options.indexOf(stateObj.state);
|
||||
}
|
||||
|
||||
private _handleClick(): void {
|
||||
handleClick(this, this.hass!, this._config!, false, false);
|
||||
}
|
||||
|
||||
private _handleHold(): void {
|
||||
handleClick(this, this.hass!, this._config!, true, false);
|
||||
}
|
||||
|
||||
private _handleDblClick(): void {
|
||||
handleClick(this, this.hass!, this._config!, false, true);
|
||||
private _handleAction(ev: ActionHandlerEvent) {
|
||||
handleAction(this, this.hass!, this._config!, ev.detail.action!);
|
||||
}
|
||||
|
||||
static get styles(): CSSResult {
|
||||
|
|
Loading…
Reference in New Issue