From 8ed4914232b6488cda7b16ab4470b5aab83e7175 Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Tue, 21 Feb 2023 11:10:44 +0100 Subject: [PATCH] Add support for custom tile features (#15411 * Move isSupported to class * Use getConfigElement to display edit button * Remove custom element for test * Don't use class static functions * Refactor render * Add support for custom tile features in editor * Add missing relative position * Rename custom tile features options * PR feedbacks + split offical and custom types * Merge is custom type function --- src/common/structs/is-custom-type.ts | 3 +- src/data/lovelace_custom_cards.ts | 20 ++ src/panels/lovelace/cards/hui-tile-card.ts | 24 +- .../create-element/create-element-base.ts | 9 +- .../hui-entities-card-editor.ts | 6 +- .../hui-tile-card-features-editor.ts | 244 ++++++++++++------ .../editor/get-card-documentation-url.ts | 8 +- .../hui-cover-open-close-tile-feature.ts | 21 +- .../hui-cover-tilt-tile-feature.ts | 21 +- .../hui-light-brightness-tile-feature.ts | 18 +- .../hui-vacuum-commands-tile-feature.ts | 20 +- .../lovelace/tile-features/tile-features.ts | 44 ---- src/panels/lovelace/types.ts | 1 + 13 files changed, 275 insertions(+), 164 deletions(-) delete mode 100644 src/panels/lovelace/tile-features/tile-features.ts diff --git a/src/common/structs/is-custom-type.ts b/src/common/structs/is-custom-type.ts index dd5de2f637..e5a0082794 100644 --- a/src/common/structs/is-custom-type.ts +++ b/src/common/structs/is-custom-type.ts @@ -1,6 +1,5 @@ import { refine, string } from "superstruct"; - -export const isCustomType = (value: string) => value.startsWith("custom:"); +import { isCustomType } from "../../data/lovelace_custom_cards"; export const customType = () => refine(string(), "custom element type", isCustomType); diff --git a/src/data/lovelace_custom_cards.ts b/src/data/lovelace_custom_cards.ts index d669b50880..0f7b5e9f02 100644 --- a/src/data/lovelace_custom_cards.ts +++ b/src/data/lovelace_custom_cards.ts @@ -1,3 +1,5 @@ +import type { HassEntity } from "home-assistant-js-websocket"; + export interface CustomCardEntry { type: string; name?: string; @@ -6,8 +8,16 @@ export interface CustomCardEntry { documentationURL?: string; } +export interface CustomTileFeatureEntry { + type: string; + name?: string; + supported?: (stateObj: HassEntity) => boolean; + configurable?: boolean; +} + export interface CustomCardsWindow { customCards?: CustomCardEntry[]; + customTileFeatures?: CustomTileFeatureEntry[]; } export const CUSTOM_TYPE_PREFIX = "custom:"; @@ -17,8 +27,18 @@ const customCardsWindow = window as CustomCardsWindow; if (!("customCards" in customCardsWindow)) { customCardsWindow.customCards = []; } +if (!("customTileFeatures" in customCardsWindow)) { + customCardsWindow.customTileFeatures = []; +} export const customCards = customCardsWindow.customCards!; +export const customTileFeatures = customCardsWindow.customTileFeatures!; export const getCustomCardEntry = (type: string) => customCards.find((card) => card.type === type); + +export const isCustomType = (type: string) => + type.startsWith(CUSTOM_TYPE_PREFIX); + +export const stripCustomPrefix = (type: string) => + type.slice(CUSTOM_TYPE_PREFIX.length); diff --git a/src/panels/lovelace/cards/hui-tile-card.ts b/src/panels/lovelace/cards/hui-tile-card.ts index 9f30749c03..be251b2d7f 100644 --- a/src/panels/lovelace/cards/hui-tile-card.ts +++ b/src/panels/lovelace/cards/hui-tile-card.ts @@ -40,7 +40,6 @@ import { findEntities } from "../common/find-entities"; import { handleAction } from "../common/handle-action"; import "../components/hui-timestamp-display"; import { createTileFeatureElement } from "../create-element/create-tile-feature-element"; -import { supportsTileFeature } from "../tile-features/tile-features"; import { LovelaceTileFeatureConfig } from "../tile-features/types"; import { LovelaceCard, @@ -309,10 +308,6 @@ export class HuiTileCard extends LitElement implements LovelaceCard { : undefined; const badge = computeTileBadge(stateObj, this.hass); - const supportedFeatures = this._config.features?.filter((feature) => - supportsTileFeature(stateObj, feature.type) - ); - return html` ${this._shouldRenderRipple ? html`` : null} @@ -373,15 +368,11 @@ export class HuiTileCard extends LitElement implements LovelaceCard { > - ${supportedFeatures?.length - ? html` -
- ${supportedFeatures.map((featureConf) => - this.renderFeature(featureConf, stateObj) - )} -
- ` - : null} +
+ ${this._config.features?.map((featureConf) => + this.renderFeature(featureConf, stateObj) + )} +
`; } @@ -412,7 +403,7 @@ export class HuiTileCard extends LitElement implements LovelaceCard { (element as LovelaceTileFeature).stateObj = stateObj; } - return html`
${element}
`; + return html`${element}`; } static get styles(): CSSResultGroup { @@ -502,6 +493,9 @@ export class HuiTileCard extends LitElement implements LovelaceCard { box-sizing: border-box; pointer-events: none; } + .features { + position: relative; + } `; } } diff --git a/src/panels/lovelace/create-element/create-element-base.ts b/src/panels/lovelace/create-element/create-element-base.ts index 4556efe509..792b8fd2e3 100644 --- a/src/panels/lovelace/create-element/create-element-base.ts +++ b/src/panels/lovelace/create-element/create-element-base.ts @@ -5,7 +5,10 @@ import { LovelaceViewConfig, LovelaceViewElement, } from "../../../data/lovelace"; -import { CUSTOM_TYPE_PREFIX } from "../../../data/lovelace_custom_cards"; +import { + isCustomType, + stripCustomPrefix, +} from "../../../data/lovelace_custom_cards"; import type { HuiErrorCard } from "../cards/hui-error-card"; import type { ErrorCardConfig } from "../cards/types"; import { LovelaceElement, LovelaceElementConfig } from "../elements/types"; @@ -153,9 +156,7 @@ const _lazyCreate = ( }; const _getCustomTag = (type: string) => - type.startsWith(CUSTOM_TYPE_PREFIX) - ? type.slice(CUSTOM_TYPE_PREFIX.length) - : undefined; + isCustomType(type) ? stripCustomPrefix(type) : undefined; export const createLovelaceElement = ( tagSuffix: T, diff --git a/src/panels/lovelace/editor/config-elements/hui-entities-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-entities-card-editor.ts index 585de1f5f2..1b0e680850 100644 --- a/src/panels/lovelace/editor/config-elements/hui-entities-card-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-entities-card-editor.ts @@ -17,10 +17,7 @@ import { union, } from "superstruct"; import { fireEvent, HASSDomEvent } from "../../../../common/dom/fire_event"; -import { - customType, - isCustomType, -} from "../../../../common/structs/is-custom-type"; +import { customType } from "../../../../common/structs/is-custom-type"; import { entityId } from "../../../../common/structs/is-entity-id"; import { computeRTLDirection } from "../../../../common/util/compute_rtl"; import "../../../../components/entity/state-badge"; @@ -50,6 +47,7 @@ import { } from "../types"; import { configElementStyle } from "./config-elements-style"; import { buttonEntityConfigStruct } from "../structs/button-entity-struct"; +import { isCustomType } from "../../../../data/lovelace_custom_cards"; const buttonEntitiesRowConfigStruct = object({ type: literal("button"), diff --git a/src/panels/lovelace/editor/config-elements/hui-tile-card-features-editor.ts b/src/panels/lovelace/editor/config-elements/hui-tile-card-features-editor.ts index ffcce2826f..372901d0f6 100644 --- a/src/panels/lovelace/editor/config-elements/hui-tile-card-features-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-tile-card-features-editor.ts @@ -1,11 +1,4 @@ -import { - mdiDelete, - mdiDrag, - mdiListBox, - mdiPencil, - mdiPlus, - mdiWindowShutter, -} from "@mdi/js"; +import { mdiDelete, mdiDrag, mdiListBox, mdiPencil, mdiPlus } from "@mdi/js"; import { HassEntity } from "home-assistant-js-websocket"; import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import { customElement, property } from "lit/decorators"; @@ -14,9 +7,17 @@ import type { SortableEvent } from "sortablejs"; import { fireEvent } from "../../../../common/dom/fire_event"; import { stopPropagation } from "../../../../common/dom/stop_propagation"; import "../../../../components/entity/ha-entity-picker"; -import "../../../../components/ha-icon-button"; import "../../../../components/ha-button"; +import "../../../../components/ha-icon-button"; +import "../../../../components/ha-list-item"; import "../../../../components/ha-svg-icon"; +import { + CustomTileFeatureEntry, + customTileFeatures, + CUSTOM_TYPE_PREFIX, + isCustomType, + stripCustomPrefix, +} from "../../../../data/lovelace_custom_cards"; import { sortableStyles } from "../../../../resources/ha-sortable-style"; import { loadSortable, @@ -24,19 +25,40 @@ import { } from "../../../../resources/sortable.ondemand"; import { HomeAssistant } from "../../../../types"; import { getTileFeatureElementClass } from "../../create-element/create-tile-feature-element"; -import { - isTileFeatureEditable, - supportsTileFeature, -} from "../../tile-features/tile-features"; +import { supportsCoverOpenCloseTileFeature } from "../../tile-features/hui-cover-open-close-tile-feature"; +import { supportsCoverTiltTileFeature } from "../../tile-features/hui-cover-tilt-tile-feature"; +import { supportsLightBrightnessTileFeature } from "../../tile-features/hui-light-brightness-tile-feature"; +import { supportsVacuumCommandTileFeature } from "../../tile-features/hui-vacuum-commands-tile-feature"; import { LovelaceTileFeatureConfig } from "../../tile-features/types"; -const FEATURES_TYPE: LovelaceTileFeatureConfig["type"][] = [ +type FeatureType = LovelaceTileFeatureConfig["type"]; +type SupportsFeature = (stateObj: HassEntity) => boolean; + +const FEATURE_TYPES: FeatureType[] = [ "cover-open-close", "cover-tilt", "light-brightness", "vacuum-commands", ]; +const EDITABLES_FEATURE_TYPES = new Set(["vacuum-commands"]); + +const SUPPORTS_FEATURE_TYPES: Record = + { + "cover-open-close": supportsCoverOpenCloseTileFeature, + "cover-tilt": supportsCoverTiltTileFeature, + "light-brightness": supportsLightBrightnessTileFeature, + "vacuum-commands": supportsVacuumCommandTileFeature, + }; + +const CUSTOM_FEATURE_ENTRIES: Record< + string, + CustomTileFeatureEntry | undefined +> = {}; +customTileFeatures.forEach((feature) => { + CUSTOM_FEATURE_ENTRIES[feature.type] = feature; +}); + declare global { interface HASSDomEvents { "features-changed": { @@ -64,6 +86,45 @@ export class HuiTileCardFeaturesEditor extends LitElement { this._destroySortable(); } + private _supportsFeatureType(type: string): boolean { + if (!this.stateObj) return false; + + if (isCustomType(type)) { + const customType = stripCustomPrefix(type); + const customFeatureEntry = CUSTOM_FEATURE_ENTRIES[customType]; + if (!customFeatureEntry?.supported) return true; + try { + return customFeatureEntry.supported(this.stateObj); + } catch { + return false; + } + } + + const supportsFeature = SUPPORTS_FEATURE_TYPES[type]; + return !supportsFeature || supportsFeature(this.stateObj); + } + + private _isFeatureTypeEditable(type: string) { + if (isCustomType(type)) { + const customType = stripCustomPrefix(type); + const customFeatureEntry = CUSTOM_FEATURE_ENTRIES[customType]; + return customFeatureEntry?.configurable; + } + + return EDITABLES_FEATURE_TYPES.has(type as FeatureType); + } + + private _getFeatureTypeLabel(type: string) { + if (isCustomType(type)) { + const customType = stripCustomPrefix(type); + const customFeatureEntry = CUSTOM_FEATURE_ENTRIES[customType]; + return customFeatureEntry?.name || type; + } + return this.hass!.localize( + `ui.panel.lovelace.editor.card.tile.features.types.${type}.label` + ); + } + private _getKey(feature: LovelaceTileFeatureConfig) { if (!this._featuresKeys.has(feature)) { this._featuresKeys.set(feature, Math.random().toString()); @@ -72,19 +133,32 @@ export class HuiTileCardFeaturesEditor extends LitElement { return this._featuresKeys.get(feature)!; } - private get _supportedFeatureTypes() { - if (!this.stateObj) return []; + protected firstUpdated() { + this._createSortable(); + } - return FEATURES_TYPE.filter((type) => - supportsTileFeature(this.stateObj!, type) + private _getSupportedFeaturesType() { + const featuresTypes = FEATURE_TYPES as string[]; + const customFeaturesTypes = customTileFeatures.map( + (feature) => `${CUSTOM_TYPE_PREFIX}${feature.type}` ); + return featuresTypes + .concat(customFeaturesTypes) + .filter((type) => this._supportsFeatureType(type)); } protected render(): TemplateResult { if (!this.features || !this.hass) { - return html``; + return null; } + const supportedFeaturesType = this._getSupportedFeaturesType(); + + const types = supportedFeaturesType.filter((type) => !isCustomType(type)); + const customTypes = supportedFeaturesType.filter((type) => + isCustomType(type) + ); + return html`

@@ -94,8 +168,7 @@ export class HuiTileCardFeaturesEditor extends LitElement { )}

- ${this._supportedFeatureTypes.length === 0 && - this.features.length === 0 + ${supportedFeaturesType.length === 0 && this.features.length === 0 ? html` ${this.hass!.localize( @@ -108,53 +181,58 @@ export class HuiTileCardFeaturesEditor extends LitElement { ${repeat( this.features, (featureConf) => this._getKey(featureConf), - (featureConf, index) => html` -
-
- -
-
-
- - ${this.hass!.localize( - `ui.panel.lovelace.editor.card.tile.features.types.${featureConf.type}.label` - )} - - ${this.stateObj && - !supportsTileFeature(this.stateObj, featureConf.type) - ? html` - ${this.hass!.localize( - "ui.panel.lovelace.editor.card.tile.features.not_compatible" - )} - ` - : null} + (featureConf, index) => { + const type = featureConf.type; + const supported = this._supportsFeatureType(type); + const editable = this._isFeatureTypeEditable(type); + return html` +
+
+
+
+
+ ${this._getFeatureTypeLabel(type)} + ${this.stateObj && !supported + ? html` + + ${this.hass!.localize( + "ui.panel.lovelace.editor.card.tile.features.not_compatible" + )} + + ` + : null} +
+
+ ${editable + ? html` + + ` + : null} +
- ${isTileFeatureEditable(featureConf.type) - ? html`` - : null} - -
- ` + `; + } )}
- ${this._supportedFeatureTypes.length > 0 + ${supportedFeaturesType.length > 0 ? html` - ${this._supportedFeatureTypes.map( - (featureType) => html` - - ${this.hass!.localize( - `ui.panel.lovelace.editor.card.tile.features.types.${featureType}.label` - )} - ` + ${types.map( + (type) => html` + + ${this._getFeatureTypeLabel(type)} + + ` + )} + ${types.length > 0 && customTypes.length > 0 + ? html`
  • ` + : null} + ${customTypes.map( + (type) => html` + + ${this._getFeatureTypeLabel(type)} + + ` )}
    ` @@ -189,10 +273,6 @@ export class HuiTileCardFeaturesEditor extends LitElement { `; } - protected firstUpdated(): void { - this._createSortable(); - } - private async _createSortable() { const Sortable = await loadSortable(); this._sortable = new Sortable( @@ -228,7 +308,9 @@ export class HuiTileCardFeaturesEditor extends LitElement { if (index == null) return; - const value = this._supportedFeatureTypes[index]; + const value = this._getSupportedFeaturesType()[index]; + if (!value) return; + const elClass = await getTileFeatureElementClass(value); let newFeature: LovelaceTileFeatureConfig; @@ -340,6 +422,10 @@ export class HuiTileCardFeaturesEditor extends LitElement { font-size: 12px; color: var(--secondary-text-color); } + + li[divider] { + border-bottom-color: var(--divider-color); + } `, ]; } diff --git a/src/panels/lovelace/editor/get-card-documentation-url.ts b/src/panels/lovelace/editor/get-card-documentation-url.ts index 7d01eb9419..e312463d4b 100644 --- a/src/panels/lovelace/editor/get-card-documentation-url.ts +++ b/src/panels/lovelace/editor/get-card-documentation-url.ts @@ -1,6 +1,7 @@ import { - CUSTOM_TYPE_PREFIX, getCustomCardEntry, + isCustomType, + stripCustomPrefix, } from "../../../data/lovelace_custom_cards"; import { HomeAssistant } from "../../../types"; import { documentationUrl } from "../../../util/documentation-url"; @@ -9,9 +10,8 @@ export const getCardDocumentationURL = ( hass: HomeAssistant, type: string ): string | undefined => { - if (type.startsWith(CUSTOM_TYPE_PREFIX)) { - return getCustomCardEntry(type.slice(CUSTOM_TYPE_PREFIX.length)) - ?.documentationURL; + if (isCustomType(type)) { + return getCustomCardEntry(stripCustomPrefix(type))?.documentationURL; } return `${documentationUrl(hass, "/lovelace/")}${type}`; diff --git a/src/panels/lovelace/tile-features/hui-cover-open-close-tile-feature.ts b/src/panels/lovelace/tile-features/hui-cover-open-close-tile-feature.ts index 9f2813b157..8a4fe2c7cb 100644 --- a/src/panels/lovelace/tile-features/hui-cover-open-close-tile-feature.ts +++ b/src/panels/lovelace/tile-features/hui-cover-open-close-tile-feature.ts @@ -2,6 +2,7 @@ import { mdiStop } from "@mdi/js"; import { HassEntity } from "home-assistant-js-websocket"; import { css, html, LitElement, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; +import { computeDomain } from "../../../common/entity/compute_domain"; import { computeCloseIcon, computeOpenIcon, @@ -19,6 +20,15 @@ import { HomeAssistant } from "../../../types"; import { LovelaceTileFeature } from "../types"; import { CoverOpenCloseTileFeatureConfig } from "./types"; +export const supportsCoverOpenCloseTileFeature = (stateObj: HassEntity) => { + const domain = computeDomain(stateObj.entity_id); + return ( + domain === "cover" && + (supportsFeature(stateObj, CoverEntityFeature.OPEN) || + supportsFeature(stateObj, CoverEntityFeature.CLOSE)) + ); +}; + @customElement("hui-cover-open-close-tile-feature") class HuiCoverOpenCloseTileFeature extends LitElement @@ -64,9 +74,14 @@ class HuiCoverOpenCloseTileFeature }); } - protected render(): TemplateResult { - if (!this._config || !this.hass || !this.stateObj) { - return html``; + protected render(): TemplateResult | null { + if ( + !this._config || + !this.hass || + !this.stateObj || + !supportsCoverOpenCloseTileFeature(this.stateObj) + ) { + return null; } return html` diff --git a/src/panels/lovelace/tile-features/hui-cover-tilt-tile-feature.ts b/src/panels/lovelace/tile-features/hui-cover-tilt-tile-feature.ts index 43f03fbd80..e2545048e7 100644 --- a/src/panels/lovelace/tile-features/hui-cover-tilt-tile-feature.ts +++ b/src/panels/lovelace/tile-features/hui-cover-tilt-tile-feature.ts @@ -2,6 +2,7 @@ import { mdiArrowBottomLeft, mdiArrowTopRight, mdiStop } from "@mdi/js"; import { HassEntity } from "home-assistant-js-websocket"; import { css, html, LitElement, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; +import { computeDomain } from "../../../common/entity/compute_domain"; import { supportsFeature } from "../../../common/entity/supports-feature"; import "../../../components/ha-control-button"; import "../../../components/ha-control-button-group"; @@ -15,6 +16,15 @@ import { HomeAssistant } from "../../../types"; import { LovelaceTileFeature } from "../types"; import { CoverTiltTileFeatureConfig } from "./types"; +export const supportsCoverTiltTileFeature = (stateObj: HassEntity) => { + const domain = computeDomain(stateObj.entity_id); + return ( + domain === "cover" && + (supportsFeature(stateObj, CoverEntityFeature.OPEN_TILT) || + supportsFeature(stateObj, CoverEntityFeature.CLOSE_TILT)) + ); +}; + @customElement("hui-cover-tilt-tile-feature") class HuiCoverTiltTileFeature extends LitElement @@ -60,9 +70,14 @@ class HuiCoverTiltTileFeature }); } - protected render(): TemplateResult { - if (!this._config || !this.hass || !this.stateObj) { - return html``; + protected render(): TemplateResult | null { + if ( + !this._config || + !this.hass || + !this.stateObj || + !supportsCoverTiltTileFeature + ) { + return null; } return html` diff --git a/src/panels/lovelace/tile-features/hui-light-brightness-tile-feature.ts b/src/panels/lovelace/tile-features/hui-light-brightness-tile-feature.ts index 6848604e21..f73261a41c 100644 --- a/src/panels/lovelace/tile-features/hui-light-brightness-tile-feature.ts +++ b/src/panels/lovelace/tile-features/hui-light-brightness-tile-feature.ts @@ -1,13 +1,20 @@ import { HassEntity } from "home-assistant-js-websocket"; import { css, html, LitElement, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; +import { computeDomain } from "../../../common/entity/compute_domain"; import { stateActive } from "../../../common/entity/state_active"; import "../../../components/tile/ha-tile-slider"; import { UNAVAILABLE } from "../../../data/entity"; +import { lightSupportsBrightness } from "../../../data/light"; import { HomeAssistant } from "../../../types"; import { LovelaceTileFeature } from "../types"; import { LightBrightnessTileFeatureConfig } from "./types"; +export const supportsLightBrightnessTileFeature = (stateObj: HassEntity) => { + const domain = computeDomain(stateObj.entity_id); + return domain === "light" && lightSupportsBrightness(stateObj); +}; + @customElement("hui-light-brightness-tile-feature") class HuiLightBrightnessTileFeature extends LitElement @@ -32,9 +39,14 @@ class HuiLightBrightnessTileFeature this._config = config; } - protected render(): TemplateResult { - if (!this._config || !this.hass || !this.stateObj) { - return html``; + protected render(): TemplateResult | null { + if ( + !this._config || + !this.hass || + !this.stateObj || + !supportsLightBrightnessTileFeature(this.stateObj) + ) { + return null; } const position = diff --git a/src/panels/lovelace/tile-features/hui-vacuum-commands-tile-feature.ts b/src/panels/lovelace/tile-features/hui-vacuum-commands-tile-feature.ts index 8089c55d23..4b1993fa2f 100644 --- a/src/panels/lovelace/tile-features/hui-vacuum-commands-tile-feature.ts +++ b/src/panels/lovelace/tile-features/hui-vacuum-commands-tile-feature.ts @@ -10,6 +10,7 @@ import { import { HassEntity } from "home-assistant-js-websocket"; import { css, html, LitElement, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; +import { computeDomain } from "../../../common/entity/compute_domain"; import { supportsFeature } from "../../../common/entity/supports-feature"; import "../../../components/ha-control-button"; import "../../../components/ha-control-button-group"; @@ -113,6 +114,14 @@ export const VACUUM_COMMANDS_BUTTONS: Record< }), }; +export const supportsVacuumCommandTileFeature = (stateObj: HassEntity) => { + const domain = computeDomain(stateObj.entity_id); + return ( + domain === "vacuum" && + VACUUM_COMMANDS.some((c) => supportsVacuumCommand(stateObj, c)) + ); +}; + @customElement("hui-vacuum-commands-tile-feature") class HuiVacuumCommandTileFeature extends LitElement @@ -160,9 +169,14 @@ class HuiVacuumCommandTileFeature }); } - protected render(): TemplateResult { - if (!this._config || !this.hass || !this.stateObj) { - return html``; + protected render(): TemplateResult | null { + if ( + !this._config || + !this.hass || + !this.stateObj || + !supportsVacuumCommandTileFeature(this.stateObj) + ) { + return null; } const stateObj = this.stateObj as VacuumEntity; diff --git a/src/panels/lovelace/tile-features/tile-features.ts b/src/panels/lovelace/tile-features/tile-features.ts deleted file mode 100644 index 5dfdb32a7f..0000000000 --- a/src/panels/lovelace/tile-features/tile-features.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { HassEntity } from "home-assistant-js-websocket"; -import { computeDomain } from "../../../common/entity/compute_domain"; -import { supportsFeature } from "../../../common/entity/supports-feature"; -import { CoverEntityFeature } from "../../../data/cover"; -import { lightSupportsBrightness } from "../../../data/light"; -import { supportsVacuumCommand } from "./hui-vacuum-commands-tile-feature"; -import { LovelaceTileFeatureConfig, VACUUM_COMMANDS } from "./types"; - -type TileFeatureType = LovelaceTileFeatureConfig["type"]; -export type SupportsTileFeature = (stateObj: HassEntity) => boolean; - -const TILE_FEATURES_SUPPORT: Record = { - "cover-open-close": (stateObj) => - computeDomain(stateObj.entity_id) === "cover" && - (supportsFeature(stateObj, CoverEntityFeature.OPEN) || - supportsFeature(stateObj, CoverEntityFeature.CLOSE)), - "cover-tilt": (stateObj) => - computeDomain(stateObj.entity_id) === "cover" && - (supportsFeature(stateObj, CoverEntityFeature.OPEN_TILT) || - supportsFeature(stateObj, CoverEntityFeature.CLOSE_TILT)), - "light-brightness": (stateObj) => - computeDomain(stateObj.entity_id) === "light" && - lightSupportsBrightness(stateObj), - "vacuum-commands": (stateObj) => - computeDomain(stateObj.entity_id) === "vacuum" && - VACUUM_COMMANDS.some((c) => supportsVacuumCommand(stateObj, c)), -}; - -const TILE_FEATURE_EDITABLE: Set = new Set([ - "vacuum-commands", -]); - -export const supportsTileFeature = ( - stateObj: HassEntity, - feature: TileFeatureType -): boolean => { - const supportFunction = TILE_FEATURES_SUPPORT[feature] as - | SupportsTileFeature - | undefined; - return !supportFunction || supportFunction(stateObj); -}; - -export const isTileFeatureEditable = (feature: TileFeatureType): boolean => - TILE_FEATURE_EDITABLE.has(feature); diff --git a/src/panels/lovelace/types.ts b/src/panels/lovelace/types.ts index 3e0652437b..c99e6a51c9 100644 --- a/src/panels/lovelace/types.ts +++ b/src/panels/lovelace/types.ts @@ -109,6 +109,7 @@ export interface LovelaceTileFeatureConstructor hass: HomeAssistant, stateObj?: HassEntity ) => LovelaceTileFeatureConfig; + isSupported?: (stateObj?: HassEntity) => boolean; } export interface LovelaceTileFeatureEditor