Fix substantial performance issue with thumbnails.

This commit is contained in:
Dermot Duffy
2022-09-22 17:44:44 -07:00
parent b9b539bf72
commit c910b5d2a4
3 changed files with 70 additions and 23 deletions
+55 -13
View File
@@ -16,6 +16,7 @@ import { renderTask } from '../utils/task.js';
import { createFetchThumbnailTask } from '../utils/thumbnail.js';
import { View } from '../view.js';
import { MediaSeek } from './viewer.js';
import { TaskStatus } from '@lit-labs/task';
import type {
ExtendedHomeAssistant,
@@ -38,22 +39,63 @@ export class FrigateCardThumbnailFeatureEvent extends LitElement {
this,
() => this.hass,
() => this.thumbnail,
false,
);
// Only load thumbnails on view in case there is a very large number of them.
protected _intersectionObserver: IntersectionObserver;
constructor() {
super();
this._intersectionObserver = new IntersectionObserver(
this._intersectionHandler.bind(this),
);
}
/**
* Component connected callback.
*/
connectedCallback(): void {
this._intersectionObserver.observe(this);
super.connectedCallback();
}
/**
* Component disconnected callback.
*/
disconnectedCallback(): void {
super.disconnectedCallback();
this._intersectionObserver.disconnect();
}
/**
* Called when the live view intersects with the viewport.
* @param entries The IntersectionObserverEntry entries (should be only 1).
*/
protected _intersectionHandler(entries: IntersectionObserverEntry[]): void {
if (
this._embedThumbnailTask.status === TaskStatus.INITIAL &&
entries.some((entry) => entry.isIntersecting)
) {
this._embedThumbnailTask.run();
}
}
protected render(): TemplateResult | void {
return html`
${this.thumbnail
? renderTask(
this,
this._embedThumbnailTask,
(embeddedThumbnail: string | null) =>
embeddedThumbnail ? html`<img src="${embeddedThumbnail}" />` : html``,
)
: html`<ha-icon
icon="mdi:image-off"
title=${localize('thumbnail.no_thumbnail')}
></ha-icon> `}
`;
const imageOff = html`<ha-icon
icon="mdi:image-off"
title=${localize('thumbnail.no_thumbnail')}
></ha-icon> `;
return html`${this.thumbnail
? renderTask(
this,
this._embedThumbnailTask,
(embeddedThumbnail: string | null) =>
embeddedThumbnail ? html`<img src="${embeddedThumbnail}" />` : html``,
() => imageOff,
)
: imageOff} `;
}
static get styles(): CSSResult {
+1
View File
@@ -30,4 +30,5 @@ ha-icon {
align-items: center;
border: 1px solid rgba(255, 255, 255, 0.3);
box-sizing: border-box;
opacity: 0.2;
}
+14 -10
View File
@@ -55,19 +55,23 @@ export const createFetchThumbnailTask = (
host: ReactiveControllerHost,
getHASS: () => HomeAssistant | undefined,
getThumbnailURL: () => string | undefined,
autoRun = true,
): Task<FetchThumbnailTaskArgs, string | null> => {
return new Task(
host,
async ([haveHASS, thumbnailURL]: FetchThumbnailTaskArgs): Promise<
string | null
> => {
const hass = getHASS();
if (!haveHASS || !hass || !thumbnailURL) {
return null;
}
return fetchThumbnail(hass, thumbnailURL);
{
// Do not re-run the task if hass changes, unless it was previously undefined.
args: (): FetchThumbnailTaskArgs => [!!getHASS(), getThumbnailURL()],
task: async ([haveHASS, thumbnailURL]: FetchThumbnailTaskArgs): Promise<
string | null
> => {
const hass = getHASS();
if (!haveHASS || !hass || !thumbnailURL) {
return null;
}
return fetchThumbnail(hass, thumbnailURL);
},
autoRun: autoRun,
},
// Do not re-run the task if hass changes, unless it was previously undefined.
(): FetchThumbnailTaskArgs => [!!getHASS(), getThumbnailURL()],
);
};