diff --git a/src/browse-media-util.ts b/src/browse-media-util.ts index 034dae8e..d635ca1f 100644 --- a/src/browse-media-util.ts +++ b/src/browse-media-util.ts @@ -67,8 +67,6 @@ export class BrowseMediaUtil { return index >= 0 ? index : null; } - // - /** * Browse Frigate media with a media content id. May throw. * @param hass The HomeAssistant object. diff --git a/src/components/live.ts b/src/components/live.ts index 90b7b537..47725ce2 100644 --- a/src/components/live.ts +++ b/src/components/live.ts @@ -1,6 +1,7 @@ import { CSSResultGroup, LitElement, TemplateResult, html, unsafeCSS } from 'lit'; import type { BrowseMediaQueryParameters, + BrowseMediaSource, ExtendedHomeAssistant, FrigateCardConfig, JSMPEGConfig, @@ -11,6 +12,9 @@ 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 { ThumbnailCarouselTap } from './thumbnail-carousel.js'; +import { View } from '../view.js'; import { localize } from '../localize/localize.js'; import { dispatchErrorMessageEvent, @@ -30,8 +34,6 @@ import liveFrigateStyle from '../scss/live-frigate.scss'; import liveJSMPEGStyle from '../scss/live-jsmpeg.scss'; import liveWebRTCStyle from '../scss/live-webrtc.scss'; -import { View } from '../view.js'; -import { ThumbnailCarouselTap } from './thumbnail-carousel.js'; // Number of seconds a signed URL is valid for. const URL_SIGN_EXPIRY_SECONDS = 24 * 60 * 60; @@ -87,23 +89,43 @@ export class FrigateCardLive extends LitElement { if (!this.config) { return; } - return html` ) => { - const mediaType = this.browseMediaQueryParameters?.mediaType; - if (mediaType && ['snapshots', 'clips'].includes(mediaType)) { - new View({ - view: mediaType === 'clips' ? 'clip-specific' : 'snapshot-specific', - target: ev.detail.target, - childIndex: ev.detail.childIndex, - }).dispatchChangeEvent(this); - } - }} - > - `; + + const fetchThumbnailsThenRender = async (): Promise => { + if (!this.hass || !this.browseMediaQueryParameters) { + return; + } + let parent: BrowseMediaSource | null; + try { + parent = await BrowseMediaUtil.browseMediaQuery( + this.hass, + this.browseMediaQueryParameters, + ); + } catch (e) { + return dispatchErrorMessageEvent(this, (e as Error).message); + } + + if (BrowseMediaUtil.getFirstTrueMediaChildIndex(parent) != null) { + return html` ) => { + const mediaType = this.browseMediaQueryParameters?.mediaType; + if (mediaType && ['snapshots', 'clips'].includes(mediaType)) { + new View({ + view: mediaType === 'clips' ? 'clip-specific' : 'snapshot-specific', + target: ev.detail.target, + childIndex: ev.detail.childIndex, + }).dispatchChangeEvent(this); + } + }} + > + `; + } + } + + return html`${until(fetchThumbnailsThenRender(), renderProgressIndicator())}`; } /** diff --git a/src/components/thumbnail-carousel.ts b/src/components/thumbnail-carousel.ts index 6bc62704..f3e90278 100644 --- a/src/components/thumbnail-carousel.ts +++ b/src/components/thumbnail-carousel.ts @@ -1,14 +1,11 @@ import { BrowseMediaUtil } from '../browse-media-util.js'; -import { CSSResultGroup, TemplateResult, html, unsafeCSS, LitElement } from 'lit'; +import { CSSResultGroup, TemplateResult, html, unsafeCSS } from 'lit'; import { customElement, property } from 'lit/decorators.js'; -import { until } from 'lit/directives/until'; -import type { BrowseMediaQueryParameters, BrowseMediaSource, ExtendedHomeAssistant, ThumbnailsControlConfig } from '../types.js'; +import type { BrowseMediaSource, ThumbnailsControlConfig } from '../types.js'; import { FrigateCardCarousel } from './carousel.js'; -import { HomeAssistant } from 'custom-card-helpers'; import { actionHandler } from '../action-handler-directive.js'; -import { dispatchErrorMessageEvent, dispatchFrigateCardEvent } from '../common.js'; -import { renderProgressIndicator } from './message.js'; +import { dispatchFrigateCardEvent } from '../common.js'; import thumbnailCarouselStyle from '../scss/thumbnail-carousel.scss'; @@ -19,56 +16,7 @@ export interface ThumbnailCarouselTap { } @customElement('frigate-card-thumbnail-carousel') -export class FrigateCardThumbnailCarousel extends LitElement { - @property({ attribute: false }) - protected hass?: HomeAssistant & ExtendedHomeAssistant; - - @property({ attribute: false }) - protected browseMediaQueryParameters?: BrowseMediaQueryParameters; - - @property({ attribute: false }) - protected config?: ThumbnailsControlConfig; - - @property({ attribute: false }) - protected highlightSelected = true; - - /** - * Master render method. - * @returns A rendered template. - */ - protected render(): TemplateResult | void { - return html`${until(this._render(), renderProgressIndicator())}`; - } - - /** - * Asyncronously render the element. - * @returns A rendered template. - */ - protected async _render(): Promise { - if (!this.hass || !this.browseMediaQueryParameters) { - return html``; - } - - let parent: BrowseMediaSource | null = null; - try { - parent = await BrowseMediaUtil.browseMediaQuery( - this.hass, - this.browseMediaQueryParameters, - ); - } catch (e) { - return dispatchErrorMessageEvent(this, (e as Error).message); - } - return html` - `; - } -} - -@customElement('frigate-card-thumbnail-carousel-core') -export class FrigateCardThumbnailCarouselCore extends FrigateCardCarousel { +export class FrigateCardThumbnailCarousel extends FrigateCardCarousel { @property({ attribute: false }) protected target?: BrowseMediaSource; diff --git a/src/components/viewer.ts b/src/components/viewer.ts index 89e2aa19..72475a53 100644 --- a/src/components/viewer.ts +++ b/src/components/viewer.ts @@ -16,7 +16,7 @@ import type { ViewerConfig, } from '../types.js'; import { FrigateCardCarousel } from './carousel.js'; -import { FrigateCardThumbnailCarouselCore, ThumbnailCarouselTap } from './thumbnail-carousel.js'; +import { FrigateCardThumbnailCarousel, ThumbnailCarouselTap } from './thumbnail-carousel.js'; import { ResolvedMediaCache, ResolvedMediaUtil } from '../resolved-media.js'; import { View } from '../view.js'; import { actionHandler } from '../action-handler-directive.js'; @@ -165,7 +165,7 @@ export class FrigateCardViewerCore extends LitElement { protected resolvedMediaCache?: ResolvedMediaCache; protected _mediaCarouselRef: Ref = createRef(); - protected _thumbnailCarouselRef: Ref = createRef(); + protected _thumbnailCarouselRef: Ref = createRef(); protected _syncThumbnailCarousel(): void { const mediaSelected = this._mediaCarouselRef.value?.carouselSelected(); @@ -179,7 +179,7 @@ export class FrigateCardViewerCore extends LitElement { return html``; } - return html` - `; + `; } protected render(): TemplateResult | void { diff --git a/src/scss/viewer-core.scss b/src/scss/viewer-core.scss index 7dcf4a98..071dafda 100644 --- a/src/scss/viewer-core.scss +++ b/src/scss/viewer-core.scss @@ -12,6 +12,6 @@ frigate-card-media-carousel { min-height: 0; } -frigate-card-thumbnail-carousel-core { +frigate-card-thumbnail-carousel { flex: 0 0 var(--frigate-card-carousel-thumbnail-size); } \ No newline at end of file