v1.49.0: content-fit zoom, swipe animation, wording, and the v1.47.0 review

Owner's batch:
- zoom now opens on what is DRAWN (rooms + 5% margin) for spaces with no
  background image; with one the image is the plan and still fits whole. A small
  plan on the square canvas no longer opens as a speck.
- swiping between spaces, and the kiosk carousel, slide sideways; honours
  prefers-reduced-motion.
- the room settings button reads 'Room settings' and lightens on hover.
- 'curation' is filtering everywhere: UI strings, docs, code.

Checked the yard while I was there: its drawing sits off-centre because it was
drawn that way — before the migration x spanned 0.12..0.54 with 0.12 and 0.46 of
margin. The migration added 0.1465 on each side, symmetrically. Content-fit zoom
makes it moot anyway.

From the v1.47.0 review:
- HP-1470-02: the picker let you delete the plan you had just selected — it is
  not in the stored config yet, so the server rightly called it free, and the
  save then stored a url with no file. The button is disabled, and since two
  clients can do this in either order, config/set now verifies every internal
  plan url against the disk under the write lock and answers .
  External and legacy urls are not ours to police.
- HP-1470-01: growth is bounded at the door rather than by deleting old files —
  that mistake cost real plans twice. check_quota refuses an upload that would
  push the store past 256 MB / 200 plans (1 GB / 1000 attachments) or leave less
  than 512 MB free. The plan list is capped at 60 newest with a total, and
  thumbnails load lazily.
- HP-1470-03: picking a saved plan waited for nothing and stored a fallback
  ratio when the signature had not arrived — a square plan came out stretched.
  It waits for the signature, binds the result to the dialog that asked, and the
  dialog preview is signed too.
- report §5: the last lifecycle comments still described age-based collection.

Not released yet — the owner asked for a release once the batch is done.
This commit is contained in:
Matysh
2026-07-28 22:44:09 +03:00
parent e1e730560d
commit f5e6c0318d
27 changed files with 638 additions and 140 deletions
+7 -7
View File
@@ -1,5 +1,5 @@
/**
* Building the device list from HA registries: curation, light groups,
* Building the device list from HA registries: filtering, light groups,
* markers (overrides/virtual). No Lit/DOM — only the hass object.
*/
import { iconFor, iconFromDeviceClasses, DOMAIN_PRIORITY, FALLBACK_ICON, type CompiledIconRule, EXCLUDED_DOMAINS } from './rules';
@@ -184,7 +184,7 @@ function applyMarker(item: DevItem, m: Marker): void {
item.tapAction = m.tap_action ?? null;
}
/** Curation + light groups + markers (metadata/rebinding) + virtual ones. A hybrid. */
/** Filtering + light groups + markers (metadata/rebinding) + virtual ones. A hybrid. */
export function buildDevices(ctx: BuildCtx): DevItem[] {
const { hass: h, areaToSpace, markers, settings, excluded, showAll, firstSpaceId, loc, iconRules } = ctx;
const groupLights = settings.group_lights !== false;
@@ -210,7 +210,7 @@ export function buildDevices(ctx: BuildCtx): DevItem[] {
if (marker && marker.hidden) continue;
const entIds = entsBy[dev.id] || [];
const dom = domainOfDevice(h, dev, entIds);
// curation (can be turned off with the “show all” toggle)
// filtering (can be turned off with the “show all” toggle)
if (!showAll) {
if (excluded.has(dom)) continue;
if (dev.model === 'Group') continue;
@@ -391,7 +391,7 @@ export function areaHum(
const vals: number[] = [];
for (const dv of devices) {
if (dv.area !== area) continue;
// same curation idea as areaTemp: climate sensors only, not fridges/plugs
// same filtering idea as areaTemp: climate sensors only, not fridges/plugs
if (dv.icon !== 'mdi:thermometer' && dv.icon !== 'mdi:air-filter' && dv.icon !== 'mdi:water-percent') continue;
const h = humFor(hass, dv.entities);
if (h != null) vals.push(h);
@@ -416,11 +416,11 @@ const NON_AIR_RE = new RegExp(
/**
* Room climate from EVERY sensor of the area — including devices that are not
* placed on the plan (hidden by curation or by the user). The old helpers read
* placed on the plan (hidden by filtering or by the user). The old helpers read
* the visible-icon list, so hiding a thermometer silently removed it from the
* room card (field report, 2026-07-27).
*
* Curation is kept: only devices the card itself recognises as thermometers /
* Filtering is kept: only devices the card itself recognises as thermometers /
* air monitors count, so fridges, TRVs and chip-temperature plugs stay out.
* The AUTO icon is used on purpose — a custom marker icon must not change what
* a device measures.
@@ -451,7 +451,7 @@ export function areaClimateMap(
// 90 C and a virtual better_thermostat duplicating the real sensor (field
// question, 2026-07-27). Three guards, cheapest first:
if (reg.entity_category) continue; // diagnostic/config readings
if (EXCLUDED_DOMAINS.has(reg.platform)) continue; // curated-out integrations
if (EXCLUDED_DOMAINS.has(reg.platform)) continue; // filtered-out integrations
if (NON_AIR_RE.test(eid)) continue; // water/chip/flow/target/...
let groups = byArea.get(area);
if (!groups) { groups = new Map(); byArea.set(area, groups); }