diff --git a/src/card.ts b/src/card.ts
index c92c33b2..2a32c48c 100644
--- a/src/card.ts
+++ b/src/card.ts
@@ -963,10 +963,8 @@ export class FrigateCard extends LitElement {
* Get the most recent triggered camera.
*/
protected _getMostRecentTrigger(): string | null {
- const sorted = (
- [...this._triggers.entries()].sort(
- (a: [string, Date], b: [string, Date]) => b[1].getTime() - a[1].getTime(),
- )
+ const sorted = [...this._triggers.entries()].sort(
+ (a: [string, Date], b: [string, Date]) => b[1].getTime() - a[1].getTime(),
);
return sorted.length ? sorted[0][0] : null;
}
@@ -1009,7 +1007,10 @@ export class FrigateCard extends LitElement {
changedCamera = true;
} else {
const targetCamera = this._getMostRecentTrigger();
- if (targetCamera && (this._view.camera !== targetCamera || !this._view.is('live'))) {
+ if (
+ targetCamera &&
+ (this._view.camera !== targetCamera || !this._view.is('live'))
+ ) {
this._changeView({ view: new View({ view: 'live', camera: targetCamera }) });
changedCamera = true;
}
@@ -1510,21 +1511,21 @@ export class FrigateCard extends LitElement {
* required).
* @returns A padding percentage.
*/
- protected _getAspectRatioPadding(): number | null {
+ protected _getAspectRatioStyle(): string {
if (!this._isAspectRatioEnforced()) {
- return null;
+ return 'auto';
}
const aspectRatioMode = this._getConfig().dimensions.aspect_ratio_mode;
if (aspectRatioMode == 'dynamic' && this._mediaShowInfo) {
- return (this._mediaShowInfo.height / this._mediaShowInfo.width) * 100;
+ return `${this._mediaShowInfo.width} / ${this._mediaShowInfo.height}`;
}
const defaultAspectRatio = this._getConfig().dimensions.aspect_ratio;
if (defaultAspectRatio) {
- return (defaultAspectRatio[1] / defaultAspectRatio[0]) * 100;
+ return `${defaultAspectRatio[0]} / ${defaultAspectRatio[1]}`;
} else {
- return (9 / 16) * 100;
+ return '16 / 9';
}
}
@@ -1557,26 +1558,15 @@ export class FrigateCard extends LitElement {
return;
}
- const padding = this._getAspectRatioPadding();
- const outerStyle = {};
-
- // Padding to force a particular aspect ratio.
- if (padding != null) {
- outerStyle['padding-top'] = `${padding}%`;
- }
-
- const outerClasses = {
- container: true,
- outer: true,
+ const cardStyle = {
+ 'aspect-ratio': this._getAspectRatioStyle(),
+ };
+ const mainClasses = {
+ main: true,
triggered:
!!this._triggers.size && this._getConfig().view.scan.show_trigger_status,
};
- const contentClasses = {
- 'frigate-card-contents': true,
- absolute: padding != null,
- };
-
const actions = this._getMergedActions();
const renderMenuAbove =
this._getConfig().menu.style === 'outside' &&
@@ -1587,6 +1577,7 @@ export class FrigateCard extends LitElement {
hasHold: frigateCardHasAction(actions.hold_action),
hasDoubleClick: frigateCardHasAction(actions.double_tap_action),
})}
+ style="${styleMap(cardStyle)}"
@action=${(ev: CustomEvent) => this._actionHandler(ev, actions)}
@ll-custom=${this._cardActionHandler.bind(this)}
@frigate-card:message=${this._messageHandler}
@@ -1595,49 +1586,47 @@ export class FrigateCard extends LitElement {
@frigate-card:render=${() => this.requestUpdate()}
>
${renderMenuAbove ? this._renderMenu() : ''}
-
-
- ${this._cameras === undefined
- ? until(
- (async () => {
- await this._loadCameras();
- // Don't reset messages as errors may have been generated
- // during the camera load.
- this._changeView({ resetMessage: false });
- return this._render();
- })(),
- renderProgressIndicator(),
- )
- : // Always want to call render even if there's a message, to
- // ensure live preload is always present (even if not displayed).
- this._render()}
- ${this._getConfig().elements
- ? // Always show elements to allow for custom menu items (etc.) to
- // be present even if a particular view has an error. Elements
- // need to render after the main views so it can render 'on top'.
- html` {
- this._addDynamicMenuButton(e.detail);
- }}
- @frigate-card:menu-remove=${(e) => {
- this._removeDynamicMenuButton(e.detail);
- }}
- @frigate-card:condition-state-request=${(ev) => {
- conditionStateRequestHandler(ev, this._conditionState);
- }}
- >
- `
- : ``}
- ${
- // Keep message rendering to last to show messages that may have
- // been generated during the render.
- this._message ? renderMessage(this._message) : ''
- }
-
+
+ ${this._cameras === undefined
+ ? until(
+ (async () => {
+ await this._loadCameras();
+ // Don't reset messages as errors may have been generated
+ // during the camera load.
+ this._changeView({ resetMessage: false });
+ return this._render();
+ })(),
+ renderProgressIndicator(),
+ )
+ : // Always want to call render even if there's a message, to
+ // ensure live preload is always present (even if not displayed).
+ this._render()}
+ ${this._getConfig().elements
+ ? // Always show elements to allow for custom menu items (etc.) to
+ // be present even if a particular view has an error. Elements
+ // need to render after the main views so it can render 'on top'.
+ html` {
+ this._addDynamicMenuButton(e.detail);
+ }}
+ @frigate-card:menu-remove=${(e) => {
+ this._removeDynamicMenuButton(e.detail);
+ }}
+ @frigate-card:condition-state-request=${(ev) => {
+ conditionStateRequestHandler(ev, this._conditionState);
+ }}
+ >
+ `
+ : ``}
+ ${
+ // Keep message rendering to last to show messages that may have
+ // been generated during the render.
+ this._message ? renderMessage(this._message) : ''
+ }
${!renderMenuAbove ? this._renderMenu() : ''}
`;
diff --git a/src/scss/card.scss b/src/scss/card.scss
index 989b85f9..f3ccbbdd 100644
--- a/src/scss/card.scss
+++ b/src/scss/card.scss
@@ -9,21 +9,31 @@
filter: brightness(50%);
}
-.container {
+div.main {
position: relative;
overflow: auto;
width: 100%;
height: 100%;
margin: auto;
display: flex;
+ align-items: center;
justify-content: center;
// Need to apply the border radius on the container level, as the ha-card has
// overflow visible in order to allow a submenu to extend beyond the card
// boundary.
border-radius: var(--ha-card-border-radius, 4px);
+
+ // Include the borders in the sizing (to keep the triggered warning pulse
+ // visible in fullscreen).
+ box-sizing: border-box;
+
+ // Hide scrollbar: Firefox
+ scrollbar-width: none;
+ // Hide scrollbar: IE and Edge
+ -ms-overflow-style: none;
}
-.container.triggered {
+div.main.triggered {
@keyframes warning-pulse {
0% {
border: solid 1px rgba(0,0,0,0);
@@ -38,39 +48,11 @@
animation: warning-pulse 5s infinite;
}
-.frigate-card-contents {
- width: inherit;
- height: inherit;
- margin: auto;
- overflow: auto;
- display: flex;
- align-items: center;
- justify-content: center;
-
- // Include the borders in the sizing (to keep the triggered warning pulse
- // visible in fullscreen).
- box-sizing: border-box;
-
- // Hide scrollbar: Firefox
- scrollbar-width: none;
- // Hide scrollbar: IE and Edge
- -ms-overflow-style: none;
-}
-
/* Hide scrollbar for Chrome, Safari and Opera */
-.frigate-card-contents::-webkit-scrollbar {
+div.main::-webkit-scrollbar {
display: none;
}
-/* When forcing aspect ratio absolute positioning is required */
-.frigate-card-contents.absolute {
- position: absolute;
- top: 0px;
- right: 0px;
- bottom: 0px;
- left: 0px;
-}
-
/* The 'hover' menu mode is styling applied outside of the menu itself */
frigate-card-menu[data-style='hover'] {
z-index: 1;