Add cheaper progress indicator.

This commit is contained in:
Dermot Duffy
2022-10-05 21:42:38 -07:00
parent 3566011d63
commit cae49e6dce
10 changed files with 96 additions and 22 deletions
+12 -1
View File
@@ -67,6 +67,7 @@ import {
MenuButton, MenuButton,
Message, Message,
RawFrigateCardConfig, RawFrigateCardConfig,
CardWideConfig,
} from './types.js'; } from './types.js';
import { import {
convertActionToFrigateCardCustomAction, convertActionToFrigateCardCustomAction,
@@ -166,6 +167,9 @@ export class FrigateCard extends LitElement {
protected _config!: FrigateCardConfig; protected _config!: FrigateCardConfig;
protected _rawConfig?: RawFrigateCardConfig; protected _rawConfig?: RawFrigateCardConfig;
@state()
protected _cardWideConfig?: CardWideConfig;
@state() @state()
protected _overriddenConfig?: FrigateCardConfig; protected _overriddenConfig?: FrigateCardConfig;
@@ -976,6 +980,10 @@ export class FrigateCard extends LitElement {
this._rawConfig = inputConfig; this._rawConfig = inputConfig;
this._config = config; this._config = config;
this._cardWideConfig = {
performance: config.performance,
};
this._overriddenConfig = undefined; this._overriddenConfig = undefined;
this._cameras = undefined; this._cameras = undefined;
this._view = undefined; this._view = undefined;
@@ -1919,7 +1927,7 @@ export class FrigateCard extends LitElement {
this._changeView({ resetMessage: false }); this._changeView({ resetMessage: false });
return this._render(); return this._render();
})(), })(),
renderProgressIndicator(), renderProgressIndicator({cardWideConfig: this._cardWideConfig}),
) )
: // Always want to call render even if there's a message, to : // Always want to call render even if there's a message, to
// ensure live preload is always present (even if not displayed). // ensure live preload is always present (even if not displayed).
@@ -1989,6 +1997,7 @@ export class FrigateCard extends LitElement {
.cameras=${this._cameras} .cameras=${this._cameras}
.galleryConfig=${this._getConfig().event_gallery} .galleryConfig=${this._getConfig().event_gallery}
.dataManager=${this._dataManager} .dataManager=${this._dataManager}
.cardWideConfig=${this._cardWideConfig}
> >
</frigate-card-gallery>` </frigate-card-gallery>`
: ``} : ``}
@@ -2000,6 +2009,7 @@ export class FrigateCard extends LitElement {
.viewerConfig=${this._getConfig().media_viewer} .viewerConfig=${this._getConfig().media_viewer}
.resolvedMediaCache=${this._resolvedMediaCache} .resolvedMediaCache=${this._resolvedMediaCache}
.dataManager=${this._dataManager} .dataManager=${this._dataManager}
.cardWideConfig=${this._cardWideConfig}
> >
</frigate-card-viewer>` </frigate-card-viewer>`
: ``} : ``}
@@ -2031,6 +2041,7 @@ export class FrigateCard extends LitElement {
.liveOverrides=${getOverridesByKey(this._getConfig().overrides, 'live')} .liveOverrides=${getOverridesByKey(this._getConfig().overrides, 'live')}
.cameras=${this._cameras} .cameras=${this._cameras}
.dataManager=${this._dataManager} .dataManager=${this._dataManager}
.cardWideConfig=${this._cardWideConfig}
class="${classMap(liveClasses)}" class="${classMap(liveClasses)}"
> >
</frigate-card-live> </frigate-card-live>
+5 -1
View File
@@ -11,6 +11,7 @@ import { customElement, property } from 'lit/decorators.js';
import galleryStyle from '../scss/gallery.scss'; import galleryStyle from '../scss/gallery.scss';
import { import {
CameraConfig, CameraConfig,
CardWideConfig,
ExtendedHomeAssistant, ExtendedHomeAssistant,
frigateCardConfigDefaults, frigateCardConfigDefaults,
GalleryConfig, GalleryConfig,
@@ -46,6 +47,9 @@ export class FrigateCardGallery extends LitElement {
@property({ attribute: false }) @property({ attribute: false })
public dataManager?: DataManager; public dataManager?: DataManager;
@property({ attribute: false })
public cardWideConfig?: CardWideConfig;
/** /**
* Master render method. * Master render method.
* @returns A rendered template. * @returns A rendered template.
@@ -96,7 +100,7 @@ export class FrigateCardGallery extends LitElement {
browseMediaQueryParameters, browseMediaQueryParameters,
); );
} }
return renderProgressIndicator(); return renderProgressIndicator({cardWideConfig: this.cardWideConfig});
} }
return html` return html`
+33 -4
View File
@@ -27,6 +27,7 @@ import liveCarouselStyle from '../scss/live-carousel.scss';
import liveProviderStyle from '../scss/live-provider.scss'; import liveProviderStyle from '../scss/live-provider.scss';
import { import {
CameraConfig, CameraConfig,
CardWideConfig,
ExtendedHomeAssistant, ExtendedHomeAssistant,
frigateCardConfigDefaults, frigateCardConfigDefaults,
FrigateCardError, FrigateCardError,
@@ -99,6 +100,9 @@ export class FrigateCardLive extends LitElement {
@property({ attribute: false }) @property({ attribute: false })
public dataManager?: DataManager; public dataManager?: DataManager;
@property({ attribute: false })
public cardWideConfig?: CardWideConfig;
// Whether or not the live view is currently in the background (i.e. preloaded // Whether or not the live view is currently in the background (i.e. preloaded
// but not visible) // but not visible)
@state() @state()
@@ -250,6 +254,7 @@ export class FrigateCardLive extends LitElement {
.inBackground=${this._inBackground} .inBackground=${this._inBackground}
.conditionState=${this.conditionState} .conditionState=${this.conditionState}
.liveOverrides=${this.liveOverrides} .liveOverrides=${this.liveOverrides}
.cardWideConfig=${this.cardWideConfig}
> >
</frigate-card-live-carousel> </frigate-card-live-carousel>
</frigate-card-surround>`, </frigate-card-surround>`,
@@ -290,6 +295,9 @@ export class FrigateCardLiveCarousel extends LitElement {
@property({ attribute: false }) @property({ attribute: false })
public conditionState?: ConditionState; public conditionState?: ConditionState;
@property({ attribute: false })
public cardWideConfig?: CardWideConfig;
// Index between camera name and slide number. // Index between camera name and slide number.
protected _cameraToSlide: Record<string, number> = {}; protected _cameraToSlide: Record<string, number> = {};
protected _refMediaCarousel: Ref<FrigateCardMediaCarousel> = createRef(); protected _refMediaCarousel: Ref<FrigateCardMediaCarousel> = createRef();
@@ -520,6 +528,7 @@ export class FrigateCardLiveCarousel extends LitElement {
.label=${getCameraTitle(this.hass, cameraConfig)} .label=${getCameraTitle(this.hass, cameraConfig)}
.liveConfig=${config} .liveConfig=${config}
.hass=${this.hass} .hass=${this.hass}
.cardWideConfig=${this.cardWideConfig}
@frigate-card:media:loaded=${(ev: CustomEvent<MediaLoadedInfo>) => { @frigate-card:media:loaded=${(ev: CustomEvent<MediaLoadedInfo>) => {
wrapMediaLoadedEventForCarousel(slideIndex, ev); wrapMediaLoadedEventForCarousel(slideIndex, ev);
}} }}
@@ -667,6 +676,9 @@ export class FrigateCardLiveProvider extends LitElement {
@property({ attribute: false }) @property({ attribute: false })
public label = ''; public label = '';
@property({ attribute: false })
public cardWideConfig?: CardWideConfig;
@state() @state()
protected _isVideoMediaLoaded = false; protected _isVideoMediaLoaded = false;
@@ -819,6 +831,7 @@ export class FrigateCardLiveProvider extends LitElement {
.hass=${this.hass} .hass=${this.hass}
.cameraConfig=${this.cameraConfig} .cameraConfig=${this.cameraConfig}
.webRTCConfig=${this.liveConfig.webrtc_card} .webRTCConfig=${this.liveConfig.webrtc_card}
.cardWideConfig=${this.cardWideConfig}
@frigate-card:media:loaded=${this._videoMediaShowHandler.bind(this)} @frigate-card:media:loaded=${this._videoMediaShowHandler.bind(this)}
> >
</frigate-card-live-webrtc-card>` </frigate-card-live-webrtc-card>`
@@ -828,6 +841,7 @@ export class FrigateCardLiveProvider extends LitElement {
.hass=${this.hass} .hass=${this.hass}
.cameraConfig=${this.cameraConfig} .cameraConfig=${this.cameraConfig}
.jsmpegConfig=${this.liveConfig.jsmpeg} .jsmpegConfig=${this.liveConfig.jsmpeg}
.cardWideConfig=${this.cardWideConfig}
@frigate-card:media:loaded=${this._videoMediaShowHandler.bind(this)} @frigate-card:media:loaded=${this._videoMediaShowHandler.bind(this)}
> >
</frigate-card-live-jsmpeg>`} </frigate-card-live-jsmpeg>`}
@@ -950,6 +964,9 @@ export class FrigateCardLiveWebRTCCard extends LitElement {
@property({ attribute: false }) @property({ attribute: false })
public cameraConfig?: CameraConfig; public cameraConfig?: CameraConfig;
@property({ attribute: false })
public cardWideConfig?: CardWideConfig;
protected hass?: HomeAssistant; protected hass?: HomeAssistant;
// A task to await the load of the WebRTC component. // A task to await the load of the WebRTC component.
@@ -1079,9 +1096,13 @@ export class FrigateCardLiveWebRTCCard extends LitElement {
// Use a task to allow us to asynchronously wait for the WebRTC card to // 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() // load, but yet still have the card load be followed by the updated()
// lifecycle callback (unlike just using `until`). // lifecycle callback (unlike just using `until`).
return renderTask(this, this._webrtcTask, render, () => return renderTask(this, this._webrtcTask, render, {
renderProgressIndicator(localize('error.webrtc_card_waiting')), inProgressFunc: () =>
); renderProgressIndicator({
message: localize('error.webrtc_card_waiting'),
cardWideConfig: this.cardWideConfig,
}),
});
} }
/** /**
@@ -1121,6 +1142,9 @@ export class FrigateCardLiveJSMPEG extends LitElement {
@property({ attribute: false, hasChanged: contentsChanged }) @property({ attribute: false, hasChanged: contentsChanged })
public jsmpegConfig?: JSMPEGConfig; public jsmpegConfig?: JSMPEGConfig;
@property({ attribute: false })
public cardWideConfig?: CardWideConfig;
protected hass?: ExtendedHomeAssistant; protected hass?: ExtendedHomeAssistant;
protected _jsmpegCanvasElement?: HTMLCanvasElement; protected _jsmpegCanvasElement?: HTMLCanvasElement;
@@ -1327,7 +1351,12 @@ export class FrigateCardLiveJSMPEG extends LitElement {
} }
return html`${this._jsmpegCanvasElement}`; return html`${this._jsmpegCanvasElement}`;
}; };
return html`${until(_render(), renderProgressIndicator())}`; return html`${until(
_render(),
renderProgressIndicator({
cardWideConfig: this.cardWideConfig,
}),
)}`;
} }
/** /**
+15 -6
View File
@@ -4,7 +4,7 @@ import { classMap } from 'lit/directives/class-map.js';
import { TROUBLESHOOTING_URL } from '../const.js'; import { TROUBLESHOOTING_URL } from '../const.js';
import { localize } from '../localize/localize.js'; import { localize } from '../localize/localize.js';
import messageStyle from '../scss/message.scss'; import messageStyle from '../scss/message.scss';
import { FrigateCardError, Message, MessageType } from '../types.js'; import { CardWideConfig, FrigateCardError, Message, MessageType } from '../types.js';
import { dispatchFrigateCardEvent } from '../utils/basic.js'; import { dispatchFrigateCardEvent } from '../utils/basic.js';
@customElement('frigate-card-message') @customElement('frigate-card-message')
@@ -82,11 +82,14 @@ export class FrigateCardProgressIndicator extends LitElement {
@property({ attribute: false }) @property({ attribute: false })
public message: string | TemplateResult = ''; public message: string | TemplateResult = '';
@property({ attribute: false })
public animated = false;
protected render(): TemplateResult { protected render(): TemplateResult {
return html` <div class="message vertical"> return html` <div class="message vertical">
<span> ${this.animated
<ha-circular-progress active="true" size="large"> </ha-circular-progress> ? html`<ha-circular-progress active="true" size="large"> </ha-circular-progress>`
</span> : html`<ha-icon icon="mdi:timer-sand"></ha-icon>`}
${this.message ? html`<span>${this.message}</span>` : html``} ${this.message ? html`<span>${this.message}</span>` : html``}
</div>`; </div>`;
} }
@@ -112,9 +115,15 @@ export function renderMessage(message: Message): TemplateResult {
return html``; return html``;
} }
export function renderProgressIndicator(message?: string): TemplateResult { export function renderProgressIndicator(options?: {
message?: string;
cardWideConfig?: CardWideConfig;
}): TemplateResult {
return html` return html`
<frigate-card-progress-indicator .message=${message || ''}> <frigate-card-progress-indicator
.message=${options?.message || ''}
.animated=${options?.cardWideConfig?.performance?.profile !== 'low'}
>
</frigate-card-progress-indicator> </frigate-card-progress-indicator>
`; `;
} }
+1 -1
View File
@@ -91,7 +91,7 @@ export class FrigateCardNextPreviousControl extends LitElement {
aria-label="${this.label}" aria-label="${this.label}"
/>` />`
: html``, : html``,
() => html`<div class=${classMap(classes)}></div>`, { inProgressFunc: () => html`<div class=${classMap(classes)}></div>` },
); );
} }
+1 -1
View File
@@ -95,7 +95,7 @@ export class FrigateCardThumbnailFeatureEvent extends LitElement {
this._embedThumbnailTask, this._embedThumbnailTask,
(embeddedThumbnail: string | null) => (embeddedThumbnail: string | null) =>
embeddedThumbnail ? html`<img src="${embeddedThumbnail}" />` : html``, embeddedThumbnail ? html`<img src="${embeddedThumbnail}" />` : html``,
() => imageOff, {inProgressFunc: () => imageOff},
) )
: imageOff} `; : imageOff} `;
} }
+12 -2
View File
@@ -20,6 +20,7 @@ import {
BrowseMediaNeighbors, BrowseMediaNeighbors,
BrowseMediaQueryParameters, BrowseMediaQueryParameters,
CameraConfig, CameraConfig,
CardWideConfig,
ExtendedHomeAssistant, ExtendedHomeAssistant,
FrigateBrowseMediaSource, FrigateBrowseMediaSource,
frigateCardConfigDefaults, frigateCardConfigDefaults,
@@ -97,6 +98,9 @@ export class FrigateCardViewer extends LitElement {
@property({ attribute: false }) @property({ attribute: false })
public dataManager?: DataManager; public dataManager?: DataManager;
@property({ attribute: false })
public cardWideConfig?: CardWideConfig;
/** /**
* Master render method. * Master render method.
* @returns A rendered template. * @returns A rendered template.
@@ -151,7 +155,7 @@ export class FrigateCardViewer extends LitElement {
}), }),
); );
} }
return renderProgressIndicator(); return renderProgressIndicator({ cardWideConfig: this.cardWideConfig });
} }
return html` <frigate-card-surround return html` <frigate-card-surround
@@ -169,6 +173,7 @@ export class FrigateCardViewer extends LitElement {
.viewerConfig=${this.viewerConfig} .viewerConfig=${this.viewerConfig}
.browseMediaQueryParameters=${browseMediaQueryParameters} .browseMediaQueryParameters=${browseMediaQueryParameters}
.resolvedMediaCache=${this.resolvedMediaCache} .resolvedMediaCache=${this.resolvedMediaCache}
.cardWideConfig=${this.cardWideConfig}
> >
</frigate-card-viewer-carousel> </frigate-card-viewer-carousel>
</frigate-card-surround>`; </frigate-card-surround>`;
@@ -206,6 +211,9 @@ export class FrigateCardViewerCarousel extends LitElement {
@property({ attribute: false }) @property({ attribute: false })
public resolvedMediaCache?: ResolvedMediaCache; public resolvedMediaCache?: ResolvedMediaCache;
@property({ attribute: false })
public cardWideConfig?: CardWideConfig;
protected _refMediaCarousel: Ref<FrigateCardMediaCarousel> = createRef(); protected _refMediaCarousel: Ref<FrigateCardMediaCarousel> = createRef();
// Mapping of slide # to FrigateBrowseMediaSource child #. // Mapping of slide # to FrigateBrowseMediaSource child #.
@@ -645,7 +653,9 @@ export class FrigateCardViewerCarousel extends LitElement {
// If lazy loading is not enabled, wait for the media resolver task to // If lazy loading is not enabled, wait for the media resolver task to
// complete and show a progress indictator until this. // complete and show a progress indictator until this.
if (!this.viewerConfig?.lazy_load && !this._isMediaFullyResolved()) { if (!this.viewerConfig?.lazy_load && !this._isMediaFullyResolved()) {
return renderTask(this, this._mediaResolutionTask, this._render.bind(this)); return renderTask(this, this._mediaResolutionTask, this._render.bind(this), {
cardWideConfig: this.cardWideConfig,
});
} }
return this._render(); return this._render();
} }
+1 -3
View File
@@ -1,7 +1,6 @@
// TODO: Change defaults themselves? // TODO: Change defaults themselves?
// TODO: Camera auto-dep detection
// TODO: CSS // TODO: CSS
// TODO: Renderprogress // TODO: Don't pump out conditionStates based on state?
import { deepRemoveDefaults } from './utils/zod.js'; import { deepRemoveDefaults } from './utils/zod.js';
import { import {
@@ -16,7 +15,6 @@ import {
CONF_EVENT_GALLERY_CONTROLS_THUMBNAILS_SHOW_FAVORITE_CONTROL, CONF_EVENT_GALLERY_CONTROLS_THUMBNAILS_SHOW_FAVORITE_CONTROL,
CONF_EVENT_GALLERY_CONTROLS_THUMBNAILS_SHOW_TIMELINE_CONTROL, CONF_EVENT_GALLERY_CONTROLS_THUMBNAILS_SHOW_TIMELINE_CONTROL,
CONF_LIVE_AUTO_MUTE, CONF_LIVE_AUTO_MUTE,
CONF_LIVE_AUTO_PLAY,
CONF_LIVE_CONTROLS_THUMBNAILS_MODE, CONF_LIVE_CONTROLS_THUMBNAILS_MODE,
CONF_LIVE_CONTROLS_THUMBNAILS_SHOW_DETAILS, CONF_LIVE_CONTROLS_THUMBNAILS_SHOW_DETAILS,
CONF_LIVE_CONTROLS_THUMBNAILS_SHOW_FAVORITE_CONTROL, CONF_LIVE_CONTROLS_THUMBNAILS_SHOW_FAVORITE_CONTROL,
+4
View File
@@ -54,6 +54,10 @@ div.message div.icon {
word-break: break-all; word-break: break-all;
} }
.message ha-icon, ha-circular-progress {
padding: 10px;
}
.dotdotdot:after { .dotdotdot:after {
@keyframes dots { @keyframes dots {
0%, 0%,
+12 -3
View File
@@ -4,6 +4,7 @@ import {
dispatchFrigateCardErrorEvent, dispatchFrigateCardErrorEvent,
renderProgressIndicator, renderProgressIndicator,
} from '../components/message'; } from '../components/message';
import { CardWideConfig } from '../types';
import { errorToConsole } from './basic'; import { errorToConsole } from './basic';
/** /**
@@ -18,11 +19,19 @@ export const renderTask = <R>(
host: EventTarget, host: EventTarget,
task: Task<unknown[], R>, task: Task<unknown[], R>,
completeFunc: (result: R) => TemplateResult | void, completeFunc: (result: R) => TemplateResult | void,
inProgressFunc?: () => TemplateResult | void, options?: {
cardWideConfig?: CardWideConfig;
inProgressFunc?: () => TemplateResult | void;
},
): TemplateResult => { ): TemplateResult => {
const progressConfig = {
...(options?.cardWideConfig && { cardWideConfig: options.cardWideConfig }),
};
return html` ${task.render({ return html` ${task.render({
initial: () => inProgressFunc?.() ?? renderProgressIndicator(), initial: () =>
pending: () => inProgressFunc?.() ?? renderProgressIndicator(), options?.inProgressFunc?.() ?? renderProgressIndicator(progressConfig),
pending: () =>
options?.inProgressFunc?.() ?? renderProgressIndicator(progressConfig),
error: (e: unknown) => { error: (e: unknown) => {
errorToConsole(e as Error); errorToConsole(e as Error);
dispatchFrigateCardErrorEvent(host, e as Error); dispatchFrigateCardErrorEvent(host, e as Error);