331 files

This commit is contained in:
Home Assistant Version Control
2026-10-04 05:26:42 +00:00
parent 22ba8b4648
commit c4d601bfba
331 changed files with 10227 additions and 50159 deletions
@@ -19,8 +19,13 @@
(function () {
"use strict";
// Fixed companion entity ids. TaskMate is a single-instance integration
// (config_flow enforces unique_id == DOMAIN), so these ids are stable.
// Default companion entity ids. TaskMate is a single-instance integration
// (config_flow enforces unique_id == DOMAIN), but these are only the ids
// Home Assistant generates by default: since 2026.6 a new entity on a device
// with an area gets the area in front ("sensor.familie_taskmate_bounties"),
// and users rename entities. The overview sensor publishes the real ids as
// `companion_entities`, keyed by the part after "sensor.taskmate_" (#1018);
// these defaults are the fallback when that map is missing.
const COMPANIONS = [
"sensor.taskmate_chores",
"sensor.taskmate_chore_availability",
@@ -40,6 +45,8 @@
// Chore auctions (#982): `auctions`, a digest with no bid amounts. The
// auction card re-fetches its own view over the WebSocket when it moves.
"sensor.taskmate_auctions",
// The Today page's chore board (#1017): `chore_board` for the board card.
"sensor.taskmate_chore_board",
];
// Attributes a companion must NOT contribute to the merge, because another
@@ -66,6 +73,37 @@
],
};
const DEFAULT_PREFIX = "sensor.taskmate_";
const OVERVIEW_ENTITY = "sensor.taskmate_overview";
// The overview's entity map (#1018). Looked up under its default id first,
// then on whichever state carries it, in case the overview was renamed too.
function entityMap(hass) {
const ov = hass.states[OVERVIEW_ENTITY];
if (ov && ov.attributes && ov.attributes.companion_entities) return ov.attributes;
for (const id in hass.states) {
const st = hass.states[id];
if (st && st.attributes && st.attributes.companion_entities) return st.attributes;
}
return null;
}
// [defaultId, realId] for every companion, cached per hass.states object.
let _idCache = { stateRef: null, pairs: null, badges: null };
function resolvedIds(hass) {
if (_idCache.stateRef !== hass.states) {
const map = entityMap(hass);
const real = (map && map.companion_entities) || {};
_idCache = {
stateRef: hass.states,
pairs: COMPANIONS.map((id) => [id, real[id.slice(DEFAULT_PREFIX.length)] || id]),
badges: (map && map.badge_entities) || {},
};
}
return _idCache;
}
function mergedAttributes(hass, primaryEntityId) {
if (!hass || !hass.states) return {};
const merged = {};
@@ -73,10 +111,10 @@
if (primary && primary.attributes) {
Object.assign(merged, primary.attributes);
}
for (const id of COMPANIONS) {
for (const [defaultId, id] of resolvedIds(hass).pairs) {
const s = hass.states[id];
if (!s || !s.attributes) continue;
const skip = COMPANION_SKIP_KEYS[id];
const skip = COMPANION_SKIP_KEYS[defaultId];
if (!skip) {
Object.assign(merged, s.attributes);
continue;
@@ -105,6 +143,19 @@
window.__taskmate_attrs = resolveAttrs;
/**
* A child's badges sensor state, by child id, from the overview's entity
* map (#1018). Null when the map doesn't list one — callers fall back to
* guessing from the default entity id.
*/
function badgesState(hass, childId) {
if (!hass || !hass.states || childId == null) return null;
const id = resolvedIds(hass).badges[String(childId)];
return (id && hass.states[id]) || null;
}
window.__taskmate_badges_state = badgesState;
/**
* Non-admin parent role (#661). True for Home Assistant admins and for users
* the admin has designated as TaskMate parents (published as the
@@ -188,7 +239,7 @@
if (oldHass.states[primaryEntityId] !== newHass.states[primaryEntityId]) return true;
}
for (const id of COMPANIONS) {
for (const [, id] of resolvedIds(newHass).pairs) {
if (oldHass.states[id] !== newHass.states[id]) return true;
}