Skip to content

Show a child's photo from their person entity - #1062

Merged
tempus2016 merged 6 commits into
tempus2016:mainfrom
cad861:upstream-pr/photo
Oct 14, 2026
Merged

tempus2016 merged 6 commits into
tempus2016:mainfrom
cad861:upstream-pr/photo

Conversation

@cad861

@cad861 cad861 commented Oct 14, 2026

Copy link
Copy Markdown
Contributor

Summary

Lets a child's face come from a Home Assistant person (or any entity with a picture) instead of an MDI icon. A new optional per-child picture_entity is read on every update and exposed as avatar_image; a shared __taskmate_child_visual helper makes every card prefer the photo and fall back to the existing MDI avatar, so nothing changes for children without one. The child dialog gets a "Photo from" picker. The picture is not stored, so a photo changed under Settings › People shows up without re-saving anything, and the sensors refresh as soon as the entity's picture changes (not on every home/away flip).

This is the photo part of #913, split out as you offered.

Related issue

N/A — split out of #913. Also covers Copilot's finding there that cached avatar images ignored picture entity updates.

Type of change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that changes existing behaviour)
  • Documentation only
  • CI / tooling / chore

How has this been tested?

  • Ran ruff check . locally (matches the Ruff CI check)
  • Ran pytest locally (matches the Run tests CI check)
  • Exercised the change on a live Home Assistant instance
  • For card changes: hard-refreshed the browser and checked the console for errors

ruff format --check and ruff check clean; pytest 3149 passed; npm test 637 passed; check_translations.py and check_data_files.py pass. New tests in tests/test_child_picture_entity.py, including six for the photo refresh that fail without the fix.

Live: running on my own HA (2026.9) for two children linked to their person entities; both photos show on the cards and in the sensors, and a child with no picture entity keeps the MDI avatar. That instance runs this change on top of 6.1.0; the branch here is rebased on current main.

Checklist

  • My code follows the existing patterns in the codebase
  • I bumped manifest.json version if this is a release-bound change
  • Any new user-facing strings are translated into all locales
    (da, de, fr, nb, nn, pl, pt, pt-BR) in this same PR — not English-only
  • I updated the README / docs where relevant
  • I did not add Claude / AI co-author attribution to commits or files

Version left for you to set at release.

Adds an optional per-child picture entity (normally the child's person.*).
Its picture is read on every update and exposed as avatar_image, and a
shared __taskmate_child_visual helper makes every card prefer the photo
and fall back to the MDI avatar. The panel's child dialog gets a
"Photo from" picker.
A child's photo is read from their picture entity, but the sensors' shared
context was cached per coordinator update, so a photo changed on the person
entity stayed stale until the next TaskMate refresh. Track each child's
picture entity and refresh the sensors when its picture really changes, and
make the shared cache aware of external entity changes.
@cad861
cad861 requested a review from tempus2016 as a code owner October 14, 2026 01:37
Copilot AI balanced review requested due to automatic review settings October 14, 2026 01:37
@github-actions github-actions Bot added backend Python integration code cards Lovelace cards / frontend (www/*.js) translations i18n / locale strings tests Test suite labels Oct 14, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Several cards remain unmigrated, the picker excludes supported entity domains, and whitespace can prevent photo refresh tracking.

3 open findings
What changed in this PR

Adds configurable child photos sourced from Home Assistant entities, with automatic refresh and MDI avatar fallback.

Changes:

  • Adds picture_entity configuration, storage, WebSocket handling, and translations.
  • Resolves and publishes avatar_image, refreshing sensors when pictures change.
  • Updates most cards to render photos and adds backend tests.
File Description
tests/​test_sensor_attributes.py Tests external-state cache invalidation.
tests/​test_child_picture_entity.py Tests photo resolution, storage, exposure, and refresh.
tests/​frontend/​harness.cjs Adds the child visual test helper.
custom_components/​taskmate/​www/​taskmate-weekly-card.js Renders child photos.
custom_components/​taskmate/​www/​taskmate-streak-card.js Renders child photos.
custom_components/​taskmate/​www/​taskmate-rewards-card.js Renders photos in tabs and avatars.
custom_components/​taskmate/​www/​taskmate-reward-progress-card.js Renders contributor photos.
custom_components/​taskmate/​www/​taskmate-reorder-card.js Uses the shared visual resolver.
custom_components/​taskmate/​www/​taskmate-points-display-card.js Prefers photos in point displays.
custom_components/​taskmate/​www/​taskmate-points-card.js Reads photos from child sensors.
custom_components/​taskmate/​www/​taskmate-parent-dashboard-card.js Renders photos throughout the dashboard.
custom_components/​taskmate/​www/​taskmate-panel.js Adds picture-entity configuration.
custom_components/​taskmate/​www/​taskmate-overview-card.js Renders photos in child tiles.
custom_components/​taskmate/​www/​taskmate-leaderboard-card.js Renders leaderboard photos.
custom_components/​taskmate/​www/​taskmate-incentive-card.js Renders photos in child selectors.
custom_components/​taskmate/​www/​taskmate-design.js Adds shared image styling and resolution.
custom_components/​taskmate/​www/​taskmate-child-card.js Renders the configured child photo.
custom_components/​taskmate/​www/​taskmate-calendar-card.js Renders photos in calendar groups.
custom_components/​taskmate/​www/​taskmate-approvals-card.js Resolves photos through overview data.
custom_components/​taskmate/​www/​locales/​pt.json Adds Portuguese labels.
custom_components/​taskmate/​www/​locales/​pt-BR.json Adds Brazilian Portuguese labels.
custom_components/​taskmate/​www/​locales/​pl.json Adds Polish labels.
custom_components/​taskmate/​www/​locales/​nn.json Adds Nynorsk labels.
custom_components/​taskmate/​www/​locales/​nb.json Adds Norwegian labels.
custom_components/​taskmate/​www/​locales/​fr.json Adds French labels.
custom_components/​taskmate/​www/​locales/​en.json Adds English labels.
custom_components/​taskmate/​www/​locales/​en-GB.json Adds British English labels.
custom_components/​taskmate/​www/​locales/​de.json Adds German labels.
custom_components/​taskmate/​www/​locales/​da.json Adds Danish labels.
custom_components/​taskmate/​websocket.py Accepts picture entities in child commands.
custom_components/​taskmate/​sensor.py Publishes photos and invalidates cached summaries.
custom_components/​taskmate/​models.py Persists the picture-entity identifier.
custom_components/​taskmate/​coordinator.py Accepts picture entities when adding children.
custom_components/​taskmate/​coord_avatars.py Resolves entity pictures.
custom_components/​taskmate/​coord_assignments.py Tracks picture changes and refreshes listeners.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread custom_components/taskmate/coord_assignments.py
Comment thread custom_components/taskmate/www/taskmate-design.js
Comment thread custom_components/taskmate/www/taskmate-panel.js Outdated
Addresses the Copilot review on tempus2016#1062:

- The chore board, kiosk and recap cards now draw a child through the
  shared face helper, so a child's photo shows there too and a child
  without one keeps their avatar. (The badges card has no per-child avatar
  to draw: its sensor sends none, so it always shows the generic icon.)
- The set of tracked picture entities trims each id the same way the photo
  lookup reads it, so a stray space can't leave a photo untracked.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Several existing child-face renderers still ignore the configured photo, including badges, team progress, bounty, and auction displays.

0 open findings

3 resolved since last review
Previously missed (2)

In code that hasn't changed since last review

Medium severity Use configured photos in bounty and auction card avatars

custom_components/​taskmate/​sensor.py:227

The overview now exposes the photo, but two existing face renderers still ignore it: taskmate-bounty-card.js:173-178 and taskmate-auction-card.js:181-186 resolve the same children rows and always render initials. Consequently configured photos do not appear on those cards, contrary to the PR's “every card” behavior. Route both _avatar methods through __taskmate_child_visual while preserving initials as the fallback.

This issue also appears on line 1589 of the same file.

Medium severity Use configured photos for joined children in team progress

custom_components/​taskmate/​www/​taskmate-child-card.js:2539

This updates the child's primary avatar, but _renderTeamProgress in the same card still reads kid.avatar directly at lines 2568-2572. Joined children therefore keep showing their MDI icon/initial even when avatar_image is present. Use __taskmate_child_visual(kid) in that renderer as well so all child faces in this card follow the new precedence.

🧠 Review effort: Balanced

Addresses the second Copilot review on tempus2016#1062: the bounty board and auction
cards drew every child as an initial, and the child card's teamwork row
read the avatar directly. All three now use the shared face helper, so a
child's photo shows there; the bounty and auction cards keep the initial
for a child without one.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The badges card still ignores configured child photos, contradicting the stated all-card behavior.

0 open findings

Previously missed (1)

In code that hasn't changed since last review

Medium severity Use resolved avatar image in badges card

custom_components/​taskmate/​sensor.py:150

The photo data only reaches overview-backed and points/stats views; the badges card still renders attrs.child_avatar directly and ignores avatar_image. A configured child photo therefore never appears on taskmate-badges-card, despite the PR's “every card” behavior. Please expose the resolved image on ChildBadgesSensor and render that header through __taskmate_child_visual as well.

🧠 Review effort: Balanced

…ty with a picture

Addresses the third Copilot review on tempus2016#1062:

- The badges sensor now says whose badges they are (child_name,
  child_avatar, avatar_image), and the card draws that face through the
  shared helper. Before, the sensor sent neither, so the card always
  showed a generic icon.
- "Photo from" lists any entity that has a picture (person, image,
  camera...) instead of person entities only, matching what the backend
  accepts.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The picker can select TaskMate’s own derived child sensor, creating a self-referential and stale photo source.

2 open findings

🧠 Review effort: Balanced

Comment thread custom_components/taskmate/www/taskmate-panel.js Outdated
Comment thread custom_components/taskmate/www/taskmate-panel.js
TaskMate's child sensors show the photo chosen for the child, so picking
one as the source made the face refer to itself and go stale. The picker
no longer lists them and the backend ignores one if it was already saved.

The hint now says any entity with a picture can be used, the child's
person being the usual choice.
@tempus2016

Copy link
Copy Markdown
Owner

Thanks for turning these round so quickly. The badges card photo, the wider picker and leaving out TaskMate's own child sensors all look good, and CI is green.

One thing left before I can merge: the picker hint (panel.child_picture_entity_hint) changed meaning in en.json (it now says any entity with a picture), but the other locales still say "pick the child's person". That covers da, de, en-GB, fr, nb, nn, pl, pt and pt-BR. The translation parity check only compares keys, so it doesn't flag this. Could you bring those in line with the new English wording? Once that's in, I'll test it on my dev instance and merge.

@tempus2016
tempus2016 merged commit 0e31d87 into tempus2016:main Oct 14, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend Python integration code cards Lovelace cards / frontend (www/*.js) tests Test suite translations i18n / locale strings

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants