Skip to content

Commit

Permalink
Add hide state option
Browse files Browse the repository at this point in the history
  • Loading branch information
piitaya committed Oct 16, 2023
1 parent b920cda commit 50fe8fd
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 108 deletions.
120 changes: 40 additions & 80 deletions src/panels/lovelace/cards/hui-tile-card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { classMap } from "lit/directives/class-map";
import { ifDefined } from "lit/directives/if-defined";
import { styleMap } from "lit/directives/style-map";
import memoizeOne from "memoize-one";
import { ensureArray } from "../../../common/array/ensure-array";
import { computeCssColor } from "../../../common/color/compute-color";
import { hsv2rgb, rgb2hex, rgb2hsv } from "../../../common/color/convert-color";
import { DOMAINS_TOGGLE } from "../../../common/const";
Expand All @@ -34,15 +35,7 @@ import "../../../components/tile/ha-tile-icon";
import "../../../components/tile/ha-tile-image";
import "../../../components/tile/ha-tile-info";
import { cameraUrlWithWidthHeight } from "../../../data/camera";
import {
CoverEntity,
computeCoverPositionStateDisplay,
} from "../../../data/cover";
import { isUnavailableState } from "../../../data/entity";
import { FanEntity, computeFanSpeedStateDisplay } from "../../../data/fan";
import type { HumidifierEntity } from "../../../data/humidifier";
import type { ClimateEntity } from "../../../data/climate";
import type { LightEntity } from "../../../data/light";
import type { ActionHandlerEvent } from "../../../data/lovelace";
import { SENSOR_DEVICE_CLASS_TIMESTAMP } from "../../../data/sensor";
import { HomeAssistant } from "../../../types";
Expand All @@ -54,7 +47,6 @@ import "../tile-features/hui-tile-features";
import type { LovelaceCard, LovelaceCardEditor } from "../types";
import { computeTileBadge } from "./tile/badges/tile-badge";
import type { ThermostatCardConfig, TileCardConfig } from "./types";
import { ensureArray } from "../../../common/array/ensure-array";

const TIMESTAMP_STATE_DOMAINS = ["button", "input_button", "scene"];

Expand Down Expand Up @@ -182,20 +174,32 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
}
);

private _computeStateContent(
private _renderStateContent(
stateObj: HassEntity,
stateContent: string | string[]
) {
const contents = ensureArray(stateContent);

if (contents.length === 1 && contents[0] === "none") {
return nothing;
}

const values = contents
.filter((content) => content !== "none")
.map((content) => {
if (content === "state") {
const domain = computeDomain(stateObj.entity_id);
if (
(stateObj.attributes.device_class ===
SENSOR_DEVICE_CLASS_TIMESTAMP ||
TIMESTAMP_STATE_DOMAINS.includes(domain)) &&
!isUnavailableState(stateObj.state)
) {
return html`
<hui-timestamp-display
.hass=${this.hass}
.ts=${new Date(stateObj.state)}
format="relative"
capitalize
></hui-timestamp-display>
`;
}

return this.hass!.formatEntityState(stateObj);
}
if (content === "last-changed") {
Expand All @@ -214,7 +218,7 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
.filter(Boolean);

if (!values.length) {
return "-";
return html`${this.hass!.formatEntityState(stateObj)}`;
}

return html`
Expand All @@ -225,80 +229,34 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
`;
}

private _formatState(stateObj: HassEntity): TemplateResult | string {
private _renderState(stateObj: HassEntity): TemplateResult | typeof nothing {
const domain = computeDomain(stateObj.entity_id);
const active = stateActive(stateObj);

if (
(stateObj.attributes.device_class === SENSOR_DEVICE_CLASS_TIMESTAMP ||
TIMESTAMP_STATE_DOMAINS.includes(domain)) &&
!isUnavailableState(stateObj.state)
) {
return html`
<hui-timestamp-display
.hass=${this.hass}
.ts=${new Date(stateObj.state)}
format="relative"
capitalize
></hui-timestamp-display>
`;
}

if (domain === "light" && stateActive(stateObj)) {
const brightness = (stateObj as LightEntity).attributes.brightness;
if (brightness) {
return this.hass!.formatEntityAttributeValue(stateObj, "brightness");
}
if (domain === "light" && active) {
return this._renderStateContent(stateObj, ["brightness"]);
}

if (domain === "fan") {
const speedStateDisplay = computeFanSpeedStateDisplay(
stateObj as FanEntity,
this.hass!
);
if (speedStateDisplay) {
return speedStateDisplay;
}
if (domain === "fan" && active) {
return this._renderStateContent(stateObj, ["percentage"]);
}

const stateDisplay = this.hass!.formatEntityState(stateObj);

if (domain === "cover") {
const positionStateDisplay = computeCoverPositionStateDisplay(
stateObj as CoverEntity,
this.hass!
);
if (positionStateDisplay) {
return `${stateDisplay}${positionStateDisplay}`;
}
if (domain === "cover" && active) {
return this._renderStateContent(stateObj, ["state", "current_position"]);
}

if (domain === "humidifier" && stateActive(stateObj)) {
const humidity = (stateObj as HumidifierEntity).attributes.humidity;
if (humidity) {
const formattedHumidity = this.hass!.formatEntityAttributeValue(
stateObj,
"humidity",
Math.round(humidity)
);
return `${stateDisplay}${formattedHumidity}`;
}
if (domain === "humidifier") {
return this._renderStateContent(stateObj, ["state", "current_humidity"]);
}

if (domain === "climate") {
const current_temperature = (stateObj as ClimateEntity).attributes
.current_temperature;
if (current_temperature) {
const formattedCurrentTemperature =
this.hass!.formatEntityAttributeValue(
stateObj,
"current_temperature",
current_temperature
);
return `${stateDisplay}${formattedCurrentTemperature}`;
}
return this._renderStateContent(stateObj, [
"state",
"current_temperature",
]);
}

return stateDisplay;
return this._renderStateContent(stateObj, "state");
}

@queryAsync("mwc-ripple") private _ripple!: Promise<Ripple | null>;
Expand Down Expand Up @@ -367,9 +325,11 @@ export class HuiTileCard extends LitElement implements LovelaceCard {

const name = this._config.name || stateObj.attributes.friendly_name;

const localizedState = this._config.state_content
? this._computeStateContent(stateObj, this._config.state_content)
: this._formatState(stateObj);
const localizedState = this._config.hide_state
? nothing
: this._config.state_content
? this._renderStateContent(stateObj, this._config.state_content)
: this._renderState(stateObj);

const active = stateActive(stateObj);
const color = this._computeStateColor(stateObj, this._config.color);
Expand Down
1 change: 1 addition & 0 deletions src/panels/lovelace/cards/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,7 @@ export interface EnergyFlowCardConfig extends LovelaceCardConfig {
export interface TileCardConfig extends LovelaceCardConfig {
entity: string;
name?: string;
hide_state?: boolean;
state_content?: string | string[];
icon?: string;
color?: string;
Expand Down
77 changes: 49 additions & 28 deletions src/panels/lovelace/editor/config-elements/hui-tile-card-editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ const cardConfigStruct = assign(
entity: optional(string()),
name: optional(string()),
icon: optional(string()),
hide_state: optional(boolean()),
state_content: optional(union([string(), array(string())])),
color: optional(string()),
show_entity_picture: optional(boolean()),
Expand Down Expand Up @@ -124,7 +125,8 @@ export class HuiTileCardEditor
(
localize: LocalizeFunc,
formatEntityAttributeName: formatEntityAttributeNameFunc,
stateObj: HassEntity | undefined
stateObj: HassEntity | undefined,
hideState: boolean
) =>
[
{ name: "entity", selector: { entity: {} } },
Expand Down Expand Up @@ -164,35 +166,48 @@ export class HuiTileCardEditor
boolean: {},
},
},
{
name: "hide_state",
selector: {
boolean: {},
},
},
],
},
{
name: "state_content",
selector: {
select: {
mode: "dropdown",
reorder: true,
custom_value: true,
multiple: true,
options: [
{
label: "State",
value: "state",
...(!hideState
? ([
{
name: "state_content",
selector: {
select: {
mode: "dropdown",
reorder: true,
custom_value: true,
multiple: true,
options: [
{
label: "State",
value: "state",
},
{
label: "Last changed",
value: "last-changed",
},
...Object.keys(stateObj?.attributes ?? {})
.filter((a) => !HIDDEN_ATTRIBUTES.includes(a))
.map((attribute) => ({
value: attribute,
label: formatEntityAttributeName(
stateObj!,
attribute
),
})),
],
},
},
{
label: "Last changed",
value: "last-changed",
},
...Object.keys(stateObj?.attributes ?? {})
.filter((a) => !HIDDEN_ATTRIBUTES.includes(a))
.map((attribute) => ({
value: attribute,
label: formatEntityAttributeName(stateObj!, attribute),
})),
],
},
},
},
},
] as const satisfies readonly HaFormSchema[])
: []),
],
},
{
Expand Down Expand Up @@ -234,7 +249,8 @@ export class HuiTileCardEditor
const schema = this._schema(
this.hass!.localize,
this.hass.formatEntityAttributeName,
stateObj
stateObj,
this._config.hide_state ?? false
);

if (this._subElementEditorConfig) {
Expand Down Expand Up @@ -286,6 +302,10 @@ export class HuiTileCardEditor
...newConfig,
};

if (config.hide_state) {
delete config.state_content;
}

if (config.state_content) {
if (config.state_content.length === 0) {
delete config.state_content;
Expand Down Expand Up @@ -361,6 +381,7 @@ export class HuiTileCardEditor
case "icon_tap_action":
case "show_entity_picture":
case "vertical":
case "hide_state":
case "state_content":
return this.hass!.localize(
`ui.panel.lovelace.editor.card.tile.${schema.name}`
Expand Down
1 change: 1 addition & 0 deletions src/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -5048,6 +5048,7 @@
"default_color": "Default color (state)",
"show_entity_picture": "Show entity picture",
"vertical": "Vertical",
"hide_state": "Hide state",
"state_content": "State content",
"features": {
"name": "Features",
Expand Down

0 comments on commit 50fe8fd

Please sign in to comment.