Allow per-camera trigger borders.

This commit is contained in:
Dermot Duffy
2024-01-23 20:56:30 -08:00
parent 64a909ead0
commit 06f2151bab
8 changed files with 45 additions and 28 deletions
+1 -1
View File
@@ -433,7 +433,7 @@ Scan mode tracks Home Assistant state *changes* -- when the card is first starte
| - | - | - | - | | - | - | - | - |
| `enabled` | `false` | :white_check_mark: | Whether to enable scan mode. | | `enabled` | `false` | :white_check_mark: | Whether to enable scan mode. |
| `filter_selected_camera` | `false` | :white_check_mark: | If set to `true` will only trigger on the currently selected camera.| | `filter_selected_camera` | `false` | :white_check_mark: | If set to `true` will only trigger on the currently selected camera.|
| `show_trigger_status` | `true` | :white_check_mark: | Whether or not the card should show a visual indication that it is triggered (a pulsing border around the card edge). | | `show_trigger_status` | `true` | :white_check_mark: | Whether or not the `live` view should show a visual indication that it is triggered (a pulsing border around the camera edge). |
| `untrigger_seconds` | `0` | :white_check_mark: | The number of seconds to wait after all entities are inactive before untriggering. | | `untrigger_seconds` | `0` | :white_check_mark: | The number of seconds to wait after all entities are inactive before untriggering. |
| `actions` | | :white_check_mark: | The actions to take when scan mode triggers (see below). | | `actions` | | :white_check_mark: | The actions to take when scan mode triggers (see below). |
+3 -6
View File
@@ -238,11 +238,6 @@ class FrigateCard extends LitElement {
const cardStyle = { const cardStyle = {
'aspect-ratio': this._controller.getStyleManager().getAspectRatioStyle(), 'aspect-ratio': this._controller.getStyleManager().getAspectRatioStyle(),
}; };
const cardClasses = {
triggered:
!!this._controller.getTriggersManager().isTriggered() &&
!!this._config?.view.scan.show_trigger_status,
};
const mainClasses = { const mainClasses = {
main: true, main: true,
'curve-top': 'curve-top':
@@ -264,7 +259,6 @@ class FrigateCard extends LitElement {
hasHold: frigateCardHasAction(actions.hold_action), hasHold: frigateCardHasAction(actions.hold_action),
hasDoubleClick: frigateCardHasAction(actions.double_tap_action), hasDoubleClick: frigateCardHasAction(actions.double_tap_action),
})} })}
class="${classMap(cardClasses)}"
style="${styleMap(cardStyle)}" style="${styleMap(cardStyle)}"
@frigate-card:message=${(ev: CustomEvent<Message>) => @frigate-card:message=${(ev: CustomEvent<Message>) =>
this._controller.getMessageManager().setMessageIfHigherPriority(ev.detail)} this._controller.getMessageManager().setMessageIfHigherPriority(ev.detail)}
@@ -313,6 +307,9 @@ class FrigateCard extends LitElement {
?.getEpoch()} ?.getEpoch()}
.hide=${!!this._controller.getMessageManager().hasMessage()} .hide=${!!this._controller.getMessageManager().hasMessage()}
.microphoneStream=${this._controller.getMicrophoneManager()?.getStream()} .microphoneStream=${this._controller.getMicrophoneManager()?.getStream()}
.triggeredCameraIDs=${this._config?.view.scan.show_trigger_status
? this._controller.getTriggersManager().getTriggeredCameraIDs()
: undefined}
></frigate-card-views>`} ></frigate-card-views>`}
${ ${
// Keep message rendering to last to show messages that may have been // Keep message rendering to last to show messages that may have been
+13 -1
View File
@@ -31,6 +31,7 @@ import {
import { localize } from '../../localize/localize.js'; import { localize } from '../../localize/localize.js';
import basicBlockStyle from '../../scss/basic-block.scss'; import basicBlockStyle from '../../scss/basic-block.scss';
import liveCarouselStyle from '../../scss/live-carousel.scss'; import liveCarouselStyle from '../../scss/live-carousel.scss';
import liveGridStyle from '../../scss/live-grid.scss';
import liveProviderStyle from '../../scss/live-provider.scss'; import liveProviderStyle from '../../scss/live-provider.scss';
import { import {
ExtendedHomeAssistant, ExtendedHomeAssistant,
@@ -114,6 +115,9 @@ export class FrigateCardLive extends LitElement {
@property({ attribute: false }) @property({ attribute: false })
public microphoneStream?: MediaStream; public microphoneStream?: MediaStream;
@property({ attribute: false })
public triggeredCameraIDs?: Set<string>;
// Whether or not the live view is currently in the background (i.e. preloaded // Whether or not the live view is currently in the background (i.e. preloaded
// but not visible) // but not visible)
@state() @state()
@@ -219,6 +223,7 @@ export class FrigateCardLive extends LitElement {
.cardWideConfig=${this.cardWideConfig} .cardWideConfig=${this.cardWideConfig}
.cameraManager=${this.cameraManager} .cameraManager=${this.cameraManager}
.microphoneStream=${this.microphoneStream} .microphoneStream=${this.microphoneStream}
.triggeredCameraIDs=${this.triggeredCameraIDs}
@frigate-card:message=${(ev: CustomEvent<Message>) => { @frigate-card:message=${(ev: CustomEvent<Message>) => {
this._renderKey++; this._renderKey++;
this._messageReceivedPostRender = true; this._messageReceivedPostRender = true;
@@ -283,7 +288,12 @@ export class FrigateCardLiveGrid extends LitElement {
@property({ attribute: false }) @property({ attribute: false })
public microphoneStream?: MediaStream; public microphoneStream?: MediaStream;
@property({ attribute: false })
public triggeredCameraIDs?: Set<string>;
protected _renderCarousel(cameraID?: string): TemplateResult { protected _renderCarousel(cameraID?: string): TemplateResult {
const triggeredCameraID = cameraID ?? this.view?.camera;
return html` return html`
<frigate-card-live-carousel <frigate-card-live-carousel
grid-id=${ifDefined(cameraID)} grid-id=${ifDefined(cameraID)}
@@ -297,6 +307,8 @@ export class FrigateCardLiveGrid extends LitElement {
.cardWideConfig=${this.cardWideConfig} .cardWideConfig=${this.cardWideConfig}
.cameraManager=${this.cameraManager} .cameraManager=${this.cameraManager}
.microphoneStream=${this.microphoneStream} .microphoneStream=${this.microphoneStream}
?triggered=${triggeredCameraID &&
!!this.triggeredCameraIDs?.has(triggeredCameraID)}
> >
</frigate-card-live-carousel> </frigate-card-live-carousel>
`; `;
@@ -351,7 +363,7 @@ export class FrigateCardLiveGrid extends LitElement {
} }
static get styles(): CSSResultGroup { static get styles(): CSSResultGroup {
return unsafeCSS(basicBlockStyle); return unsafeCSS(liveGridStyle);
} }
} }
+2 -1
View File
@@ -43,6 +43,7 @@ export class FrigateCardThumbnailCarousel extends LitElement {
public fadeThumbnails = false; public fadeThumbnails = false;
protected _thumbnailSlides: TemplateResult[] = []; protected _thumbnailSlides: TemplateResult[] = [];
protected _plugins = [AutoSize()];
protected willUpdate(changedProps: PropertyValues): void { protected willUpdate(changedProps: PropertyValues): void {
if (changedProps.has('config')) { if (changedProps.has('config')) {
@@ -137,7 +138,7 @@ export class FrigateCardThumbnailCarousel extends LitElement {
return html`<frigate-card-carousel return html`<frigate-card-carousel
direction=${direction} direction=${direction}
.plugins=${[AutoSize()]} .plugins=${this._plugins}
.selected=${this._getSelectedSlide() ?? 0} .selected=${this._getSelectedSlide() ?? 0}
.dragFree=${true} .dragFree=${true}
> >
+4
View File
@@ -62,6 +62,9 @@ export class FrigateCardViews extends LitElement {
@property({ attribute: false }) @property({ attribute: false })
public microphoneStream?: MediaStream; public microphoneStream?: MediaStream;
@property({ attribute: false })
public triggeredCameraIDs?: Set<string>;
protected willUpdate(changedProps: PropertyValues): void { protected willUpdate(changedProps: PropertyValues): void {
if (changedProps.has('view') || changedProps.has('config')) { if (changedProps.has('view') || changedProps.has('config')) {
if (this.view?.is('live') || this._shouldLivePreload()) { if (this.view?.is('live') || this._shouldLivePreload()) {
@@ -239,6 +242,7 @@ export class FrigateCardViews extends LitElement {
.cameraManager=${this.cameraManager} .cameraManager=${this.cameraManager}
.cardWideConfig=${this.cardWideConfig} .cardWideConfig=${this.cardWideConfig}
.microphoneStream=${this.microphoneStream} .microphoneStream=${this.microphoneStream}
.triggeredCameraIDs=${this.triggeredCameraIDs}
class="${classMap(liveClasses)}" class="${classMap(liveClasses)}"
> >
</frigate-card-live> </frigate-card-live>
+1 -19
View File
@@ -21,7 +21,7 @@
// The standard HA header is 56 pixels tall, so that much off the top (header) // The standard HA header is 56 pixels tall, so that much off the top (header)
// and bottom (to maintain center), before doing the calculation of // and bottom (to maintain center), before doing the calculation of
// max-height. This matters on small mobile devices in landscape orientation. // max-height. This matters on small mobile devices in landscape orientation.
--frigate-card-expand-max-height: calc( ( 100vh - (2 * 56px) ) * 0.85 ); --frigate-card-expand-max-height: calc((100vh - (2 * 56px)) * 0.85);
--frigate-card-expand-max-width: 85vw; --frigate-card-expand-max-width: 85vw;
--frigate-card-expand-width: none; --frigate-card-expand-width: none;
--frigate-card-expand-height: none; --frigate-card-expand-height: none;
@@ -52,10 +52,6 @@ div.main {
// Necessary to get Safari to show border-radius correctly. // Necessary to get Safari to show border-radius correctly.
transform: translateZ(0); transform: translateZ(0);
// Include the borders in the sizing (to keep the triggered warning pulse
// visible in fullscreen).
box-sizing: border-box;
// Hide scrollbar: Firefox // Hide scrollbar: Firefox
scrollbar-width: none; scrollbar-width: none;
// Hide scrollbar: IE and Edge // Hide scrollbar: IE and Edge
@@ -112,20 +108,6 @@ ha-card {
position: static; position: static;
color: var(--secondary-text-color, white); color: var(--secondary-text-color, white);
} }
ha-card.triggered {
@keyframes warning-pulse {
0% {
border: solid 2px rgba(0, 0, 0, 0);
}
50% {
border: solid 2px var(--warning-color);
}
100% {
border: solid 2px rgba(0, 0, 0, 0);
}
}
animation: warning-pulse 5s infinite;
}
/************ /************
* Fullscreen * Fullscreen
+1
View File
@@ -1,4 +1,5 @@
:host { :host {
display: block;
--video-max-height: none; --video-max-height: none;
} }
+20
View File
@@ -0,0 +1,20 @@
@use 'basic-block.scss';
@keyframes warning-pulse {
0% {
border: solid 2px var(--frigate-card-triggered-color-1, rgba(0, 0, 0, 0));
}
50% {
border: solid 2px var(--frigate-card-triggered-color-2, var(--warning-color));
}
100% {
border: solid 2px var(--frigate-card-triggered-color-1, rgba(0, 0, 0, 0));
}
}
frigate-card-live-carousel[triggered] {
animation: warning-pulse 5s infinite;
}
frigate-card-live-carousel[selected] {
--frigate-card-triggered-color-1: var(--primary-color);
}