/* eslint-disable @typescript-eslint/no-explicit-any */ import { CSSResultGroup, LitElement, TemplateResult, html, unsafeCSS } from 'lit'; import { HomeAssistant } from 'custom-card-helpers'; import { customElement, property, state } from 'lit/decorators.js'; import { styleMap } from 'lit/directives/style-map.js'; import { CameraConfig, ExtendedHomeAssistant, GalleryConfig, frigateCardConfigDefaults, } from '../types.js'; import { BrowseMediaUtil } from '../browse-media-util.js'; import { View } from '../view.js'; import { renderProgressIndicator } from './message.js'; import galleryStyle from '../scss/gallery.scss'; const MAX_THUMBNAIL_WIDTH = 175; @customElement('frigate-card-gallery') export class FrigateCardGallery extends LitElement { @property({ attribute: false }) protected hass?: HomeAssistant & ExtendedHomeAssistant; @property({ attribute: false }) protected view?: Readonly; @property({ attribute: false }) protected cameraConfig?: CameraConfig; @property({ attribute: false }) protected galleryConfig?: GalleryConfig; /** * Master render method. * @returns A rendered template. */ protected render(): TemplateResult | void { if (!this.hass || !this.view || !this.cameraConfig) { return; } if (!this.view.target) { const browseMediaQueryParameters = BrowseMediaUtil.getBrowseMediaQueryParametersOrDispatchError( this, this.view, this.cameraConfig, ); if (!browseMediaQueryParameters) { return; } BrowseMediaUtil.fetchLatestMediaAndDispatchViewChange( this, this.hass, this.view, browseMediaQueryParameters, ); return renderProgressIndicator(); } return html` `; } /** * Get element styles. */ static get styles(): CSSResultGroup { return unsafeCSS(galleryStyle); } } @customElement('frigate-card-gallery-core') export class FrigateCardGalleryCore extends LitElement { @property({ attribute: false }) protected hass?: HomeAssistant & ExtendedHomeAssistant; @property({ attribute: false }) protected view?: Readonly; @property({ attribute: false }) protected galleryConfig?: GalleryConfig; protected _resizeObserver: ResizeObserver; @state() protected _columns = frigateCardConfigDefaults.event_gallery.min_columns; constructor() { super(); this._resizeObserver = new ResizeObserver(this._resizeHandler.bind(this)); } /** * Component connected callback. */ connectedCallback(): void { super.connectedCallback(); this._resizeObserver.observe(this); } /** * Component disconnected callback. */ disconnectedCallback(): void { this._resizeObserver.disconnect(); super.disconnectedCallback(); } /** * Handle gallery resize. */ protected _resizeHandler(): void { this._columns = Math.max( this.galleryConfig?.min_columns ?? frigateCardConfigDefaults.event_gallery.min_columns, Math.ceil(this.clientWidth / MAX_THUMBNAIL_WIDTH), ); } /** * Master render method. * @returns A rendered template. */ protected render(): TemplateResult | void { if ( !this.hass || !this.view || !this.view.target || !this.view.target.children || !(this.view.is('clips') || this.view.is('snapshots')) ) { return html``; } const itemStyle = { // Controls the number of columns in the gallery (allows for 5px gutter). width: `calc(${100 / this._columns}% - 5.25px)`, }; const folderStyle = { // Values derived from experimentation on typical Lovelace card sizes. 'font-size': `${Math.min( 1.1, (0.6 * (this.clientWidth / this._columns)) / 50.0, )}em`, }; return html` `; } /** * Get styles. */ static get styles(): CSSResultGroup { return unsafeCSS(galleryStyle); } }