Allow custom actions to control the frigate card.
This commit is contained in:
@@ -10,7 +10,11 @@ import {
|
||||
MenuStateIcon,
|
||||
PictureElements,
|
||||
} from '../types.js';
|
||||
import { dispatchErrorMessageEvent, dispatchFrigateCardEvent } from '../common.js';
|
||||
import {
|
||||
convertLovelaceEventToCardActionEvent,
|
||||
dispatchErrorMessageEvent,
|
||||
dispatchFrigateCardEvent,
|
||||
} from '../common.js';
|
||||
|
||||
import elementsStyle from '../scss/elements.scss';
|
||||
import { localize } from '../localize/localize.js';
|
||||
@@ -180,6 +184,7 @@ export class FrigateCardElements extends LitElement {
|
||||
.hass=${this._hass}
|
||||
.view=${this.view}
|
||||
.elements=${this.elements}
|
||||
@ll-custom=${(ev: CustomEvent) => convertLovelaceEventToCardActionEvent(this, ev)}
|
||||
>
|
||||
</frigate-card-elements-core>`;
|
||||
}
|
||||
|
||||
+79
-54
@@ -1,5 +1,5 @@
|
||||
import { HassEntity } from 'home-assistant-js-websocket';
|
||||
import { HomeAssistant, hasAction, stateIcon } from 'custom-card-helpers';
|
||||
import { HomeAssistant, handleAction, hasAction, stateIcon } from 'custom-card-helpers';
|
||||
import {
|
||||
CSSResultGroup,
|
||||
LitElement,
|
||||
@@ -10,21 +10,28 @@ import {
|
||||
} from 'lit';
|
||||
import { customElement, property } from 'lit/decorators.js';
|
||||
import { classMap } from 'lit/directives/class-map.js';
|
||||
import { styleMap } from 'lit/directives/style-map.js';
|
||||
import { StyleInfo, styleMap } from 'lit/directives/style-map.js';
|
||||
|
||||
import { actionHandler } from '../action-handler-directive.js';
|
||||
|
||||
import type {
|
||||
CardAction,
|
||||
ElementsActionType,
|
||||
ExtendedHomeAssistant,
|
||||
MenuButton,
|
||||
MenuConfig,
|
||||
MenuInteraction,
|
||||
} from '../types.js';
|
||||
import { dispatchFrigateCardEvent, shouldUpdateBasedOnHass } from '../common.js';
|
||||
import {
|
||||
convertActionToFrigateCardCustomAction,
|
||||
convertLovelaceEventToCardActionEvent,
|
||||
dispatchFrigateCardEvent,
|
||||
shouldUpdateBasedOnHass,
|
||||
} from '../common.js';
|
||||
|
||||
import menuStyle from '../scss/menu.scss';
|
||||
|
||||
export const MENU_HEIGHT = 46;
|
||||
export const FRIGATE_BUTTON_MENU_ICON = 'frigate';
|
||||
|
||||
// A menu for the Frigate card.
|
||||
@customElement('frigate-card-menu')
|
||||
@@ -48,19 +55,50 @@ export class FrigateCardMenu extends LitElement {
|
||||
public buttons: MenuButton[] = [];
|
||||
|
||||
protected _interactionHandler(ev: CustomEvent, button: MenuButton): void {
|
||||
if (this._menuConfig?.mode.startsWith('hidden-')) {
|
||||
if (button.type == 'internal-menu-icon' && button.tap_action === 'frigate') {
|
||||
this.expand = !this.expand;
|
||||
return;
|
||||
}
|
||||
// Collapse menu after the user clicks on something.
|
||||
this.expand = false;
|
||||
if (!ev) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatchFrigateCardEvent<MenuInteraction>(this, 'menu-interaction', {
|
||||
interaction: ev.detail.action,
|
||||
button: button,
|
||||
});
|
||||
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;
|
||||
}
|
||||
if (!action) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 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<CardAction>(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);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Determine whether the menu should be updated.
|
||||
@@ -82,38 +120,47 @@ export class FrigateCardMenu extends LitElement {
|
||||
return shouldUpdateBasedOnHass(this.hass, oldHass, entities);
|
||||
}
|
||||
|
||||
public static getEmphasizedStyle(): StyleInfo {
|
||||
return {
|
||||
color: 'var(--primary-color, white)',
|
||||
};
|
||||
}
|
||||
|
||||
// Render a menu button.
|
||||
protected _renderButton(button: MenuButton): TemplateResult | void {
|
||||
let state: HassEntity | null = null;
|
||||
let emphasize = false;
|
||||
let title = button.title;
|
||||
let icon = button.icon;
|
||||
const style = ('style' in button ? button.style : {}) || {};
|
||||
let style = ('style' in button ? button.style : {}) || {};
|
||||
|
||||
if (icon == FRIGATE_BUTTON_MENU_ICON) {
|
||||
icon =
|
||||
this._menuConfig?.mode.startsWith('hidden-') && !this.expand
|
||||
? 'mdi:alpha-f-box-outline'
|
||||
: 'mdi:alpha-f-box';
|
||||
}
|
||||
|
||||
if (button.type === 'custom:frigate-card-menu-state-icon') {
|
||||
if (!this.hass) {
|
||||
return;
|
||||
}
|
||||
state = this.hass.states[button.entity];
|
||||
emphasize =
|
||||
!!state && button.state_color && ['on', 'active', 'home'].includes(state.state);
|
||||
if (
|
||||
!!state &&
|
||||
button.state_color &&
|
||||
['on', 'active', 'home'].includes(state.state)
|
||||
) {
|
||||
style = { ...style, ...FrigateCardMenu.getEmphasizedStyle() };
|
||||
}
|
||||
title = title ?? (state?.attributes?.friendly_name || button.entity);
|
||||
icon = icon ?? stateIcon(state);
|
||||
} else if (button.type === 'internal-menu-icon') {
|
||||
emphasize = button.emphasize ?? false;
|
||||
}
|
||||
|
||||
let hasHold = false;
|
||||
let hasDoubleClick = false;
|
||||
|
||||
if (button.type != 'internal-menu-icon') {
|
||||
hasHold = hasAction(button.hold_action);
|
||||
hasDoubleClick = hasAction(button.double_tap_action);
|
||||
}
|
||||
const hasHold = hasAction(button.hold_action);
|
||||
const hasDoubleClick = hasAction(button.double_tap_action);
|
||||
|
||||
const classes = {
|
||||
button: true,
|
||||
emphasize: emphasize,
|
||||
};
|
||||
|
||||
// TODO: Upon a safe distance from the release of HA 2021.11 these
|
||||
@@ -127,6 +174,7 @@ export class FrigateCardMenu extends LitElement {
|
||||
.label=${title || ''}
|
||||
title=${title || ''}
|
||||
@action=${(ev) => this._interactionHandler(ev, button)}
|
||||
@ll-custom=${(ev: CustomEvent) => convertLovelaceEventToCardActionEvent(this, ev)}
|
||||
.actionHandler=${actionHandler({
|
||||
hasHold: hasHold,
|
||||
hasDoubleClick: hasDoubleClick,
|
||||
@@ -136,16 +184,6 @@ export class FrigateCardMenu extends LitElement {
|
||||
</ha-icon-button>`;
|
||||
}
|
||||
|
||||
// Render the Frigate menu button.
|
||||
protected _renderFrigateButton(button: MenuButton): TemplateResult | void {
|
||||
const icon =
|
||||
this._menuConfig?.mode.startsWith('hidden-') && !this.expand
|
||||
? 'mdi:alpha-f-box-outline'
|
||||
: 'mdi:alpha-f-box';
|
||||
|
||||
return this._renderButton(Object.assign({}, button, { icon: icon }));
|
||||
}
|
||||
|
||||
// Render the menu.
|
||||
protected render(): TemplateResult | void {
|
||||
if (!this._menuConfig) {
|
||||
@@ -153,16 +191,7 @@ export class FrigateCardMenu extends LitElement {
|
||||
}
|
||||
const mode = this._menuConfig.mode;
|
||||
|
||||
const isFrigateButton = function (button: MenuButton): boolean {
|
||||
return button.type === 'internal-menu-icon' && button.tap_action === 'frigate';
|
||||
};
|
||||
|
||||
// If the menu is off, or if it's in hidden mode but there's no button to
|
||||
// unhide it, just show nothing.
|
||||
if (
|
||||
mode == 'none' ||
|
||||
(mode.startsWith('hidden-') && !this.buttons.find(isFrigateButton))
|
||||
) {
|
||||
if (mode == 'none') {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -187,11 +216,7 @@ export class FrigateCardMenu extends LitElement {
|
||||
|
||||
return html`
|
||||
<div class=${classMap(classes)}>
|
||||
${Array.from(this.buttons).map((button) => {
|
||||
return isFrigateButton(button)
|
||||
? this._renderFrigateButton(button)
|
||||
: this._renderButton(button);
|
||||
})}
|
||||
${Array.from(this.buttons).map((button) => this._renderButton(button))}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user