mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-30 11:49:16 +00:00
Fix confirmation guards for unrenderable branches
Issue: #417 User-Visible: yes
This commit is contained in:
@@ -1,52 +1,52 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"fingerprint": "d90076d3f49d110c3959a6c08a86895a6b98ca810fe122b37b76e22adc38ad73",
|
||||
"fingerprint": "c3f3b28b3149752a2b63584dbe161b2a247db77770fd5bd84bd87a14f303b3a6",
|
||||
"entry": "houseplan-card.js",
|
||||
"initialViewFiles": [
|
||||
"houseplan-assets/houseplan-card-HIu1PXGU.js",
|
||||
"houseplan-assets/houseplan-card-DoTfrXZx.js",
|
||||
"houseplan-card.js"
|
||||
],
|
||||
"initialViewGzipBytes": 290460,
|
||||
"initialViewGzipBytes": 290566,
|
||||
"lazyFiles": [
|
||||
"houseplan-assets/backdrop-pick-CI0weKTj.js",
|
||||
"houseplan-assets/de-Db5jQSzb.js",
|
||||
"houseplan-assets/editor-DrFXz_Hr.js",
|
||||
"houseplan-assets/fr-gYskL0hZ.js",
|
||||
"houseplan-assets/houseplan-editor-runtime-BHxJWPq7.js",
|
||||
"houseplan-assets/houseplan-onboarding-runtime-CXZ19w7L.js"
|
||||
"houseplan-assets/backdrop-pick-CrHBqjf1.js",
|
||||
"houseplan-assets/de-Bja91KNY.js",
|
||||
"houseplan-assets/editor-CMVCfgT3.js",
|
||||
"houseplan-assets/fr-ClzwnAMY.js",
|
||||
"houseplan-assets/houseplan-editor-runtime-BSYUK6nC.js",
|
||||
"houseplan-assets/houseplan-onboarding-runtime-B9wPxaO1.js"
|
||||
],
|
||||
"lazyGzipBytes": 205822,
|
||||
"lazyGzipBytes": 205825,
|
||||
"lazyEditorFiles": [
|
||||
"houseplan-assets/backdrop-pick-CI0weKTj.js",
|
||||
"houseplan-assets/editor-DrFXz_Hr.js",
|
||||
"houseplan-assets/houseplan-editor-runtime-BHxJWPq7.js"
|
||||
"houseplan-assets/backdrop-pick-CrHBqjf1.js",
|
||||
"houseplan-assets/editor-CMVCfgT3.js",
|
||||
"houseplan-assets/houseplan-editor-runtime-BSYUK6nC.js"
|
||||
],
|
||||
"lazyEditorGzipBytes": 148716,
|
||||
"lazyEditorGzipBytes": 148718,
|
||||
"lazyOnboardingFiles": [
|
||||
"houseplan-assets/backdrop-pick-CI0weKTj.js",
|
||||
"houseplan-assets/houseplan-onboarding-runtime-CXZ19w7L.js"
|
||||
"houseplan-assets/backdrop-pick-CrHBqjf1.js",
|
||||
"houseplan-assets/houseplan-onboarding-runtime-B9wPxaO1.js"
|
||||
],
|
||||
"lazyOnboardingGzipBytes": 14032,
|
||||
"lazyLocaleFiles": [
|
||||
"houseplan-assets/de-Db5jQSzb.js",
|
||||
"houseplan-assets/fr-gYskL0hZ.js"
|
||||
"houseplan-assets/de-Bja91KNY.js",
|
||||
"houseplan-assets/fr-ClzwnAMY.js"
|
||||
],
|
||||
"lazyLocaleGzipBytes": 50146,
|
||||
"lazyLocaleGzipBytes": 50147,
|
||||
"files": [
|
||||
{
|
||||
"path": "houseplan-assets/backdrop-pick-CI0weKTj.js",
|
||||
"sha256": "36f0fbfeccd0ac6981be68fc7446f7b548a5cb40a542b48e07331f2791e7f555",
|
||||
"path": "houseplan-assets/backdrop-pick-CrHBqjf1.js",
|
||||
"sha256": "5dfc1f1a537f2026f2b2e0628bde0dde81e62278f9fd07647b748a334af220ac",
|
||||
"rawBytes": 20636,
|
||||
"gzipBytes": 7072,
|
||||
"isEntry": false,
|
||||
"imports": [
|
||||
"houseplan-assets/houseplan-card-HIu1PXGU.js"
|
||||
"houseplan-assets/houseplan-card-DoTfrXZx.js"
|
||||
],
|
||||
"dynamicImports": []
|
||||
},
|
||||
{
|
||||
"path": "houseplan-assets/de-Db5jQSzb.js",
|
||||
"sha256": "412aaaff8a26a9d7fd6d5e4335711e821ea5ad38cc095b61a3ae56ece4c0a7e9",
|
||||
"path": "houseplan-assets/de-Bja91KNY.js",
|
||||
"sha256": "62fc9d40d1de845df4c83a527d1426b927c7b87b2a83da8271e14485edebca51",
|
||||
"rawBytes": 83981,
|
||||
"gzipBytes": 25344,
|
||||
"isEntry": false,
|
||||
@@ -54,72 +54,72 @@
|
||||
"dynamicImports": []
|
||||
},
|
||||
{
|
||||
"path": "houseplan-assets/editor-DrFXz_Hr.js",
|
||||
"sha256": "cba3f4d097d84c823946d966677f02fcae841233c3a683e2deda6c7084f1f7f2",
|
||||
"path": "houseplan-assets/editor-CMVCfgT3.js",
|
||||
"sha256": "408f5bc440896e6b29eaf3ab59d30960974215e3d0341161675a3e88a8f2700e",
|
||||
"rawBytes": 3826,
|
||||
"gzipBytes": 1582,
|
||||
"gzipBytes": 1583,
|
||||
"isEntry": false,
|
||||
"imports": [
|
||||
"houseplan-assets/houseplan-card-HIu1PXGU.js"
|
||||
"houseplan-assets/houseplan-card-DoTfrXZx.js"
|
||||
],
|
||||
"dynamicImports": []
|
||||
},
|
||||
{
|
||||
"path": "houseplan-assets/fr-gYskL0hZ.js",
|
||||
"sha256": "6fe8d00dfa1f3b29b669aa81b205547f49778c86441e5723ab3982b970af09b0",
|
||||
"path": "houseplan-assets/fr-ClzwnAMY.js",
|
||||
"sha256": "976d7e2294ffccbd4223e2ffba4b5c43697edbb8e1baa37d6b785f6a98c69bcc",
|
||||
"rawBytes": 86212,
|
||||
"gzipBytes": 24802,
|
||||
"gzipBytes": 24803,
|
||||
"isEntry": false,
|
||||
"imports": [],
|
||||
"dynamicImports": []
|
||||
},
|
||||
{
|
||||
"path": "houseplan-assets/houseplan-card-HIu1PXGU.js",
|
||||
"sha256": "d43a961780a297835fa6b3d8b3ff534897b8376128afa9e7c1db7829dee74ee4",
|
||||
"rawBytes": 1032568,
|
||||
"gzipBytes": 289663,
|
||||
"path": "houseplan-assets/houseplan-card-DoTfrXZx.js",
|
||||
"sha256": "40cc6422072c6017550b0cbf73a772ae4839e172d1187510f1eb92dd78ccb1d5",
|
||||
"rawBytes": 1032986,
|
||||
"gzipBytes": 289769,
|
||||
"isEntry": false,
|
||||
"imports": [],
|
||||
"dynamicImports": [
|
||||
"houseplan-assets/de-Db5jQSzb.js",
|
||||
"houseplan-assets/editor-DrFXz_Hr.js",
|
||||
"houseplan-assets/fr-gYskL0hZ.js",
|
||||
"houseplan-assets/houseplan-editor-runtime-BHxJWPq7.js",
|
||||
"houseplan-assets/houseplan-onboarding-runtime-CXZ19w7L.js"
|
||||
"houseplan-assets/de-Bja91KNY.js",
|
||||
"houseplan-assets/editor-CMVCfgT3.js",
|
||||
"houseplan-assets/fr-ClzwnAMY.js",
|
||||
"houseplan-assets/houseplan-editor-runtime-BSYUK6nC.js",
|
||||
"houseplan-assets/houseplan-onboarding-runtime-B9wPxaO1.js"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "houseplan-assets/houseplan-editor-runtime-BHxJWPq7.js",
|
||||
"sha256": "df085c635b6b02fa11c1b0b5d9f8e87fc56309ed905de32f6eaee5b8e7c10af4",
|
||||
"path": "houseplan-assets/houseplan-editor-runtime-BSYUK6nC.js",
|
||||
"sha256": "9d86b76630217ad0b95a8f9f5b3ee8c04776f3450f911b3d24eb5c0d6170e10b",
|
||||
"rawBytes": 543265,
|
||||
"gzipBytes": 140062,
|
||||
"gzipBytes": 140063,
|
||||
"isEntry": false,
|
||||
"imports": [
|
||||
"houseplan-assets/backdrop-pick-CI0weKTj.js",
|
||||
"houseplan-assets/houseplan-card-HIu1PXGU.js"
|
||||
"houseplan-assets/backdrop-pick-CrHBqjf1.js",
|
||||
"houseplan-assets/houseplan-card-DoTfrXZx.js"
|
||||
],
|
||||
"dynamicImports": []
|
||||
},
|
||||
{
|
||||
"path": "houseplan-assets/houseplan-onboarding-runtime-CXZ19w7L.js",
|
||||
"sha256": "0a7828064aa00462836ba7d7fd7bd975b9a0751894d5546aa5c1bad60b987702",
|
||||
"path": "houseplan-assets/houseplan-onboarding-runtime-B9wPxaO1.js",
|
||||
"sha256": "9e5fb7f22b8a9fba1afd1e5930b8da2e1250a55aac7610d60061d9cb80aa9091",
|
||||
"rawBytes": 28088,
|
||||
"gzipBytes": 6960,
|
||||
"isEntry": false,
|
||||
"imports": [
|
||||
"houseplan-assets/backdrop-pick-CI0weKTj.js",
|
||||
"houseplan-assets/houseplan-card-HIu1PXGU.js"
|
||||
"houseplan-assets/backdrop-pick-CrHBqjf1.js",
|
||||
"houseplan-assets/houseplan-card-DoTfrXZx.js"
|
||||
],
|
||||
"dynamicImports": []
|
||||
},
|
||||
{
|
||||
"path": "houseplan-card.js",
|
||||
"sha256": "0ac5ff1feac770dfe96547960ca7e5816d4f501fc37cdaf47f5e6cd93d3e427b",
|
||||
"sha256": "9e0f7a84c95cc7aec1c4e3e20e3a8663e12f418a089e3897dcac67fa1be94ae0",
|
||||
"rawBytes": 1183,
|
||||
"gzipBytes": 797,
|
||||
"isEntry": true,
|
||||
"imports": [
|
||||
"houseplan-assets/houseplan-card-HIu1PXGU.js"
|
||||
"houseplan-assets/houseplan-card-DoTfrXZx.js"
|
||||
],
|
||||
"dynamicImports": []
|
||||
}
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1,4 +1,4 @@
|
||||
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="d90076d3f49d110c3959a6c08a86895a6b98ca810fe122b37b76e22adc38ad73";import{b as e,l as o,t,d8 as s,A as a,d9 as i,da as l,db as n,E as r,c}from"./houseplan-card-HIu1PXGU.js";class h extends e{constructor(){super(...arguments),this._spaces=null,this._spacesLoading=!1,this._spacesAuthoritative=!1}setConfig(e){this._config=e}async _loadSpaces(){if(!this._spaces&&!this._spacesLoading&&this.hass){this._spacesLoading=!0;try{const e=await this.hass.callWS({type:"houseplan/config/get"});this._spaces=(e?.config?.spaces||[]).map(e=>({value:e.id,label:e.title||e.id})),this._spacesAuthoritative=!0}catch{this._spaces=[],this._spacesAuthoritative=!1}finally{this._spacesLoading=!1}}}get _lang(){return o(this.hass,this._config?.language)}get _floorToken(){const e=this._config?.floor;return"number"==typeof e?`__houseplan_yaml_floor_index__:${String(e)}`:null}get _formData(){const e={...this._config},o=this._floorToken;return o?e.floor=o:Object.prototype.hasOwnProperty.call(e,"floor")||(e.floor=""),e}get _schema(){const e=this._spaces||[],o=this._lang,a=[{value:"",label:t(o,"editor.floor_none")}],i=this._floorToken;i&&a.push({value:i,label:t(o,"editor.floor_index",{index:String(this._config?.floor)})});const l="string"==typeof this._config?.floor?this._config.floor:"";l&&!e.some(e=>e.value===l)&&a.push({value:l,label:l}),a.push(...e);const n="string"==typeof this._config?.default_floor?this._config.default_floor:"",r=[...e];return n&&!e.some(e=>e.value===n)&&r.unshift({value:n,label:n}),[{name:"title",selector:{text:{}}},{name:"floor",selector:{select:{mode:"dropdown",options:a}}},e.length?{name:"default_floor",selector:{select:{mode:"dropdown",options:r}}}:{name:"default_floor",selector:{text:{}}},{name:"language",selector:{select:{mode:"dropdown",options:s(t(o,"editor.lang_auto"),this._config?.language)}}},{name:"icon_size",selector:{number:{min:1,max:6,step:.1,mode:"box"}}},{name:"show_temperature",selector:{boolean:{}}},{name:"live_states",selector:{boolean:{}}},{name:"show_signal",selector:{boolean:{}}},{name:"kiosk",selector:{boolean:{}}},{name:"cycle",selector:{number:{min:0,max:3600,step:5,mode:"box"}}}]}render(){if(!this.hass||!this._config)return a;const e=i(this,l,o(this.hass,this._config.language));if("cold"===e)return n();if("warm"===e)return r;this._loadSpaces();const s=this._lang,h={title:t(s,"editor.title"),floor:t(s,"editor.floor"),default_floor:t(s,"editor.default_floor"),language:t(s,"editor.language"),icon_size:t(s,"editor.icon_size"),show_temperature:t(s,"editor.show_temperature"),live_states:t(s,"editor.live_states"),show_signal:t(s,"editor.show_signal"),kiosk:t(s,"editor.kiosk"),cycle:t(s,"editor.cycle")},f=this._schema,_=function(e,o,t){if(!t||null===o)return null;const s="string"==typeof e?.default_floor?e.default_floor:"";return!s||o.some(e=>e.value===s)?null:s}(this._config,this._spaces,this._spacesAuthoritative),d=e=>c`<ha-form
|
||||
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="c3f3b28b3149752a2b63584dbe161b2a247db77770fd5bd84bd87a14f303b3a6";import{b as e,l as o,t,d8 as s,A as a,d9 as i,da as l,db as n,E as r,c}from"./houseplan-card-DoTfrXZx.js";class h extends e{constructor(){super(...arguments),this._spaces=null,this._spacesLoading=!1,this._spacesAuthoritative=!1}setConfig(e){this._config=e}async _loadSpaces(){if(!this._spaces&&!this._spacesLoading&&this.hass){this._spacesLoading=!0;try{const e=await this.hass.callWS({type:"houseplan/config/get"});this._spaces=(e?.config?.spaces||[]).map(e=>({value:e.id,label:e.title||e.id})),this._spacesAuthoritative=!0}catch{this._spaces=[],this._spacesAuthoritative=!1}finally{this._spacesLoading=!1}}}get _lang(){return o(this.hass,this._config?.language)}get _floorToken(){const e=this._config?.floor;return"number"==typeof e?`__houseplan_yaml_floor_index__:${String(e)}`:null}get _formData(){const e={...this._config},o=this._floorToken;return o?e.floor=o:Object.prototype.hasOwnProperty.call(e,"floor")||(e.floor=""),e}get _schema(){const e=this._spaces||[],o=this._lang,a=[{value:"",label:t(o,"editor.floor_none")}],i=this._floorToken;i&&a.push({value:i,label:t(o,"editor.floor_index",{index:String(this._config?.floor)})});const l="string"==typeof this._config?.floor?this._config.floor:"";l&&!e.some(e=>e.value===l)&&a.push({value:l,label:l}),a.push(...e);const n="string"==typeof this._config?.default_floor?this._config.default_floor:"",r=[...e];return n&&!e.some(e=>e.value===n)&&r.unshift({value:n,label:n}),[{name:"title",selector:{text:{}}},{name:"floor",selector:{select:{mode:"dropdown",options:a}}},e.length?{name:"default_floor",selector:{select:{mode:"dropdown",options:r}}}:{name:"default_floor",selector:{text:{}}},{name:"language",selector:{select:{mode:"dropdown",options:s(t(o,"editor.lang_auto"),this._config?.language)}}},{name:"icon_size",selector:{number:{min:1,max:6,step:.1,mode:"box"}}},{name:"show_temperature",selector:{boolean:{}}},{name:"live_states",selector:{boolean:{}}},{name:"show_signal",selector:{boolean:{}}},{name:"kiosk",selector:{boolean:{}}},{name:"cycle",selector:{number:{min:0,max:3600,step:5,mode:"box"}}}]}render(){if(!this.hass||!this._config)return a;const e=i(this,l,o(this.hass,this._config.language));if("cold"===e)return n();if("warm"===e)return r;this._loadSpaces();const s=this._lang,h={title:t(s,"editor.title"),floor:t(s,"editor.floor"),default_floor:t(s,"editor.default_floor"),language:t(s,"editor.language"),icon_size:t(s,"editor.icon_size"),show_temperature:t(s,"editor.show_temperature"),live_states:t(s,"editor.live_states"),show_signal:t(s,"editor.show_signal"),kiosk:t(s,"editor.kiosk"),cycle:t(s,"editor.cycle")},f=this._schema,_=function(e,o,t){if(!t||null===o)return null;const s="string"==typeof e?.default_floor?e.default_floor:"";return!s||o.some(e=>e.value===s)?null:s}(this._config,this._spaces,this._spacesAuthoritative),d=e=>c`<ha-form
|
||||
.hass=${this.hass}
|
||||
.data=${this._formData}
|
||||
.schema=${e}
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+22
-22
File diff suppressed because one or more lines are too long
+2
-2
File diff suppressed because one or more lines are too long
+7
-7
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="d90076d3f49d110c3959a6c08a86895a6b98ca810fe122b37b76e22adc38ad73";try{await import("./houseplan-assets/houseplan-card-HIu1PXGU.js")}catch(e){if(!customElements.get("houseplan-card")){const l=String(navigator.language||"en").toLowerCase();const m=l.startsWith("ru")?"House Plan обновился — перезагрузите страницу (Ctrl+F5).":l.startsWith("de")?"House Plan wurde aktualisiert — bitte laden Sie die Seite neu (Strg+F5).":l.startsWith("fr")?"House Plan a été mis à jour — veuillez recharger la page (Ctrl+F5).":"House Plan was updated — please reload the page (Ctrl+F5).";customElements.define("houseplan-card",class extends HTMLElement{setConfig(){}getCardSize(){return 1}connectedCallback(){this.style.cssText="display:block;box-sizing:border-box;padding:16px;border:1px solid var(--divider-color,#e0e0e0);border-radius:var(--ha-card-border-radius,12px);background:var(--card-background-color,#fff);color:var(--primary-text-color,#212121);font:14px/1.4 var(--paper-font-body1_-_font-family,sans-serif)";this.textContent=m}})}console.error("[houseplan] stale entry: the main chunk is unavailable",e)}
|
||||
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="c3f3b28b3149752a2b63584dbe161b2a247db77770fd5bd84bd87a14f303b3a6";try{await import("./houseplan-assets/houseplan-card-DoTfrXZx.js")}catch(e){if(!customElements.get("houseplan-card")){const l=String(navigator.language||"en").toLowerCase();const m=l.startsWith("ru")?"House Plan обновился — перезагрузите страницу (Ctrl+F5).":l.startsWith("de")?"House Plan wurde aktualisiert — bitte laden Sie die Seite neu (Strg+F5).":l.startsWith("fr")?"House Plan a été mis à jour — veuillez recharger la page (Ctrl+F5).":"House Plan was updated — please reload the page (Ctrl+F5).";customElements.define("houseplan-card",class extends HTMLElement{setConfig(){}getCardSize(){return 1}connectedCallback(){this.style.cssText="display:block;box-sizing:border-box;padding:16px;border:1px solid var(--divider-color,#e0e0e0);border-radius:var(--ha-card-border-radius,12px);background:var(--card-background-color,#fff);color:var(--primary-text-color,#212121);font:14px/1.4 var(--paper-font-body1_-_font-family,sans-serif)";this.textContent=m}})}console.error("[houseplan] stale entry: the main chunk is unavailable",e)}
|
||||
|
||||
@@ -15,6 +15,75 @@ const { page, browser } = await launch(
|
||||
{ width: 390, height: 760 }, 1, [], { hasTouch: true, isMobile: true },
|
||||
);
|
||||
|
||||
// Hold the first German chunk request so the card remains in the real `warm`
|
||||
// language gate long enough to exercise it. Aborting would immediately select
|
||||
// the English fallback and could turn this into a test that never enters the
|
||||
// branch it claims to cover.
|
||||
const germanAsset = /\/houseplan-assets\/de-[^/?]+\.js(?:\?.*)?$/;
|
||||
let releaseGerman;
|
||||
let markGermanStarted;
|
||||
let markGermanCompleted;
|
||||
const germanStarted = new Promise((resolve) => { markGermanStarted = resolve; });
|
||||
const germanCompleted = new Promise((resolve) => { markGermanCompleted = resolve; });
|
||||
const holdGerman = async (route) => {
|
||||
markGermanStarted();
|
||||
await new Promise((resolve) => { releaseGerman = resolve; });
|
||||
await route.continue();
|
||||
markGermanCompleted();
|
||||
};
|
||||
await page.route(germanAsset, holdGerman);
|
||||
|
||||
const warmGate = await page.evaluate(async () => {
|
||||
const card = window.__card;
|
||||
const root = () => card.shadowRoot || card.renderRoot;
|
||||
const settle = async () => {
|
||||
await card.updateComplete;
|
||||
await new Promise((resolve) => requestAnimationFrame(() => requestAnimationFrame(resolve)));
|
||||
};
|
||||
const originalLanguage = card._config?.language;
|
||||
card._config = { ...card._config, language: 'de' };
|
||||
card.requestUpdate();
|
||||
for (let attempt = 0; attempt < 50 && card._dangerConfirmLocaleGate !== 'warm'; attempt++) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 10));
|
||||
await settle();
|
||||
}
|
||||
|
||||
const entered = card._dangerConfirmLocaleGate === 'warm' && card.inert;
|
||||
const before = root().innerHTML;
|
||||
const decision = await Promise.race([
|
||||
card._confirmDanger({
|
||||
key: 'warm-language-gate',
|
||||
kind: 'destructive',
|
||||
title: 'Delete?',
|
||||
message: 'The plan and all its rooms will be deleted.',
|
||||
confirmLabel: 'Delete',
|
||||
cancelLabel: 'Cancel',
|
||||
}),
|
||||
new Promise((resolve) => setTimeout(() => resolve('timeout'), 100)),
|
||||
]);
|
||||
const result = {
|
||||
warmLanguageGateActuallyEntered: entered,
|
||||
warmLanguageGateRefusesImmediately: decision === false,
|
||||
warmLanguageGateKeepsControllerEmpty: card._dangerConfirm === null
|
||||
&& card._dangerConfirmController.state === null,
|
||||
warmLanguageGateKeepsNoChangeDom: root().innerHTML === before
|
||||
&& !root().querySelector('hp-confirm'),
|
||||
};
|
||||
|
||||
card._config = { ...card._config, language: originalLanguage };
|
||||
card.requestUpdate();
|
||||
await settle();
|
||||
return result;
|
||||
});
|
||||
|
||||
await Promise.race([
|
||||
germanStarted,
|
||||
new Promise((_, reject) => setTimeout(() => reject(new Error('German locale request not seen')), 1000)),
|
||||
]);
|
||||
releaseGerman();
|
||||
await germanCompleted;
|
||||
await page.unroute(germanAsset, holdGerman);
|
||||
|
||||
const out = await page.evaluate(async () => {
|
||||
const result = {};
|
||||
const card = window.__card;
|
||||
@@ -152,6 +221,58 @@ const out = await page.evaluate(async () => {
|
||||
&& (await survivor) === true;
|
||||
await leaveBranch();
|
||||
|
||||
// The exact missed branch from #417: a non-empty model whose active space
|
||||
// cannot be resolved returns `nothing`, unlike onboarding and fixed-floor
|
||||
// status cards. An already open request must be cancelled during the same
|
||||
// update, and a new request must never enter the controller.
|
||||
const originalSpaceModel = card._spaceModel;
|
||||
const pendingAtSpaceLoss = card._confirmDanger(request('space-lost-after-open'));
|
||||
await settle();
|
||||
card._spaceModel = () => undefined;
|
||||
card.requestUpdate();
|
||||
await settle();
|
||||
const spaceLossDecision = await Promise.race([
|
||||
pendingAtSpaceLoss,
|
||||
new Promise((resolve) => setTimeout(() => resolve('timeout'), 100)),
|
||||
]);
|
||||
result.lostSpaceBranchIsActuallyEntered = root().childElementCount === 0;
|
||||
result.openConfirmCancelsWhenSpaceIsLost = spaceLossDecision === false
|
||||
&& card._dangerConfirm === null && card._dangerConfirmController.state === null;
|
||||
const refusedWithoutSpace = await Promise.race([
|
||||
card._confirmDanger(request('space-already-lost')),
|
||||
new Promise((resolve) => setTimeout(() => resolve('timeout'), 100)),
|
||||
]);
|
||||
result.lostSpaceRequestRefusesImmediately = refusedWithoutSpace === false
|
||||
&& card._dangerConfirm === null && card._dangerConfirmController.state === null
|
||||
&& dialogs() === 0;
|
||||
card._spaceModel = originalSpaceModel;
|
||||
card.requestUpdate();
|
||||
await settle();
|
||||
|
||||
// The two status branches called out by #402 still paint a card, so they
|
||||
// must keep hosting the confirmation instead of being caught by the new
|
||||
// lost-space guard.
|
||||
const originalConfig = card._config;
|
||||
const originalLoadOk = card._loadOk;
|
||||
const confirmInFixedBranch = async (loadOk, state) => {
|
||||
card._loadOk = loadOk;
|
||||
card._config = { ...originalConfig, floor: 'missing-floor-for-confirm-smoke' };
|
||||
card.requestUpdate();
|
||||
await settle();
|
||||
const branchEntered = !!root().querySelector(`[data-fixed-floor-state="${state}"]`);
|
||||
const pending = card._confirmDanger(request(`fixed-${state}`));
|
||||
await settle();
|
||||
const shown = dialogs() === 1;
|
||||
await decide(false);
|
||||
return branchEntered && shown && (await pending) === false;
|
||||
};
|
||||
result.fixedFloorPendingStillShowsConfirm = await confirmInFixedBranch(false, 'pending');
|
||||
result.fixedFloorInvalidStillShowsConfirm = await confirmInFixedBranch(true, 'invalid');
|
||||
card._loadOk = originalLoadOk;
|
||||
card._config = originalConfig;
|
||||
card.requestUpdate();
|
||||
await settle();
|
||||
|
||||
// Тап по «Отмена» — тот же путь, что и клик: на touch подтверждение обязано
|
||||
// спрашиваться, а не деградировать (TOUCH-SUPPORT § Safety floor).
|
||||
await enterBranch([]);
|
||||
@@ -236,6 +357,8 @@ const out = await page.evaluate(async () => {
|
||||
return result;
|
||||
});
|
||||
|
||||
Object.assign(out, warmGate);
|
||||
|
||||
await page.evaluate(async () => {
|
||||
const element = document.createElement('hp-confirm');
|
||||
element.token = 4_060_000;
|
||||
|
||||
Vendored
+51
-51
@@ -1,52 +1,52 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"fingerprint": "d90076d3f49d110c3959a6c08a86895a6b98ca810fe122b37b76e22adc38ad73",
|
||||
"fingerprint": "c3f3b28b3149752a2b63584dbe161b2a247db77770fd5bd84bd87a14f303b3a6",
|
||||
"entry": "houseplan-card.js",
|
||||
"initialViewFiles": [
|
||||
"houseplan-assets/houseplan-card-HIu1PXGU.js",
|
||||
"houseplan-assets/houseplan-card-DoTfrXZx.js",
|
||||
"houseplan-card.js"
|
||||
],
|
||||
"initialViewGzipBytes": 290460,
|
||||
"initialViewGzipBytes": 290566,
|
||||
"lazyFiles": [
|
||||
"houseplan-assets/backdrop-pick-CI0weKTj.js",
|
||||
"houseplan-assets/de-Db5jQSzb.js",
|
||||
"houseplan-assets/editor-DrFXz_Hr.js",
|
||||
"houseplan-assets/fr-gYskL0hZ.js",
|
||||
"houseplan-assets/houseplan-editor-runtime-BHxJWPq7.js",
|
||||
"houseplan-assets/houseplan-onboarding-runtime-CXZ19w7L.js"
|
||||
"houseplan-assets/backdrop-pick-CrHBqjf1.js",
|
||||
"houseplan-assets/de-Bja91KNY.js",
|
||||
"houseplan-assets/editor-CMVCfgT3.js",
|
||||
"houseplan-assets/fr-ClzwnAMY.js",
|
||||
"houseplan-assets/houseplan-editor-runtime-BSYUK6nC.js",
|
||||
"houseplan-assets/houseplan-onboarding-runtime-B9wPxaO1.js"
|
||||
],
|
||||
"lazyGzipBytes": 205822,
|
||||
"lazyGzipBytes": 205825,
|
||||
"lazyEditorFiles": [
|
||||
"houseplan-assets/backdrop-pick-CI0weKTj.js",
|
||||
"houseplan-assets/editor-DrFXz_Hr.js",
|
||||
"houseplan-assets/houseplan-editor-runtime-BHxJWPq7.js"
|
||||
"houseplan-assets/backdrop-pick-CrHBqjf1.js",
|
||||
"houseplan-assets/editor-CMVCfgT3.js",
|
||||
"houseplan-assets/houseplan-editor-runtime-BSYUK6nC.js"
|
||||
],
|
||||
"lazyEditorGzipBytes": 148716,
|
||||
"lazyEditorGzipBytes": 148718,
|
||||
"lazyOnboardingFiles": [
|
||||
"houseplan-assets/backdrop-pick-CI0weKTj.js",
|
||||
"houseplan-assets/houseplan-onboarding-runtime-CXZ19w7L.js"
|
||||
"houseplan-assets/backdrop-pick-CrHBqjf1.js",
|
||||
"houseplan-assets/houseplan-onboarding-runtime-B9wPxaO1.js"
|
||||
],
|
||||
"lazyOnboardingGzipBytes": 14032,
|
||||
"lazyLocaleFiles": [
|
||||
"houseplan-assets/de-Db5jQSzb.js",
|
||||
"houseplan-assets/fr-gYskL0hZ.js"
|
||||
"houseplan-assets/de-Bja91KNY.js",
|
||||
"houseplan-assets/fr-ClzwnAMY.js"
|
||||
],
|
||||
"lazyLocaleGzipBytes": 50146,
|
||||
"lazyLocaleGzipBytes": 50147,
|
||||
"files": [
|
||||
{
|
||||
"path": "houseplan-assets/backdrop-pick-CI0weKTj.js",
|
||||
"sha256": "36f0fbfeccd0ac6981be68fc7446f7b548a5cb40a542b48e07331f2791e7f555",
|
||||
"path": "houseplan-assets/backdrop-pick-CrHBqjf1.js",
|
||||
"sha256": "5dfc1f1a537f2026f2b2e0628bde0dde81e62278f9fd07647b748a334af220ac",
|
||||
"rawBytes": 20636,
|
||||
"gzipBytes": 7072,
|
||||
"isEntry": false,
|
||||
"imports": [
|
||||
"houseplan-assets/houseplan-card-HIu1PXGU.js"
|
||||
"houseplan-assets/houseplan-card-DoTfrXZx.js"
|
||||
],
|
||||
"dynamicImports": []
|
||||
},
|
||||
{
|
||||
"path": "houseplan-assets/de-Db5jQSzb.js",
|
||||
"sha256": "412aaaff8a26a9d7fd6d5e4335711e821ea5ad38cc095b61a3ae56ece4c0a7e9",
|
||||
"path": "houseplan-assets/de-Bja91KNY.js",
|
||||
"sha256": "62fc9d40d1de845df4c83a527d1426b927c7b87b2a83da8271e14485edebca51",
|
||||
"rawBytes": 83981,
|
||||
"gzipBytes": 25344,
|
||||
"isEntry": false,
|
||||
@@ -54,72 +54,72 @@
|
||||
"dynamicImports": []
|
||||
},
|
||||
{
|
||||
"path": "houseplan-assets/editor-DrFXz_Hr.js",
|
||||
"sha256": "cba3f4d097d84c823946d966677f02fcae841233c3a683e2deda6c7084f1f7f2",
|
||||
"path": "houseplan-assets/editor-CMVCfgT3.js",
|
||||
"sha256": "408f5bc440896e6b29eaf3ab59d30960974215e3d0341161675a3e88a8f2700e",
|
||||
"rawBytes": 3826,
|
||||
"gzipBytes": 1582,
|
||||
"gzipBytes": 1583,
|
||||
"isEntry": false,
|
||||
"imports": [
|
||||
"houseplan-assets/houseplan-card-HIu1PXGU.js"
|
||||
"houseplan-assets/houseplan-card-DoTfrXZx.js"
|
||||
],
|
||||
"dynamicImports": []
|
||||
},
|
||||
{
|
||||
"path": "houseplan-assets/fr-gYskL0hZ.js",
|
||||
"sha256": "6fe8d00dfa1f3b29b669aa81b205547f49778c86441e5723ab3982b970af09b0",
|
||||
"path": "houseplan-assets/fr-ClzwnAMY.js",
|
||||
"sha256": "976d7e2294ffccbd4223e2ffba4b5c43697edbb8e1baa37d6b785f6a98c69bcc",
|
||||
"rawBytes": 86212,
|
||||
"gzipBytes": 24802,
|
||||
"gzipBytes": 24803,
|
||||
"isEntry": false,
|
||||
"imports": [],
|
||||
"dynamicImports": []
|
||||
},
|
||||
{
|
||||
"path": "houseplan-assets/houseplan-card-HIu1PXGU.js",
|
||||
"sha256": "d43a961780a297835fa6b3d8b3ff534897b8376128afa9e7c1db7829dee74ee4",
|
||||
"rawBytes": 1032568,
|
||||
"gzipBytes": 289663,
|
||||
"path": "houseplan-assets/houseplan-card-DoTfrXZx.js",
|
||||
"sha256": "40cc6422072c6017550b0cbf73a772ae4839e172d1187510f1eb92dd78ccb1d5",
|
||||
"rawBytes": 1032986,
|
||||
"gzipBytes": 289769,
|
||||
"isEntry": false,
|
||||
"imports": [],
|
||||
"dynamicImports": [
|
||||
"houseplan-assets/de-Db5jQSzb.js",
|
||||
"houseplan-assets/editor-DrFXz_Hr.js",
|
||||
"houseplan-assets/fr-gYskL0hZ.js",
|
||||
"houseplan-assets/houseplan-editor-runtime-BHxJWPq7.js",
|
||||
"houseplan-assets/houseplan-onboarding-runtime-CXZ19w7L.js"
|
||||
"houseplan-assets/de-Bja91KNY.js",
|
||||
"houseplan-assets/editor-CMVCfgT3.js",
|
||||
"houseplan-assets/fr-ClzwnAMY.js",
|
||||
"houseplan-assets/houseplan-editor-runtime-BSYUK6nC.js",
|
||||
"houseplan-assets/houseplan-onboarding-runtime-B9wPxaO1.js"
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "houseplan-assets/houseplan-editor-runtime-BHxJWPq7.js",
|
||||
"sha256": "df085c635b6b02fa11c1b0b5d9f8e87fc56309ed905de32f6eaee5b8e7c10af4",
|
||||
"path": "houseplan-assets/houseplan-editor-runtime-BSYUK6nC.js",
|
||||
"sha256": "9d86b76630217ad0b95a8f9f5b3ee8c04776f3450f911b3d24eb5c0d6170e10b",
|
||||
"rawBytes": 543265,
|
||||
"gzipBytes": 140062,
|
||||
"gzipBytes": 140063,
|
||||
"isEntry": false,
|
||||
"imports": [
|
||||
"houseplan-assets/backdrop-pick-CI0weKTj.js",
|
||||
"houseplan-assets/houseplan-card-HIu1PXGU.js"
|
||||
"houseplan-assets/backdrop-pick-CrHBqjf1.js",
|
||||
"houseplan-assets/houseplan-card-DoTfrXZx.js"
|
||||
],
|
||||
"dynamicImports": []
|
||||
},
|
||||
{
|
||||
"path": "houseplan-assets/houseplan-onboarding-runtime-CXZ19w7L.js",
|
||||
"sha256": "0a7828064aa00462836ba7d7fd7bd975b9a0751894d5546aa5c1bad60b987702",
|
||||
"path": "houseplan-assets/houseplan-onboarding-runtime-B9wPxaO1.js",
|
||||
"sha256": "9e5fb7f22b8a9fba1afd1e5930b8da2e1250a55aac7610d60061d9cb80aa9091",
|
||||
"rawBytes": 28088,
|
||||
"gzipBytes": 6960,
|
||||
"isEntry": false,
|
||||
"imports": [
|
||||
"houseplan-assets/backdrop-pick-CI0weKTj.js",
|
||||
"houseplan-assets/houseplan-card-HIu1PXGU.js"
|
||||
"houseplan-assets/backdrop-pick-CrHBqjf1.js",
|
||||
"houseplan-assets/houseplan-card-DoTfrXZx.js"
|
||||
],
|
||||
"dynamicImports": []
|
||||
},
|
||||
{
|
||||
"path": "houseplan-card.js",
|
||||
"sha256": "0ac5ff1feac770dfe96547960ca7e5816d4f501fc37cdaf47f5e6cd93d3e427b",
|
||||
"sha256": "9e0f7a84c95cc7aec1c4e3e20e3a8663e12f418a089e3897dcac67fa1be94ae0",
|
||||
"rawBytes": 1183,
|
||||
"gzipBytes": 797,
|
||||
"isEntry": true,
|
||||
"imports": [
|
||||
"houseplan-assets/houseplan-card-HIu1PXGU.js"
|
||||
"houseplan-assets/houseplan-card-DoTfrXZx.js"
|
||||
],
|
||||
"dynamicImports": []
|
||||
}
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1,4 +1,4 @@
|
||||
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="d90076d3f49d110c3959a6c08a86895a6b98ca810fe122b37b76e22adc38ad73";import{b as e,l as o,t,d8 as s,A as a,d9 as i,da as l,db as n,E as r,c}from"./houseplan-card-HIu1PXGU.js";class h extends e{constructor(){super(...arguments),this._spaces=null,this._spacesLoading=!1,this._spacesAuthoritative=!1}setConfig(e){this._config=e}async _loadSpaces(){if(!this._spaces&&!this._spacesLoading&&this.hass){this._spacesLoading=!0;try{const e=await this.hass.callWS({type:"houseplan/config/get"});this._spaces=(e?.config?.spaces||[]).map(e=>({value:e.id,label:e.title||e.id})),this._spacesAuthoritative=!0}catch{this._spaces=[],this._spacesAuthoritative=!1}finally{this._spacesLoading=!1}}}get _lang(){return o(this.hass,this._config?.language)}get _floorToken(){const e=this._config?.floor;return"number"==typeof e?`__houseplan_yaml_floor_index__:${String(e)}`:null}get _formData(){const e={...this._config},o=this._floorToken;return o?e.floor=o:Object.prototype.hasOwnProperty.call(e,"floor")||(e.floor=""),e}get _schema(){const e=this._spaces||[],o=this._lang,a=[{value:"",label:t(o,"editor.floor_none")}],i=this._floorToken;i&&a.push({value:i,label:t(o,"editor.floor_index",{index:String(this._config?.floor)})});const l="string"==typeof this._config?.floor?this._config.floor:"";l&&!e.some(e=>e.value===l)&&a.push({value:l,label:l}),a.push(...e);const n="string"==typeof this._config?.default_floor?this._config.default_floor:"",r=[...e];return n&&!e.some(e=>e.value===n)&&r.unshift({value:n,label:n}),[{name:"title",selector:{text:{}}},{name:"floor",selector:{select:{mode:"dropdown",options:a}}},e.length?{name:"default_floor",selector:{select:{mode:"dropdown",options:r}}}:{name:"default_floor",selector:{text:{}}},{name:"language",selector:{select:{mode:"dropdown",options:s(t(o,"editor.lang_auto"),this._config?.language)}}},{name:"icon_size",selector:{number:{min:1,max:6,step:.1,mode:"box"}}},{name:"show_temperature",selector:{boolean:{}}},{name:"live_states",selector:{boolean:{}}},{name:"show_signal",selector:{boolean:{}}},{name:"kiosk",selector:{boolean:{}}},{name:"cycle",selector:{number:{min:0,max:3600,step:5,mode:"box"}}}]}render(){if(!this.hass||!this._config)return a;const e=i(this,l,o(this.hass,this._config.language));if("cold"===e)return n();if("warm"===e)return r;this._loadSpaces();const s=this._lang,h={title:t(s,"editor.title"),floor:t(s,"editor.floor"),default_floor:t(s,"editor.default_floor"),language:t(s,"editor.language"),icon_size:t(s,"editor.icon_size"),show_temperature:t(s,"editor.show_temperature"),live_states:t(s,"editor.live_states"),show_signal:t(s,"editor.show_signal"),kiosk:t(s,"editor.kiosk"),cycle:t(s,"editor.cycle")},f=this._schema,_=function(e,o,t){if(!t||null===o)return null;const s="string"==typeof e?.default_floor?e.default_floor:"";return!s||o.some(e=>e.value===s)?null:s}(this._config,this._spaces,this._spacesAuthoritative),d=e=>c`<ha-form
|
||||
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="c3f3b28b3149752a2b63584dbe161b2a247db77770fd5bd84bd87a14f303b3a6";import{b as e,l as o,t,d8 as s,A as a,d9 as i,da as l,db as n,E as r,c}from"./houseplan-card-DoTfrXZx.js";class h extends e{constructor(){super(...arguments),this._spaces=null,this._spacesLoading=!1,this._spacesAuthoritative=!1}setConfig(e){this._config=e}async _loadSpaces(){if(!this._spaces&&!this._spacesLoading&&this.hass){this._spacesLoading=!0;try{const e=await this.hass.callWS({type:"houseplan/config/get"});this._spaces=(e?.config?.spaces||[]).map(e=>({value:e.id,label:e.title||e.id})),this._spacesAuthoritative=!0}catch{this._spaces=[],this._spacesAuthoritative=!1}finally{this._spacesLoading=!1}}}get _lang(){return o(this.hass,this._config?.language)}get _floorToken(){const e=this._config?.floor;return"number"==typeof e?`__houseplan_yaml_floor_index__:${String(e)}`:null}get _formData(){const e={...this._config},o=this._floorToken;return o?e.floor=o:Object.prototype.hasOwnProperty.call(e,"floor")||(e.floor=""),e}get _schema(){const e=this._spaces||[],o=this._lang,a=[{value:"",label:t(o,"editor.floor_none")}],i=this._floorToken;i&&a.push({value:i,label:t(o,"editor.floor_index",{index:String(this._config?.floor)})});const l="string"==typeof this._config?.floor?this._config.floor:"";l&&!e.some(e=>e.value===l)&&a.push({value:l,label:l}),a.push(...e);const n="string"==typeof this._config?.default_floor?this._config.default_floor:"",r=[...e];return n&&!e.some(e=>e.value===n)&&r.unshift({value:n,label:n}),[{name:"title",selector:{text:{}}},{name:"floor",selector:{select:{mode:"dropdown",options:a}}},e.length?{name:"default_floor",selector:{select:{mode:"dropdown",options:r}}}:{name:"default_floor",selector:{text:{}}},{name:"language",selector:{select:{mode:"dropdown",options:s(t(o,"editor.lang_auto"),this._config?.language)}}},{name:"icon_size",selector:{number:{min:1,max:6,step:.1,mode:"box"}}},{name:"show_temperature",selector:{boolean:{}}},{name:"live_states",selector:{boolean:{}}},{name:"show_signal",selector:{boolean:{}}},{name:"kiosk",selector:{boolean:{}}},{name:"cycle",selector:{number:{min:0,max:3600,step:5,mode:"box"}}}]}render(){if(!this.hass||!this._config)return a;const e=i(this,l,o(this.hass,this._config.language));if("cold"===e)return n();if("warm"===e)return r;this._loadSpaces();const s=this._lang,h={title:t(s,"editor.title"),floor:t(s,"editor.floor"),default_floor:t(s,"editor.default_floor"),language:t(s,"editor.language"),icon_size:t(s,"editor.icon_size"),show_temperature:t(s,"editor.show_temperature"),live_states:t(s,"editor.live_states"),show_signal:t(s,"editor.show_signal"),kiosk:t(s,"editor.kiosk"),cycle:t(s,"editor.cycle")},f=this._schema,_=function(e,o,t){if(!t||null===o)return null;const s="string"==typeof e?.default_floor?e.default_floor:"";return!s||o.some(e=>e.value===s)?null:s}(this._config,this._spaces,this._spacesAuthoritative),d=e=>c`<ha-form
|
||||
.hass=${this.hass}
|
||||
.data=${this._formData}
|
||||
.schema=${e}
|
||||
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+22
-22
File diff suppressed because one or more lines are too long
+2
-2
File diff suppressed because one or more lines are too long
+7
-7
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -1 +1 @@
|
||||
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="d90076d3f49d110c3959a6c08a86895a6b98ca810fe122b37b76e22adc38ad73";try{await import("./houseplan-assets/houseplan-card-HIu1PXGU.js")}catch(e){if(!customElements.get("houseplan-card")){const l=String(navigator.language||"en").toLowerCase();const m=l.startsWith("ru")?"House Plan обновился — перезагрузите страницу (Ctrl+F5).":l.startsWith("de")?"House Plan wurde aktualisiert — bitte laden Sie die Seite neu (Strg+F5).":l.startsWith("fr")?"House Plan a été mis à jour — veuillez recharger la page (Ctrl+F5).":"House Plan was updated — please reload the page (Ctrl+F5).";customElements.define("houseplan-card",class extends HTMLElement{setConfig(){}getCardSize(){return 1}connectedCallback(){this.style.cssText="display:block;box-sizing:border-box;padding:16px;border:1px solid var(--divider-color,#e0e0e0);border-radius:var(--ha-card-border-radius,12px);background:var(--card-background-color,#fff);color:var(--primary-text-color,#212121);font:14px/1.4 var(--paper-font-body1_-_font-family,sans-serif)";this.textContent=m}})}console.error("[houseplan] stale entry: the main chunk is unavailable",e)}
|
||||
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="c3f3b28b3149752a2b63584dbe161b2a247db77770fd5bd84bd87a14f303b3a6";try{await import("./houseplan-assets/houseplan-card-DoTfrXZx.js")}catch(e){if(!customElements.get("houseplan-card")){const l=String(navigator.language||"en").toLowerCase();const m=l.startsWith("ru")?"House Plan обновился — перезагрузите страницу (Ctrl+F5).":l.startsWith("de")?"House Plan wurde aktualisiert — bitte laden Sie die Seite neu (Strg+F5).":l.startsWith("fr")?"House Plan a été mis à jour — veuillez recharger la page (Ctrl+F5).":"House Plan was updated — please reload the page (Ctrl+F5).";customElements.define("houseplan-card",class extends HTMLElement{setConfig(){}getCardSize(){return 1}connectedCallback(){this.style.cssText="display:block;box-sizing:border-box;padding:16px;border:1px solid var(--divider-color,#e0e0e0);border-radius:var(--ha-card-border-radius,12px);background:var(--card-background-color,#fff);color:var(--primary-text-color,#212121);font:14px/1.4 var(--paper-font-body1_-_font-family,sans-serif)";this.textContent=m}})}console.error("[houseplan] stale entry: the main chunk is unavailable",e)}
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
## Unreleased
|
||||
|
||||
- Dangerous-action confirmation no longer hangs if the active space disappears
|
||||
or a request arrives while a lazy language is switching; House Plan now
|
||||
refuses safely when no confirmation dialog can be rendered
|
||||
([#417](https://github.com/Matysh/houseplan-card/issues/417)).
|
||||
|
||||
## v1.70.0 — 2026-09-02
|
||||
|
||||
- House Plan adds a private **Help & feedback** flow, localized backend errors
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
|
||||
## Не выпущено
|
||||
|
||||
- Подтверждение опасного действия больше не зависает, если активное пространство
|
||||
исчезло или запрос пришёл во время переключения лениво загружаемого языка:
|
||||
когда показать диалог невозможно, House Plan безопасно отвечает отказом
|
||||
([#417](https://github.com/Matysh/houseplan-card/issues/417)).
|
||||
|
||||
## v1.70.0 — 2026-09-02
|
||||
|
||||
- В House Plan появился закрытый канал **«Помощь и обратная связь»**, ошибки
|
||||
|
||||
@@ -828,6 +828,39 @@ const MUTANT_DEFINITIONS = [
|
||||
replace: ' return html`${body}`;',
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'danger-confirm-lost-space-request-guard-removed',
|
||||
guard: 'node demo/smoke_danger_confirm_branches.mjs',
|
||||
because: 'accepting a new confirmation while the active space resolves to nothing '
|
||||
+ 'registers a promise whose hp-confirm owner cannot exist (#417 AC1)',
|
||||
patches: [{
|
||||
file: 'src/houseplan-card.ts',
|
||||
find: " if (this._dangerConfirmMissingSpace()) return Promise.resolve(false);",
|
||||
replace: " void this._dangerConfirmMissingSpace();",
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'danger-confirm-lost-space-transition-cancel-removed',
|
||||
guard: 'node demo/smoke_danger_confirm_branches.mjs',
|
||||
because: 'an open confirmation must resolve false before a lost-space render clears '
|
||||
+ 'its only decision source (#417 AC1)',
|
||||
patches: [{
|
||||
file: 'src/houseplan-card.ts',
|
||||
find: " if (this._dangerConfirm && this._dangerConfirmMissingSpace()) {\n this._cancelDangerConfirm();\n }",
|
||||
replace: " void this._dangerConfirm;\n void this._dangerConfirmMissingSpace;",
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'danger-confirm-warm-language-guard-removed',
|
||||
guard: 'node demo/smoke_danger_confirm_branches.mjs',
|
||||
because: 'the warm language branch returns Lit noChange, so a newly registered '
|
||||
+ 'confirmation has no rendered decision source and hangs (#417 AC2)',
|
||||
patches: [{
|
||||
file: 'src/houseplan-card.ts',
|
||||
find: " if (this._dangerConfirmLocaleGate === 'warm') return Promise.resolve(false);",
|
||||
replace: " void this._dangerConfirmLocaleGate;",
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'furniture-edge-handles-steal-the-corner',
|
||||
guard: 'node demo/smoke_furniture_polish.mjs',
|
||||
|
||||
+29
-6
@@ -247,7 +247,9 @@ import {
|
||||
import { enqueueSerializedWrite } from './serialized-write-queue';
|
||||
import { hasTranslation, langOf, t, type I18nKey } from './i18n';
|
||||
import { LANGUAGE_RUNTIME, subscribeLanguageLoadFailures } from './i18n/registry';
|
||||
import { languageLoadingTemplate, languageRenderGate } from './i18n/language-runtime';
|
||||
import {
|
||||
languageLoadingTemplate, languageRenderGate, type LanguageRenderGate,
|
||||
} from './i18n/language-runtime';
|
||||
import { CommandStack } from './command-stack';
|
||||
import {
|
||||
applyDevicePlacement,
|
||||
@@ -2148,16 +2150,31 @@ export class HouseplanCard extends LitElement {
|
||||
} | { kind: 'run'; text: string; exec: () => void } | null = null;
|
||||
/** One eager confirmation owner shared by View, onboarding and lazy editors. */
|
||||
private _dangerConfirm: HpConfirmState | null = null;
|
||||
/** Last language branch painted by `_renderBody`; `warm` cannot accept new dialogs. */
|
||||
private _dangerConfirmLocaleGate: LanguageRenderGate = 'ready';
|
||||
private readonly _dangerConfirmController = new HpConfirmController((state) => {
|
||||
this._dangerConfirm = state;
|
||||
});
|
||||
/**
|
||||
* The only post-initialisation branch whose body is literally `nothing`.
|
||||
* Onboarding and fixed-floor errors paint a card and can host hp-confirm;
|
||||
* a lost active space cannot.
|
||||
*/
|
||||
private _dangerConfirmMissingSpace(): boolean {
|
||||
const model = this._model;
|
||||
if (!model.length) return false;
|
||||
const fixed = this._fixedFloorState(model);
|
||||
if (fixed.kind === 'pending' || fixed.kind === 'invalid') return false;
|
||||
return !this._spaceModel();
|
||||
}
|
||||
private _confirmDanger = (request: HpConfirmRequest): Promise<boolean> => {
|
||||
// #402: a card that draws nothing cannot ask. Refusing outright is the
|
||||
// honest answer — the alternative is a promise nobody will ever resolve,
|
||||
// which is exactly the defect this issue closes. The caller already treats
|
||||
// `false` as «the user declined», and at this point the user has pressed
|
||||
// nothing: the card is not on screen yet.
|
||||
// #402/#417: a card that draws nothing cannot ask. Refusing outright is
|
||||
// the honest answer — the alternative is a promise nobody will ever
|
||||
// resolve. Keep the guards aligned with `_renderBody`'s two unrenderable
|
||||
// branches instead of registering a controller request with no DOM owner.
|
||||
if (!this._config || !this.hass) return Promise.resolve(false);
|
||||
if (this._dangerConfirmLocaleGate === 'warm') return Promise.resolve(false);
|
||||
if (this._dangerConfirmMissingSpace()) return Promise.resolve(false);
|
||||
return this._dangerConfirmController.confirm(request);
|
||||
};
|
||||
private _cancelDangerConfirm = (): void => {
|
||||
@@ -4149,6 +4166,11 @@ export class HouseplanCard extends LitElement {
|
||||
if (!preserveGeometry) this._cfgEpoch++;
|
||||
}
|
||||
this._syncEmptySpaceState();
|
||||
// #417: losing the only renderable space while a decision is pending must
|
||||
// settle it before render() clears hp-confirm with `nothing`.
|
||||
if (this._dangerConfirm && this._dangerConfirmMissingSpace()) {
|
||||
this._cancelDangerConfirm();
|
||||
}
|
||||
if (changed.has('hass') && this.hass) {
|
||||
this._hassSequence++;
|
||||
this._renderSnapshotAt = Date.now();
|
||||
@@ -11284,6 +11306,7 @@ export class HouseplanCard extends LitElement {
|
||||
const localeGate = languageRenderGate(
|
||||
this, LANGUAGE_RUNTIME, langOf(this.hass, this._config.language),
|
||||
);
|
||||
this._dangerConfirmLocaleGate = localeGate;
|
||||
if (localeGate === 'cold') return languageLoadingTemplate();
|
||||
if (localeGate === 'warm') return noChange;
|
||||
const onboardingRuntimeRequested = !!this._importDialog
|
||||
|
||||
Reference in New Issue
Block a user