Reset the carousel of the plugins/options change.
This commit is contained in:
@@ -65,6 +65,21 @@ export class FrigateCardCarousel extends LitElement {
|
||||
super.disconnectedCallback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the carousel if certain properties change.
|
||||
* @param changedProps The changed properties
|
||||
*/
|
||||
protected willUpdate(changedProps: PropertyValues): void {
|
||||
const destroyProperties = [
|
||||
'direction',
|
||||
'carouselOptions',
|
||||
'carouselOptions',
|
||||
] as const;
|
||||
if (destroyProperties.some((prop) => changedProps.has(prop))) {
|
||||
this._destroyCarousel();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scroll to a particular slide.
|
||||
* @param index Slide number.
|
||||
@@ -193,6 +208,10 @@ export class FrigateCardCarousel extends LitElement {
|
||||
index: selected,
|
||||
});
|
||||
}
|
||||
|
||||
// Make sure every select causes a refresh to allow for re-paint of the
|
||||
// next/previous controls.
|
||||
this.requestUpdate();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,6 @@ export class FrigateCardImage extends LitElement {
|
||||
* Ensure there is a cached value before an update.
|
||||
* @param _changedProps The changed properties
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
protected willUpdate(changedProps: PropertyValues): void {
|
||||
if (changedProps.has('imageConfig')) {
|
||||
if (this._cachedValueController) {
|
||||
|
||||
+30
-33
@@ -1,7 +1,7 @@
|
||||
import JSMpeg from '@cycjimmy/jsmpeg-player';
|
||||
import { Task } from '@lit-labs/task';
|
||||
import { HomeAssistant } from 'custom-card-helpers';
|
||||
import { EmblaOptionsType, EmblaPluginType } from 'embla-carousel';
|
||||
import { EmblaOptionsType } from 'embla-carousel';
|
||||
import { WheelGesturesPlugin } from 'embla-carousel-wheel-gestures';
|
||||
import {
|
||||
CSSResultGroup,
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
} from 'lit';
|
||||
import { customElement, property, state } from 'lit/decorators.js';
|
||||
import { createRef, Ref, ref } from 'lit/directives/ref.js';
|
||||
import { guard } from 'lit/directives/guard.js';
|
||||
import { until } from 'lit/directives/until.js';
|
||||
import { ConditionState, getOverriddenConfig } from '../card-condition.js';
|
||||
import {
|
||||
@@ -51,12 +52,16 @@ import {
|
||||
import { View } from '../view.js';
|
||||
import { AutoMediaPlugin } from './embla-plugins/automedia.js';
|
||||
import { Lazyload } from './embla-plugins/lazyload.js';
|
||||
import { FrigateCardMediaCarousel, wrapMediaShowEventForCarousel } from './media-carousel.js';
|
||||
import {
|
||||
FrigateCardMediaCarousel,
|
||||
wrapMediaShowEventForCarousel,
|
||||
} from './media-carousel.js';
|
||||
import { dispatchErrorMessageEvent } from './message.js';
|
||||
import './next-prev-control.js';
|
||||
import './title-control.js';
|
||||
import './surround-thumbnails';
|
||||
import '../patches/ha-camera-stream';
|
||||
import { EmblaCarouselPlugins } from './carousel.js';
|
||||
|
||||
// Number of seconds a signed URL is valid for.
|
||||
const URL_SIGN_EXPIRY_SECONDS = 24 * 60 * 60;
|
||||
@@ -241,27 +246,14 @@ export class FrigateCardLiveCarousel extends LitElement {
|
||||
frigateCardCarousel &&
|
||||
changedProperties.has('preloaded')
|
||||
) {
|
||||
const automedia = frigateCardCarousel.getCarouselPlugins()?.autoMedia;
|
||||
if (automedia) {
|
||||
// If this has changed to preloaded (i.e. is now loaded but in the
|
||||
// background) take the appropriate play/pause/mute/unmute actions.
|
||||
if (this.preloaded) {
|
||||
if (
|
||||
this.liveConfig?.auto_pause &&
|
||||
['all', 'unselected'].includes(this.liveConfig.auto_pause)
|
||||
) {
|
||||
automedia.pause();
|
||||
}
|
||||
if (
|
||||
this.liveConfig?.auto_mute &&
|
||||
['all', 'unselected'].includes(this.liveConfig.auto_mute)
|
||||
) {
|
||||
automedia.mute();
|
||||
}
|
||||
} else {
|
||||
frigateCardMediaCarousel.autoPlay();
|
||||
frigateCardMediaCarousel.autoUnmute();
|
||||
}
|
||||
// If this has changed to preloaded (i.e. is now loaded but in the
|
||||
// background) take the appropriate play/pause/mute/unmute actions.
|
||||
if (this.preloaded) {
|
||||
frigateCardMediaCarousel.autoPause();
|
||||
frigateCardMediaCarousel.autoMute();
|
||||
} else {
|
||||
frigateCardMediaCarousel.autoPlay();
|
||||
frigateCardMediaCarousel.autoUnmute();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -296,7 +288,7 @@ export class FrigateCardLiveCarousel extends LitElement {
|
||||
* Get the Embla plugins to use.
|
||||
* @returns A list of EmblaOptionsTypes.
|
||||
*/
|
||||
protected _getPlugins(): EmblaPluginType[] {
|
||||
protected _getPlugins(): EmblaCarouselPlugins {
|
||||
return [
|
||||
// Only enable wheel plugin if there is more than one camera.
|
||||
...(this.cameras && this.cameras.size > 1
|
||||
@@ -406,7 +398,7 @@ export class FrigateCardLiveCarousel extends LitElement {
|
||||
slide: Element,
|
||||
): void {
|
||||
if (slide instanceof HTMLSlotElement) {
|
||||
slide = slide.assignedElements({flatten: true})[0];
|
||||
slide = slide.assignedElements({ flatten: true })[0];
|
||||
}
|
||||
|
||||
const liveProvider = slide?.querySelector(
|
||||
@@ -448,7 +440,7 @@ export class FrigateCardLiveCarousel extends LitElement {
|
||||
.liveConfig=${config}
|
||||
.hass=${this.hass}
|
||||
@frigate-card:media-show=${(e: CustomEvent<MediaShowInfo>) => {
|
||||
wrapMediaShowEventForCarousel(slideIndex, e)
|
||||
wrapMediaShowEventForCarousel(slideIndex, e);
|
||||
}}
|
||||
>
|
||||
</frigate-card-live-provider>
|
||||
@@ -498,15 +490,20 @@ export class FrigateCardLiveCarousel extends LitElement {
|
||||
const [prev, next] = this._getCameraNeighbors();
|
||||
const title = getCameraTitle(this.hass, this.cameras.get(this.view.camera));
|
||||
|
||||
// guard() is used below to avoid reseting the carousel unless the
|
||||
// options/plugins actually change.
|
||||
|
||||
return html`
|
||||
<frigate-card-media-carousel
|
||||
${ref(this._refMediaCarousel)}
|
||||
.carouselOptions=${this._getOptions()}
|
||||
.carouselPlugins=${this._getPlugins()}
|
||||
.autoPlayCondition=${this.liveConfig.auto_play}
|
||||
.autoPauseCondition=${this.liveConfig.auto_pause}
|
||||
.autoMuteCondition=${this.liveConfig.auto_mute}
|
||||
.autoUnmuteCondition=${this.liveConfig.auto_unmute}
|
||||
.carouselOptions=${guard(
|
||||
[this.cameras, this.liveConfig],
|
||||
this._getOptions.bind(this),
|
||||
)}
|
||||
.carouselPlugins=${guard(
|
||||
[this.cameras, this.liveConfig],
|
||||
this._getPlugins.bind(this),
|
||||
) as EmblaCarouselPlugins}
|
||||
.label="${title ? `${localize('common.live')}: ${title}` : ''}"
|
||||
.titlePopupConfig=${config.controls.title}
|
||||
transitionEffect=${this._getTransitionEffect()}
|
||||
@@ -548,7 +545,7 @@ export class FrigateCardLiveCarousel extends LitElement {
|
||||
/**
|
||||
* Get styles.
|
||||
*/
|
||||
static get styles(): CSSResultGroup {
|
||||
static get styles(): CSSResultGroup {
|
||||
return unsafeCSS(liveCarouselStyle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,12 @@
|
||||
// TODO: Use the auto-height plugin instead of adaptive height
|
||||
|
||||
import { EmblaOptionsType } from 'embla-carousel';
|
||||
import { EmblaPluginsType } from 'embla-carousel/components/Plugins';
|
||||
import { CSSResultGroup, html, LitElement, TemplateResult, unsafeCSS } from 'lit';
|
||||
import { customElement, property } from 'lit/decorators.js';
|
||||
import { ifDefined } from 'lit/directives/if-defined.js';
|
||||
import { createRef, ref, Ref } from 'lit/directives/ref.js';
|
||||
import mediaCarouselStyle from '../scss/media-carousel.scss';
|
||||
import type {
|
||||
AutoMuteCondition,
|
||||
AutoPauseCondition,
|
||||
AutoPlayCondition,
|
||||
AutoUnmuteCondition,
|
||||
MediaShowInfo,
|
||||
NextPreviousControlConfig,
|
||||
TitleControlConfig,
|
||||
@@ -106,18 +101,6 @@ export class FrigateCardMediaCarousel extends LitElement {
|
||||
@property({ attribute: false })
|
||||
public titlePopupConfig?: TitleControlConfig;
|
||||
|
||||
@property({ attribute: false })
|
||||
public autoPlayCondition?: AutoPlayCondition;
|
||||
|
||||
@property({ attribute: false })
|
||||
public autoUnmuteCondition?: AutoUnmuteCondition;
|
||||
|
||||
@property({ attribute: false })
|
||||
public autoPauseCondition?: AutoPauseCondition;
|
||||
|
||||
@property({ attribute: false })
|
||||
public autoMuteCondition?: AutoMuteCondition;
|
||||
|
||||
// A "map" from slide number to MediaShowInfo object.
|
||||
protected _mediaShowInfo: Record<number, MediaShowInfo> = {};
|
||||
protected _nextControlRef: Ref<FrigateCardNextPreviousControl> = createRef();
|
||||
@@ -126,9 +109,9 @@ export class FrigateCardMediaCarousel extends LitElement {
|
||||
protected _titleTimerID: number | null = null;
|
||||
|
||||
protected _boundAutoPlayHandler = this.autoPlay.bind(this);
|
||||
protected _boundAutoPauseHandler = this.autoPause.bind(this);
|
||||
protected _boundAutoMuteHandler = this.autoMute.bind(this);
|
||||
protected _boundAutoUnmuteHandler = this.autoUnmute.bind(this);
|
||||
protected _boundAdaptiveHeightHandler = this._adaptiveHeightHandler.bind(this);
|
||||
protected _boundTitleHandler = this._titleHandler.bind(this);
|
||||
|
||||
// This carousel may be resized by Lovelace resizes, window resizes,
|
||||
// fullscreen, etc. Always call the adaptive height handler when the size
|
||||
@@ -165,7 +148,11 @@ export class FrigateCardMediaCarousel extends LitElement {
|
||||
* Play the media on the selected slide.
|
||||
*/
|
||||
public autoPlay(): void {
|
||||
if (this.autoPlayCondition && ['all', 'selected'].includes(this.autoPlayCondition)) {
|
||||
const automediaOptions = this._getAutoMediaPlugin()?.options;
|
||||
if (
|
||||
automediaOptions?.autoPlayCondition &&
|
||||
['all', 'selected'].includes(automediaOptions?.autoPlayCondition)
|
||||
) {
|
||||
this._getAutoMediaPlugin()?.play();
|
||||
}
|
||||
}
|
||||
@@ -174,9 +161,10 @@ export class FrigateCardMediaCarousel extends LitElement {
|
||||
* Pause the media on the selected slide.
|
||||
*/
|
||||
public autoPause(): void {
|
||||
const automediaOptions = this._getAutoMediaPlugin()?.options;
|
||||
if (
|
||||
this.autoPauseCondition &&
|
||||
['all', 'selected'].includes(this.autoPauseCondition)
|
||||
automediaOptions?.autoPauseCondition &&
|
||||
['all', 'selected'].includes(automediaOptions.autoPauseCondition)
|
||||
) {
|
||||
this._getAutoMediaPlugin()?.pause();
|
||||
}
|
||||
@@ -186,9 +174,10 @@ export class FrigateCardMediaCarousel extends LitElement {
|
||||
* Unmute the media on the selected slide.
|
||||
*/
|
||||
public autoUnmute(): void {
|
||||
const automediaOptions = this._getAutoMediaPlugin()?.options;
|
||||
if (
|
||||
this.autoUnmuteCondition &&
|
||||
['all', 'selected'].includes(this.autoUnmuteCondition)
|
||||
automediaOptions?.autoUnmuteCondition &&
|
||||
['all', 'selected'].includes(automediaOptions?.autoUnmuteCondition)
|
||||
) {
|
||||
this._getAutoMediaPlugin()?.unmute();
|
||||
}
|
||||
@@ -198,7 +187,11 @@ export class FrigateCardMediaCarousel extends LitElement {
|
||||
* Mute the media on the selected slide.
|
||||
*/
|
||||
public autoMute(): void {
|
||||
if (this.autoMuteCondition && ['all', 'selected'].includes(this.autoMuteCondition)) {
|
||||
const automediaOptions = this._getAutoMediaPlugin()?.options;
|
||||
if (
|
||||
automediaOptions?.autoMuteCondition &&
|
||||
['all', 'selected'].includes(automediaOptions?.autoMuteCondition)
|
||||
) {
|
||||
this._getAutoMediaPlugin()?.mute();
|
||||
}
|
||||
}
|
||||
@@ -233,10 +226,11 @@ export class FrigateCardMediaCarousel extends LitElement {
|
||||
*/
|
||||
connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
this.addEventListener('frigate-card:media-show', this.autoPlay);
|
||||
this.addEventListener('frigate-card:media-show', this.autoUnmute);
|
||||
this.addEventListener('frigate-card:media-show', this._adaptiveHeightHandler);
|
||||
this.addEventListener('frigate-card:media-show', this._titleHandler);
|
||||
|
||||
this.addEventListener('frigate-card:media-show', this._boundAutoPlayHandler);
|
||||
this.addEventListener('frigate-card:media-show', this._boundAutoUnmuteHandler);
|
||||
this.addEventListener('frigate-card:media-show', this._boundAdaptiveHeightHandler);
|
||||
this.addEventListener('frigate-card:media-show', this._boundTitleHandler);
|
||||
this._resizeObserver.observe(this);
|
||||
this._intersectionObserver.observe(this);
|
||||
}
|
||||
@@ -245,13 +239,17 @@ export class FrigateCardMediaCarousel extends LitElement {
|
||||
* Component disconnected callback.
|
||||
*/
|
||||
disconnectedCallback(): void {
|
||||
super.disconnectedCallback();
|
||||
this.removeEventListener('frigate-card:media-show', this.autoPlay);
|
||||
this.removeEventListener('frigate-card:media-show', this.autoUnmute);
|
||||
this.removeEventListener('frigate-card:media-show', this._adaptiveHeightHandler);
|
||||
this.removeEventListener('frigate-card:media-show', this._titleHandler);
|
||||
this.removeEventListener('frigate-card:media-show', this._boundAutoPlayHandler);
|
||||
this.removeEventListener('frigate-card:media-show', this._boundAutoUnmuteHandler);
|
||||
this.removeEventListener(
|
||||
'frigate-card:media-show',
|
||||
this._boundAdaptiveHeightHandler,
|
||||
);
|
||||
this.removeEventListener('frigate-card:media-show', this._boundTitleHandler);
|
||||
this._resizeObserver.disconnect();
|
||||
this._intersectionObserver.disconnect();
|
||||
|
||||
super.disconnectedCallback();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
TemplateResult,
|
||||
unsafeCSS,
|
||||
} from 'lit';
|
||||
import { guard } from 'lit/directives/guard.js';
|
||||
import { customElement, property } from 'lit/decorators.js';
|
||||
import { ifDefined } from 'lit/directives/if-defined.js';
|
||||
import { createRef, Ref, ref } from 'lit/directives/ref.js';
|
||||
@@ -54,6 +55,7 @@ import './next-prev-control.js';
|
||||
import './title-control.js';
|
||||
import '../patches/ha-hls-player';
|
||||
import './surround-thumbnails';
|
||||
import { EmblaCarouselPlugins } from './carousel.js';
|
||||
|
||||
@customElement('frigate-card-viewer')
|
||||
export class FrigateCardViewer extends LitElement {
|
||||
@@ -603,14 +605,16 @@ export class FrigateCardViewerCarousel extends LitElement {
|
||||
const neighbors = this._getMediaNeighbors();
|
||||
const [prev, next] = [neighbors?.previous, neighbors?.next];
|
||||
|
||||
// guard() is used below to avoid reseting the carousel unless the
|
||||
// options/plugins actually change.
|
||||
|
||||
return html` <frigate-card-media-carousel
|
||||
${ref(this._refMediaCarousel)}
|
||||
.carouselOptions=${this._getOptions()}
|
||||
.carouselPlugins=${this._getPlugins()}
|
||||
.autoPlayCondition=${this.viewerConfig?.auto_play}
|
||||
.autoPauseCondition=${this.viewerConfig?.auto_pause}
|
||||
.autoMuteCondition=${this.viewerConfig?.auto_mute}
|
||||
.autoUnmuteCondition=${this.viewerConfig?.auto_unmute}
|
||||
.carouselOptions=${guard([this.viewerConfig], this._getOptions.bind(this))}
|
||||
.carouselPlugins=${guard(
|
||||
[this.viewerConfig, this.view?.target?.children?.length],
|
||||
this._getPlugins.bind(this),
|
||||
) as EmblaCarouselPlugins}
|
||||
.label="${this.view.media.title}"
|
||||
.titlePopupConfig=${this.viewerConfig?.controls.title}
|
||||
transitionEffect=${this._getTransitionEffect()}
|
||||
|
||||
Reference in New Issue
Block a user