From de763f3e5650f8d16c4c8550bb64764fbb0916fd Mon Sep 17 00:00:00 2001 From: Dermot Duffy Date: Tue, 25 Jan 2022 22:01:09 -0800 Subject: [PATCH] Implement support for {start,end}_tap actions. --- src/action-handler-directive.ts | 5 ++++ src/card.ts | 25 +++++++++++------- src/common.ts | 46 +++++++++++++++++++++++++++++---- src/components/menu.ts | 5 ++-- src/types.ts | 8 +++--- 5 files changed, 69 insertions(+), 20 deletions(-) diff --git a/src/action-handler-directive.ts b/src/action-handler-directive.ts index cc281235..714bd0bc 100644 --- a/src/action-handler-directive.ts +++ b/src/action-handler-directive.ts @@ -117,6 +117,8 @@ class ActionHandler extends HTMLElement implements ActionHandler { this.held = true; }, this.holdTime); } + + fireEvent(element, 'action', { action: 'start_tap' }); }; const end = (ev: Event): void => { @@ -133,6 +135,9 @@ class ActionHandler extends HTMLElement implements ActionHandler { this.stopAnimation(); this.timer = undefined; } + + fireEvent(element, 'action', { action: 'end_tap' }); + if (options?.hasHold && this.held) { fireEvent(element, 'action', { action: 'hold' }); } else if (options?.hasDoubleClick) { diff --git a/src/card.ts b/src/card.ts index fdef5b30..8c3eacf4 100644 --- a/src/card.ts +++ b/src/card.ts @@ -14,7 +14,6 @@ import { HomeAssistant, LovelaceCardEditor, getLovelace, - handleAction, hasAction, } from 'custom-card-helpers'; import screenfull from 'screenfull'; @@ -46,6 +45,7 @@ import { contentsChanged, convertActionToFrigateCardCustomAction, createFrigateCardCustomAction, + frigateCardHandleAction, getActionConfigGivenAction, getCameraIcon, getCameraTitle, @@ -102,8 +102,8 @@ import { * * The card supports actions being configured in a number of places (e.g. tap on an * element, double_tap on a menu item, hold on the live view). These actions are - * handled by handleAction() from custom-card-helpers. For Frigate-card specific - * actions, handleAction() call will result in an ll-custom DOM event being + * handled frigateCardHandleAction(). For Frigate-card specific actions, + * frigateCardHandleAction() call will result in an ll-custom DOM event being * fired, which needs to be caught at the card level to handle. */ @@ -880,6 +880,8 @@ export class FrigateCard extends LitElement { hold_action?: ActionType; tap_action?: ActionType; double_tap_action?: ActionType; + start_tap_action?: ActionType; + end_tap_action?: ActionType; }, ): void { const interaction = ev.detail.action; @@ -888,12 +890,17 @@ export class FrigateCard extends LitElement { config && node && interaction && - // Don't call handleAction() unless there is explicitly an action defined - // (as it uses a default that is unhelpful for views that have default - // tap/click actions). + // Don't call frigateCardHandleAction() unless there is explicitly an + // action defined (as it uses a default that is unhelpful for views that + // have default tap/click actions). getActionConfigGivenAction(interaction, config) ) { - handleAction(node, this._hass as HomeAssistant, config, ev.detail.action); + frigateCardHandleAction( + node, + this._hass as HomeAssistant, + config, + ev.detail.action, + ); } // Set the 'screensaver' timer. @@ -950,9 +957,7 @@ export class FrigateCard extends LitElement { * @returns `true` if it's allowed, `false` otherwise. */ protected _isAutomatedViewUpdateAllowed(): boolean { - return ( - this._getConfig().view.update_force || !this._interactionTimerID - ); + return this._getConfig().view.update_force || !this._interactionTimerID; } /** diff --git a/src/common.ts b/src/common.ts index b589cac9..01eb1b76 100644 --- a/src/common.ts +++ b/src/common.ts @@ -1,5 +1,9 @@ import { HassEntity, MessageBase } from 'home-assistant-js-websocket'; -import { HomeAssistant, stateIcon } from 'custom-card-helpers'; +import { + HomeAssistant, + handleActionConfig, + stateIcon, +} from 'custom-card-helpers'; import { StyleInfo } from 'lit/directives/style-map'; import { ZodSchema, z } from 'zod'; import { isEqual } from 'lodash-es'; @@ -302,10 +306,12 @@ export function getActionConfigGivenAction( hold_action?: ActionType; tap_action?: ActionType; double_tap_action?: ActionType; + start_tap_action?: ActionType; + end_tap_action?: ActionType; }, -): ActionType | null { +): ActionType | undefined { if (!interaction || !config) { - return null; + return undefined; } if (interaction == 'tap' && config.tap_action) { return config.tap_action; @@ -313,8 +319,12 @@ export function getActionConfigGivenAction( return config.hold_action; } else if (interaction == 'double_tap' && config.double_tap_action) { return config.double_tap_action; + } else if (interaction == 'end_tap' && config.end_tap_action) { + return config.end_tap_action; + } else if (interaction == 'start_tap' && config.start_tap_action) { + return config.start_tap_action; } - return null; + return undefined; } /** @@ -479,4 +489,30 @@ export function arrayMove(target: unknown[], from: number, to: number): void { */ export function contentsChanged(n: unknown, o: unknown): boolean { return !isEqual(n, o); -} \ No newline at end of file +} + +/** + * Frigate card custom version of handleAction + * (https://github.com/custom-cards/custom-card-helpers/blob/master/src/handle-action.ts) + * that handles the custom action events the card supports. + * @param node The node that fired the event. + * @param hass The Home Assistant object. + * @param config The multi-action configuration. + * @param action The action string (e.g. 'hold') + */ +export const frigateCardHandleAction = ( + node: HTMLElement, + hass: HomeAssistant, + config: { + entity?: string; + camera_image?: string; + hold_action?: ActionType; + tap_action?: ActionType; + double_tap_action?: ActionType; + start_tap_action?: ActionType; + end_tap_action?: ActionType; + }, + action: string, +): void => { + handleActionConfig(node, hass, config, getActionConfigGivenAction(action, config)); +}; diff --git a/src/components/menu.ts b/src/components/menu.ts index 36046859..3a877128 100644 --- a/src/components/menu.ts +++ b/src/components/menu.ts @@ -1,4 +1,4 @@ -import { HASSDomEvent, HomeAssistant, handleAction, hasAction } from 'custom-card-helpers'; +import { HASSDomEvent, HomeAssistant, hasAction } from 'custom-card-helpers'; import { CSSResultGroup, LitElement, TemplateResult, html, unsafeCSS } from 'lit'; import { customElement, property, state } from 'lit/decorators.js'; import { classMap } from 'lit/directives/class-map.js'; @@ -18,6 +18,7 @@ import type { } from '../types.js'; import { convertActionToFrigateCardCustomAction, + frigateCardHandleAction, getActionConfigGivenAction, refreshDynamicStateParameters, } from '../common.js'; @@ -103,7 +104,7 @@ export class FrigateCardMenu extends LitElement { // Collapse menu after the user clicks on something. this.expanded = false; - handleAction(this, this.hass as HomeAssistant, config, interaction); + frigateCardHandleAction(this, this.hass as HomeAssistant, config, interaction); } /** diff --git a/src/types.ts b/src/types.ts index c8865038..d2fe26d4 100644 --- a/src/types.ts +++ b/src/types.ts @@ -162,14 +162,16 @@ const actionBaseSchema = z tap_action: actionSchema.optional(), hold_action: actionSchema.optional(), double_tap_action: actionSchema.optional(), + start_tap_action: actionSchema.optional(), + end_tap_action: actionSchema.optional(), }) + // Passthrough to allow (at least) entity/camera_image to go through. This + // card doesn't need these attributes, but handleAction() in + // custom_card_helpers may depending on how the action is configured. .passthrough(); export type Actions = z.infer; const actionsSchema = z.object({ - // Passthrough to allow (at least) entity/camera_image to go through. This - // card doesn't need these attributes, but handleAction() in - // custom_card_helpers may depending on how the action is configured. actions: actionBaseSchema.optional(), });