Skip to content

fix(mirror): re-measure grid width when the mirror canvas resizes - #381

Merged
jherforth merged 1 commit into
jherforth:mainfrom
adamecker:feature/mirror-remeasure
Nov 6, 2026
Merged

jherforth merged 1 commit into
jherforth:mainfrom
adamecker:feature/mirror-remeasure

Conversation

@adamecker

@adamecker adamecker commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

What this changes

Mirror mode renders the target device's dashboard on a canvas sized to the target's viewport, but the grid width was measured once on mount — while the canvas was still at the 1280×800 fallback viewport, before the real viewport arrived. Anything width-sensitive then rendered for the fallback width and never updated, so mirror showed the compact weather layout while the target display itself showed medium.

  • A ResizeObserver on the grid container re-runs the width measurement whenever the measured width actually changes, so the layout follows the real viewport when it arrives.
  • New client/src/utils/containerWidth.js holds the measure logic; WidgetContainer.jsx uses it; 7 new tests in containerWidth.test.js.
  • No behaviour change on a direct display: the width is measured the same way, and the observer only re-runs when the width actually changes. On a slow connection mirror may briefly show the fallback layout, then flip to the correct one.

Testing

Tested end to end with demo data:

  • Mirror at the fallback viewport (grid 1248), then the real viewport arrives (grid 1408): the weather iframe goes from compact to 334×326 medium, matching the target display's 332.
  • Rendering directly on the target display is identical before and after.
  • Full client suite: 89 files, 971 tests pass; vite build passes.

Screenshots

Before — mirror, weather compact:

Before, mirror weather compact

After — mirror, weather medium, matching the target display:

After, mirror weather medium

Generated with Muse AI 🤖

WidgetContainer measured its container width once on mount plus on
window resize only. In mirror the canvas starts at the 1280 fallback
width and widens to the target's real width once its viewport arrives;
that widening is not a window resize, so the grid stayed laid out at
the fallback size and the weather widget landed compact (294px iframe)
instead of medium (332px) like on the wall.

Watch the container element itself with a ResizeObserver (window
resize kept as a no-ResizeObserver fallback) and report only on an
actual width change, so no layout rebuild runs on a no-op.
@jherforth jherforth added the bug Something isn't working label Nov 6, 2026
@jherforth jherforth added this to the 2.0 milestone Nov 6, 2026
@jherforth
jherforth merged commit 838ed8a into jherforth:main Nov 6, 2026
3 checks passed
@github-project-automation github-project-automation Bot moved this from Backlog to Done in HomeGlow Kanban Nov 6, 2026
adamecker pushed a commit to adamecker/HomeGlow that referenced this pull request Nov 7, 2026
…rforth#382, jherforth#384) and origin/test/all-combined into test/all-combined

Upstream: Stacks/display Modes/takeovers (jherforth#378), routine complete-all
(jherforth#380), mirror re-measure (jherforth#381), shared New Chore dialog (jherforth#382), admin
PIN chooses the mode helper (jherforth#384). Fork side: Open-Meteo provider,
precipitation probability, bonus-chore return to pool, Google Tasks
no-due-date fix, dock-hide-on-dialog, HA panel test seed.

Conflicts (fork's jherforth#380/jherforth#382 branches vs upstream's merged versions):
took upstream's refinements (scheduleOnly, tickRemainingStepsOrThrow);
app.jsx combines both (dock stays hidden while dragging is false and a
dialog is open).

Auto-seed now strips the HA mode-helper link from seeded settings, so a
new display never inherits another display's helper (jherforth#384: only the
admin PIN chooses it). The Stacks tests pre-create their devices in
before(), while no device has widgets yet, so auto-seed leaves them
empty.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants