diff --git a/src/components/live.ts b/src/components/live.ts
index 7ebf27ae..877e0571 100644
--- a/src/components/live.ts
+++ b/src/components/live.ts
@@ -1,7 +1,8 @@
-// TODO controls
-// TODO media events
// TODO lazy loading
+// TODO media events
// TODO height adapting
+// TODO can height adapting remove need for 16x9 dummy in the media carousel?
+// TODO controls
import { CSSResultGroup, LitElement, TemplateResult, html, unsafeCSS } from 'lit';
import type {
@@ -13,13 +14,13 @@ import type {
MediaShowInfo,
WebRTCConfig,
} from '../types.js';
-import { EmblaCarouselType, EmblaOptionsType } from 'embla-carousel';
+import { EmblaOptionsType } from 'embla-carousel';
import { HomeAssistant } from 'custom-card-helpers';
import { customElement, property } from 'lit/decorators.js';
import { until } from 'lit/directives/until.js';
import { BrowseMediaUtil } from '../browse-media-util.js';
-import { FrigateCardCarousel } from './carousel.js';
+import { FrigateCardMediaCarousel } from './media-carousel.js';
import { ThumbnailCarouselTap } from './thumbnail-carousel.js';
import { View } from '../view.js';
import { localize } from '../localize/localize.js';
@@ -40,7 +41,6 @@ import liveStyle from '../scss/live.scss';
import liveFrigateStyle from '../scss/live-frigate.scss';
import liveJSMPEGStyle from '../scss/live-jsmpeg.scss';
import liveWebRTCStyle from '../scss/live-webrtc.scss';
-import mediaCarouselStyle from '../scss/media-carousel.scss';
// Number of seconds a signed URL is valid for.
const URL_SIGN_EXPIRY_SECONDS = 24 * 60 * 60;
@@ -184,7 +184,7 @@ export class FrigateCardLive extends LitElement {
}
@customElement('frigate-card-live-carousel')
-export class FrigateCardLiveCarousel extends FrigateCardCarousel {
+export class FrigateCardLiveCarousel extends FrigateCardMediaCarousel {
@property({ attribute: false })
protected hass?: HomeAssistant & ExtendedHomeAssistant;
@@ -213,18 +213,6 @@ export class FrigateCardLiveCarousel extends FrigateCardCarousel {
};
}
- /**
- * Load the carousel.
- */
- protected _loadCarousel(): void {
- super._loadCarousel();
-
- // Necessary because typescript local type narrowing is not paying attention
- // to the side-effect of the call to super._loadCarousel().
- const carousel = this._carousel as EmblaCarouselType | undefined;
- carousel?.on('select', this._selectSlideSetViewHandler.bind(this));
- }
-
/**
* Get slides to include in the render.
* @returns The slides to include in the render.
@@ -233,12 +221,12 @@ export class FrigateCardLiveCarousel extends FrigateCardCarousel {
if (!this.cameras) {
return [];
}
- return Array.from(this.cameras.values()).map(this._renderLive.bind(this));
+ return Array.from(this.cameras.values()).map((cameraConfig, index) => this._renderLive(cameraConfig, index));
}
- // /**
- // * Handle the user selecting a new slide in the carousel.
- // */
+ /**
+ * Handle the user selecting a new slide in the carousel.
+ */
protected _selectSlideSetViewHandler(): void {
if (!this._carousel || !this.view || !this.cameras) {
return;
@@ -248,13 +236,18 @@ export class FrigateCardLiveCarousel extends FrigateCardCarousel {
this.view.camera = Array.from(this.cameras.keys())[selectedSnap];
}
- protected _renderLive(cameraConfig: CameraConfig): TemplateResult {
+ protected _renderLive(
+ cameraConfig: CameraConfig,
+ slideIndex: number,
+ ): TemplateResult {
// TODO: Add lazy load
return html`
) =>
+ this._mediaShowEventHandler(slideIndex, e)}
>
`;
@@ -307,13 +300,6 @@ export class FrigateCardLiveCarousel extends FrigateCardCarousel {
// >`
// : ``}
}
-
- /**
- * Get element styles.
- */
- static get styles(): CSSResultGroup {
- return [super.styles, unsafeCSS(mediaCarouselStyle)];
- }
}
@customElement('frigate-card-live-provider')
diff --git a/src/components/media-carousel.ts b/src/components/media-carousel.ts
new file mode 100644
index 00000000..1cd59118
--- /dev/null
+++ b/src/components/media-carousel.ts
@@ -0,0 +1,212 @@
+import { CSSResultGroup, unsafeCSS } from 'lit';
+import { EmblaCarouselType } from 'embla-carousel';
+import { customElement } from 'lit/decorators.js';
+
+import { FrigateCardCarousel } from './carousel.js';
+import type { MediaShowInfo } from '../types.js';
+import {
+ dispatchExistingMediaShowInfoAsEvent,
+ isValidMediaShowInfo,
+} from '../common.js';
+
+import './next-prev-control.js';
+
+import mediaCarouselStyle from '../scss/media-carousel.scss';
+
+// TODO Remove this if not needed (and below)
+// const getEmptyImageSrc = (width: number, height: number) =>
+// `data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}"%3E%3C/svg%3E`;
+// const IMG_EMPTY = getEmptyImageSrc(16, 9);
+
+@customElement('frigate-card-media-carousel')
+export class FrigateCardMediaCarousel extends FrigateCardCarousel {
+ // A "map" from slide number to MediaShowInfo object.
+ protected _mediaShowInfo: Record = {};
+
+ // Whether or not a given slide has been successfully lazily loaded.
+ protected _slideHasBeenLazyLoaded: Record = {};
+
+ /**
+ * Returns the number of slides to lazily load. 0 means all slides are lazy
+ * loaded, 1 means that 1 slide on each side of the currently selected slide
+ * should lazy load, etc. `null` means lazy loading is disabled and everything
+ * should load simultaneously.
+ * @returns
+ */
+ protected _getLazyLoadCount(): number | null {
+ // Defaults to fully-lazy loading.
+ return 0;
+ }
+
+ /**
+ * Load the carousel with "slides" (clips or snapshots).
+ */
+ protected _loadCarousel(): void {
+ super._loadCarousel();
+
+ // Necessary because typescript local type narrowing is not paying attention
+ // to the side-effect of the call to super._loadCarousel().
+ const carousel = this._carousel as EmblaCarouselType | undefined;
+ carousel?.on('select', this._selectSlideSetViewHandler.bind(this));
+
+ carousel?.on('init', this._selectSlideMediaShowHandler.bind(this));
+ carousel?.on('select', this._selectSlideMediaShowHandler.bind(this));
+
+ if (this._getLazyLoadCount() != null) {
+ carousel?.on('init', this._lazyLoadMediaHandler.bind(this));
+ carousel?.on('select', this._lazyLoadMediaHandler.bind(this));
+ carousel?.on('resize', this._lazyLoadMediaHandler.bind(this));
+ }
+ }
+
+ /**
+ * Handle the user selecting a new slide in the carousel.
+ */
+ protected _selectSlideSetViewHandler(): void {
+ // To be overridden in children.
+ }
+
+ /**
+ * Handle a next/previous control interaction.
+ * @param direction The direction requested, previous or next.
+ */
+ protected _nextPreviousHandler(direction: 'previous' | 'next'): void {
+ if (direction == 'previous') {
+ this._carousel?.scrollPrev();
+ } else if (direction == 'next') {
+ this._carousel?.scrollNext();
+ }
+ }
+
+ /**
+ * Lazily load media in the carousel.
+ */
+ protected _lazyLoadMediaHandler(): void {
+ if (!this._carousel) {
+ return;
+ }
+ const lazyLoadCount = this._getLazyLoadCount();
+ if (lazyLoadCount === null) {
+ return;
+ }
+
+ const slides = this._carousel.slideNodes();
+ const slidesInView = this._carousel.slidesInView(true);
+ const slidesToLoad = new Set();
+
+ const minSlide = Math.min(...slidesInView);
+ const maxSlide = Math.max(...slidesInView);
+
+ // Lazily load 'lazyLoadCount' slides on either side of the slides in view.
+ for (let i = 1; i <= lazyLoadCount && minSlide - i >= 0; i++) {
+ slidesToLoad.add(minSlide - i);
+ }
+ slidesInView.forEach((index) => slidesToLoad.add(index));
+ for (let i = 1; i <= lazyLoadCount && maxSlide + i < slides.length; i++) {
+ slidesToLoad.add(maxSlide + i);
+ }
+
+ slidesToLoad.forEach((index) => {
+ // Only lazy load slides that are not already loaded.
+ if (this._slideHasBeenLazyLoaded[index]) {
+ return;
+ }
+ this._slideHasBeenLazyLoaded[index] = true;
+ this._lazyLoadSlide(slides[index]);
+ });
+ }
+
+ /**
+ * Lazy load a slide.
+ * @param _slide The slide to lazy load.
+ */
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ protected _lazyLoadSlide(_slide: HTMLElement): void {
+ // To be overridden in children.
+ }
+
+ /**
+ * Fire a media show event when a slide is selected.
+ */
+ protected _selectSlideMediaShowHandler(): void {
+ if (!this._carousel) {
+ return;
+ }
+
+ this._carousel.slidesInView(true).forEach((slideIndex) => {
+ if (slideIndex in this._mediaShowInfo) {
+ dispatchExistingMediaShowInfoAsEvent(this, this._mediaShowInfo[slideIndex]);
+ }
+ });
+ }
+
+ /**
+ * Handle a media-show event that is generated by a child component, saving the
+ * contents for future use when the relevant slide is actually shown.
+ * @param slideIndex The relevant slide index.
+ * @param event The media-show event from the child component.
+ */
+ protected _mediaShowEventHandler(
+ slideIndex: number,
+ event: CustomEvent,
+ ): void {
+ // Don't allow the inbound event to propagate upwards, that will be
+ // automatically done at the appropriate time as the slide is shown.
+ event.stopPropagation();
+ this._mediaLoadedHandler(slideIndex, event.detail);
+ }
+
+ /**
+ * Handle a MediaShowInfo object that is generated on media load, by saving it
+ * for future, or immediate use, when the relevant slide is displayed.
+ * @param slideIndex The relevant slide index.
+ * @param mediaShowInfo The MediaShowInfo object generated by the media.
+ */
+ protected _mediaLoadedHandler(
+ slideIndex: number,
+ mediaShowInfo?: MediaShowInfo | null,
+ ): void {
+ // isValidMediaShowInfo is used to prevent saving media info that will be
+ // rejected upstream.
+ if (mediaShowInfo && isValidMediaShowInfo(mediaShowInfo)) {
+ this._mediaShowInfo[slideIndex] = mediaShowInfo;
+ if (this._carousel && this._carousel?.slidesInView(true).includes(slideIndex)) {
+ dispatchExistingMediaShowInfoAsEvent(this, mediaShowInfo);
+ }
+ /**
+ * Images need a width/height from initial load, and browsers will assume
+ * that the aspect ratio of the initial dummy-image load will persist. In
+ * lazy-loading, this can cause a 1x1 pixel dummy image to cause the
+ * browser to assume all images will be square, so the whole carousel will
+ * have the wrong aspect-ratio until every single image has been lazily
+ * loaded. To avoid this, we use a 16:9 dummy image at first (most
+ * likely?) and once the first piece of real media has been loaded, all
+ * dummy images are replaced with dummy images that match the aspect ratio
+ * of the real image. It still might be wrong, but it's the best option
+ * available.
+ */
+ // TODO remove this
+ // const firstMediaLoad = !Object.keys(this._mediaShowInfo).length;
+ // if (firstMediaLoad && this.viewerConfig.lazy_load) {
+ // const replacementImageSrc = getEmptyImageSrc(
+ // mediaShowInfo.width,
+ // mediaShowInfo.height,
+ // );
+
+ // this.renderRoot.querySelectorAll('.embla__container img').forEach((img) => {
+ // const imageElement: HTMLImageElement = img as HTMLImageElement;
+ // if (imageElement.src === IMG_EMPTY) {
+ // imageElement.src = replacementImageSrc;
+ // }
+ // });
+ // }
+ }
+ }
+
+ /**
+ * Get element styles.
+ */
+ static get styles(): CSSResultGroup {
+ return [super.styles, unsafeCSS(mediaCarouselStyle)];
+ }
+}
diff --git a/src/components/viewer.ts b/src/components/viewer.ts
index c47d6789..c8dd067a 100644
--- a/src/components/viewer.ts
+++ b/src/components/viewer.ts
@@ -1,6 +1,6 @@
import { CSSResultGroup, LitElement, TemplateResult, html, unsafeCSS } from 'lit';
import { BrowseMediaUtil } from '../browse-media-util.js';
-import { EmblaCarouselType, EmblaOptionsType } from 'embla-carousel';
+import { EmblaOptionsType } from 'embla-carousel';
import { HomeAssistant } from 'custom-card-helpers';
import { createRef, Ref, ref } from 'lit/directives/ref.js';
import { customElement, property } from 'lit/decorators.js';
@@ -15,7 +15,7 @@ import type {
MediaShowInfo,
ViewerConfig,
} from '../types.js';
-import { FrigateCardCarousel } from './carousel.js';
+import { FrigateCardMediaCarousel } from './media-carousel.js';
import { FrigateCardThumbnailCarousel, ThumbnailCarouselTap } from './thumbnail-carousel.js';
import { ResolvedMediaCache, ResolvedMediaUtil } from '../resolved-media.js';
import { View } from '../view.js';
@@ -26,8 +26,6 @@ import {
dispatchMessageEvent,
dispatchPauseEvent,
dispatchPlayEvent,
- dispatchExistingMediaShowInfoAsEvent,
- isValidMediaShowInfo,
} from '../common.js';
import { localize } from '../localize/localize.js';
import { renderProgressIndicator } from '../components/message.js';
@@ -36,7 +34,6 @@ import './next-prev-control.js';
import viewerStyle from '../scss/viewer.scss';
import viewerCoreStyle from '../scss/viewer-core.scss';
-import mediaCarouselStyle from '../scss/media-carousel.scss';
const getEmptyImageSrc = (width: number, height: number) =>
`data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}"%3E%3C/svg%3E`;
@@ -164,11 +161,11 @@ export class FrigateCardViewerCore extends LitElement {
@property({ attribute: false })
protected resolvedMediaCache?: ResolvedMediaCache;
- protected _mediaCarouselRef: Ref = createRef();
+ protected _viewerCarouselRef: Ref = createRef();
protected _thumbnailCarouselRef: Ref = createRef();
protected _syncThumbnailCarousel(): void {
- const mediaSelected = this._mediaCarouselRef.value?.carouselSelected();
+ const mediaSelected = this._viewerCarouselRef.value?.carouselSelected();
if (mediaSelected !== undefined) {
this._thumbnailCarouselRef.value?.carouselScrollTo(mediaSelected);
}
@@ -184,7 +181,7 @@ export class FrigateCardViewerCore extends LitElement {
.target=${this.view.target}
.config=${this.viewerConfig.controls.thumbnails}
@frigate-card:carousel:tap=${(ev: CustomEvent) => {
- this._mediaCarouselRef.value?.carouselScrollTo(ev.detail.slideIndex);
+ this._viewerCarouselRef.value?.carouselScrollTo(ev.detail.slideIndex);
}}
@frigate-card:carousel:init=${this._syncThumbnailCarousel.bind(this)}
>
@@ -199,8 +196,8 @@ export class FrigateCardViewerCore extends LitElement {
this.viewerConfig.controls.thumbnails.mode === 'above'
? this._renderThumbnails()
: ''}
-
-
+
${this.viewerConfig && this.viewerConfig.controls.thumbnails.mode === 'below'
? this._renderThumbnails()
: ''}`;
@@ -222,8 +219,8 @@ export class FrigateCardViewerCore extends LitElement {
}
}
-@customElement('frigate-card-media-carousel')
-export class FrigateCardMediaCarousel extends FrigateCardCarousel {
+@customElement('frigate-card-viewer-carousel')
+export class FrigateCardViewerCarousel extends FrigateCardMediaCarousel {
@property({ attribute: false })
protected hass?: HomeAssistant & ExtendedHomeAssistant;
@@ -243,12 +240,6 @@ export class FrigateCardMediaCarousel extends FrigateCardCarousel {
// (Folders are not media items that can be rendered).
protected _slideToChild: Record = {};
- // A "map" from slide number to MediaShowInfo object.
- protected _mediaShowInfo: Record = {};
-
- // Whether or not a given slide has been successfully lazily loaded.
- protected _slideHasBeenLazyLoaded: Record = {};
-
/**
* Get the Embla options to use.
* @returns An EmblaOptionsType object or undefined for no options.
@@ -267,28 +258,6 @@ export class FrigateCardMediaCarousel extends FrigateCardCarousel {
};
}
- /**
- * Load the carousel with "slides" (clips or snapshots).
- */
- protected _loadCarousel(): void {
- super._loadCarousel();
-
- // Necessary because typescript local type narrowing is not paying attention
- // to the side-effect of the call to super._loadCarousel().
- const carousel = this._carousel as EmblaCarouselType | undefined;
-
- // Update views and dispatch media-show events based on slide selections.
- carousel?.on('select', this._selectSlideSetViewHandler.bind(this));
- carousel?.on('select', this._selectSlideMediaShowHandler.bind(this));
-
- // Lazily load media that is displayed. These handlers are registered
- // regardless of the value of this.lazyLoad to allow that value to change
- // after the carousel has been initialized.
- carousel?.on('init', this._lazyLoadMediaHandler.bind(this));
- carousel?.on('select', this._lazyLoadMediaHandler.bind(this));
- carousel?.on('resize', this._lazyLoadMediaHandler.bind(this));
- }
-
/**
* Get the previous and next true media items from the current view.
* @returns A BrowseMediaNeighbors with indices and objects of true media
@@ -438,79 +407,39 @@ export class FrigateCardMediaCarousel extends FrigateCardCarousel {
if (childIndex !== undefined) {
// Update the currently live view in place.
this.view.childIndex = childIndex;
- this.requestUpdate();
}
}
}
- /**
- * Handle a next/previous control interaction.
- * @param direction The direction requested, previous or next.
+ /**
+ * Lazy load a slide.
+ * @param slide The slide to lazy load.
*/
- protected _nextPreviousHandler(direction: 'previous' | 'next'): void {
- if (direction == 'previous') {
- this._carousel?.scrollPrev();
- } else if (direction == 'next') {
- this._carousel?.scrollNext();
+ protected _lazyLoadSlide(slide: HTMLElement): void {
+
+ // Snapshots.
+ const img = slide.querySelector('img') as HTMLImageElement;
+
+ // Frigate >= 0.9.0+ clips.
+ const hls_player = slide.querySelector(
+ 'frigate-card-ha-hls-player',
+ ) as HTMLElement & { url: string };
+
+ // Frigate < 0.9.0 clips. frigate-card-ha-hls-player will also have a
+ // video source element, so search for that first.
+ const video_source = slide.querySelector('video source') as HTMLElement & {
+ src: string;
+ };
+
+ if (img) {
+ img.src = img.getAttribute('data-src') || img.src;
+ } else if (hls_player) {
+ hls_player.url = hls_player.getAttribute('data-url') || hls_player.url;
+ } else if (video_source) {
+ video_source.src = video_source.getAttribute('data-src') || video_source.src;
}
}
- /**
- * Lazily load media in the carousel.
- */
- protected _lazyLoadMediaHandler(): void {
- if (!this.viewerConfig?.lazy_load || !this._carousel) {
- return;
- }
- const slides = this._carousel.slideNodes();
- const slidesInView = this._carousel.slidesInView(true);
- const slidesToLoad = new Set();
-
- // Lazily load the selected slide and the one on each side of it to improve
- // the user navigation experience.
- for (let i = 0; i < slidesInView.length; i++) {
- const index = slidesInView[i];
- if (index > 0) {
- slidesToLoad.add(index - 1);
- }
- slidesToLoad.add(index);
- if (index < slides.length - 1) {
- slidesToLoad.add(index + 1);
- }
- }
-
- slidesToLoad.forEach((index) => {
- // Only lazy load slides that are not already loaded.
- if (this._slideHasBeenLazyLoaded[index]) {
- return;
- }
- this._slideHasBeenLazyLoaded[index] = true;
- const slide = slides[index];
-
- // Snapshots.
- const img = slide.querySelector('img') as HTMLImageElement;
-
- // Frigate >= 0.9.0+ clips.
- const hls_player = slide.querySelector(
- 'frigate-card-ha-hls-player',
- ) as HTMLElement & { url: string };
-
- // Frigate < 0.9.0 clips. frigate-card-ha-hls-player will also have a
- // video source element, so search for that first.
- const video_source = slide.querySelector('video source') as HTMLElement & {
- src: string;
- };
-
- if (img) {
- img.src = img.getAttribute('data-src') || img.src;
- } else if (hls_player) {
- hls_player.url = hls_player.getAttribute('data-url') || hls_player.url;
- } else if (video_source) {
- video_source.src = video_source.getAttribute('data-src') || video_source.src;
- }
- });
- }
-
/**
* Get slides to include in the render.
* @returns The slides to include in the render.
@@ -587,82 +516,6 @@ export class FrigateCardMediaCarousel extends FrigateCardCarousel {
`;
}
- /**
- * Fire a media show event when a slide is selected.
- */
- protected _selectSlideMediaShowHandler(): void {
- if (!this._carousel || !this.view) {
- return;
- }
-
- this._carousel.slidesInView(true).forEach((slideIndex) => {
- if (slideIndex in this._mediaShowInfo) {
- dispatchExistingMediaShowInfoAsEvent(this, this._mediaShowInfo[slideIndex]);
- }
- });
- }
-
- /**
- * Handle a media-show event that is generated by a child component, saving the
- * contents for future use when the relevant slide is shown.
- * @param slideIndex The relevant slide index.
- * @param event The media-show event from the child component.
- */
- protected _mediaShowEventHandler(
- slideIndex: number,
- event: CustomEvent,
- ): void {
- // Don't allow the inbound event to propagate upwards, that will be
- // automatically done at the appropriate time as the slide is shown.
- event.stopPropagation();
- this._mediaShowInfoHandler(slideIndex, event.detail);
- }
-
- /**
- * Handle a MediaShowInfo object that is generated on media load, by saving it
- * for future, or immediate use, when the relevant slide is displayed.
- * @param slideIndex The relevant slide index.
- * @param mediaShowInfo The MediaShowInfo object generated by the media.
- */
- protected _mediaShowInfoHandler(
- slideIndex: number,
- mediaShowInfo?: MediaShowInfo | null,
- ): void {
- // isValidMediaShowInfo is used to prevent saving media info that will be
- // rejected upstream.
- if (this.viewerConfig && mediaShowInfo && isValidMediaShowInfo(mediaShowInfo)) {
- const firstMediaLoad = !Object.keys(this._mediaShowInfo).length;
- this._mediaShowInfo[slideIndex] = mediaShowInfo;
- if (this._carousel && this._carousel?.slidesInView(true).includes(slideIndex)) {
- dispatchExistingMediaShowInfoAsEvent(this, mediaShowInfo);
- }
- /**
- * Images need a width/height from initial load, and browsers will assume
- * that the aspect ratio of the initial dummy-image load will persist. In
- * lazy-loading, this can cause a 1x1 pixel dummy image to cause the
- * browser to assume all images will be square, so the whole carousel will
- * have the wrong aspect-ratio until every single image has been lazily
- * loaded. To avoid this, we use a 16:9 dummy image at first (most
- * likely?) and once the first piece of real media has been loaded, all
- * dummy images are replaced with dummy images that match the aspect ratio
- * of the real image. It still might be wrong, but it's the best option
- * available.
- */
- if (firstMediaLoad && this.viewerConfig.lazy_load) {
- const replacementImageSrc = getEmptyImageSrc(
- mediaShowInfo.width,
- mediaShowInfo.height,
- );
-
- this.renderRoot.querySelectorAll('.embla__container img').forEach((img) => {
- const imageElement: HTMLImageElement = img as HTMLImageElement;
- if (imageElement.src === IMG_EMPTY) {
- imageElement.src = replacementImageSrc;
- }
- });
- }
- }
- }
protected _renderMediaItem(
mediaToRender: BrowseMediaSource,
@@ -720,7 +573,7 @@ export class FrigateCardMediaCarousel extends FrigateCardCarousel {
playsinline
?autoplay="${autoplay}"
@loadedmetadata="${(e: Event) => {
- this._mediaShowInfoHandler(slideIndex, createMediaShowInfo(e));
+ this._mediaLoadedHandler(slideIndex, createMediaShowInfo(e));
}}"
@play=${() => dispatchPlayEvent(this)}
@pause=${() => dispatchPauseEvent(this)}
@@ -754,18 +607,11 @@ export class FrigateCardMediaCarousel extends FrigateCardCarousel {
(!this.viewerConfig.lazy_load ||
this._slideHasBeenLazyLoaded[slideIndex])
) {
- this._mediaShowInfoHandler(slideIndex, createMediaShowInfo(e));
+ this._mediaLoadedHandler(slideIndex, createMediaShowInfo(e));
}
}}"
/>`}
`;
}
-
- /**
- * Get element styles.
- */
- static get styles(): CSSResultGroup {
- return [super.styles, unsafeCSS(mediaCarouselStyle)];
- }
}
diff --git a/src/scss/media-carousel.scss b/src/scss/media-carousel.scss
index 39c877d0..b4a7dd1d 100644
--- a/src/scss/media-carousel.scss
+++ b/src/scss/media-carousel.scss
@@ -6,7 +6,7 @@
flex: 0 0 100%;
}
-frigate-card-ha-hls-player {
+* {
height: 100%;
width: 100%;
transform-style: preserve-3d;
diff --git a/src/scss/viewer-core.scss b/src/scss/viewer-core.scss
index 071dafda..f8822b5a 100644
--- a/src/scss/viewer-core.scss
+++ b/src/scss/viewer-core.scss
@@ -7,7 +7,7 @@
width: 100%;
}
-frigate-card-media-carousel {
+frigate-card-viewer-carousel {
flex: 1;
min-height: 0;
}