mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-28 19:01:34 +00:00
- settings.volumetric_view (General settings › Display, third switch) replaces the alpha entry, the header projection toggle and the phone-menu item; one rule for card, sidebar page and kiosk; editors stay Flat; backend accepts only a boolean, support package copies it. - Raised tiles in 2.5D View: no ring, rounded body min(0.275 D, 0.3 h), edge 0.1 D with the lab filters, ×1.12 size also in layout/collision, lift 0.075 D, one floor-shadow layer under all markers (theme × floor table), frames hugging tile and edge (Alert > Focus > Selected > Hover), forced colours without edge and shadow (src/iso-tiles.ts, styles/iso-tiles). - Soft sun wash instead of projected Flat wedges (src/iso-sun.ts): same gates and windows as sun_rays, length from elevation, parallelogram along the sun, tone and streaks by floor lightness, sill line. - Walls take the user's wall colour (top opaque, sides × .77/.68/.60); theme rules for walls/openings/labels removed; furniture uses the Flat stroke rule. - Smokes smoke_iso_tiles/iso_sun/iso_theme_walls/volumetric_setting, 16 new mutants, acceptance scenes STAGE6_ACCEPTANCE_SCENARIOS (golden with their Linux CI baselines), ACCEPTANCE.md side by side. Issue: #649 User-Visible: yes
91 lines
3.9 KiB
JavaScript
91 lines
3.9 KiB
JavaScript
// #649 п.4 (docs/ISOMETRIC.md, Stage 6): 2.5D is the installation-wide switch
|
||
// «General settings › Display», third after «Show live presence on the plan».
|
||
// Saving it changes the View at once in every space and in the kiosk; editors
|
||
// stay Flat; «Reset» turns it off; there is no card toggle and no alpha entry.
|
||
import { launch, checkAll, finish } from './serve.mjs';
|
||
|
||
const { page, browser } = await launch({ width: 1280, height: 900 });
|
||
const res = await page.evaluate(async () => {
|
||
const out = {};
|
||
const c = window.__card;
|
||
const t = window.__hpTest;
|
||
const sr = () => c.renderRoot;
|
||
const iso = (root = sr()) => !!root.querySelector('.stage')?.classList.contains('projection-iso');
|
||
const dlg = () => sr().querySelector('hp-dialog[data-kind="settings"]');
|
||
const q = (sel) => dlg()?.querySelector(sel);
|
||
const waitFor = async (predicate, ms = 8000) => {
|
||
const end = performance.now() + ms;
|
||
while (!predicate()) {
|
||
if (performance.now() > end) return false;
|
||
await new Promise((done) => setTimeout(done, 25));
|
||
}
|
||
return true;
|
||
};
|
||
const openSettings = async () => {
|
||
sr().querySelector('[data-hp="settings"]').click();
|
||
await t.settled();
|
||
return waitFor(() => !!q('#gs-volumetric-view'));
|
||
};
|
||
const save = async () => {
|
||
q('[data-hp="dialog-confirm"]').click();
|
||
await t.settled();
|
||
await waitFor(() => !dlg());
|
||
};
|
||
|
||
out.noCardToggle = !sr().querySelector('[data-hp="projection-toggle"], .projection-toggle');
|
||
out.startsFlat = !iso();
|
||
out.dialogOpens = await openSettings();
|
||
const display = q('.hpf-card[data-card="display"]');
|
||
const ids = [...display.querySelectorAll('.hpf-toggle > input[type="checkbox"]')].map((i) => i.id);
|
||
out.thirdInDisplay = JSON.stringify(ids) === JSON.stringify(['gs-room-tooltip', 'gs-radar-live', 'gs-volumetric-view']);
|
||
const row = q('#gs-volumetric-view').closest('.hpf-toggle')?.parentElement ?? null;
|
||
out.rowTitleAndIcon = !!row && row.textContent.includes(c._t('gs.volumetric_view'))
|
||
&& !!row.querySelector('ha-icon[icon="mdi:cube-outline"]');
|
||
out.offByDefault = q('#gs-volumetric-view').checked === false;
|
||
|
||
q('#gs-volumetric-view').click();
|
||
await t.settled();
|
||
out.previewDoesNotSwitch = !iso();
|
||
await save();
|
||
out.saveSwitchesAtOnce = await waitFor(() => iso());
|
||
out.storedAsTrue = c._serverCfg.settings.volumetric_view === true;
|
||
|
||
// Every space follows the one setting.
|
||
await t.switchSpace('garden');
|
||
out.otherSpaceIso = await waitFor(() => iso());
|
||
await t.switchSpace('f1');
|
||
out.backSpaceIso = await waitFor(() => iso());
|
||
|
||
// Editors are Flat, View returns to 2.5D.
|
||
await t.setMode('plan');
|
||
out.editorFlat = !iso();
|
||
await t.setMode('view');
|
||
out.viewIsoAgain = await waitFor(() => iso());
|
||
|
||
// The kiosk reads the same installation setting. The fixture does not keep
|
||
// writes, so the saved config is published as the server's state first.
|
||
await t.setServerConfig((cfg) => cfg);
|
||
const kiosk = document.createElement('houseplan-card');
|
||
kiosk.setConfig({ type: 'custom:houseplan-card', kiosk: true, cycle: 0 });
|
||
kiosk.hass = c.hass;
|
||
kiosk.style.cssText = 'position:fixed;left:0;top:0;width:900px;height:700px;z-index:99';
|
||
document.body.appendChild(kiosk);
|
||
out.kioskIso = await waitFor(() => !!kiosk.renderRoot?.querySelector('.stage')
|
||
&& iso(kiosk.renderRoot), 10000);
|
||
kiosk.remove();
|
||
|
||
// Reset turns it off; saving returns Flat without a reload.
|
||
await openSettings();
|
||
out.dialogShowsOn = q('#gs-volumetric-view').checked === true;
|
||
[...dlg().querySelectorAll('.dialog-action-footer .btn')]
|
||
.find((b) => b.textContent.trim() === c._t('gs.reset')).click();
|
||
await t.settled();
|
||
out.resetUnchecks = q('#gs-volumetric-view').checked === false;
|
||
await save();
|
||
out.resetSavesFlat = await waitFor(() => !iso());
|
||
out.falseNotStored = !('volumetric_view' in (c._serverCfg.settings || {}));
|
||
return out;
|
||
});
|
||
checkAll(res);
|
||
await finish(browser, res);
|