diff --git a/src/cards/climate-card/climate-card.ts b/src/cards/climate-card/climate-card.ts index 18d783fe..0f1841a4 100644 --- a/src/cards/climate-card/climate-card.ts +++ b/src/cards/climate-card/climate-card.ts @@ -51,7 +51,7 @@ registerCustomCard({ }); @customElement(CLIMATE_CARD_NAME) -export class ClimateCard extends MushroomBaseCard implements LovelaceCard { +export class ClimateCard extends MushroomBaseCard implements LovelaceCard { public static async getConfigElement(): Promise { await import("./climate-card-editor"); return document.createElement(CLIMATE_CARD_EDITOR_NAME) as LovelaceCardEditor; @@ -69,12 +69,9 @@ export class ClimateCard extends MushroomBaseCard implements @state() private _activeControl?: ClimateCardControl; private get _controls(): ClimateCardControl[] { - if (!this._config || !this.hass || !this._config.entity) return []; - - const entityId = this._config.entity; - const stateObj = this.hass.states[entityId] as ClimateEntity | undefined; - if (!stateObj) return []; - + if (!this._config || !this._stateObj) return []; + + const stateObj = this._stateObj; const controls: ClimateCardControl[] = []; if (isTemperatureControlVisible(stateObj) && this._config.show_temperature_control) { controls.push("temperature_control"); @@ -85,16 +82,8 @@ export class ClimateCard extends MushroomBaseCard implements return controls; } - public getGridSize(): [number, number] { - const size = super.getGridSize(); - if ( - this._controls.length && - !this._config?.collapsible_controls && - this._appearance?.layout !== "horizontal" - ) { - size[1] += 1; - } - return size; + protected get hasControls(): boolean { + return this._controls.length > 0; } _onControlTap(ctrl, e): void { @@ -134,12 +123,11 @@ export class ClimateCard extends MushroomBaseCard implements } protected render() { - if (!this.hass || !this._config || !this._config.entity) { + if (!this.hass || !this._config) { return nothing; } - const entityId = this._config.entity; - const stateObj = this.hass.states[entityId] as ClimateEntity | undefined; + const stateObj = this._stateObj; if (!stateObj) { return this.renderNotFound(this._config); diff --git a/src/cards/light-card/light-card.ts b/src/cards/light-card/light-card.ts index a78a930d..cf4fad80 100644 --- a/src/cards/light-card/light-card.ts +++ b/src/cards/light-card/light-card.ts @@ -59,7 +59,7 @@ registerCustomCard({ }); @customElement(LIGHT_CARD_NAME) -export class LightCard extends MushroomBaseCard implements LovelaceCard { +export class LightCard extends MushroomBaseCard implements LovelaceCard { public static async getConfigElement(): Promise { await import("./light-card-editor"); return document.createElement(LIGHT_CARD_EDITOR_NAME) as LovelaceCardEditor; @@ -79,12 +79,9 @@ export class LightCard extends MushroomBaseCard implements Love @state() private brightness?: number; private get _controls(): LightCardControl[] { - if (!this._config || !this.hass || !this._config.entity) return []; - - const entityId = this._config.entity; - const stateObj = this.hass.states[entityId] as LightEntity | undefined; - if (!stateObj) return []; + if (!this._config || !this._stateObj) return []; + const stateObj = this._stateObj; const controls: LightCardControl[] = []; if (this._config.show_brightness_control && supportsBrightnessControl(stateObj)) { controls.push("brightness_control"); @@ -98,16 +95,8 @@ export class LightCard extends MushroomBaseCard implements Love return controls; } - public getGridSize(): [number, number] { - const size = super.getGridSize(); - if ( - this._controls.length && - !this._config?.collapsible_controls && - this._appearance?.layout !== "horizontal" - ) { - size[1] += 1; - } - return size; + protected get hasControls(): boolean { + return this._controls.length > 0; } setConfig(config: LightCardConfig): void { diff --git a/src/cards/update-card/update-card.ts b/src/cards/update-card/update-card.ts index e7b0f863..a3d0f056 100644 --- a/src/cards/update-card/update-card.ts +++ b/src/cards/update-card/update-card.ts @@ -40,7 +40,10 @@ registerCustomCard({ }); @customElement(UPDATE_CARD_NAME) -export class UpdateCard extends MushroomBaseCard implements LovelaceCard { +export class UpdateCard + extends MushroomBaseCard + implements LovelaceCard +{ public static async getConfigElement(): Promise { await import("./update-card-editor"); return document.createElement(UPDATE_CARD_EDITOR_NAME) as LovelaceCardEditor; @@ -55,14 +58,15 @@ export class UpdateCard extends MushroomBaseCard implements LovelaceCard { }; } - @state() private _config?: UpdateCardConfig; - - getCardSize(): number | Promise { - return 1; + protected get hasControls() { + if (!this._stateObj || !this._config) return false; + return ( + Boolean(this._config.show_buttons_control) && + supportsFeature(this._stateObj, UPDATE_SUPPORT_INSTALL) + ); } - setConfig(config: UpdateCardConfig): void { - this._config = { + super.setConfig({ tap_action: { action: "more-info", }, @@ -70,7 +74,7 @@ export class UpdateCard extends MushroomBaseCard implements LovelaceCard { action: "more-info", }, ...config, - }; + }); } private _handleAction(ev: ActionHandlerEvent) { @@ -78,12 +82,11 @@ export class UpdateCard extends MushroomBaseCard implements LovelaceCard { } protected render() { - if (!this._config || !this.hass || !this._config.entity) { + if (!this._config || !this.hass) { return nothing; } - const entityId = this._config.entity; - const stateObj = this.hass.states[entityId] as UpdateEntity | undefined; + const stateObj = this._stateObj; if (!stateObj) { return this.renderNotFound(this._config); diff --git a/src/cards/vacuum-card/vacuum-card.ts b/src/cards/vacuum-card/vacuum-card.ts index e135a974..7e08cedd 100644 --- a/src/cards/vacuum-card/vacuum-card.ts +++ b/src/cards/vacuum-card/vacuum-card.ts @@ -41,7 +41,10 @@ registerCustomCard({ }); @customElement(VACUUM_CARD_NAME) -export class VacuumCard extends MushroomBaseCard implements LovelaceCard { +export class VacuumCard + extends MushroomBaseCard + implements LovelaceCard +{ public static async getConfigElement(): Promise { await import("./vacuum-card-editor"); return document.createElement(VACUUM_CARD_EDITOR_NAME) as LovelaceCardEditor; @@ -56,22 +59,9 @@ export class VacuumCard extends MushroomBaseCard implements Lo }; } - isControlSupported() { - if (!this._config || !this.hass || !this._config.entity) return false; - - const entityId = this._config.entity; - const stateObj = this.hass.states[entityId] as VacuumEntity | undefined; - if (!stateObj) return false; - - return isCommandsControlSupported(stateObj, this._config.commands ?? []); - } - - public getGridSize(): [number, number] { - const size = super.getGridSize(); - if (this.isControlSupported() && this._appearance?.layout !== "horizontal") { - size[1] += 1; - } - return size; + protected get hasControls() { + if (!this._stateObj || !this._config) return false; + return isCommandsControlSupported(this._stateObj, this._config.commands ?? []); } setConfig(config: VacuumCardConfig): void { @@ -91,12 +81,11 @@ export class VacuumCard extends MushroomBaseCard implements Lo } protected render() { - if (!this._config || !this.hass || !this._config.entity) { + if (!this._config || !this.hass) { return nothing; } - - const entityId = this._config.entity; - const stateObj = this.hass.states[entityId] as VacuumEntity | undefined; + + const stateObj = this._stateObj; if (!stateObj) { return this.renderNotFound(this._config); diff --git a/src/utils/base-card.ts b/src/utils/base-card.ts index d920601e..9a6acdfc 100644 --- a/src/utils/base-card.ts +++ b/src/utils/base-card.ts @@ -22,12 +22,26 @@ export function computeDarkMode(hass?: HomeAssistant): boolean { if (!hass) return false; return (hass.themes as any).darkMode as boolean; } -export class MushroomBaseCard extends MushroomBaseElement { +export class MushroomBaseCard< + T extends BaseConfig = BaseConfig, + E extends HassEntity = HassEntity, +> extends MushroomBaseElement { @state() protected _config?: T; @property({ attribute: "in-grid", reflect: true, type: Boolean }) protected _inGrid = false; + protected get _stateObj(): E | undefined { + if (!this._config || !this.hass || !this._config.entity) return undefined; + + const entityId = this._config.entity; + return this.hass.states[entityId] as E; + } + + protected get hasControls(): boolean { + return false; + } + public getCardSize(): number | Promise { return 1; } @@ -36,22 +50,25 @@ export class MushroomBaseCard extends Mushroo this._config = config; } - public get _appearance(): Appearance | undefined { - if (!this._config) return undefined; - return computeAppearance(this._config); - } - public getGridSize(): [number, number] { this._inGrid = true; let column = 2; let row = 1; - if (!this._appearance) return [column, row]; - if (this._appearance.layout === "vertical") { + if (!this._config) return [column, row]; + const appearance = computeAppearance(this._config); + if (appearance.layout === "vertical") { row += 1; } - if (this._appearance.layout === "horizontal") { + if (appearance.layout === "horizontal") { column = 4; } + if ( + appearance?.layout !== "horizontal" && + this.hasControls && + !("collapsible_controls" in this._config && this._config?.collapsible_controls) + ) { + row += 1; + } return [column, row]; }