@@ -999,7 +1068,6 @@ export class FrigateCard extends LitElement {
// 'frigate-card-elements' to re-render (by being a property).
e.view = this._view;
}}
- @frigate-card:card-action=${this._cardActionHandler.bind(this)}
>
`
diff --git a/src/common.ts b/src/common.ts
index df2fbdf5..429b0ca4 100644
--- a/src/common.ts
+++ b/src/common.ts
@@ -3,7 +3,7 @@ import { MessageBase } from 'home-assistant-js-websocket';
import { HomeAssistant } from 'custom-card-helpers';
import { localize } from './localize/localize.js';
import {
- ElementsActionType,
+ ActionType,
ExtendedHomeAssistant,
FrigateCardCustomAction,
frigateCardCustomActionSchema,
@@ -258,7 +258,9 @@ export function isValidMediaShowInfo(info: MediaShowInfo): boolean {
);
}
-export function convertActionToFrigateCardCustomAction(action: ElementsActionType): FrigateCardCustomAction | null {
+export function convertActionToFrigateCardCustomAction(
+ action: ActionType,
+): FrigateCardCustomAction | null {
// Parse a custom event as other things could generate ll-custom events that
// are not related to Frigate Card.
const parseResult = frigateCardCustomActionSchema.safeParse(action);
@@ -269,18 +271,26 @@ export function createFrigateCardCustomAction(action: string): FrigateCardCustom
return {
action: 'fire-dom-event',
frigate_card_action: action,
- }
+ };
}
-export function convertLovelaceEventToCardActionEvent(
- node: HTMLElement,
- ev: CustomEvent,
-): void {
- const frigateCardAction = convertActionToFrigateCardCustomAction(ev.detail);
- if (frigateCardAction) {
- ev.stopPropagation();
- dispatchFrigateCardEvent(node, 'card-action', {
- action: frigateCardAction.frigate_card_action,
- });
+export function getActionConfigGivenAction(
+ interaction?: string,
+ config?: {
+ hold_action?: ActionType;
+ tap_action?: ActionType;
+ double_tap_action?: ActionType;
+ },
+): ActionType | null {
+ if (!interaction || !config) {
+ return null;
}
+ if (interaction == 'tap' && config.tap_action) {
+ return config.tap_action;
+ } else if (interaction == 'hold' && config.hold_action) {
+ return config.hold_action;
+ } else if (interaction == 'double_tap' && config.double_tap_action) {
+ return config.double_tap_action;
+ }
+ return null;
}
diff --git a/src/components/elements.ts b/src/components/elements.ts
index 366c9055..b92ca112 100644
--- a/src/components/elements.ts
+++ b/src/components/elements.ts
@@ -11,7 +11,6 @@ import {
PictureElements,
} from '../types.js';
import {
- convertLovelaceEventToCardActionEvent,
dispatchErrorMessageEvent,
dispatchFrigateCardEvent,
} from '../common.js';
@@ -184,7 +183,6 @@ export class FrigateCardElements extends LitElement {
.hass=${this._hass}
.view=${this.view}
.elements=${this.elements}
- @ll-custom=${(ev: CustomEvent) => convertLovelaceEventToCardActionEvent(this, ev)}
>
`;
}
diff --git a/src/components/menu.ts b/src/components/menu.ts
index fcf5f0bf..b6beeb4d 100644
--- a/src/components/menu.ts
+++ b/src/components/menu.ts
@@ -15,16 +15,13 @@ import { StyleInfo, styleMap } from 'lit/directives/style-map.js';
import { actionHandler } from '../action-handler-directive.js';
import type {
- CardAction,
- ElementsActionType,
ExtendedHomeAssistant,
MenuButton,
MenuConfig,
} from '../types.js';
import {
convertActionToFrigateCardCustomAction,
- convertLovelaceEventToCardActionEvent,
- dispatchFrigateCardEvent,
+ getActionConfigGivenAction,
shouldUpdateBasedOnHass,
} from '../common.js';
@@ -54,21 +51,13 @@ export class FrigateCardMenu extends LitElement {
@property({ attribute: false })
public buttons: MenuButton[] = [];
- protected _interactionHandler(ev: CustomEvent, button: MenuButton): void {
+ protected _actionHandler(ev: CustomEvent, button: MenuButton): void {
if (!ev) {
return;
}
const interaction: string = ev.detail.action;
- let action: ElementsActionType | undefined;
-
- if (interaction == 'tap') {
- action = button.tap_action;
- } else if (interaction == 'hold') {
- action = button.hold_action;
- } else if (interaction == 'double_tap') {
- action = button.double_tap_action;
- }
+ const action = getActionConfigGivenAction(interaction, button);
if (!action) {
return;
}
@@ -76,29 +65,20 @@ export class FrigateCardMenu extends LitElement {
// Determine if this action is a Frigate card action, if so handle it
// internally.
const frigateCardAction = convertActionToFrigateCardCustomAction(action);
- if (frigateCardAction) {
- if (frigateCardAction.frigate_card_action == 'frigate') {
- // If the user presses the frigate button and it's a hide-away menu,
- // then expand the menu and return.
- if (this._menuConfig?.mode.startsWith('hidden-')) {
- this.expand = !this.expand;
- return;
- }
- }
-
- // Collapse menu after the user clicks on something.
- this.expand = false;
-
- dispatchFrigateCardEvent(this, 'card-action', {
- action: frigateCardAction.frigate_card_action,
- });
- }
-
- const node: HTMLElement | null = ev.currentTarget as HTMLElement | null;
- if (node) {
- handleAction(node, this.hass as HomeAssistant, button, interaction);
+ if (
+ frigateCardAction &&
+ frigateCardAction.frigate_card_action == 'frigate' &&
+ this._menuConfig?.mode.startsWith('hidden-')
+ ) {
+ // If the user presses the frigate button and it's a hide-away menu,
+ // then expand the menu and return.
+ this.expand = !this.expand;
return;
}
+
+ // Collapse menu after the user clicks on something.
+ this.expand = false;
+ handleAction(this, this.hass as HomeAssistant, button, interaction);
}
// Determine whether the menu should be updated.
@@ -173,8 +153,7 @@ export class FrigateCardMenu extends LitElement {
icon=${icon || 'mdi:gesture-tap-button'}
.label=${title || ''}
title=${title || ''}
- @action=${(ev) => this._interactionHandler(ev, button)}
- @ll-custom=${(ev: CustomEvent) => convertLovelaceEventToCardActionEvent(this, ev)}
+ @action=${(ev) => this._actionHandler(ev, button)}
.actionHandler=${actionHandler({
hasHold: hasHold,
hasDoubleClick: hasDoubleClick,
diff --git a/src/types.ts b/src/types.ts
index 853a6ebc..2fdc2182 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -117,7 +117,7 @@ export const frigateCardCustomActionSchema = customActionSchema.merge(
);
export type FrigateCardCustomAction = z.infer;
-const elementsActionSchema = z.union([
+const actionSchema = z.union([
toggleActionSchema,
callServiceActionSchema,
navigateActionSchema,
@@ -125,16 +125,29 @@ const elementsActionSchema = z.union([
moreInfoActionSchema,
frigateCardCustomActionSchema,
]);
-export type ElementsActionType = z.infer;
+export type ActionType = z.infer;
-const elementsBaseSchema = z.object({
- style: z.object({}).passthrough().optional(),
- title: z.string().nullable().optional(),
- tap_action: elementsActionSchema.optional(),
- hold_action: elementsActionSchema.optional(),
- double_tap_action: elementsActionSchema.optional(),
+const actionBaseSchema = z.object({
+ tap_action: actionSchema.optional(),
+ hold_action: actionSchema.optional(),
+ double_tap_action: actionSchema.optional(),
+}).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(),
});
+const elementsBaseSchema = actionBaseSchema.merge(
+ z.object({
+ style: z.object({}).passthrough().optional(),
+ title: z.string().nullable().optional(),
+ }),
+);
+
/**
* Picture Element Configuration.
*
@@ -322,6 +335,7 @@ const viewConfigSchema = z
.optional()
.default(viewConfigDefault.timeout),
})
+ .merge(actionsSchema)
.default(viewConfigDefault);
/**
@@ -331,6 +345,7 @@ const imageConfigSchema = z
.object({
src: z.string().optional(),
})
+ .merge(actionsSchema)
.optional();
export type ImageViewConfig = z.infer;
@@ -356,6 +371,7 @@ const liveConfigSchema = z
preload: z.boolean().default(liveConfigDefault.preload),
webrtc: webrtcConfigSchema,
})
+ .merge(actionsSchema)
.default(liveConfigDefault);
/**
@@ -430,9 +446,16 @@ const viewerConfigSchema = z
})
.default(viewerConfigDefault.controls),
})
+ .merge(actionsSchema)
.default(viewerConfigDefault);
export type ViewerConfig = z.infer;
+/**
+ * Event gallery configuration section (clips, snapshots).
+ */
+
+const galleryConfigSchema = actionsSchema.optional();
+
/**
* Dimensions configuration section.
*/
@@ -471,6 +494,7 @@ export const frigateCardConfigSchema = z.object({
menu: menuConfigSchema,
live: liveConfigSchema,
event_viewer: viewerConfigSchema,
+ event_gallery: galleryConfigSchema,
image: imageConfigSchema,
elements: pictureElementsSchema,
dimensions: dimensionsConfigSchema,
@@ -537,10 +561,6 @@ export interface Message {
icon?: string;
}
-export interface CardAction {
- action: string;
-}
-
/**
* Home Assistant API types.
*/