mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-19 15:26:36 +00:00
Cache thumbnails (#2924)
This commit is contained in:
parent
e2ed1a9fd9
commit
bbc32278d8
@ -6,6 +6,7 @@ import { html } from "@polymer/polymer/lib/utils/html-tag";
|
|||||||
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
import { PolymerElement } from "@polymer/polymer/polymer-element";
|
||||||
|
|
||||||
import HassMediaPlayerEntity from "../util/hass-media-player-model";
|
import HassMediaPlayerEntity from "../util/hass-media-player-model";
|
||||||
|
import { fetchMediaPlayerThumbnailWithCache } from "../data/media-player";
|
||||||
|
|
||||||
import computeStateName from "../common/entity/compute_state_name";
|
import computeStateName from "../common/entity/compute_state_name";
|
||||||
import EventsMixin from "../mixins/events-mixin";
|
import EventsMixin from "../mixins/events-mixin";
|
||||||
@ -271,10 +272,13 @@ class HaMediaPlayerCard extends LocalizeMixin(EventsMixin(PolymerElement)) {
|
|||||||
|
|
||||||
// We have a new picture url
|
// We have a new picture url
|
||||||
try {
|
try {
|
||||||
const { content_type: contentType, content } = await this.hass.callWS({
|
const {
|
||||||
type: "media_player_thumbnail",
|
content_type: contentType,
|
||||||
entity_id: playerObj.stateObj.entity_id,
|
content,
|
||||||
});
|
} = await fetchMediaPlayerThumbnailWithCache(
|
||||||
|
this.hass,
|
||||||
|
playerObj.stateObj.entity_id
|
||||||
|
);
|
||||||
this._coverShowing = true;
|
this._coverShowing = true;
|
||||||
this._coverLoadError = false;
|
this._coverLoadError = false;
|
||||||
this.$.cover.style.backgroundImage = `url(data:${contentType};base64,${content})`;
|
this.$.cover.style.backgroundImage = `url(data:${contentType};base64,${content})`;
|
||||||
|
47
src/common/util/time-cache-function-promise.ts
Normal file
47
src/common/util/time-cache-function-promise.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import { HomeAssistant } from "../../types";
|
||||||
|
|
||||||
|
interface ResultCache<T> {
|
||||||
|
[entityId: string]: Promise<T> | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const timeCachePromiseFunc = async <T>(
|
||||||
|
cacheKey: string,
|
||||||
|
cacheTime: number,
|
||||||
|
func: (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entityId: string,
|
||||||
|
...args: Array<unknown>
|
||||||
|
) => Promise<T>,
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entityId: string,
|
||||||
|
...args: Array<unknown>
|
||||||
|
): Promise<T> => {
|
||||||
|
let cache: ResultCache<T> | undefined = (hass as any)[cacheKey];
|
||||||
|
|
||||||
|
if (!cache) {
|
||||||
|
cache = hass[cacheKey] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const lastResult = cache[entityId];
|
||||||
|
|
||||||
|
if (lastResult) {
|
||||||
|
return lastResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = func(hass, entityId, ...args);
|
||||||
|
cache[entityId] = result;
|
||||||
|
|
||||||
|
result.then(
|
||||||
|
// When successful, set timer to clear cache
|
||||||
|
() =>
|
||||||
|
setTimeout(() => {
|
||||||
|
cache![entityId] = undefined;
|
||||||
|
}, cacheTime),
|
||||||
|
// On failure, clear cache right away
|
||||||
|
() => {
|
||||||
|
cache![entityId] = undefined;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
@ -1,4 +1,5 @@
|
|||||||
import { HomeAssistant, CameraEntity } from "../types";
|
import { HomeAssistant, CameraEntity } from "../types";
|
||||||
|
import { timeCachePromiseFunc } from "../common/util/time-cache-function-promise";
|
||||||
|
|
||||||
export interface CameraThumbnail {
|
export interface CameraThumbnail {
|
||||||
content_type: string;
|
content_type: string;
|
||||||
@ -14,6 +15,11 @@ export const computeMJPEGStreamUrl = (entity: CameraEntity) =>
|
|||||||
entity.attributes.access_token
|
entity.attributes.access_token
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
|
export const fetchThumbnailWithCache = (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entityId: string
|
||||||
|
) => timeCachePromiseFunc("_cameraTmb", 9000, fetchThumbnail, hass, entityId);
|
||||||
|
|
||||||
export const fetchThumbnail = (hass: HomeAssistant, entityId: string) =>
|
export const fetchThumbnail = (hass: HomeAssistant, entityId: string) =>
|
||||||
hass.callWS<CameraThumbnail>({
|
hass.callWS<CameraThumbnail>({
|
||||||
type: "camera_thumbnail",
|
type: "camera_thumbnail",
|
||||||
|
@ -1,4 +1,35 @@
|
|||||||
|
import { HomeAssistant } from "../types";
|
||||||
|
|
||||||
|
import { timeCachePromiseFunc } from "../common/util/time-cache-function-promise";
|
||||||
|
|
||||||
export const SUPPORT_PAUSE = 1;
|
export const SUPPORT_PAUSE = 1;
|
||||||
export const SUPPORT_NEXT_TRACK = 32;
|
export const SUPPORT_NEXT_TRACK = 32;
|
||||||
export const SUPPORTS_PLAY = 16384;
|
export const SUPPORTS_PLAY = 16384;
|
||||||
export const OFF_STATES = ["off", "idle"];
|
export const OFF_STATES = ["off", "idle"];
|
||||||
|
|
||||||
|
export interface MediaPlayerThumbnail {
|
||||||
|
content_type: string;
|
||||||
|
content: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const fetchMediaPlayerThumbnailWithCache = (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entityId: string
|
||||||
|
) =>
|
||||||
|
timeCachePromiseFunc(
|
||||||
|
"_media_playerTmb",
|
||||||
|
9000,
|
||||||
|
fetchMediaPlayerThumbnail,
|
||||||
|
hass,
|
||||||
|
entityId
|
||||||
|
);
|
||||||
|
|
||||||
|
export const fetchMediaPlayerThumbnail = (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entityId: string
|
||||||
|
) => {
|
||||||
|
return hass.callWS<MediaPlayerThumbnail>({
|
||||||
|
type: "media_player_thumbnail",
|
||||||
|
entity_id: entityId,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
@ -18,7 +18,7 @@ import { HomeAssistant } from "../../../types";
|
|||||||
import { styleMap } from "lit-html/directives/style-map";
|
import { styleMap } from "lit-html/directives/style-map";
|
||||||
import { classMap } from "lit-html/directives/class-map";
|
import { classMap } from "lit-html/directives/class-map";
|
||||||
import { b64toBlob } from "../../../common/file/b64-to-blob";
|
import { b64toBlob } from "../../../common/file/b64-to-blob";
|
||||||
import { fetchThumbnail } from "../../../data/camera";
|
import { fetchThumbnailWithCache } from "../../../data/camera";
|
||||||
|
|
||||||
const UPDATE_INTERVAL = 10000;
|
const UPDATE_INTERVAL = 10000;
|
||||||
const DEFAULT_FILTER = "grayscale(100%)";
|
const DEFAULT_FILTER = "grayscale(100%)";
|
||||||
@ -179,10 +179,10 @@ class HuiImage extends LitElement {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const { content_type: contentType, content } = await fetchThumbnail(
|
const {
|
||||||
this.hass,
|
content_type: contentType,
|
||||||
this.cameraImage
|
content,
|
||||||
);
|
} = await fetchThumbnailWithCache(this.hass, this.cameraImage);
|
||||||
if (this._cameraImageSrc) {
|
if (this._cameraImageSrc) {
|
||||||
URL.revokeObjectURL(this._cameraImageSrc);
|
URL.revokeObjectURL(this._cameraImageSrc);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user