diff --git a/src/cached-value-controller.ts b/src/cached-value-controller.ts index 1022c46d..9e39e06d 100644 --- a/src/cached-value-controller.ts +++ b/src/cached-value-controller.ts @@ -17,6 +17,7 @@ export class CachedValueController implements ReactiveController { * Remove the controller for the host. */ public removeController(): void { + this.stopTimer(); this._host.removeController(this); } diff --git a/src/card.ts b/src/card.ts index 1776ed2e..c623130b 100644 --- a/src/card.ts +++ b/src/card.ts @@ -1602,6 +1602,10 @@ export class FrigateCard extends LitElement { if (!this._message || newPriority >= currentPriority) { this._message = message; + + // When a message is displayed it is effectively unloading the media. + this._mediaUnloadedHandler(); + if (!skipUpdate) { this.requestUpdate(); this._resetMainScroll(); @@ -1646,6 +1650,14 @@ export class FrigateCard extends LitElement { this.requestUpdate(); } + /** + * Unload a media item. + */ + protected _mediaUnloadedHandler(): void { + this._currentMediaLoadedInfo = null; + this._generateConditionState(); + } + /** * Handler called when fullscreen is toggled. */ @@ -1672,6 +1684,9 @@ export class FrigateCard extends LitElement { * Component disconnected callback. */ disconnectedCallback(): void { + // When the dashboard 'tab' is changed, the media is effectively unloaded. + this._mediaUnloadedHandler(); + if (screenfull.isEnabled) { screenfull.off('change', this._fullscreenHandler.bind(this)); } @@ -1797,6 +1812,7 @@ export class FrigateCard extends LitElement { @frigate-card:view:change=${this._changeViewHandler.bind(this)} @frigate-card:view:change-context=${this._addViewContextHandler.bind(this)} @frigate-card:media:loaded=${this._mediaLoadedHandler.bind(this)} + @frigate-card:media:unloaded=${this._mediaUnloadedHandler.bind(this)} @frigate-card:render=${() => this.requestUpdate()} > ${renderMenuAbove ? this._renderMenu() : ''} diff --git a/src/components/image.ts b/src/components/image.ts index b1ffb6f8..a8f5a743 100644 --- a/src/components/image.ts +++ b/src/components/image.ts @@ -21,8 +21,9 @@ import { updateElementStyleFromMediaLayoutConfig } from '../utils/media-layout.j import { dispatchMediaLoadedEvent } from '../utils/media-info.js'; import { View } from '../view.js'; import { dispatchErrorMessageEvent } from './message.js'; +import { contentsChanged } from '../utils/basic.js'; -// See: https://github.com/home-assistant/core/blob/dev/homeassistant/components/camera/__init__.py#L101 +// See TOKEN_CHANGE_INTERVAL in https://github.com/home-assistant/core/blob/dev/homeassistant/components/camera/__init__.py . const HASS_REJECTION_CUTOFF_MS = 5 * 60 * 1000; @customElement('frigate-card-image') @@ -36,7 +37,10 @@ export class FrigateCardImage extends LitElement { @property({ attribute: false }) public cameraConfig?: CameraConfig; - @property({ attribute: false }) + // Using contentsChanged to ensure overridden configs (e.g. when the + // 'show_image_during_load' option is true for live views, an overridden + // config may be used here). + @property({ attribute: false, hasChanged: contentsChanged }) public imageConfig?: ImageViewConfig; protected _refImage: Ref = createRef(); diff --git a/src/components/live.ts b/src/components/live.ts index bb8fbbb5..9b67c980 100644 --- a/src/components/live.ts +++ b/src/components/live.ts @@ -106,7 +106,7 @@ export class FrigateCardLive extends LitElement { // MediaLoadedInfo object and message from the underlying live object. In the // case of pre-loading these may be propagated upwards later. - protected _savedMediaLoadedInfo: MediaLoadedInfo | null = null; + protected _backgroundMediaLoadedInfo: MediaLoadedInfo | null = null; protected _messageReceivedPostRender = false; protected _renderKey = 0; @@ -127,11 +127,12 @@ export class FrigateCardLive extends LitElement { if ( !this._inBackground && !this._messageReceivedPostRender && - this._savedMediaLoadedInfo + this._backgroundMediaLoadedInfo ) { // If this isn't being rendered in the background, the last render did not // generate a message and there's a saved MediaInfo, dispatch it upwards. - dispatchExistingMediaLoadedInfoAsEvent(this, this._savedMediaLoadedInfo); + dispatchExistingMediaLoadedInfoAsEvent(this, this._backgroundMediaLoadedInfo); + this._backgroundMediaLoadedInfo = null; } // Trigger a re-render which may be necessary if the prior render resulted @@ -223,8 +224,8 @@ export class FrigateCardLive extends LitElement { } }} @frigate-card:media:loaded=${(ev: CustomEvent) => { - this._savedMediaLoadedInfo = ev.detail; if (this._inBackground) { + this._backgroundMediaLoadedInfo = ev.detail; ev.stopPropagation(); } }} @@ -735,6 +736,13 @@ export class FrigateCardLiveProvider extends LitElement { ); } + /** + * Component disconnected callback. + */ + disconnectedCallback(): void { + this._isVideoMediaLoaded = false; + } + /** * Record that video media is being shown. */ diff --git a/src/components/media-carousel.ts b/src/components/media-carousel.ts index d4192897..8f7c7280 100644 --- a/src/components/media-carousel.ts +++ b/src/components/media-carousel.ts @@ -293,6 +293,7 @@ export class FrigateCardMediaCarousel extends LitElement { this._resizeObserver.disconnect(); this._intersectionObserver.disconnect(); + this._mediaLoadedInfo = {}; super.disconnectedCallback(); }