mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
45 lines
15 KiB
JavaScript
45 lines
15 KiB
JavaScript
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="7d666f118b3321f5eca092f330ca7f1a3985cf7ab65ea69a2247c9064d4d2e7d";import{l as t,br as s,A as e,aC as o,c as a,g as i,cF as l,cG as h,cH as n,bo as r,cI as c,cN as p,cJ as d,cK as _,cL as u,cM as g,cO as m,cP as f}from"./houseplan-card-CY6xhpFf.js";import{D as b,C as v,E as y,G as w,H as D,I as $,J as S,v as C}from"./backdrop-pick-ChtekkjK.js";import"./form-kit.styles-B_5CMgdi.js";const k="7d666f118b3321f5eca092f330ca7f1a3985cf7ab65ea69a2247c9064d4d2e7d";class F{constructor(t){this.host=t,this._toggleServerPlans=async()=>{const t=this.host._spaceDialog;if(t)if(t.pickSaved)this.host._spaceDialog={...t,pickSaved:!1};else{this.host._spaceDialog={...t,pickSaved:!0,savedBusy:!0};try{const t=await this.host.hass.callWS({type:"houseplan/plans/list"}),s=this.host._spaceDialog;s&&(this.host._spaceDialog={...s,saved:t?.plans||[],savedBusy:!1})}catch(t){const s=this.host._spaceDialog;s&&(this.host._spaceDialog={...s,saved:[],savedBusy:!1}),this.host._showToast(this.host._t("toast.plans_list_failed",{err:this.host._errText(t)}))}}}}_help(i){const l=`${i}.aria`,h=t(this.host.hass,this.host._config?.language);return s(h,i)&&s(h,l)?a`<hp-help data-help-key=${i}
|
|
.text=${o(h,i)} .ariaLabel=${o(h,l)}></hp-help>`:e}_openSpaceDialog(t,s){if(!this.host._serverStorage||!this.host._serverCfg)return void this.host._showToast(this.host._t("toast.integration_missing"));if("edit"===t){const e=this.host._serverCfg.spaces.find(t=>t.id===s);if(!e)return;const o=i(e),a=e.settings?.custom_fill&&"object"==typeof e.settings.custom_fill?l(e.settings.custom_fill):null,p="none"===o.fill?{...a||h,a:0}:a;return void(this.host._spaceDialog={mode:t,spaceId:s,title:e.title,planUrl:e.plan_url||null,planFile:null,source:e.plan_url?"file":"draw",showBorders:o.showBorders,showNames:o.showNames,zeroWallStyle:c(e),displayTouched:!0,hideDecor:o.hideDecor,hideOpenings:o.hideOpenings,roomColor:o.color,roomOpacity:o.opacity,fillMode:"none"===o.fill?"custom":o.fill,customFill:p,glowEnabled:o.glow,bgColor:o.bgColor,bgMode:"static"===e.settings?.bg_mode||"daynight"===e.settings?.bg_mode?e.settings.bg_mode:null,northDeg:r({},e.settings),sunRays:"boolean"==typeof e.settings?.sun_rays?e.settings.sun_rays:null,tempMin:o.tempMin,tempMax:o.tempMax,showLqi:o.showLqi??this.host._config?.show_signal??!0,cardFontScale:o.cardFontScale,labelTemp:o.labelTemp,labelHum:o.labelHum,labelLqi:o.labelLqi,labelLight:o.labelLight,cellCm:Number(e.cell_cm)>0?Number(e.cell_cm):5,cellCmInput:n(Number(e.cell_cm)>0?Number(e.cell_cm):5,this.host._imperial),cellCmTouched:!1,busy:!1})}const e=p(this.host._imperial);this.host._spaceDialog={mode:t,title:"",planUrl:null,planFile:null,...m(),hideDecor:!1,hideOpenings:!1,zeroWallStyle:"dashed",roomColor:g,roomOpacity:u,fillMode:"custom",customFill:{...h,a:0},glowEnabled:!0,bgColor:null,bgMode:"daynight",northDeg:null,sunRays:null,tempMin:_,tempMax:d,showLqi:this.host._config?.show_signal??!0,cardFontScale:1,labelTemp:!1,labelHum:!1,labelLqi:!1,labelLight:!1,cellCm:e,cellCmInput:n(e,this.host._imperial),cellCmTouched:!1,busy:!1},b(this.host,this.host._spaceDialog)}async _pickPlanFile(t){const s=t.target,e=s.files?.[0];if(!e||!this.host._spaceDialog)return;s.value="";const o=await v(e);if("reject"===o.kind)return void this.host._showToast(this.host._t("toast.plan_formats"));if("guard"===o.kind)return void(this.host._backdropGuard=o.state);const a=await y(e,o.ext,e.name);this.host._spaceDialog&&(this.host._spaceDialog={...this.host._spaceDialog,planFile:a})}_renderBackdropGuard(){return w(this.host,t=>{this.host._spaceDialog&&(this.host._spaceDialog={...this.host._spaceDialog,planFile:t})},()=>{this.host._backdropGuard=null},this.host.hass)??e}_useServerPlan(t){const s=this.host._spaceDialog;s&&(this.host._spaceDialog={...s,planUrl:t,planFile:null,pickSaved:!1,savedAspect:void 0},this.host._aspectJob=this._readPlanAspect(t))}async _readPlanAspect(t){for(let s=0;s<40;s++){const s=this.host._display(t);if(s){const e=await new Promise(t=>{const e=new Image;e.onload=()=>t(e.naturalWidth&&e.naturalHeight?e.naturalWidth/e.naturalHeight:0),e.onerror=()=>t(0),e.src=s}),o=this.host._spaceDialog;return o&&o.planUrl===t&&Number.isFinite(e)&&e>0?(this.host._spaceDialog={...o,savedAspect:e},e):0}if(await new Promise(t=>setTimeout(t,150)),this.host._spaceDialog?.planUrl!==t)return 0}return 0}async _deleteServerPlan(t){const s=this.host._spaceDialog,e=s?.saved?.find(s=>s.name===t);if(!s||!e||e.used_by.length||e.url===s.planUrl)return;const o=await this.host._confirmDanger({key:"delete-plan",kind:"destructive",title:this.host._t("confirm.delete_plan_title"),message:this.host._t("confirm.delete_plan_body"),objectName:t,confirmLabel:this.host._t("btn.delete"),cancelLabel:this.host._t("btn.cancel")}),a=this.host._spaceDialog,i=a?.saved?.find(s=>s.name===t);if(o&&a&&i&&i.url===e.url&&i.modified===e.modified&&!i.used_by.length&&i.url!==a.planUrl)try{await this.host.hass.callWS({type:"houseplan/plans/delete",name:t});const s=this.host._spaceDialog;s?.saved&&(this.host._spaceDialog={...s,saved:s.saved.filter(s=>s.name!==t)})}catch(t){this.host._showToast(this.host._t("toast.plan_delete_failed",{err:this.host._errText(t)}))}}_renderServerPlans(t){if(t.savedBusy)return a`<div class="savedplans muted">${this.host._t("space.loading")}</div>`;const s=t.saved||[];if(!s.length)return a`<div class="savedplans muted">${this.host._t("space.no_saved")}</div>`;return a`<div class="savedplans">
|
|
${s.map(s=>{return a`
|
|
<div class="savedplan ${s.url===t.planUrl?"cur":""}">
|
|
<img src=${this.host._display(s.url)} alt="" loading="lazy" decoding="async" />
|
|
<div class="savedmeta">
|
|
<b>${s.name}</b>
|
|
<span class="muted">${e=s.size,e>=1048576?`${(e/1048576).toFixed(1)} MB`:`${Math.round(e/1024)} KB`}${s.used_by.length?` · ${this.host._t("space.used_by",{list:s.used_by.join(", ")})}`:""}</span>
|
|
</div>
|
|
<button class="btn ghost" @click=${()=>this._useServerPlan(s.url)}
|
|
?disabled=${s.url===t.planUrl}>${this.host._t("btn.use")}</button>
|
|
<button class="btn ghost danger"
|
|
title=${s.used_by.length||s.url===t.planUrl?this.host._t("space.in_use"):this.host._t("btn.delete")}
|
|
?disabled=${s.used_by.length>0||s.url===t.planUrl}
|
|
@click=${()=>this._deleteServerPlan(s.name)}>
|
|
<ha-icon icon="mdi:trash-can-outline"></ha-icon>
|
|
</button>
|
|
</div>`;var e})}
|
|
</div>`}async _saveConfigNow(){this.host._cfgEpoch++;try{await this.host._writeConfig()}catch(t){const s=t;throw s?.physicalGeometryRolledBack?await this.host._reloadRejectedPhysicalWrite():"conflict"===s?.code&&await this.host._reloadConfigOnly(),t}}async _saveSpaceDialog(){const t=this.host._spaceDialog;if(!t||t.busy||!t.title.trim())return;if("file"===t.source&&!t.planFile&&!t.planUrl)return void this.host._showToast(this.host._t("toast.plan_required"));const s="create"===t.mode&&0===(this.host._serverCfg?.spaces.length||0);this.host._spaceDialog={...t,busy:!0};try{const e="create"===t.mode?`s${Date.now().toString(36)}`:t.spaceId;let o=null;if("file"===t.source&&t.planFile){o={url:(await this.host.hass.callWS({type:"houseplan/plan/set",space_id:e,ext:t.planFile.ext,data:t.planFile.b64})).url,aspect:t.planFile.aspect}}let a=t.savedAspect||null;!o&&"file"===t.source&&t.planUrl&&!a&&this.host._aspectJob&&(a=await this.host._aspectJob||null);const i=this.host._serverCfg;let l=i.spaces.find(t=>t.id===e);if("create"===t.mode)l=f(e,t.title.trim()),i.spaces.push(l);else{if(!l)throw new Error(`space ${e} is gone from the config`);l.title=t.title.trim()}if(!l)throw new Error(`space ${e} is unavailable`);if(o?(l.plan_url=o.url,l.plan_aspect=o.aspect):"file"===t.source&&t.planUrl&&t.planUrl!==l.plan_url&&(l.plan_url=t.planUrl,l.plan_aspect=a),"draw"===t.source&&(l.plan_url=null,l.plan_aspect=null,delete l.plan_x,delete l.plan_y,delete l.plan_scale,delete l.plan_scale_x,delete l.plan_scale_y,delete l.plan_angle),l.settings={...l.settings||{},show_borders:t.showBorders,show_names:t.showNames,hide_decor:t.hideDecor||void 0,hide_openings:t.hideOpenings||void 0,room_color:t.roomColor,room_opacity:t.roomOpacity,bg_color:t.bgColor||void 0,bg_mode:t.bgMode||void 0,north_deg:t.northDeg??void 0,sun_rays:t.sunRays??void 0,fill_mode:t.fillMode,custom_fill:t.customFill||void 0,glow_enabled:t.glowEnabled,temp_min:Number.isFinite(t.tempMin)?Math.min(t.tempMin,t.tempMax):_,temp_max:Number.isFinite(t.tempMax)?Math.max(t.tempMin,t.tempMax):d,show_lqi:t.showLqi,card_font_scale:1!==t.cardFontScale?t.cardFontScale:void 0,label_temp:t.labelTemp,label_hum:t.labelHum,label_lqi:t.labelLqi,label_light:t.labelLight},l.zero_wall_style=t.zeroWallStyle,l.cell_cm=Number.isFinite(t.cellCm)&&t.cellCm>0?Math.max(D,Math.min($,t.cellCm)):5,await this._saveConfigNow(),this.host._spaceDialog=null,"create"===t.mode&&this.host._commitSpace(l.id),this.host._regSignature="",this.host._maybeRebuildDevices(),this.host._importQueue.length)this._openNextImport();else if(s||this.host._importTotal>0){const t=this.host._importTotal>0;this.host._importTotal=0,this.host._commitSpace(this.host._serverCfg.spaces[0]?.id||this.host._space),await this.host._requestMode("plan"),this.host._tool="draw",this.host._path=[],this.host._cursorPt=null,this.host._primeDrawWallField(),this.host._showToast(this.host._t(s&&!t?"toast.space_added_onboard":"import.done"))}else this.host._showToast(this.host._t("create"===t.mode?"toast.space_added":"toast.space_saved")),"create"===t.mode&&("plan"!==this.host._mode?await this.host._requestMode("plan"):(this.host._tool="draw",this.host._path=[],this.host._cursorPt=null,this.host._primeDrawWallField(),this.host._saveNav()))}catch(t){const s=t;"conflict"!==s?.code&&await this.host._reloadConfigOnly(!0),this.host._spaceDialog&&(this.host._spaceDialog={...this.host._spaceDialog,busy:!1}),this.host._showToast(this.host._t("toast.error",{err:this.host._errText(t)}))}}async _deleteSpace(){const t=this.host._spaceDialog;if(!t||"edit"!==t.mode)return;const s=this.host._serverCfg;if(!s)return;const e=s.spaces.find(s=>s.id===t.spaceId);if(!e)return;const o=S(s,this.host._layout||{},t.spaceId||""),a=1===s.spaces.length&&s.spaces[0]?.id===t.spaceId;if(o.count&&!a)return void(this.host._spaceDialog={...t,deleteBlockers:o.count});const i=t.spaceId,l=await this.host._confirmDanger({key:"delete-space",kind:"destructive",title:this.host._t("confirm.delete_space_title"),message:this.host._t("confirm.delete_space_body"),objectName:e.title,confirmLabel:this.host._t("btn.delete"),cancelLabel:this.host._t("btn.cancel")}),h=this.host._spaceDialog,n=this.host._serverCfg;if(!l||!h||"edit"!==h.mode||h.busy||h.spaceId!==i||!n)return;if(!n.spaces.find(t=>t.id===i))return;const r=S(n,this.host._layout||{},i),c=1===n.spaces.length&&n.spaces[0]?.id===i;if(!r.count||c){this.host._spaceDialog={...h,deleteBlockers:0,busy:!0};try{this.host._saveConfigDebounced.pending()&&this.host._saveConfigDebounced.flush(),this.host._persistLayout.pending()&&this.host._persistLayout.flush(),await this.host._writeChain,await this.host.hass.callWS({type:"houseplan/space/delete",space_id:i,expected_config_rev:this.host._cfgRev,expected_layout_rev:this.host._layoutRev});const[t,s]=await Promise.all([this.host._getAuthoritativeConfig(),this.host.hass.callWS({type:"houseplan/layout/get"})]);if("adopted"!==(await this.host._adoptAuthoritative({cfgResp:t,layResp:s,reason:"space-delete",profile:"post-write"})).status)return this.host._spaceDialog={...h,busy:!1},void this.host.requestUpdate();this.host._spaceDialog=null,this.host._space===i&&this.host._commitSpace(this.host._serverCfg.spaces[0]?.id||""),this.host._regSignature="",this.host._maybeRebuildDevices(),this.host._showToast(this.host._t("toast.space_deleted"))}catch(t){const s=t;"conflict"!==s?.code&&"space_in_use"!==s?.code||await Promise.all([this.host._reloadConfigOnly(!0),this.host._reloadLayoutOnly()]);const e=this.host._serverCfg;if(this.host._spaceDialog&&e){const t=S(e,this.host._layout||{},i),s=1===e.spaces.length&&e.spaces[0]?.id===i;this.host._spaceDialog={...this.host._spaceDialog,busy:!1,deleteBlockers:s?0:t.count}}this.host._showToast(this.host._t("toast.delete_failed",{err:this.host._errText(t)}))}}else this.host._spaceDialog={...h,deleteBlockers:r.count}}_startImport(){const t=this.host._importDialog;if(!t)return;const s=t.floors.filter(t=>t.checked).map(t=>t.name);this.host._importDialog=null,s.length?(this.host._importQueue=s,this.host._importTotal=s.length,this._openNextImport()):this._openSpaceDialog("create")}_openNextImport(){const t=this.host._importQueue.shift();if(void 0===t)return;const s=p(this.host._imperial);this.host._spaceDialog={mode:"create",title:t,planUrl:null,planFile:null,...m(),hideDecor:!1,hideOpenings:!1,zeroWallStyle:"dashed",roomColor:g,roomOpacity:u,fillMode:"custom",customFill:null,glowEnabled:!0,bgColor:null,bgMode:"daynight",northDeg:null,sunRays:null,tempMin:_,tempMax:d,showLqi:this.host._config?.show_signal??!0,cardFontScale:1,labelTemp:!1,labelHum:!1,labelLqi:!1,labelLight:!1,cellCm:s,cellCmInput:n(s,this.host._imperial),cellCmTouched:!1,busy:!1},b(this.host,this.host._spaceDialog)}_skipImport(){this.host._spaceDialog=null,this.host._importQueue.length?this._openNextImport():this.host._importTotal>0&&this.host._model.length&&(this.host._importTotal=0,this.host._commitSpace(this.host._serverCfg.spaces[0]?.id||this.host._space),this.host._requestMode("plan").then(()=>{this.host._showToast(this.host._t("import.done"))}))}_renderImportDialog(){const t=this.host._importDialog,s=t.floors.filter(t=>t.checked).length;return a`<hp-dialog .hass=${this.host.hass} data-kind="import"
|
|
.title=${this.host._t("import.title")}
|
|
icon="mdi:home-floor-1" @hp-close=${()=>this.host._importDialog=null}>
|
|
<div class="body">
|
|
<div class="rhint">${this.host._t("import.hint")}</div>
|
|
${t.floors.map((s,o)=>a`<label class="floorrow">
|
|
<input type="checkbox" .checked=${s.checked}
|
|
@change=${e=>{const a=[...t.floors];a[o]={...s,checked:e.target.checked},this.host._importDialog={floors:a}}} />
|
|
<span>${s.name}</span>
|
|
${null!=s.level?a`<span class="floorlvl">L${s.level}</span>`:e}
|
|
</label>`)}
|
|
</div>
|
|
<div class="row" slot="footer">
|
|
<button class="btn ghost" @click=${()=>{this.host._importDialog=null,this._openSpaceDialog("create")}}>${this.host._t("import.manual")}</button>
|
|
<span class="spacer"></span>
|
|
<button class="btn on" data-hp="dialog-confirm"
|
|
@click=${()=>this._startImport()} ?disabled=${!s}>
|
|
<ha-icon icon="mdi:import"></ha-icon>${this.host._t("import.start",{n:s})}
|
|
</button>
|
|
</div>
|
|
</hp-dialog>`}_rangeInput(t,s,o,i,l,h=!1,n){return a`<input type="range" min=${t} max=${s} step=${o} .value=${String(i)}
|
|
?disabled=${h} aria-label=${n??e}
|
|
@input=${t=>l(Number(t.target.value))} />`}_renderSpaceDialog(){const t=C({host:this.host,idPrefix:"onboarding-space",help:this._help.bind(this),rangeInput:(t,s,e,o,a,i,l)=>this._rangeInput(t,s,e,o,a,i,l),pickPlanFile:t=>this._pickPlanFile(t),toggleServerPlans:()=>this._toggleServerPlans(),renderServerPlans:t=>this._renderServerPlans(t),save:()=>this._saveSpaceDialog(),skipImport:()=>this._skipImport()});return a`<hp-dialog .hass=${this.host.hass} data-kind="onboarding" form-shell wide
|
|
.title=${t.title} .badge=${t.badge} icon="mdi:floor-plan" @hp-close=${t.requestClose}>
|
|
${t.body}${t.footer}
|
|
</hp-dialog>`}}export{F as HouseplanOnboardingRuntime,k as ONBOARDING_RUNTIME_FINGERPRINT};
|