From c4995a8fb3407418865014c47ce0a85d2dad1325 Mon Sep 17 00:00:00 2001 From: Dermot Duffy Date: Sun, 7 Aug 2022 19:02:57 -0700 Subject: [PATCH] Refactor media load events to add unload. --- src/card.ts | 32 +++---- src/components/live.ts | 42 +++++---- src/components/media-carousel.ts | 148 +++++++++++++++++++++---------- src/components/viewer.ts | 19 ++-- src/types.ts | 2 +- src/utils/media-info.ts | 42 +++++---- src/view.ts | 2 +- 7 files changed, 176 insertions(+), 111 deletions(-) diff --git a/src/card.ts b/src/card.ts index cb512052..1776ed2e 100644 --- a/src/card.ts +++ b/src/card.ts @@ -60,7 +60,7 @@ import { FrigateCardCustomAction, FrigateCardView, FRIGATE_CARD_VIEWS_USER_SPECIFIED, - MediaShowInfo, + MediaLoadedInfo, MEDIA_TYPE_IMAGE, MEDIA_TYPE_VIDEO, MESSAGE_TYPE_PRIORITIES, @@ -96,7 +96,7 @@ import { } from './utils/ha/entity-registry.js'; import { ResolvedMediaCache } from './utils/ha/resolved-media.js'; import { supportsFeature } from './utils/ha/update.js'; -import { isValidMediaShowInfo } from './utils/media-info.js'; +import { isValidMediaLoadedInfo } from './utils/media-info.js'; import { View } from './view.js'; import pkg from '../package.json'; import { ViewContext } from 'view'; @@ -186,8 +186,8 @@ export class FrigateCard extends LitElement { protected _updateTimerID: number | null = null; // Information about loaded media items. - protected _currentMediaShowInfo: MediaShowInfo | null = null; - protected _lastValidMediaShowInfo: MediaShowInfo | null = null; + protected _currentMediaLoadedInfo: MediaLoadedInfo | null = null; + protected _lastValidMediaLoadedInfo: MediaLoadedInfo | null = null; // Array of dynamic menu buttons to be added to menu. protected _dynamicMenuButtons: MenuButton[] = []; @@ -279,7 +279,7 @@ export class FrigateCard extends LitElement { fullscreen: screenfull.isEnabled && screenfull.isFullscreen, camera: this._view?.camera, state: this._hass?.states, - mediaLoaded: !!this._currentMediaShowInfo, + mediaLoaded: !!this._currentMediaLoadedInfo, }; // Update the components that need the new condition state. Passed directly @@ -934,7 +934,7 @@ export class FrigateCard extends LitElement { protected _changeView(args?: { view?: View; resetMessage?: boolean }): void { const changeView = (view: View): void => { if (View.isMediaChange(this._view, view)) { - this._currentMediaShowInfo = null; + this._currentMediaLoadedInfo = null; } this._view = view; this._generateConditionState(); @@ -1629,17 +1629,17 @@ export class FrigateCard extends LitElement { /** * Handle a new piece of media being shown. - * @param e Event with MediaShowInfo details for the media. + * @param ev Event with MediaLoadedInfo details for the media. */ - protected _mediaShowHandler(e: CustomEvent): void { - const mediaShowInfo = e.detail; + protected _mediaLoadedHandler(ev: CustomEvent): void { + const mediaLoadedInfo = ev.detail; // In Safari, with WebRTC, 0x0 is occasionally returned during loading, // so treat anything less than a safety cutoff as bogus. - if (!isValidMediaShowInfo(mediaShowInfo)) { + if (!isValidMediaLoadedInfo(mediaLoadedInfo)) { return; } - this._lastValidMediaShowInfo = this._currentMediaShowInfo = mediaShowInfo; + this._lastValidMediaLoadedInfo = this._currentMediaLoadedInfo = mediaLoadedInfo; // An update may be required to draw elements. this._generateConditionState(); @@ -1719,8 +1719,8 @@ export class FrigateCard extends LitElement { } const aspectRatioMode = this._getConfig().dimensions.aspect_ratio_mode; - if (aspectRatioMode == 'dynamic' && this._lastValidMediaShowInfo) { - return `${this._lastValidMediaShowInfo.width} / ${this._lastValidMediaShowInfo.height}`; + if (aspectRatioMode == 'dynamic' && this._lastValidMediaLoadedInfo) { + return `${this._lastValidMediaLoadedInfo.width} / ${this._lastValidMediaLoadedInfo.height}`; } const defaultAspectRatio = this._getConfig().dimensions.aspect_ratio; @@ -1796,7 +1796,7 @@ export class FrigateCard extends LitElement { @frigate-card:message=${this._messageHandler.bind(this)} @frigate-card:view:change=${this._changeViewHandler.bind(this)} @frigate-card:view:change-context=${this._addViewContextHandler.bind(this)} - @frigate-card:media-show=${this._mediaShowHandler.bind(this)} + @frigate-card:media:loaded=${this._mediaLoadedHandler.bind(this)} @frigate-card:render=${() => this.requestUpdate()} > ${renderMenuAbove ? this._renderMenu() : ''} @@ -1940,8 +1940,8 @@ export class FrigateCard extends LitElement { * @returns The Lovelace card size in units of 50px. */ public getCardSize(): number { - if (this._lastValidMediaShowInfo) { - return this._lastValidMediaShowInfo.height / 50; + if (this._lastValidMediaLoadedInfo) { + return this._lastValidMediaLoadedInfo.height / 50; } return 6; } diff --git a/src/components/live.ts b/src/components/live.ts index 86109a75..2e7be0ed 100644 --- a/src/components/live.ts +++ b/src/components/live.ts @@ -35,7 +35,7 @@ import { LiveConfig, LiveOverrides, LiveProvider, - MediaShowInfo, + MediaLoadedInfo, Message, TransitionEffect, WebRTCCardConfig, @@ -46,15 +46,17 @@ import { getCameraIcon, getCameraTitle } from '../utils/camera.js'; import { homeAssistantSignPath } from '../utils/ha'; import { getFullDependentBrowseMediaQueryParameters } from '../utils/ha/browse-media.js'; import { - dispatchExistingMediaShowInfoAsEvent, + dispatchExistingMediaLoadedInfoAsEvent, dispatchMediaShowEvent, + dispatchMediaUnloadedEvent, } from '../utils/media-info.js'; import { dispatchViewContextChangeEvent, View } from '../view.js'; import { AutoMediaPlugin } from './embla-plugins/automedia.js'; import { Lazyload } from './embla-plugins/lazyload.js'; import { FrigateCardMediaCarousel, - wrapMediaShowEventForCarousel, + wrapMediaLoadedEventForCarousel, + wrapMediaUnloadedEventForCarousel, } from './media-carousel.js'; import { dispatchErrorMessageEvent } from './message.js'; import './next-prev-control.js'; @@ -101,9 +103,9 @@ export class FrigateCardLive extends LitElement { // foreground and background (in preload mode). protected _intersectionObserver: IntersectionObserver; - // MediaShowInfo object and message from the underlying live object. In the + // MediaLoadedInfo object and message from the underlying live object. In the // case of pre-loading these may be propagated upwards later. - protected _savedMediaShowInfo: MediaShowInfo | null = null; + protected _savedMediaLoadedInfo: MediaLoadedInfo | null = null; protected _messageReceivedPostRender = false; protected _renderKey = 0; @@ -124,11 +126,11 @@ export class FrigateCardLive extends LitElement { if ( !this._inBackground && !this._messageReceivedPostRender && - this._savedMediaShowInfo + this._savedMediaLoadedInfo ) { // 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. - dispatchExistingMediaShowInfoAsEvent(this, this._savedMediaShowInfo); + dispatchExistingMediaLoadedInfoAsEvent(this, this._savedMediaLoadedInfo); } // Trigger a re-render which may be necessary if the prior render resulted @@ -219,8 +221,8 @@ export class FrigateCardLive extends LitElement { ev.stopPropagation(); } }} - @frigate-card:media-show=${(ev: CustomEvent) => { - this._savedMediaShowInfo = ev.detail; + @frigate-card:media:loaded=${(ev: CustomEvent) => { + this._savedMediaLoadedInfo = ev.detail; if (this._inBackground) { ev.stopPropagation(); } @@ -509,8 +511,11 @@ export class FrigateCardLiveCarousel extends LitElement { .label=${getCameraTitle(this.hass, cameraConfig)} .liveConfig=${config} .hass=${this.hass} - @frigate-card:media-show=${(e: CustomEvent) => { - wrapMediaShowEventForCarousel(slideIndex, e); + @frigate-card:media:loaded=${(ev: CustomEvent) => { + wrapMediaLoadedEventForCarousel(slideIndex, ev); + }} + @frigate-card:media:unloaded=${(ev: CustomEvent) => { + wrapMediaUnloadedEventForCarousel(slideIndex, ev); }} > @@ -739,9 +744,12 @@ export class FrigateCardLiveProvider extends LitElement { /** * Called before each update. */ - protected willUpdate(): void { - if (this.disabled) { - this._isVideoMediaLoaded = false; + protected willUpdate(changedProps: PropertyValues): void { + if (changedProps.has('disabled')) { + if (this.disabled) { + this._isVideoMediaLoaded = false; + dispatchMediaUnloadedEvent(this); + } } } @@ -782,7 +790,7 @@ export class FrigateCardLiveProvider extends LitElement { class=${classMap(providerClasses)} .hass=${this.hass} .cameraConfig=${this.cameraConfig} - @frigate-card:media-show=${this._videoMediaShowHandler.bind(this)} + @frigate-card:media:loaded=${this._videoMediaShowHandler.bind(this)} > ` : provider === 'webrtc-card' @@ -792,7 +800,7 @@ export class FrigateCardLiveProvider extends LitElement { .hass=${this.hass} .cameraConfig=${this.cameraConfig} .webRTCConfig=${this.liveConfig.webrtc_card} - @frigate-card:media-show=${this._videoMediaShowHandler.bind(this)} + @frigate-card:media:loaded=${this._videoMediaShowHandler.bind(this)} > ` : html` `} `; diff --git a/src/components/media-carousel.ts b/src/components/media-carousel.ts index f1b31b7e..d4192897 100644 --- a/src/components/media-carousel.ts +++ b/src/components/media-carousel.ts @@ -5,16 +5,16 @@ 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 { - MediaShowInfo, + MediaLoadedInfo, NextPreviousControlConfig, TitleControlConfig, TransitionEffect, } from '../types.js'; import { dispatchFrigateCardEvent } from '../utils/basic'; import { - createMediaShowInfo, - dispatchExistingMediaShowInfoAsEvent, - isValidMediaShowInfo, + createMediaLoadedInfo, + dispatchExistingMediaLoadedInfoAsEvent, + isValidMediaLoadedInfo, } from '../utils/media-info.js'; import { CarouselSelect, EmblaCarouselPlugins, FrigateCardCarousel } from './carousel'; import { AutoMediaType } from './embla-plugins/automedia.js'; @@ -27,58 +27,93 @@ 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`; export const IMG_EMPTY = getEmptyImageSrc(16, 9); -export interface CarouselMediaShowInfo { +export interface CarouselMediaLoadedInfo { + slide: number; + mediaLoadedInfo: MediaLoadedInfo; +} + +export interface CarouselMediaUnloadedInfo { slide: number; - mediaShowInfo: MediaShowInfo; } /** - * Dispatch a carousel media show event. + * Dispatch a carousel media loaded event. * @param target The target to send it from. - * @param carouselMediaShowInfo The CarouselMediaShowInfo. + * @param carouselMediaLoadedInfo The CarouselMediaLoadedInfo. */ -const dispatchFrigateCardCarouselMediaShow = ( +const dispatchFrigateCardCarouselMediaLoaded = ( target: EventTarget, - carouselMediaShowInfo: CarouselMediaShowInfo, + carouselMediaLoadedInfo: CarouselMediaLoadedInfo, ): void => { - dispatchFrigateCardEvent( + dispatchFrigateCardEvent( target, - 'carousel:media-show', - carouselMediaShowInfo, + 'carousel:media:loaded', + carouselMediaLoadedInfo, ); }; /** - * Turn a MediaShowEvent into a CarouselMediaShowInfo. + * Dispatch a carousel media UNloaded event. + * @param target The target to send it from. + * @param carouselMediaUnloadedInfo The CarouselMediaUnloadedInfo. + */ +const dispatchFrigateCardCarouselMediaUnloaded = ( + target: EventTarget, + carouselMediaUnloadedInfo: CarouselMediaUnloadedInfo, +): void => { + dispatchFrigateCardEvent( + target, + 'carousel:media:unloaded', + carouselMediaUnloadedInfo, + ); +}; + +/** + * Turn a MediaLoadedInfo into a CarouselMediaLoadedInfo. * @param slide The slide number. * @param event The MediaShowEvent. */ -export const wrapMediaShowEventForCarousel = ( +export const wrapMediaLoadedEventForCarousel = ( slide: number, - event: CustomEvent, + event: CustomEvent, ) => { event.stopPropagation(); - dispatchFrigateCardCarouselMediaShow(event.composedPath()[0], { + dispatchFrigateCardCarouselMediaLoaded(event.composedPath()[0], { slide: slide, - mediaShowInfo: event.detail, + mediaLoadedInfo: event.detail, }); }; /** - * Turn a (stock) media load event into a CarouselMediaShowInfo. + * Turn a (raw, e.g. img) media load event into a CarouselMediaLoadedInfo. * @param slide The slide number. * @param event The MediaShowEvent. */ -export const wrapMediaLoadEventForCarousel = (slide: number, event: Event) => { - const mediaShowInfo = createMediaShowInfo(event); - if (mediaShowInfo) { - dispatchFrigateCardCarouselMediaShow(event.composedPath()[0], { +export const wrapRawMediaLoadedEventForCarousel = (slide: number, event: Event) => { + const mediaLoadedInfo = createMediaLoadedInfo(event); + if (mediaLoadedInfo) { + dispatchFrigateCardCarouselMediaLoaded(event.composedPath()[0], { slide: slide, - mediaShowInfo: mediaShowInfo, + mediaLoadedInfo: mediaLoadedInfo, }); } }; +/** + * Turn a MediaUnloadedInfo into a CarouselMediaUnloadedInfo. + * @param slide The slide number. + * @param event The MediaUnloadedEvent. + */ +export const wrapMediaUnloadedEventForCarousel = ( + slide: number, + event: CustomEvent, +) => { + event.stopPropagation(); + dispatchFrigateCardCarouselMediaUnloaded(event.composedPath()[0], { + slide: slide, + }); +}; + @customElement('frigate-card-media-carousel') export class FrigateCardMediaCarousel extends LitElement { @property({ attribute: false }) @@ -99,8 +134,8 @@ export class FrigateCardMediaCarousel extends LitElement { @property({ attribute: false }) public titlePopupConfig?: TitleControlConfig; - // A "map" from slide number to MediaShowInfo object. - protected _mediaShowInfo: Record = {}; + // A "map" from slide number to MediaLoadedInfo object. + protected _mediaLoadedInfo: Record = {}; protected _nextControlRef: Ref = createRef(); protected _previousControlRef: Ref = createRef(); protected _titleControlRef: Ref = createRef(); @@ -233,13 +268,13 @@ export class FrigateCardMediaCarousel extends LitElement { connectedCallback(): void { super.connectedCallback(); - this.addEventListener('frigate-card:media-show', this._boundAutoPlayHandler); - this.addEventListener('frigate-card:media-show', this._boundAutoUnmuteHandler); + this.addEventListener('frigate-card:media:loaded', this._boundAutoPlayHandler); + this.addEventListener('frigate-card:media:loaded', this._boundAutoUnmuteHandler); this.addEventListener( - 'frigate-card:media-show', + 'frigate-card:media:loaded', this._boundAdaptContainerHeightToSlide, ); - this.addEventListener('frigate-card:media-show', this._boundTitleHandler); + this.addEventListener('frigate-card:media:loaded', this._boundTitleHandler); this._resizeObserver.observe(this); this._intersectionObserver.observe(this); } @@ -248,13 +283,13 @@ export class FrigateCardMediaCarousel extends LitElement { * Component disconnected callback. */ disconnectedCallback(): void { - this.removeEventListener('frigate-card:media-show', this._boundAutoPlayHandler); - this.removeEventListener('frigate-card:media-show', this._boundAutoUnmuteHandler); + this.removeEventListener('frigate-card:media:loaded', this._boundAutoPlayHandler); + this.removeEventListener('frigate-card:media:loaded', this._boundAutoUnmuteHandler); this.removeEventListener( - 'frigate-card:media-show', + 'frigate-card:media:loaded', this._boundAdaptContainerHeightToSlide, ); - this.removeEventListener('frigate-card:media-show', this._boundTitleHandler); + this.removeEventListener('frigate-card:media:loaded', this._boundTitleHandler); this._resizeObserver.disconnect(); this._intersectionObserver.disconnect(); @@ -312,7 +347,7 @@ export class FrigateCardMediaCarousel extends LitElement { // Hack: This method attempts to measure the height of the selected slide in // order to set the overall carousel height to match. This method is - // triggered from `frigate-card:media-show` events, which are usually in + // triggered from `frigate-card:media:loaded` events, which are usually in // turn triggered from media/metadata load events from media players. // Sufficient time needs to be allowed after these metadata load events to // allow the browser to repaint the element heights, so that we can get the @@ -323,43 +358,57 @@ export class FrigateCardMediaCarousel extends LitElement { /** * Fire a media show event when a slide is selected. */ - protected _dispatchMediaShowInfo(): void { + protected _dispatchMediaLoadedInfo(): void { const slideIndex = this.frigateCardCarousel()?.getCarouselSelected()?.index; - if (slideIndex !== undefined && slideIndex in this._mediaShowInfo) { - dispatchExistingMediaShowInfoAsEvent(this, this._mediaShowInfo[slideIndex]); + if (slideIndex !== undefined && slideIndex in this._mediaLoadedInfo) { + dispatchExistingMediaLoadedInfoAsEvent(this, this._mediaLoadedInfo[slideIndex]); } } /** - * Handle a media-show event that is generated by a child component, saving the + * Handle a media:loaded 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. + * @param event The media:loaded event from the child component. */ - protected _storeMediaShowInfo(event: CustomEvent): void { + protected _storeMediaLoadedInfo(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(); - const mediaShowInfo = event.detail.mediaShowInfo; + const mediaLoadedInfo = event.detail.mediaLoadedInfo; const slideIndex = event.detail.slide; - // isValidMediaShowInfo is used to prevent saving media info that will be + // isValidMediaLoadedInfo is used to prevent saving media info that will be // rejected upstream (empty 1x1 images will be rejected here). - if (mediaShowInfo && isValidMediaShowInfo(mediaShowInfo)) { - this._mediaShowInfo[slideIndex] = mediaShowInfo; + if (mediaLoadedInfo && isValidMediaLoadedInfo(mediaLoadedInfo)) { + this._mediaLoadedInfo[slideIndex] = mediaLoadedInfo; if (this.frigateCardCarousel()?.getCarouselSelected()?.index === slideIndex) { - dispatchExistingMediaShowInfoAsEvent(this, mediaShowInfo); + dispatchExistingMediaLoadedInfoAsEvent(this, mediaLoadedInfo); } } } + /** + * Remove a media loaded info (i.e. a media item has unloaded). + * @param event The CarouselMediaUnloadedInfo event. + */ + protected _removeMediaLoadedInfo(event: CustomEvent): void { + const slideIndex = event.detail.slide; + delete this._mediaLoadedInfo[slideIndex]; + + // If the slide that unloaded is not visible, don't propagate the event upwards. + if (this.frigateCardCarousel()?.getCarouselSelected()?.index !== slideIndex) { + event.stopPropagation(); + } + } + protected render(): TemplateResult | void { return html` ) => { this._slideResizeObserver.disconnect(); this._slideResizeObserver.observe(ev.detail.element); @@ -373,9 +422,10 @@ export class FrigateCardMediaCarousel extends LitElement { ); // Dispatch media info. - this._dispatchMediaShowInfo(); + this._dispatchMediaLoadedInfo(); }} - @frigate-card:carousel:media-show=${this._storeMediaShowInfo.bind(this)} + @frigate-card:carousel:media:loaded=${this._storeMediaLoadedInfo.bind(this)} + @frigate-card:carousel:media:unloaded=${this._removeMediaLoadedInfo.bind(this)} > diff --git a/src/components/viewer.ts b/src/components/viewer.ts index 3a932472..44d54b6c 100644 --- a/src/components/viewer.ts +++ b/src/components/viewer.ts @@ -13,10 +13,7 @@ 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'; -import { - dispatchFrigateCardErrorEvent, - renderProgressIndicator, -} from '../components/message.js'; +import { renderProgressIndicator } from '../components/message.js'; import viewerStyle from '../scss/viewer.scss'; import viewerCarouselStyle from '../scss/viewer-carousel.scss'; import { @@ -27,7 +24,7 @@ import { FrigateBrowseMediaSource, frigateCardConfigDefaults, FrigateCardMediaPlayer, - MediaShowInfo, + MediaLoadedInfo, TransitionEffect, ViewerConfig, } from '../types.js'; @@ -48,8 +45,8 @@ import { Lazyload } from './embla-plugins/lazyload.js'; import { FrigateCardMediaCarousel, IMG_EMPTY, - wrapMediaLoadEventForCarousel, - wrapMediaShowEventForCarousel, + wrapRawMediaLoadedEventForCarousel, + wrapMediaLoadedEventForCarousel, } from './media-carousel.js'; import './next-prev-control.js'; import './title-control.js'; @@ -619,7 +616,7 @@ export class FrigateCardViewerCarousel extends LitElement { .titlePopupConfig=${this.viewerConfig?.controls.title} transitionEffect=${this._getTransitionEffect()} @frigate-card:media-carousel:select=${this._setViewHandler.bind(this)} - @frigate-card:media-show=${this._recordingSeekHandler.bind(this)} + @frigate-card:media:loaded=${this._recordingSeekHandler.bind(this)} > ) => { - wrapMediaShowEventForCarousel(slideIndex, e); + @frigate-card:media:loaded=${(e: CustomEvent) => { + wrapMediaLoadedEventForCarousel(slideIndex, e); }} > ` @@ -743,7 +740,7 @@ export class FrigateCardViewerCarousel extends LitElement { !lazyLoad || lazyloadPlugin?.hasLazyloaded(slideIndex) ) { - wrapMediaLoadEventForCarousel(slideIndex, e); + wrapRawMediaLoadedEventForCarousel(slideIndex, e); } }}" />`} diff --git a/src/types.ts b/src/types.ts index 3153b742..c7c33be7 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1203,7 +1203,7 @@ export interface BrowseMediaNeighbors { nextIndex: number | null; } -export interface MediaShowInfo { +export interface MediaLoadedInfo { width: number; height: number; } diff --git a/src/utils/media-info.ts b/src/utils/media-info.ts index d5482b51..f7fcee69 100644 --- a/src/utils/media-info.ts +++ b/src/utils/media-info.ts @@ -1,15 +1,17 @@ -import { MediaShowInfo } from '../types.js'; +import { MediaLoadedInfo } from '../types.js'; import { dispatchFrigateCardEvent } from './basic.js'; const MEDIA_INFO_HEIGHT_CUTOFF = 50; const MEDIA_INFO_WIDTH_CUTOFF = MEDIA_INFO_HEIGHT_CUTOFF; /** - * Create a MediaShowInfo object. + * Create a MediaLoadedInfo object. * @param source An event or HTMLElement that should be used as a source. - * @returns A new MediaShowInfo object or null if one could not be created. + * @returns A new MediaLoadedInfo object or null if one could not be created. */ -export function createMediaShowInfo(source: Event | HTMLElement): MediaShowInfo | null { +export function createMediaLoadedInfo( + source: Event | HTMLElement, +): MediaLoadedInfo | null { let target: HTMLElement | EventTarget; if (source instanceof Event) { target = source.composedPath()[0]; @@ -37,7 +39,7 @@ export function createMediaShowInfo(source: Event | HTMLElement): MediaShowInfo } /** - * Dispatch a Frigate card media show event. + * Dispatch a Frigate card media loaded event. * @param element The element to send the event. * @param source An event or HTMLElement that should be used as a source. */ @@ -45,31 +47,39 @@ export function dispatchMediaShowEvent( element: HTMLElement, source: Event | HTMLElement, ): void { - const mediaShowInfo = createMediaShowInfo(source); - if (mediaShowInfo) { - dispatchExistingMediaShowInfoAsEvent(element, mediaShowInfo); + const mediaLoadedInfo = createMediaLoadedInfo(source); + if (mediaLoadedInfo) { + dispatchExistingMediaLoadedInfoAsEvent(element, mediaLoadedInfo); } } /** - * Dispatch a pre-existing MediaShowInfo object as an event. + * Dispatch a pre-existing MediaLoadedInfo object as an event. * @param element The element to send the event. - * @param mediaShowInfo The MediaShowInfo object to send. + * @param MediaLoadedInfo The MediaLoadedInfo object to send. */ -export function dispatchExistingMediaShowInfoAsEvent( +export function dispatchExistingMediaLoadedInfoAsEvent( element: HTMLElement, - mediaShowInfo: MediaShowInfo, + MediaLoadedInfo: MediaLoadedInfo, ): void { - dispatchFrigateCardEvent(element, 'media-show', mediaShowInfo); + dispatchFrigateCardEvent(element, 'media:loaded', MediaLoadedInfo); } /** - * Determine if a MediaShowInfo object is valid/acceptable. - * @param info The MediaShowInfo object. + * Determine if a MediaLoadedInfo object is valid/acceptable. + * @param info The MediaLoadedInfo object. * @returns True if the object is valid, false otherwise. */ -export function isValidMediaShowInfo(info: MediaShowInfo): boolean { +export function isValidMediaLoadedInfo(info: MediaLoadedInfo): boolean { return ( info.height >= MEDIA_INFO_HEIGHT_CUTOFF && info.width >= MEDIA_INFO_WIDTH_CUTOFF ); } + +/** + * Dispatch a media unloaded event. + * @param element The element to send the event. + */ +export function dispatchMediaUnloadedEvent(element: HTMLElement): void { + dispatchFrigateCardEvent(element, 'media:unloaded'); +} diff --git a/src/view.ts b/src/view.ts index 8b5cc665..9c75b90f 100644 --- a/src/view.ts +++ b/src/view.ts @@ -152,7 +152,7 @@ export class View { /** * Determine if a view is of a piece of media (including the media viewer, - * live view, image view -- anything that can create a MediaShowInfo event). + * live view, image view -- anything that can create a MediaLoadedInfo event). */ public isAnyMediaView(): boolean { return this.isViewerView() || this.is('live') || this.is('image');