From 9c9548afc8800964f5ab4d971078456a333a71be Mon Sep 17 00:00:00 2001 From: Dermot Duffy Date: Sun, 7 Apr 2024 21:18:55 -0700 Subject: [PATCH 1/3] Fix card-wide actions. --- src/card-controller/actions-manager.ts | 24 ++++++++++++++--- src/card-controller/card-element-manager.ts | 12 +++++++-- tests/card-controller/actions-manager.test.ts | 26 ++++++++++++++++--- 3 files changed, 52 insertions(+), 10 deletions(-) diff --git a/src/card-controller/actions-manager.ts b/src/card-controller/actions-manager.ts index 89060699..8546dc9b 100644 --- a/src/card-controller/actions-manager.ts +++ b/src/card-controller/actions-manager.ts @@ -1,3 +1,4 @@ +import { z } from 'zod'; import { Actions, ActionsConfig, @@ -13,6 +14,15 @@ import { import { getStreamCameraID } from '../utils/substream.js'; import { CardActionsManagerAPI } from './types.js'; +const interactionSchema = z.object({ + action: z.enum(['tap', 'double_tap', 'hold', 'start_tap', 'end_tap']), +}); +export type Interaction = z.infer; + +const interactionEventSchema = z.object({ + detail: interactionSchema, +}); + export class ActionsManager { protected _api: CardActionsManagerAPI; @@ -49,7 +59,14 @@ export class ActionsManager { /** * Handle an human interaction called on an element (e.g. 'tap'). */ - public handleInteraction(interaction: string): void { + public handleInteractionEvent = (ev: Event): void => { + const result = interactionEventSchema.safeParse(ev); + if (!result.success) { + // The event may not be a CustomEvent object, see: + // https://github.com/custom-cards/custom-card-helpers/blob/master/src/fire-event.ts#L70 + return; + } + const interaction = result.data.detail.action; const hass = this._api.getHASSManager().getHASS(); const config = this.getMergedActions(); const actionConfig = getActionConfigGivenAction(interaction, config); @@ -70,12 +87,11 @@ export class ActionsManager { actionConfig, ); } - } + }; public handleActionEvent = (ev: Event): void => { if (!('detail' in ev)) { - // The event may not actually be a CustomEvent object, but may still have a - // detail field. See: + // The event may not be a CustomEvent object, see: // https://github.com/custom-cards/custom-card-helpers/blob/master/src/fire-event.ts#L70 return; } diff --git a/src/card-controller/card-element-manager.ts b/src/card-controller/card-element-manager.ts index 38599fd2..1b442f1e 100644 --- a/src/card-controller/card-element-manager.ts +++ b/src/card-controller/card-element-manager.ts @@ -77,7 +77,11 @@ export class CardElementManager { this._api.getActionsManager().handleActionEvent, ); this._element.addEventListener( - '@action', + 'action', + this._api.getActionsManager().handleInteractionEvent, + ); + this._element.addEventListener( + 'action', this._api.getInteractionManager().reportInteraction, ); @@ -123,7 +127,11 @@ export class CardElementManager { this._api.getActionsManager().handleActionEvent, ); this._element.removeEventListener( - '@action', + 'action', + this._api.getActionsManager().handleInteractionEvent, + ); + this._element.removeEventListener( + 'action', this._api.getInteractionManager().reportInteraction, ); diff --git a/tests/card-controller/actions-manager.test.ts b/tests/card-controller/actions-manager.test.ts index 02742759..8b11b640 100644 --- a/tests/card-controller/actions-manager.test.ts +++ b/tests/card-controller/actions-manager.test.ts @@ -14,7 +14,7 @@ import { frigateCardHandleActionConfig, getActionConfigGivenAction, } from '../../src/utils/action.js'; -import { ActionsManager } from '../../src/card-controller/actions-manager'; +import { ActionsManager, Interaction } from '../../src/card-controller/actions-manager'; import { createCardAPI, createConfig, @@ -165,7 +165,9 @@ describe('ActionsManager.handleInteraction', () => { }; vi.mocked(getActionConfigGivenAction).mockReturnValue(actionForThisInteraction); - manager.handleInteraction('tap'); + manager.handleInteractionEvent( + new CustomEvent('event', { detail: { action: 'tap' } }), + ); expect(frigateCardHandleActionConfig).toBeCalledWith( element, @@ -176,13 +178,29 @@ describe('ActionsManager.handleInteraction', () => { ); }); - it('should not handle interaction', () => { + it('should not handle interaction without hass', () => { const api = createCardAPI(); const manager = new ActionsManager(api); vi.mocked(api.getHASSManager().getHASS).mockReturnValue(null); // No values of hass. - manager.handleInteraction('tap'); + manager.handleInteractionEvent( + new CustomEvent('event', { detail: { action: 'tap' } }), + ); + expect(frigateCardHandleActionConfig).not.toBeCalledWith(); + }); + + it('should not handle malformed interaction', () => { + const api = createCardAPI(); + const manager = new ActionsManager(api); + + manager.handleInteractionEvent( + new CustomEvent('event', { + + // Malformed interaction type. + detail: { action: 'double_finger_snap' } as unknown as Interaction, + }), + ); expect(frigateCardHandleActionConfig).not.toBeCalledWith(); }); }); From 25d080f0d43a3b802d982a2abc87f079c312a8de Mon Sep 17 00:00:00 2001 From: Dermot Duffy Date: Sun, 7 Apr 2024 21:21:27 -0700 Subject: [PATCH 2/3] Remove unnecessary comment. --- src/card-controller/actions-manager.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/card-controller/actions-manager.ts b/src/card-controller/actions-manager.ts index 8546dc9b..69c54ab4 100644 --- a/src/card-controller/actions-manager.ts +++ b/src/card-controller/actions-manager.ts @@ -62,8 +62,6 @@ export class ActionsManager { public handleInteractionEvent = (ev: Event): void => { const result = interactionEventSchema.safeParse(ev); if (!result.success) { - // The event may not be a CustomEvent object, see: - // https://github.com/custom-cards/custom-card-helpers/blob/master/src/fire-event.ts#L70 return; } const interaction = result.data.detail.action; From 18bbe3a6415ddadfb5f7215f55afc50496129ce3 Mon Sep 17 00:00:00 2001 From: Dermot Duffy Date: Sun, 7 Apr 2024 21:24:35 -0700 Subject: [PATCH 3/3] Fix element tests. --- tests/card-controller/card-element-manager.test.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/card-controller/card-element-manager.test.ts b/tests/card-controller/card-element-manager.test.ts index c378ab10..82f9392b 100644 --- a/tests/card-controller/card-element-manager.test.ts +++ b/tests/card-controller/card-element-manager.test.ts @@ -122,7 +122,11 @@ describe('CardElementManager', () => { api.getActionsManager().handleActionEvent, ); expect(addEventListener).toBeCalledWith( - '@action', + 'action', + api.getActionsManager().handleInteractionEvent, + ); + expect(addEventListener).toBeCalledWith( + 'action', api.getInteractionManager().reportInteraction, ); expect(windowAddEventListener).toBeCalledWith('location-changed', expect.anything()); @@ -169,7 +173,11 @@ describe('CardElementManager', () => { api.getActionsManager().handleActionEvent, ); expect(removeEventListener).toBeCalledWith( - '@action', + 'action', + api.getActionsManager().handleInteractionEvent, + ); + expect(removeEventListener).toBeCalledWith( + 'action', api.getInteractionManager().reportInteraction, ); expect(windowRemoveEventListener).toBeCalledWith(