Viewer fixes to avoid resetting carousel when not necessary.

This commit is contained in:
Dermot Duffy
2022-01-16 15:53:54 -08:00
parent 6fadc862e3
commit 0e8b40f648
5 changed files with 42 additions and 27 deletions
+8 -1
View File
@@ -43,6 +43,7 @@ import { FrigateCardElements } from './components/elements.js';
import { FRIGATE_BUTTON_MENU_ICON, FrigateCardMenu } from './components/menu.js'; import { FRIGATE_BUTTON_MENU_ICON, FrigateCardMenu } from './components/menu.js';
import { View } from './view.js'; import { View } from './view.js';
import { import {
contentsChanged,
convertActionToFrigateCardCustomAction, convertActionToFrigateCardCustomAction,
createFrigateCardCustomAction, createFrigateCardCustomAction,
getActionConfigGivenAction, getActionConfigGivenAction,
@@ -231,11 +232,17 @@ export class FrigateCard extends LitElement {
camera: this._view?.camera, camera: this._view?.camera,
}; };
this._overriddenConfig = getOverriddenConfig( const overriddenConfig = getOverriddenConfig(
this._baseConfig, this._baseConfig,
this._baseConfig.overrides, this._baseConfig.overrides,
this._conditionState, this._conditionState,
) as FrigateCardConfig; ) as FrigateCardConfig;
// Save on Lit re-rendering costs by only updating the configuration if it
// actually changes.
if (contentsChanged(overriddenConfig, this._overriddenConfig)) {
this._overriddenConfig = overriddenConfig;
}
} }
/** /**
+13
View File
@@ -2,6 +2,7 @@ import { HassEntity, MessageBase } from 'home-assistant-js-websocket';
import { HomeAssistant, stateIcon } from 'custom-card-helpers'; import { HomeAssistant, stateIcon } from 'custom-card-helpers';
import { StyleInfo } from 'lit/directives/style-map'; import { StyleInfo } from 'lit/directives/style-map';
import { ZodSchema, z } from 'zod'; import { ZodSchema, z } from 'zod';
import { isEqual } from 'lodash-es';
import { localize } from './localize/localize.js'; import { localize } from './localize/localize.js';
import { import {
@@ -483,3 +484,15 @@ export function arrayMove(target: unknown[], from: number, to: number): void {
target.splice(from, 1); target.splice(from, 1);
target.splice(to, 0, element); target.splice(to, 0, element);
} }
/**
* Determine if the contents of the n(ew) and o(ld) values have changed. For use
* in lit web components that may have a value that changes address but not
* contents -- and for which a re-render is expensive/jarring.
* @param n The new value.
* @param o The old value.
* @returns `true` is the contents have changed.
*/
export function contentsChanged(n: unknown, o: unknown): boolean {
return !isEqual(n, o);
}
+7 -23
View File
@@ -1,4 +1,3 @@
// TODO use the schema default remover code to simplify config schema
// TODO in fullscreen mode on live view with mixed cameras, center video // TODO in fullscreen mode on live view with mixed cameras, center video
// TODO verify README links worked correctly (e.g. basic cameras configuration) // TODO verify README links worked correctly (e.g. basic cameras configuration)
@@ -26,7 +25,6 @@ import {
import { EmblaOptionsType } from 'embla-carousel'; import { EmblaOptionsType } from 'embla-carousel';
import { HomeAssistant } from 'custom-card-helpers'; import { HomeAssistant } from 'custom-card-helpers';
import { customElement, property, state } from 'lit/decorators.js'; import { customElement, property, state } from 'lit/decorators.js';
import { isEqual } from 'lodash-es';
import { ref } from 'lit/directives/ref'; import { ref } from 'lit/directives/ref';
import { until } from 'lit/directives/until.js'; import { until } from 'lit/directives/until.js';
@@ -38,6 +36,7 @@ import { ThumbnailCarouselTap } from './thumbnail-carousel.js';
import { View } from '../view.js'; import { View } from '../view.js';
import { localize } from '../localize/localize.js'; import { localize } from '../localize/localize.js';
import { import {
contentsChanged,
dispatchErrorMessageEvent, dispatchErrorMessageEvent,
dispatchExistingMediaShowInfoAsEvent, dispatchExistingMediaShowInfoAsEvent,
dispatchMediaShowEvent, dispatchMediaShowEvent,
@@ -518,7 +517,7 @@ export class FrigateCardLiveProvider extends LitElement {
// Label that is used for ARIA support and as tooltip. // Label that is used for ARIA support and as tooltip.
@property({ attribute: false }) @property({ attribute: false })
public label = ""; public label = '';
protected _getResolvedProvider(): LiveProvider { protected _getResolvedProvider(): LiveProvider {
if (this.cameraConfig?.live_provider === 'auto') { if (this.cameraConfig?.live_provider === 'auto') {
@@ -531,7 +530,9 @@ export class FrigateCardLiveProvider extends LitElement {
} }
return frigateCardConfigDefaults.cameras.live_provider; return frigateCardConfigDefaults.cameras.live_provider;
} }
return this.cameraConfig?.live_provider || frigateCardConfigDefaults.cameras.live_provider; return (
this.cameraConfig?.live_provider || frigateCardConfigDefaults.cameras.live_provider
);
} }
/** /**
@@ -618,18 +619,7 @@ export class FrigateCardLiveFrigate extends LitElement {
// - https://github.com/AlexxIT/WebRTC // - https://github.com/AlexxIT/WebRTC
@customElement('frigate-card-live-webrtc') @customElement('frigate-card-live-webrtc')
export class FrigateCardLiveWebRTC extends LitElement { export class FrigateCardLiveWebRTC extends LitElement {
@property({ @property({ attribute: false, hasChanged: contentsChanged })
attribute: false,
// Resetting the WebRTC/JSMPEG configuration is expensive as the connections
// need to be re-established. These configurations may be overridden which
// creates semantically equal configurations at different addresses --
// ensure LIT only considers the property as having changed if it's actually
// different.
hasChanged(n: WebRTCConfig, o: WebRTCConfig): boolean {
return !isEqual(n, o);
},
})
protected webRTCConfig?: WebRTCConfig; protected webRTCConfig?: WebRTCConfig;
@property({ attribute: false }) @property({ attribute: false })
@@ -734,13 +724,7 @@ export class FrigateCardLiveJSMPEG extends LitElement {
@property({ attribute: false }) @property({ attribute: false })
protected cameraConfig?: CameraConfig; protected cameraConfig?: CameraConfig;
@property({ @property({ attribute: false, hasChanged: contentsChanged })
attribute: false,
// See note under FrigateCardLiveWebRTC.
hasChanged(n: JSMPEGConfig, o: JSMPEGConfig): boolean {
return !isEqual(n, o);
},
})
protected jsmpegConfig?: JSMPEGConfig; protected jsmpegConfig?: JSMPEGConfig;
protected hass?: HomeAssistant & ExtendedHomeAssistant; protected hass?: HomeAssistant & ExtendedHomeAssistant;
+9 -3
View File
@@ -31,7 +31,7 @@ import {
} from './thumbnail-carousel.js'; } from './thumbnail-carousel.js';
import { ResolvedMediaCache, ResolvedMediaUtil } from '../resolved-media.js'; import { ResolvedMediaCache, ResolvedMediaUtil } from '../resolved-media.js';
import { View } from '../view.js'; import { View } from '../view.js';
import { createMediaShowInfo, dispatchErrorMessageEvent } from '../common.js'; import { contentsChanged, createMediaShowInfo, dispatchErrorMessageEvent } from '../common.js';
import { renderProgressIndicator } from '../components/message.js'; import { renderProgressIndicator } from '../components/message.js';
import './next-prev-control.js'; import './next-prev-control.js';
@@ -111,7 +111,8 @@ export class FrigateCardViewerCore extends LitElement {
@property({ attribute: false }) @property({ attribute: false })
protected view?: Readonly<View>; protected view?: Readonly<View>;
@property({ attribute: false }) // See note on viewerConfig in <frigate-card-viewer-carousel>.
@property({ attribute: false, hasChanged: contentsChanged })
protected viewerConfig?: ViewerConfig; protected viewerConfig?: ViewerConfig;
@property({ attribute: false }) @property({ attribute: false })
@@ -186,7 +187,12 @@ export class FrigateCardViewerCarousel extends FrigateCardMediaCarousel {
@property({ attribute: false }) @property({ attribute: false })
protected view?: Readonly<View>; protected view?: Readonly<View>;
@property({ attribute: false }) // Resetting the viewer configuration causes a full reset so ensure the config
// has actually changed with a full comparison (dynamic configuration
// overrides may causes changes elsewhere in the full card configuration that
// could lead to the address of the viewerConfig changing without it being
// semantically different).
@property({ attribute: false, hasChanged: contentsChanged })
protected viewerConfig?: ViewerConfig; protected viewerConfig?: ViewerConfig;
@property({ attribute: false }) @property({ attribute: false })
+5
View File
@@ -33,6 +33,11 @@ img,video {
width: 100%; width: 100%;
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;
// Center vertically in the viewport.
display: flex;
flex-direction: column;
justify-content: center;
} }
.embla__viewport.is-draggable { .embla__viewport.is-draggable {
cursor: move; cursor: move;