Wait for WebRTC component to definitely be loaded.

This commit is contained in:
Dermot Duffy
2022-01-28 23:42:17 -08:00
parent 1664abef53
commit 6a8278deee
4 changed files with 60 additions and 29 deletions
+28 -8
View File
@@ -22,6 +22,7 @@ import {
import { EmblaOptionsType, EmblaPluginType } from 'embla-carousel'; import { EmblaOptionsType, EmblaPluginType } from 'embla-carousel';
import { HomeAssistant } from 'custom-card-helpers'; import { HomeAssistant } from 'custom-card-helpers';
import { Ref, createRef, ref } from 'lit/directives/ref.js'; import { Ref, createRef, ref } from 'lit/directives/ref.js';
import { Task } from '@lit-labs/task';
import { customElement, property, state } from 'lit/decorators.js'; import { customElement, property, state } from 'lit/decorators.js';
import { until } from 'lit/directives/until.js'; import { until } from 'lit/directives/until.js';
@@ -681,6 +682,9 @@ export class FrigateCardLiveWebRTC extends LitElement {
protected hass?: HomeAssistant & ExtendedHomeAssistant; protected hass?: HomeAssistant & ExtendedHomeAssistant;
// A task to await the load of the WebRTC component.
protected _webrtcTask = new Task(this, this._getWebRTCElement, () => [1]);
/** /**
* Play the video. * Play the video.
*/ */
@@ -709,14 +713,22 @@ export class FrigateCardLiveWebRTC extends LitElement {
return this.renderRoot?.querySelector('#video') as HTMLVideoElement | null; return this.renderRoot?.querySelector('#video') as HTMLVideoElement | null;
} }
protected async _getWebRTCElement(): Promise<CustomElementConstructor | undefined> {
await customElements.whenDefined('webrtc-camera');
return customElements.get('webrtc-camera');
}
/** /**
* Create the WebRTC element. May throw. * Create the WebRTC element. May throw.
*/ */
protected _createWebRTC(): HTMLElement | undefined { protected _createWebRTC(): HTMLElement | undefined {
// 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 = this._webrtcTask.value;
if (webrtcElement) { if (webrtcElement && this.hass) {
const webrtc = new webrtcElement(); const webrtc = new webrtcElement() as HTMLElement & {
hass: HomeAssistant;
setConfig: (config: Record<string, unknown>) => void;
};
const config = { ...this.webRTCConfig }; const config = { ...this.webRTCConfig };
// If the live WebRTC configuration does not specify a URL/entity to use, // If the live WebRTC configuration does not specify a URL/entity to use,
@@ -731,9 +743,8 @@ export class FrigateCardLiveWebRTC extends LitElement {
webrtc.setConfig(config); webrtc.setConfig(config);
webrtc.hass = this.hass; webrtc.hass = this.hass;
return webrtc; return webrtc;
} else {
throw new FrigateCardError(localize('error.webrtc_missing'));
} }
return undefined;
} }
/** /**
@@ -741,9 +752,7 @@ export class FrigateCardLiveWebRTC extends LitElement {
* @returns A rendered template. * @returns A rendered template.
*/ */
protected render(): TemplateResult | void { protected render(): TemplateResult | void {
if (!this.hass) { const render = (): TemplateResult | void => {
return;
}
let webrtcElement: HTMLElement | undefined; let webrtcElement: HTMLElement | undefined;
try { try {
webrtcElement = this._createWebRTC(); webrtcElement = this._createWebRTC();
@@ -756,6 +765,17 @@ export class FrigateCardLiveWebRTC extends LitElement {
); );
} }
return html`${webrtcElement}`; return html`${webrtcElement}`;
};
// Use a task to allow us to asynchronously wait for the WebRTC card to
// load, but yet still have the card load be followed by the updated()
// lifecycle callback (unlike just using `until`).
return html`${this._webrtcTask.render({
initial: () => renderProgressIndicator(localize('error.webrtc_waiting')),
pending: () => renderProgressIndicator(localize('error.webrtc_waiting')),
error: (e: unknown) => dispatchErrorMessageEvent(this, (e as Error).message),
complete: () => render(),
})}`;
} }
/** /**
+13 -6
View File
@@ -22,9 +22,7 @@ export class FrigateCardMessage extends LitElement {
<span> <span>
<ha-icon icon="${icon}"> </ha-icon> <ha-icon icon="${icon}"> </ha-icon>
</span> </span>
<span> <span> ${this.message ? html`${this.message}` : ''} </span>
${this.message ? html`${this.message}` : ''}
</span>
</div>`; </div>`;
} }
@@ -50,9 +48,15 @@ export class FrigateCardErrorMessage extends LitElement {
@customElement('frigate-card-progress-indicator') @customElement('frigate-card-progress-indicator')
export class FrigateCardProgressIndicator extends LitElement { export class FrigateCardProgressIndicator extends LitElement {
@property({ attribute: false })
protected message = '';
protected render(): TemplateResult { protected render(): TemplateResult {
return html` <div class="message"> return html` <div class="message vertical">
<span>
<ha-circular-progress active="true" size="large"> </ha-circular-progress> <ha-circular-progress active="true" size="large"> </ha-circular-progress>
</span>
${this.message ? html`<span>${this.message}</span>` : html``}
</div>`; </div>`;
} }
@@ -75,6 +79,9 @@ export function renderMessage(message: Message): TemplateResult {
return html``; return html``;
} }
export function renderProgressIndicator(): TemplateResult { export function renderProgressIndicator(message?: string): TemplateResult {
return html` <frigate-card-progress-indicator> </frigate-card-progress-indicator> `; return html`
<frigate-card-progress-indicator .message=${message || ''}>
</frigate-card-progress-indicator>
`;
} }
+1 -1
View File
@@ -179,8 +179,8 @@
"invalid_configuration": "Invalid configuration", "invalid_configuration": "Invalid configuration",
"invalid_configuration_no_hint": "No location hint available (bad or missing type?)", "invalid_configuration_no_hint": "No location hint available (bad or missing type?)",
"upgrade_available": "An automated card configuration upgrade is available, please visit the visual card editor", "upgrade_available": "An automated card configuration upgrade is available, please visit the visual card editor",
"webrtc_missing": "WebRTC component not found",
"webrtc_reported_error": "WebRTC component reported an error", "webrtc_reported_error": "WebRTC component reported an error",
"webrtc_waiting": "Waiting for WebRTC Card to load ...",
"no_cameras": "No valid cameras found, you must configure at least one camera entry", "no_cameras": "No valid cameras found, you must configure at least one camera entry",
"no_camera_id": "Could not determine camera id for the following camera, may need to set 'id' parameter manually", "no_camera_id": "Could not determine camera id for the following camera, may need to set 'id' parameter manually",
"duplicate_camera_id": "Duplicate Frigate camera id for the following camera, use the 'id' parameter to uniquely identify cameras", "duplicate_camera_id": "Duplicate Frigate camera id for the following camera, use the 'id' parameter to uniquely identify cameras",
+4
View File
@@ -13,6 +13,10 @@
padding: 10%; padding: 10%;
} }
.vertical {
flex-direction: column;
}
.message a { .message a {
color: var(--primary-text-color, white); color: var(--primary-text-color, white);
} }