/**
* TaskMate Photo Gallery Card
* A history grid of chore-evidence photos. Reads the activity sensor's
* `photo_gallery` attribute and renders thumbnails. A card's can't send a
* bearer token, so each photo path is signed via the `auth/sign_path` WS command
* before use.
*/
const LitElement = customElements.get("hui-masonry-view")
? Object.getPrototypeOf(customElements.get("hui-masonry-view"))
: Object.getPrototypeOf(customElements.get("hui-view"));
const html = LitElement.prototype.html;
const css = LitElement.prototype.css;
const _safeColor = (c, d) => (typeof c === "string" && /^#[0-9a-fA-F]{3,8}$/.test(c) ? c : d);
class TaskMatePhotoGalleryCard extends LitElement {
static get properties() {
return { hass: { type: Object }, config: { type: Object }, _signed: { state: true } };
}
constructor() {
super();
this._signed = {}; // photo_url -> signed path
this._inflight = new Set();
}
setConfig(config) {
if (!config || !config.entity) {
throw new Error("A TaskMate activity entity is required");
}
this.config = config;
}
static getStubConfig() {
return { entity: "sensor.taskmate_activity" };
}
getCardSize() {
return 4;
}
_t(key, params) {
const fn = window.__taskmate_localize;
return fn ? fn(this.hass, key, params) : key;
}
// Open the shared in-page lightbox; fall through to the href if it's absent.
_openPhoto(e, url, caption) {
if (window.__taskmate_lightbox) {
e.preventDefault();
window.__taskmate_lightbox(url, caption, this._t("common.close"));
}
}
_gallery() {
const entity = this.hass && this.hass.states[this.config.entity];
const items = (entity && entity.attributes && entity.attributes.photo_gallery) || [];
return this.config.max ? items.slice(0, Number(this.config.max)) : items;
}
async _ensureSigned(items) {
for (const it of items) {
const url = it.photo_url;
if (!url || this._signed[url] || this._inflight.has(url)) continue;
this._inflight.add(url);
try {
const res = await this.hass.callWS({ type: "auth/sign_path", path: url, expires: 3600 });
if (res && res.path) {
this._signed = { ...this._signed, [url]: res.path };
}
} catch (e) {
// Leave unsigned; the tile shows a placeholder.
console.warn("taskmate: sign_path failed", e);
} finally {
this._inflight.delete(url);
}
}
}
updated() {
this._ensureSigned(this._gallery());
}
render() {
if (!this.hass || !this.config) return html``;
const entity = this.hass.states[this.config.entity];
if (!entity) {
return html`