Refactor aspect-ratio logic.

This commit is contained in:
Dermot Duffy
2022-05-23 21:15:31 -07:00
parent b92e7a6f80
commit f7da2c2793
2 changed files with 71 additions and 100 deletions
+58 -69
View File
@@ -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
View File
@@ -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;