fix: Use HA style and coloring for all icons (#1790)
This commit is contained in:
@@ -5,6 +5,7 @@ import { localize } from '../localize/localize';
|
||||
import datePickerStyle from '../scss/date-picker.scss';
|
||||
import { stopEventFromActivatingCardWideActions } from '../utils/action';
|
||||
import { dispatchFrigateCardEvent } from '../utils/basic';
|
||||
import './icon';
|
||||
|
||||
export interface DatePickerEvent {
|
||||
date: Date | null;
|
||||
@@ -44,16 +45,16 @@ export class FrigateCardDatePicker extends LitElement {
|
||||
@input=${() => changed()}
|
||||
@change=${() => changed()}
|
||||
/>
|
||||
<ha-icon
|
||||
<frigate-card-icon
|
||||
aria-label="${localize('timeline.select_date')}"
|
||||
title="${localize('timeline.select_date')}"
|
||||
.icon=${this.icon ?? `mdi:calendar-search`}
|
||||
.icon=${{ icon: this.icon ?? `mdi:calendar-search` }}
|
||||
@click=${(ev: Event) => {
|
||||
stopEventFromActivatingCardWideActions(ev);
|
||||
this._refInput.value?.showPicker();
|
||||
}}
|
||||
>
|
||||
</ha-icon>`;
|
||||
</frigate-card-icon>`;
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
|
||||
@@ -14,6 +14,7 @@ import drawerInjectStyle from '../scss/drawer-inject.scss';
|
||||
import drawerStyle from '../scss/drawer.scss';
|
||||
import { stopEventFromActivatingCardWideActions } from '../utils/action';
|
||||
import { getChildrenFromElement, isHoverableDevice } from '../utils/basic';
|
||||
import './icon';
|
||||
|
||||
export interface DrawerIcons {
|
||||
open?: string;
|
||||
@@ -121,11 +122,13 @@ export class FrigateCardDrawer extends LitElement {
|
||||
this.open = !this.open;
|
||||
}}
|
||||
>
|
||||
<ha-icon
|
||||
<frigate-card-icon
|
||||
class="control"
|
||||
icon="${this.open
|
||||
? this.icons?.open ?? 'mdi:menu-open'
|
||||
: this.icons?.closed ?? 'mdi:menu'}"
|
||||
.icon="${{
|
||||
icon: this.open
|
||||
? this.icons?.open ?? 'mdi:menu-open'
|
||||
: this.icons?.closed ?? 'mdi:menu',
|
||||
}}"
|
||||
@mouseenter=${() => {
|
||||
// Only open the drawer on mousenter when the device
|
||||
// supports hover (otherwise iOS may end up passing on
|
||||
@@ -136,7 +139,7 @@ export class FrigateCardDrawer extends LitElement {
|
||||
}
|
||||
}}
|
||||
>
|
||||
</ha-icon>
|
||||
</frigate-card-icon>
|
||||
</div>
|
||||
`
|
||||
: ''}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import { HomeAssistant } from '@dermotduffy/custom-card-helpers';
|
||||
import { CSSResultGroup, html, LitElement, TemplateResult, unsafeCSS } from 'lit';
|
||||
import { customElement, property } from 'lit/decorators.js';
|
||||
import { IconController } from '../components-lib/icon-controller';
|
||||
import iconStyle from '../scss/icon.scss';
|
||||
import { Icon } from '../types';
|
||||
|
||||
@customElement('frigate-card-icon')
|
||||
export class FrigateCardIcon extends LitElement {
|
||||
@property({ attribute: false })
|
||||
public hass?: HomeAssistant;
|
||||
|
||||
@property({ attribute: false })
|
||||
public icon?: Icon;
|
||||
|
||||
private _controller = new IconController();
|
||||
|
||||
protected render(): TemplateResult {
|
||||
const customIconURL = this._controller.getCustomIcon(this.icon);
|
||||
if (customIconURL) {
|
||||
return html`<img src="${customIconURL}" />`;
|
||||
}
|
||||
if (this.icon?.icon) {
|
||||
return html`<ha-icon icon="${this.icon.icon}"></ha-icon>`;
|
||||
}
|
||||
if (this.hass && this.icon?.entity) {
|
||||
const stateObj = this._controller.createStateObjectForStateBadge(
|
||||
this.hass,
|
||||
this.icon.entity,
|
||||
);
|
||||
if (stateObj) {
|
||||
return html`<state-badge
|
||||
.stateColor=${this.icon.stateColor ?? true}
|
||||
.hass=${this.hass}
|
||||
.stateObj=${stateObj}
|
||||
></state-badge>`;
|
||||
}
|
||||
}
|
||||
if (this.icon?.fallback) {
|
||||
return html`<ha-icon icon="${this.icon.fallback}"></ha-icon>`;
|
||||
}
|
||||
return html``;
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return unsafeCSS(iconStyle);
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'frigate-card-icon': FrigateCardIcon;
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import { KeyAssignerController } from '../components-lib/key-assigner-controller
|
||||
import { KeyboardShortcut } from '../config/keyboard-shortcuts';
|
||||
import keyAssignerStyle from '../scss/key-assigner.scss';
|
||||
import { localize } from '../localize/localize';
|
||||
import './icon';
|
||||
|
||||
@customElement('frigate-card-key-assigner')
|
||||
export class FrigateCardKeyAssigner extends LitElement {
|
||||
@@ -48,15 +49,11 @@ export class FrigateCardKeyAssigner extends LitElement {
|
||||
this._controller.toggleAssigning();
|
||||
}}
|
||||
>
|
||||
<ha-icon icon="mdi:keyboard-settings"></ha-icon>
|
||||
<frigate-card-icon .icon=${{ icon: 'mdi:keyboard-settings' }}></frigate-card-icon>
|
||||
<span class="${classMap({
|
||||
dotdotdot: this._controller.isAssigning(),
|
||||
})}">
|
||||
${
|
||||
this._controller.isAssigning()
|
||||
? localize('key_assigner.assigning')
|
||||
: localize('key_assigner.assign')
|
||||
}
|
||||
${this._controller.isAssigning() ? '' : localize('key_assigner.assign')}
|
||||
</span>
|
||||
</ha-button>
|
||||
${
|
||||
@@ -66,7 +63,9 @@ export class FrigateCardKeyAssigner extends LitElement {
|
||||
this._controller.setValue(null);
|
||||
}}
|
||||
>
|
||||
<ha-icon icon="mdi:keyboard-off"></ha-icon>
|
||||
<frigate-card-icon
|
||||
.icon=${{ icon: 'mdi:keyboard-off' }}
|
||||
></frigate-card-icon>
|
||||
<span> ${localize('key_assigner.unassign')} </span>
|
||||
</ha-button>`
|
||||
: ''
|
||||
|
||||
@@ -11,6 +11,7 @@ import { classMap } from 'lit/directives/class-map.js';
|
||||
import { guard } from 'lit/directives/guard.js';
|
||||
import { createRef, Ref, ref } from 'lit/directives/ref.js';
|
||||
import { CameraEndpoints } from '../../camera-manager/types.js';
|
||||
import { dispatchLiveErrorEvent } from '../../components-lib/live/utils/dispatch-live-error.js';
|
||||
import { PartialZoomSettings } from '../../components-lib/zoom/types.js';
|
||||
import {
|
||||
CameraConfig,
|
||||
@@ -26,11 +27,11 @@ import { aspectRatioToString } from '../../utils/basic.js';
|
||||
import { dispatchMediaUnloadedEvent } from '../../utils/media-info.js';
|
||||
import { updateElementStyleFromMediaLayoutConfig } from '../../utils/media-layout.js';
|
||||
import { playMediaMutingIfNecessary } from '../../utils/media.js';
|
||||
import '../icon.js';
|
||||
import { renderMessage } from '../message.js';
|
||||
import '../next-prev-control.js';
|
||||
import '../ptz.js';
|
||||
import '../surround.js';
|
||||
import { dispatchLiveErrorEvent } from '../../components-lib/live/utils/dispatch-live-error.js';
|
||||
|
||||
@customElement('frigate-card-live-provider')
|
||||
export class FrigateCardLiveProvider
|
||||
@@ -385,10 +386,10 @@ export class FrigateCardLiveProvider
|
||||
: html``}
|
||||
`)}
|
||||
${showImageDuringLoading && !this._isVideoMediaLoaded
|
||||
? html`<ha-icon
|
||||
? html`<frigate-card-icon
|
||||
title=${localize('error.awaiting_live')}
|
||||
icon="mdi:progress-helper"
|
||||
></ha-icon>`
|
||||
.icon=${{ icon: 'mdi:progress-helper' }}
|
||||
></frigate-card-icon>`
|
||||
: ''} `;
|
||||
}
|
||||
|
||||
|
||||
+17
-25
@@ -1,15 +1,15 @@
|
||||
import { HomeAssistant } from '@dermotduffy/custom-card-helpers';
|
||||
import { CSSResultGroup, LitElement, TemplateResult, html, unsafeCSS } from 'lit';
|
||||
import { customElement, property } from 'lit/decorators.js';
|
||||
import { ifDefined } from 'lit/directives/if-defined.js';
|
||||
import { styleMap } from 'lit/directives/style-map.js';
|
||||
import { actionHandler } from '../action-handler-directive.js';
|
||||
import { MenuController } from '../components-lib/menu-controller.js';
|
||||
import type { MenuConfig, MenuItem } from '../config/types.js';
|
||||
import menuStyle from '../scss/menu.scss';
|
||||
import { frigateCardHasAction } from '../utils/action.js';
|
||||
import { getCustomIconURL } from '../utils/custom-icons.js';
|
||||
import { getEntityTitle } from '../utils/ha/index.js';
|
||||
import { EntityRegistryManager } from '../utils/ha/registry/entity/index.js';
|
||||
import './icon.js';
|
||||
import './submenu.js';
|
||||
|
||||
@customElement('frigate-card-menu')
|
||||
@@ -60,38 +60,30 @@ export class FrigateCardMenu extends LitElement {
|
||||
</frigate-card-submenu-select>`;
|
||||
}
|
||||
|
||||
// =====================================================================================
|
||||
// For `data-domain` and `data-state`, see: See
|
||||
// https://github.com/home-assistant/frontend/blob/dev/src/components/entity/state-badge.ts#L54
|
||||
// =====================================================================================
|
||||
// Buttons are styled in a few ways (in order of precedence):
|
||||
//
|
||||
// - User provided style
|
||||
// - Color/Brightness styling for the `light` domain (calculated in
|
||||
// `refreshDynamicStateParameters`)
|
||||
// - Static styling based on domain (`data-domain`) and state
|
||||
// (`data-state`). This looks up a CSS style in `menu.scss`.
|
||||
|
||||
const buttonState = this._controller.getFreshButtonState(this.hass, button);
|
||||
const customImageURL = getCustomIconURL(buttonState.icon);
|
||||
const title =
|
||||
this.hass && button.type === 'custom:frigate-card-menu-state-icon' && !button.title
|
||||
? getEntityTitle(this.hass, button.entity)
|
||||
: button.title;
|
||||
|
||||
return html` <ha-icon-button
|
||||
data-domain=${ifDefined(buttonState.data_domain)}
|
||||
data-state=${ifDefined(buttonState.data_state)}
|
||||
class="button"
|
||||
style="${styleMap(buttonState.style || {})}"
|
||||
style="${styleMap(button.style || {})}"
|
||||
.actionHandler=${actionHandler({
|
||||
hasHold: frigateCardHasAction(button.hold_action),
|
||||
hasDoubleClick: frigateCardHasAction(button.double_tap_action),
|
||||
})}
|
||||
.label=${buttonState.title || ''}
|
||||
.label=${title ?? ''}
|
||||
@action=${(ev) => this._controller.actionHandler(ev, button)}
|
||||
>
|
||||
${customImageURL
|
||||
? html`<img src="${customImageURL}" />`
|
||||
: html`<ha-icon
|
||||
icon="${buttonState.icon || 'mdi:gesture-tap-button'}"
|
||||
></ha-icon>`}
|
||||
<frigate-card-icon
|
||||
.hass=${this.hass}
|
||||
.icon=${{
|
||||
icon: button.icon,
|
||||
entity: button.entity,
|
||||
stateColor: button.state_color,
|
||||
fallback: 'mdi:gesture-tap-button',
|
||||
}}
|
||||
></frigate-card-icon>
|
||||
</ha-icon-button>`;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import { localize } from '../localize/localize.js';
|
||||
import messageStyle from '../scss/message.scss';
|
||||
import { FrigateCardError, Message, MessageType } from '../types.js';
|
||||
import { dispatchFrigateCardEvent } from '../utils/basic.js';
|
||||
import './icon.js';
|
||||
|
||||
@customElement('frigate-card-message')
|
||||
export class FrigateCardMessage extends LitElement {
|
||||
@@ -38,7 +39,7 @@ export class FrigateCardMessage extends LitElement {
|
||||
return html` <div class="wrapper">
|
||||
<div class="message padded">
|
||||
<div class="icon">
|
||||
<ha-icon icon="${icon}"> </ha-icon>
|
||||
<frigate-card-icon .icon="${{ icon: icon }}"></frigate-card-icon>
|
||||
</div>
|
||||
<div class="contents">
|
||||
<span class="${classMap(classes)}">
|
||||
@@ -103,9 +104,11 @@ export class FrigateCardProgressIndicator extends LitElement {
|
||||
protected render(): TemplateResult {
|
||||
return html` <div class="message vertical">
|
||||
${this.animated
|
||||
? html`<ha-circular-progress active="true" size="${this.size}">
|
||||
? html`<ha-circular-progress indeterminate size="${this.size}">
|
||||
</ha-circular-progress>`
|
||||
: html`<ha-icon icon="mdi:timer-sand"></ha-icon>`}
|
||||
: html`<frigate-card-icon
|
||||
.icon=${{ icon: 'mdi:timer-sand' }}
|
||||
></frigate-card-icon>`}
|
||||
${this.message ? html`<span>${this.message}</span>` : html``}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { customElement, property, state } from 'lit/decorators.js';
|
||||
import { classMap } from 'lit/directives/class-map.js';
|
||||
import { NextPreviousControlConfig } from '../config/types.js';
|
||||
import controlStyle from '../scss/next-previous-control.scss';
|
||||
import { Icon } from '../types.js';
|
||||
import { renderTask } from '../utils/task.js';
|
||||
import { createFetchThumbnailTask } from '../utils/thumbnail.js';
|
||||
|
||||
@@ -29,7 +30,7 @@ export class FrigateCardNextPreviousControl extends LitElement {
|
||||
public thumbnail?: string;
|
||||
|
||||
@property({ attribute: false })
|
||||
public icon?: string;
|
||||
public icon?: Icon;
|
||||
|
||||
@property({ attribute: true, type: Boolean })
|
||||
public disabled = false;
|
||||
@@ -67,17 +68,14 @@ export class FrigateCardNextPreviousControl extends LitElement {
|
||||
|
||||
if (renderIcon) {
|
||||
const icon =
|
||||
!this.thumbnail ||
|
||||
!this.icon ||
|
||||
this._controlConfig.style === 'chevrons' ||
|
||||
this._thumbnailError
|
||||
? this.side === 'left'
|
||||
? 'mdi:chevron-left'
|
||||
: 'mdi:chevron-right'
|
||||
: this.icon;
|
||||
this.icon && !this._thumbnailError && this._controlConfig.style !== 'chevrons'
|
||||
? this.icon
|
||||
: this.side === 'left'
|
||||
? { icon: 'mdi:chevron-left' }
|
||||
: { icon: 'mdi:chevron-right' };
|
||||
|
||||
return html` <ha-icon-button class="${classMap(classes)}" .label=${this.label}>
|
||||
<ha-icon icon=${icon}></ha-icon>
|
||||
<frigate-card-icon .hass=${this.hass} .icon=${icon}></frigate-card-icon>
|
||||
</ha-icon-button>`;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import { Actions, PTZControlsConfig } from '../config/types.js';
|
||||
import { localize } from '../localize/localize.js';
|
||||
import ptzStyle from '../scss/ptz.scss';
|
||||
import { frigateCardHasAction } from '../utils/action.js';
|
||||
import './icon.js';
|
||||
|
||||
@customElement('frigate-card-ptz')
|
||||
export class FrigateCardPTZ extends LitElement {
|
||||
@@ -67,9 +68,9 @@ export class FrigateCardPTZ extends LitElement {
|
||||
};
|
||||
|
||||
return actions
|
||||
? html`<ha-icon
|
||||
? html`<frigate-card-icon
|
||||
class=${classMap(classes)}
|
||||
icon=${icon}
|
||||
.icon=${{ icon: icon }}
|
||||
.actionHandler=${actionHandler({
|
||||
hasHold: frigateCardHasAction(actions?.hold_action),
|
||||
hasDoubleClick: frigateCardHasAction(actions?.double_tap_action),
|
||||
@@ -77,7 +78,7 @@ export class FrigateCardPTZ extends LitElement {
|
||||
.title=${localize(`elements.ptz.${name}`)}
|
||||
@action=${(ev: HASSDomEvent<{ action: string }>) =>
|
||||
this._controller.handleAction(ev, actions)}
|
||||
></ha-icon>`
|
||||
></frigate-card-icon>`
|
||||
: html``;
|
||||
};
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import { StatusBarController } from '../components-lib/status-bar-controller';
|
||||
import { StatusBarConfig, StatusBarItem } from '../config/types';
|
||||
import statusStyle from '../scss/status.scss';
|
||||
import { frigateCardHasAction } from '../utils/action';
|
||||
import { getCustomIconURL } from '../utils/custom-icons.js';
|
||||
import './icon.js';
|
||||
|
||||
@customElement('frigate-card-status-bar')
|
||||
export class FrigateCardStatusBar extends LitElement {
|
||||
@@ -68,20 +68,12 @@ export class FrigateCardStatusBar extends LitElement {
|
||||
${item.string}
|
||||
</div>`;
|
||||
} else if (item.type === 'custom:frigate-card-status-bar-icon') {
|
||||
const customIconURL = getCustomIconURL(item.icon);
|
||||
return customIconURL
|
||||
? html`<img
|
||||
.actionHandler=${handler}
|
||||
class="${classes}"
|
||||
src="${customIconURL}"
|
||||
@action=${(ev) => this._controller.actionHandler(ev, item.actions)}
|
||||
/>`
|
||||
: html`<ha-icon
|
||||
.actionHandler=${handler}
|
||||
class="${classes}"
|
||||
icon="${item.icon}"
|
||||
@action=${(ev) => this._controller.actionHandler(ev, item.actions)}
|
||||
></ha-icon>`;
|
||||
return html`<frigate-card-icon
|
||||
.actionHandler=${handler}
|
||||
.icon=${{ icon: item.icon }}
|
||||
class="${classes}"
|
||||
@action=${(ev) => this._controller.actionHandler(ev, item.actions)}
|
||||
></frigate-card-icon>`;
|
||||
} else if (item.type === 'custom:frigate-card-status-bar-image') {
|
||||
return html`<img
|
||||
.actionHandler=${handler}
|
||||
|
||||
+40
-43
@@ -13,16 +13,21 @@ import { StyleInfo, styleMap } from 'lit/directives/style-map.js';
|
||||
import { actionHandler } from '../action-handler-directive.js';
|
||||
import { MenuSubmenu, MenuSubmenuItem, MenuSubmenuSelect } from '../config/types.js';
|
||||
import submenuStyle from '../scss/submenu.scss';
|
||||
import { StateParameters } from '../types.js';
|
||||
import {
|
||||
frigateCardHasAction,
|
||||
stopEventFromActivatingCardWideActions,
|
||||
} from '../utils/action.js';
|
||||
import { getCustomIconURL } from '../utils/custom-icons.js';
|
||||
import { isHassDifferent, refreshDynamicStateParameters } from '../utils/ha';
|
||||
import { getEntityTitle, isHassDifferent } from '../utils/ha';
|
||||
import { getEntityStateTranslation } from '../utils/ha/entity-state-translation.js';
|
||||
import { EntityRegistryManager } from '../utils/ha/registry/entity/index.js';
|
||||
import { domainIcon } from '../utils/icons/domain-icon.js';
|
||||
import './icon.js';
|
||||
import { Icon } from '../types.js';
|
||||
|
||||
interface ExtendedMenuSubmenu extends MenuSubmenu {
|
||||
// An internal version of a submenu that allows entity-based submenus (for
|
||||
// FrigateCardSubmenuSelect).
|
||||
icon: string | Icon;
|
||||
}
|
||||
|
||||
@customElement('frigate-card-submenu')
|
||||
export class FrigateCardSubmenu extends LitElement {
|
||||
@@ -30,47 +35,23 @@ export class FrigateCardSubmenu extends LitElement {
|
||||
public hass?: HomeAssistant;
|
||||
|
||||
@property({ attribute: false })
|
||||
public submenu?: MenuSubmenu;
|
||||
public submenu?: ExtendedMenuSubmenu;
|
||||
|
||||
protected _renderItem(item: MenuSubmenuItem): TemplateResult | void {
|
||||
if (!this.hass) {
|
||||
return;
|
||||
}
|
||||
const stateParameters = refreshDynamicStateParameters(this.hass, {
|
||||
...item,
|
||||
} as StateParameters);
|
||||
const getIcon = (stateParameters: StateParameters): TemplateResult => {
|
||||
if (stateParameters.icon) {
|
||||
const url = getCustomIconURL(stateParameters.icon);
|
||||
return url
|
||||
? html`<img
|
||||
style="${styleMap(stateParameters.style || {})}"
|
||||
data-domain=${ifDefined(stateParameters.data_domain)}
|
||||
data-state=${ifDefined(stateParameters.data_state)}
|
||||
slot="graphic"
|
||||
src=${url}
|
||||
/>`
|
||||
: html` <ha-icon
|
||||
style="${styleMap(stateParameters.style || {})}"
|
||||
data-domain=${ifDefined(stateParameters.data_domain)}
|
||||
data-state=${ifDefined(stateParameters.data_state)}
|
||||
slot="graphic"
|
||||
icon="${stateParameters.icon || ''}"
|
||||
>
|
||||
</ha-icon>`;
|
||||
}
|
||||
return html``;
|
||||
};
|
||||
|
||||
const title = item.title ?? getEntityTitle(this.hass, item.entity);
|
||||
return html`
|
||||
<mwc-list-item
|
||||
style="${styleMap(stateParameters.style || {})}"
|
||||
graphic=${ifDefined(stateParameters.icon ? 'icon' : undefined)}
|
||||
style="${styleMap(item.style || {})}"
|
||||
graphic=${ifDefined(item.icon || item.entity ? 'icon' : undefined)}
|
||||
?twoline=${!!item.subtitle}
|
||||
?selected=${item.selected}
|
||||
?activated=${item.selected}
|
||||
?disabled=${item.enabled === false}
|
||||
aria-label="${stateParameters.title || ''}"
|
||||
aria-label="${title ?? ''}"
|
||||
@action=${(ev) => {
|
||||
// Attach the action config so ascendants have access to it.
|
||||
ev.detail.config = item;
|
||||
@@ -80,9 +61,17 @@ export class FrigateCardSubmenu extends LitElement {
|
||||
hasDoubleClick: frigateCardHasAction(item.double_tap_action),
|
||||
})}
|
||||
>
|
||||
<span>${stateParameters.title || ''}</span>
|
||||
<span>${title ?? ''}</span>
|
||||
${item.subtitle ? html`<span slot="secondary">${item.subtitle}</span>` : ''}
|
||||
${getIcon(stateParameters)}
|
||||
<frigate-card-icon
|
||||
slot="graphic"
|
||||
.hass=${this.hass}
|
||||
.icon=${{
|
||||
icon: item.icon,
|
||||
entity: item.entity,
|
||||
}}
|
||||
style="${styleMap(item.style || {})}"
|
||||
></frigate-card-icon>
|
||||
</mwc-list-item>
|
||||
`;
|
||||
}
|
||||
@@ -118,7 +107,14 @@ export class FrigateCardSubmenu extends LitElement {
|
||||
hasDoubleClick: frigateCardHasAction(this.submenu.double_tap_action),
|
||||
})}
|
||||
>
|
||||
<ha-icon icon="${this.submenu.icon}"></ha-icon>
|
||||
<frigate-card-icon
|
||||
.hass=${this.hass}
|
||||
.icon=${typeof this.submenu.icon === 'string'
|
||||
? {
|
||||
icon: this.submenu.icon,
|
||||
}
|
||||
: this.submenu.icon}
|
||||
></frigate-card-icon>
|
||||
</ha-icon-button>
|
||||
${items.map(this._renderItem.bind(this))}
|
||||
</ha-button-menu>
|
||||
@@ -207,18 +203,19 @@ export class FrigateCardSubmenuSelect extends LitElement {
|
||||
return;
|
||||
}
|
||||
|
||||
const title = getEntityTitle(this.hass, entityID);
|
||||
const submenu: MenuSubmenu = {
|
||||
// Default icon. It should be impossible for this to be used, since
|
||||
// this.submenuSelect will always have an entity, which means
|
||||
// refreshDynamicStateParameters will always return an icon.
|
||||
icon: domainIcon('select'),
|
||||
|
||||
// Pull out the dynamic properties (like icon, and title) from the state.
|
||||
...refreshDynamicStateParameters(this.hass, this.submenuSelect as StateParameters),
|
||||
...(title && { title }),
|
||||
|
||||
// Override it with anything explicitly set in the submenuSelect.
|
||||
...this.submenuSelect,
|
||||
|
||||
icon: {
|
||||
icon: this.submenuSelect.icon,
|
||||
entity: entityID,
|
||||
fallback: 'mdi:format-list-bulleted',
|
||||
},
|
||||
|
||||
type: 'custom:frigate-card-menu-submenu',
|
||||
items: [],
|
||||
};
|
||||
|
||||
+49
-40
@@ -105,10 +105,10 @@ export class FrigateCardThumbnailFeatureThumbnail extends LitElement {
|
||||
}
|
||||
|
||||
protected render(): TemplateResult | void {
|
||||
const imageOff = html`<ha-icon
|
||||
icon="mdi:image-off"
|
||||
const imageOff = html`<frigate-card-icon
|
||||
.icon=${{ icon: 'mdi:image-off' }}
|
||||
title=${localize('thumbnail.no_thumbnail')}
|
||||
></ha-icon> `;
|
||||
></frigate-card-icon> `;
|
||||
|
||||
if (!this._embedThumbnailTask || this._thumbnailError) {
|
||||
return imageOff;
|
||||
@@ -150,8 +150,11 @@ export class FrigateCardThumbnailFeatureText extends LitElement {
|
||||
return;
|
||||
}
|
||||
return html`
|
||||
${this.cameraMetadata?.engineLogo
|
||||
? html`<img class="background" src="${this.cameraMetadata.engineLogo}" />`
|
||||
${this.cameraMetadata?.engineIcon
|
||||
? html`<frigate-card-icon
|
||||
class="background"
|
||||
.icon=${{ icon: this.cameraMetadata.engineIcon }}
|
||||
></frigate-card-icon>`
|
||||
: ''}
|
||||
<div class="content">
|
||||
<div class="title">${format(this.date, 'HH:mm')}</div>
|
||||
@@ -211,18 +214,18 @@ export class FrigateCardThumbnailDetailsEvent extends LitElement {
|
||||
<div class="details">
|
||||
${startTime
|
||||
? html` <div>
|
||||
<ha-icon
|
||||
<frigate-card-icon
|
||||
title=${localize('event.start')}
|
||||
.icon=${'mdi:calendar-clock-outline'}
|
||||
></ha-icon>
|
||||
.icon=${{ icon: 'mdi:calendar-clock-outline' }}
|
||||
></frigate-card-icon>
|
||||
<span title="${startTime}">${startTime}</span>
|
||||
</div>
|
||||
${duration || inProgress
|
||||
? html` <div>
|
||||
<ha-icon
|
||||
<frigate-card-icon
|
||||
title=${localize('event.duration')}
|
||||
.icon=${'mdi:clock-outline'}
|
||||
></ha-icon>
|
||||
.icon=${{ icon: 'mdi:clock-outline' }}
|
||||
></frigate-card-icon>
|
||||
${duration ? html`<span title="${duration}">${duration}</span>` : ''}
|
||||
${inProgress
|
||||
? html`<span title="${inProgress}">${inProgress}</span>`
|
||||
@@ -232,31 +235,37 @@ export class FrigateCardThumbnailDetailsEvent extends LitElement {
|
||||
: ''}
|
||||
${this.cameraTitle
|
||||
? html` <div>
|
||||
<ha-icon title=${localize('event.camera')} .icon=${'mdi:cctv'}></ha-icon>
|
||||
<frigate-card-icon
|
||||
title=${localize('event.camera')}
|
||||
.icon=${{ icon: 'mdi:cctv' }}
|
||||
></frigate-card-icon>
|
||||
<span title="${this.cameraTitle}">${this.cameraTitle}</span>
|
||||
</div>`
|
||||
: ''}
|
||||
${where
|
||||
? html` <div>
|
||||
<ha-icon
|
||||
<frigate-card-icon
|
||||
title=${localize('event.where')}
|
||||
.icon=${'mdi:map-marker-outline'}
|
||||
></ha-icon>
|
||||
.icon=${{ icon: 'mdi:map-marker-outline' }}
|
||||
></frigate-card-icon>
|
||||
<span title="${where}">${where}</span>
|
||||
</div>`
|
||||
: html``}
|
||||
${tags
|
||||
? html` <div>
|
||||
<ha-icon title=${localize('event.tag')} .icon=${'mdi:tag'}></ha-icon>
|
||||
<frigate-card-icon
|
||||
title=${localize('event.tag')}
|
||||
.icon=${{ icon: 'mdi:tag' }}
|
||||
></frigate-card-icon>
|
||||
<span title="${tags}">${tags}</span>
|
||||
</div>`
|
||||
: html``}
|
||||
${seek
|
||||
? html` <div>
|
||||
<ha-icon
|
||||
<frigate-card-icon
|
||||
title=${localize('event.seek')}
|
||||
.icon=${'mdi:clock-fast'}
|
||||
></ha-icon>
|
||||
.icon=${{ icon: 'mdi:clock-fast' }}
|
||||
></frigate-card-icon>
|
||||
<span title="${seek}">${seek}</span>
|
||||
</div>`
|
||||
: html``}
|
||||
@@ -306,18 +315,18 @@ export class FrigateCardThumbnailDetailsRecording extends LitElement {
|
||||
<div class="details">
|
||||
${startTime
|
||||
? html` <div>
|
||||
<ha-icon
|
||||
<frigate-card-icon
|
||||
title=${localize('recording.start')}
|
||||
.icon=${'mdi:calendar-clock-outline'}
|
||||
></ha-icon>
|
||||
.icon=${{ icon: 'mdi:calendar-clock-outline' }}
|
||||
></frigate-card-icon>
|
||||
<span title="${startTime}">${startTime}</span>
|
||||
</div>
|
||||
${duration || inProgress
|
||||
? html` <div>
|
||||
<ha-icon
|
||||
<frigate-card-icon
|
||||
title=${localize('recording.duration')}
|
||||
.icon=${'mdi:clock-outline'}
|
||||
></ha-icon>
|
||||
.icon=${{ icon: 'mdi:clock-outline' }}
|
||||
></frigate-card-icon>
|
||||
${duration ? html`<span title="${duration}">${duration}</span>` : ''}
|
||||
${inProgress
|
||||
? html`<span title="${inProgress}">${inProgress}</span>`
|
||||
@@ -327,19 +336,19 @@ export class FrigateCardThumbnailDetailsRecording extends LitElement {
|
||||
: ''}
|
||||
${seek
|
||||
? html` <div>
|
||||
<ha-icon
|
||||
<frigate-card-icon
|
||||
title=${localize('event.seek')}
|
||||
.icon=${'mdi:clock-fast'}
|
||||
></ha-icon>
|
||||
.icon=${{ icon: 'mdi:clock-fast' }}
|
||||
></frigate-card-icon>
|
||||
<span title="${seek}">${seek}</span>
|
||||
</div>`
|
||||
: html``}
|
||||
${eventCount !== null
|
||||
? html`<div>
|
||||
<ha-icon
|
||||
<frigate-card-icon
|
||||
title=${localize('recording.events')}
|
||||
.icon=${'mdi:shield-alert'}
|
||||
></ha-icon>
|
||||
.icon=${{ icon: 'mdi:shield-alert' }}
|
||||
></frigate-card-icon>
|
||||
<span title="${eventCount}">${eventCount}</span>
|
||||
</div>`
|
||||
: ``}
|
||||
@@ -448,10 +457,10 @@ export class FrigateCardThumbnail extends LitElement {
|
||||
></frigate-card-thumbnail-feature-text>`
|
||||
: html``}
|
||||
${shouldShowFavoriteControl
|
||||
? html` <ha-icon
|
||||
? html` <frigate-card-icon
|
||||
class="${classMap(starClasses)}"
|
||||
icon=${this.media.isFavorite() ? 'mdi:star' : 'mdi:star-outline'}
|
||||
title=${localize('thumbnail.retain_indefinitely')}
|
||||
.icon=${{ icon: this.media.isFavorite() ? 'mdi:star' : 'mdi:star-outline' }}
|
||||
@click=${async (ev: Event) => {
|
||||
stopEventFromActivatingCardWideActions(ev);
|
||||
if (this.hass && this.media) {
|
||||
@@ -467,7 +476,7 @@ export class FrigateCardThumbnail extends LitElement {
|
||||
this.requestUpdate();
|
||||
}
|
||||
}}
|
||||
/></ha-icon>`
|
||||
/></frigate-card-icon>`
|
||||
: ``}
|
||||
${this.details && ViewMediaClassifier.isEvent(this.media)
|
||||
? html`<frigate-card-thumbnail-details-event
|
||||
@@ -483,9 +492,9 @@ export class FrigateCardThumbnail extends LitElement {
|
||||
></frigate-card-thumbnail-details-recording>`
|
||||
: html``}
|
||||
${shouldShowTimelineControl
|
||||
? html`<ha-icon
|
||||
? html`<frigate-card-icon
|
||||
class="timeline"
|
||||
icon="mdi:target"
|
||||
.icon=${{ icon: 'mdi:target' }}
|
||||
title=${localize('thumbnail.timeline')}
|
||||
@click=${(ev: Event) => {
|
||||
stopEventFromActivatingCardWideActions(ev);
|
||||
@@ -503,12 +512,12 @@ export class FrigateCardThumbnail extends LitElement {
|
||||
modifiers: [new RemoveContextViewModifier(['timeline'])],
|
||||
});
|
||||
}}
|
||||
></ha-icon>`
|
||||
></frigate-card-icon>`
|
||||
: ''}
|
||||
${shouldShowDownloadControl
|
||||
? html` <ha-icon
|
||||
? html` <frigate-card-icon
|
||||
class="download"
|
||||
icon=${'mdi:download'}
|
||||
.icon=${{ icon: 'mdi:download' }}
|
||||
title=${localize('thumbnail.download')}
|
||||
@click=${async (ev: Event) => {
|
||||
stopEventFromActivatingCardWideActions(ev);
|
||||
@@ -520,7 +529,7 @@ export class FrigateCardThumbnail extends LitElement {
|
||||
}
|
||||
}
|
||||
}}
|
||||
></ha-icon>`
|
||||
></frigate-card-icon>`
|
||||
: ``}
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -69,6 +69,7 @@ import { MediaQueriesResults } from '../view/media-queries-results';
|
||||
import { mergeViewContext } from '../view/view';
|
||||
import './date-picker.js';
|
||||
import { DatePickerEvent, FrigateCardDatePicker } from './date-picker.js';
|
||||
import './icon';
|
||||
import './thumbnail.js';
|
||||
|
||||
interface FrigateCardGroupData {
|
||||
@@ -304,8 +305,8 @@ export class FrigateCardTimelineCore extends LitElement {
|
||||
>
|
||||
<div class="timeline-tools">
|
||||
${this._shouldSupportSeeking()
|
||||
? html` <ha-icon
|
||||
.icon=${panIcon}
|
||||
? html` <frigate-card-icon
|
||||
.icon=${{ icon: panIcon }}
|
||||
@click=${() => {
|
||||
this._panMode =
|
||||
panMode === 'pan'
|
||||
@@ -319,7 +320,7 @@ export class FrigateCardTimelineCore extends LitElement {
|
||||
aria-label="${panTitle}"
|
||||
title="${panTitle}"
|
||||
>
|
||||
</ha-icon>`
|
||||
</frigate-card-icon>`
|
||||
: ''}
|
||||
<frigate-card-date-picker
|
||||
${ref(this._refDatePicker)}
|
||||
|
||||
@@ -402,8 +402,11 @@ export class FrigateCardViewerCarousel extends LitElement {
|
||||
</frigate-card-ptz>`
|
||||
: ''}
|
||||
<div class="seek-warning">
|
||||
<ha-icon title="${localize('media_viewer.unseekable')}" icon="mdi:clock-remove">
|
||||
</ha-icon>
|
||||
<frigate-card-icon
|
||||
title="${localize('media_viewer.unseekable')}"
|
||||
.icon=${{ icon: 'mdi:clock-remove' }}
|
||||
>
|
||||
</frigate-card-icon>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user