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