Add play/pause event support.
This commit is contained in:
+16
-33
@@ -106,8 +106,8 @@ export class FrigateCard extends LitElement {
|
|||||||
@query('frigate-card-menu')
|
@query('frigate-card-menu')
|
||||||
_menu!: FrigateCardMenu;
|
_menu!: FrigateCardMenu;
|
||||||
|
|
||||||
// Whether or not there is an active clip being played.
|
// Whether or not media is actively playing (live or clip).
|
||||||
protected _clipPlaying = false;
|
protected _mediaPlaying = false;
|
||||||
|
|
||||||
// A small cache to avoid needing to create a new list of entities every time
|
// A small cache to avoid needing to create a new list of entities every time
|
||||||
// a hass update arrives.
|
// a hass update arrives.
|
||||||
@@ -253,7 +253,7 @@ export class FrigateCard extends LitElement {
|
|||||||
// are browsing the mini-gallery). Do not allow re-rendering from a Home
|
// are browsing the mini-gallery). Do not allow re-rendering from a Home
|
||||||
// Assistant update if there's been recent interaction (e.g. clicks on the
|
// Assistant update if there's been recent interaction (e.g. clicks on the
|
||||||
// card) or if there is a clip active playing.
|
// card) or if there is a clip active playing.
|
||||||
if (this._interactionTimerID || this._clipPlaying) {
|
if (this._interactionTimerID || this._mediaPlaying) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return shouldUpdateBasedOnHass(this._hass, oldHass, this._entitiesToMonitor);
|
return shouldUpdateBasedOnHass(this._hass, oldHass, this._entitiesToMonitor);
|
||||||
@@ -294,35 +294,6 @@ export class FrigateCard extends LitElement {
|
|||||||
return `${this.config.frigate_url}/events?camera=${this.config.frigate_camera_name}`;
|
return `${this.config.frigate_url}/events?camera=${this.config.frigate_camera_name}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
public updated(): void {
|
|
||||||
this.updateComplete.then(() => {
|
|
||||||
// DOM elements are not always present until after updateComplete promise
|
|
||||||
// is resolved. Note that children of children (i.e. the underlying video
|
|
||||||
// element) is not always present even when the promise returns, so
|
|
||||||
// capture the event at the upper shadow root instead.
|
|
||||||
const hls_player = this.renderRoot
|
|
||||||
?.querySelector('ha-card')
|
|
||||||
?.querySelector('ha-hls-player');
|
|
||||||
|
|
||||||
if (hls_player) {
|
|
||||||
hls_player.shadowRoot?.addEventListener(
|
|
||||||
'play',
|
|
||||||
() => {
|
|
||||||
this._clipPlaying = true;
|
|
||||||
},
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
hls_player.shadowRoot?.addEventListener(
|
|
||||||
'pause',
|
|
||||||
() => {
|
|
||||||
this._clipPlaying = true;
|
|
||||||
},
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Record interactions with the card.
|
// Record interactions with the card.
|
||||||
protected _interactionHandler(): void {
|
protected _interactionHandler(): void {
|
||||||
if (!this.config.view_timeout) {
|
if (!this.config.view_timeout) {
|
||||||
@@ -363,6 +334,14 @@ export class FrigateCard extends LitElement {
|
|||||||
zone: this.config.zone,
|
zone: this.config.zone,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected _playHandler(): void {
|
||||||
|
this._mediaPlaying = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected _pauseHandler(): void {
|
||||||
|
this._mediaPlaying = false;
|
||||||
|
}
|
||||||
|
|
||||||
protected _mediaLoadHandler(e: CustomEvent<MediaLoadInfo>): void {
|
protected _mediaLoadHandler(e: CustomEvent<MediaLoadInfo>): void {
|
||||||
const mediaInfo = e.detail;
|
const mediaInfo = e.detail;
|
||||||
@@ -461,7 +440,9 @@ export class FrigateCard extends LitElement {
|
|||||||
.autoplayClip=${this.config.autoplay_clip}
|
.autoplayClip=${this.config.autoplay_clip}
|
||||||
@frigate-card:change-view=${this._changeViewHandler}
|
@frigate-card:change-view=${this._changeViewHandler}
|
||||||
@frigate-card:media-load=${this._mediaLoadHandler}
|
@frigate-card:media-load=${this._mediaLoadHandler}
|
||||||
>
|
@frigate-card:pause=${this._pauseHandler}
|
||||||
|
@frigate-card:play=${this._playHandler}
|
||||||
|
>
|
||||||
</frigate-card-viewer>`
|
</frigate-card-viewer>`
|
||||||
: ``}
|
: ``}
|
||||||
${this._view.is('live')
|
${this._view.is('live')
|
||||||
@@ -469,6 +450,8 @@ export class FrigateCard extends LitElement {
|
|||||||
.hass=${this._hass}
|
.hass=${this._hass}
|
||||||
.config=${this.config}
|
.config=${this.config}
|
||||||
@frigate-card:media-load=${this._mediaLoadHandler}
|
@frigate-card:media-load=${this._mediaLoadHandler}
|
||||||
|
@frigate-card:pause=${this._pauseHandler}
|
||||||
|
@frigate-card:play=${this._playHandler}
|
||||||
>
|
>
|
||||||
</frigate-card-live>`
|
</frigate-card-live>`
|
||||||
: ``}
|
: ``}
|
||||||
|
|||||||
+36
-8
@@ -7,7 +7,12 @@ import { signedPathSchema } from '../types';
|
|||||||
import type { ExtendedHomeAssistant, FrigateCardConfig } from '../types';
|
import type { ExtendedHomeAssistant, FrigateCardConfig } from '../types';
|
||||||
|
|
||||||
import { localize } from '../localize/localize';
|
import { localize } from '../localize/localize';
|
||||||
import { dispatchMediaLoadEvent, homeAssistantWSRequest } from '../common';
|
import {
|
||||||
|
dispatchMediaLoadEvent,
|
||||||
|
dispatchPauseEvent,
|
||||||
|
dispatchPlayEvent,
|
||||||
|
homeAssistantWSRequest,
|
||||||
|
} from '../common';
|
||||||
import {
|
import {
|
||||||
renderMessage,
|
renderMessage,
|
||||||
renderErrorMessage,
|
renderErrorMessage,
|
||||||
@@ -95,7 +100,6 @@ export class FrigateCardViewerWebRTC extends LitElement {
|
|||||||
protected _webRTCElement: HTMLElement | null = null;
|
protected _webRTCElement: HTMLElement | null = null;
|
||||||
|
|
||||||
protected _createWebRTC(): TemplateResult | void {
|
protected _createWebRTC(): TemplateResult | void {
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const webrtcElement = customElements.get('webrtc-camera') as any;
|
const webrtcElement = customElements.get('webrtc-camera') as any;
|
||||||
if (webrtcElement) {
|
if (webrtcElement) {
|
||||||
@@ -125,11 +129,30 @@ export class FrigateCardViewerWebRTC extends LitElement {
|
|||||||
this.updateComplete.then(() => {
|
this.updateComplete.then(() => {
|
||||||
const video = this.renderRoot.querySelector('#video') as HTMLVideoElement;
|
const video = this.renderRoot.querySelector('#video') as HTMLVideoElement;
|
||||||
if (video) {
|
if (video) {
|
||||||
video.onloadedmetadata = () => {
|
const onloadedmetadata = video.onloadedmetadata;
|
||||||
|
const onplay = video.onplay;
|
||||||
|
const onpause = video.onpause;
|
||||||
|
|
||||||
|
video.onloadedmetadata = (e) => {
|
||||||
|
if (onloadedmetadata) {
|
||||||
|
onloadedmetadata.call(video, e);
|
||||||
|
}
|
||||||
dispatchMediaLoadEvent(this, video);
|
dispatchMediaLoadEvent(this, video);
|
||||||
}
|
};
|
||||||
|
video.onplay = (e) => {
|
||||||
|
if (onplay) {
|
||||||
|
onplay.call(video, e);
|
||||||
|
}
|
||||||
|
dispatchPlayEvent(this);
|
||||||
|
};
|
||||||
|
video.onpause = (e) => {
|
||||||
|
if (onpause) {
|
||||||
|
onpause.call(video, e);
|
||||||
|
}
|
||||||
|
dispatchPauseEvent(this);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
@@ -212,11 +235,16 @@ export class FrigateCardViewerJSMPEG extends LitElement {
|
|||||||
// amount of time the canvas is empty (and show the spinner
|
// amount of time the canvas is empty (and show the spinner
|
||||||
// instead).
|
// instead).
|
||||||
play: () => {
|
play: () => {
|
||||||
|
dispatchPlayEvent(this);
|
||||||
resolve(html`${this._jsmpegCanvasElement}`);
|
resolve(html`${this._jsmpegCanvasElement}`);
|
||||||
},
|
},
|
||||||
|
pause: () => {
|
||||||
|
dispatchPauseEvent(this);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{ protocols: [],
|
{
|
||||||
|
protocols: [],
|
||||||
videoBufferSize: 1024 * 1024 * 4,
|
videoBufferSize: 1024 * 1024 * 4,
|
||||||
onVideoDecode: () => {
|
onVideoDecode: () => {
|
||||||
// This is the only callback that is called after the dimensions
|
// This is the only callback that is called after the dimensions
|
||||||
@@ -226,8 +254,8 @@ export class FrigateCardViewerJSMPEG extends LitElement {
|
|||||||
videoDecoded = true;
|
videoDecoded = true;
|
||||||
dispatchMediaLoadEvent(this, this._jsmpegCanvasElement);
|
dispatchMediaLoadEvent(this, this._jsmpegCanvasElement);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import {
|
|||||||
html,
|
html,
|
||||||
} from 'lit';
|
} from 'lit';
|
||||||
import { customElement } from 'lit/decorators';
|
import { customElement } from 'lit/decorators';
|
||||||
import { dispatchMediaLoadEvent } from '../common';
|
import { dispatchMediaLoadEvent, dispatchPauseEvent, dispatchPlayEvent } from '../common';
|
||||||
|
|
||||||
customElements.whenDefined("ha-hls-player").then(() => {
|
customElements.whenDefined("ha-hls-player").then(() => {
|
||||||
@customElement("frigate-card-ha-hls-player")
|
@customElement("frigate-card-ha-hls-player")
|
||||||
@@ -33,6 +33,8 @@ customElements.whenDefined("ha-hls-player").then(() => {
|
|||||||
?controls=${this.controls}
|
?controls=${this.controls}
|
||||||
@loadedmetadata=${(e) => dispatchMediaLoadEvent(this, e)}
|
@loadedmetadata=${(e) => dispatchMediaLoadEvent(this, e)}
|
||||||
@loadeddata=${this._elementResized}
|
@loadeddata=${this._elementResized}
|
||||||
|
@pause=${() => dispatchPauseEvent(this)}
|
||||||
|
@play=${() => dispatchPlayEvent(this)}
|
||||||
></video>
|
></video>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user